所用芯片是STM32L071RZ,硬件I2C2,非I2C1、I2C3。SCL用的是PB10,SDA用的是PB11.
刚接触固件编程,不熟悉。求一个STM32L0xx系列硬件I2C2范例代码。可发至邮箱tclxspy@163.com.
非常感谢!
下面是主要代码,总感觉I2C时钟配置有问题。
main.c
- #include "main.h"
- /** @addtogroup STM32L0xx_HAL_Examples
- * @{
- */
- /** @addtogroup I2C_TwoBoards_AdvComIT
- * @{
- */
- /* Private typedef -----------------------------------------------------------*/
- /* Private define ------------------------------------------------------------*/
- /* Uncomment this line to use the board as master, if not it is used as slave */
- #define MASTER_BOARD
- #define I2C_ADDRESS 0xA0
- #define MASTER_REQ_READ 0xA0
- #define MASTER_REQ_WRITE 0xA0
- /* I2C TIMING Register define when I2C clock source is SYSCLK */
- /* I2C TIMING is calculated in case of the I2C Clock source is the SYSCLK = 32 MHz */
- //#define I2C_TIMING 0x10A13E56 /* 100 kHz with analog Filter ON, Rise Time 400ns, Fall Time 100ns */
- #define I2C_TIMING 0x00B1112E /* 400 kHz with analog Filter ON, Rise Time 250ns, Fall Time 100ns */
- /* Private macro -------------------------------------------------------------*/
- /* Private variables ---------------------------------------------------------*/
- /* I2C handler declaration */
- I2C_HandleTypeDef I2cHandle;
- /* Buffer used for transmission */
- //uint8_t aTxBuffer[] = {0x33, 0x34};
- uint8_t aTxBuffer[] = {0x46, 0x54};//{"FT"}
- /* Buffer used for reception */
- uint8_t aRxBuffer[RXBUFFERSIZE];
- __IO uint16_t hTxNumData = 0;
- __IO uint16_t hRxNumData = 0;
- uint8_t bTransferRequest = 0;
- /* Private function prototypes -----------------------------------------------*/
- void SystemClock_Config(void);
- static uint16_t Buffercmp(uint8_t *pBuffer1, uint8_t *pBuffer2, uint16_t BufferLength);
- static void Flush_Buffer(uint8_t* pBuffer, uint16_t BufferLength);
- static void Error_Handler(void);
- /* Private functions ---------------------------------------------------------*/
- /**
- * @brief Main program
- * @param None
- * @retval None
- */
- int main(void)
- {
- /* STM32L0xx HAL library initialization:
- - Configure the Flash prefetch, Flash preread and Buffer caches
- - Systick timer is configured by default as source of time base, but user
- can eventually implement his proper time base source (a general purpose
- timer for example or other time source), keeping in mind that Time base
- duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
- handled in milliseconds basis.
- - Low Level Initialization
- */
- HAL_Init();
-
- /* Configure the system clock to 32 MHz */
- SystemClock_Config();
- /* Configure LED2 */
- //BSP_LED_Init(LED2);
- /*##-1- Configure the I2C peripheral ######################################*/
- I2cHandle.Instance = I2Cx;
- I2cHandle.Init.Timing = I2C_TIMING;
- I2cHandle.Init.OwnAddress1 = I2C_ADDRESS;
- I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
- I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
- I2cHandle.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
- I2cHandle.Init.OwnAddress2 = 0xFF;
- I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
- I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
- if(HAL_I2C_Init(&I2cHandle) != HAL_OK)
- {
- /* Initialization Error */
- Error_Handler();
- }
- /* Enable the Analog I2C Filter */
- HAL_I2CEx_ConfigAnalogFilter(&I2cHandle,I2C_ANALOGFILTER_ENABLE);
- #ifdef MASTER_BOARD
- /* Configure User push-button */
- //BSP_PB_Init(BUTTON_KEY,BUTTON_MODE_GPIO);
- /* Wait for User push-button press before starting the Communication */
- // while (BSP_PB_GetState(BUTTON_KEY) != GPIO_PIN_RESET)
- // {
- // }
- /* Wait for User push-button release before starting the Communication */
- // while (BSP_PB_GetState(BUTTON_KEY) != GPIO_PIN_SET)
- // {
- // }
- while(1)
- {
- /* Initialize number of data variables */
- hTxNumData = TXBUFFERSIZE;
- hRxNumData = RXBUFFERSIZE;
- /* Update bTransferRequest to send buffer write request for Slave */
- bTransferRequest = MASTER_REQ_WRITE;
- /*##-2- Master sends write request for slave #############################*/
- /*##-3- Master sends number of data to be written ########################*/
- do
- {
- if(HAL_I2C_Mem_Write_IT(&I2cHandle, (uint16_t)I2C_ADDRESS, 0xA8, I2C_MEMADD_SIZE_8BIT, (uint8_t*)&aTxBuffer, TXBUFFERSIZE)!= HAL_OK)
- {
- /* Error_Handler() function is called when error occurs. */
- Error_Handler();
- }
- /* Before starting a new communication transfer, you need to check the current
- state of the peripheral; if it抯 busy you need to wait for the end of current
- transfer before starting a new one.
- For simplicity reasons, this example is just waiting till the end of the
- transfer, but application may perform other tasks while transfer operation
- is ongoing. */
- while (HAL_I2C_GetState(&I2cHandle) != HAL_I2C_STATE_READY)
- {
- }
- /* When Acknowledge failure occurs (Slave don't acknowledge it's address)
- Master restarts communication */
- }
- while(HAL_I2C_GetError(&I2cHandle) == HAL_I2C_ERROR_AF);
- HAL_Delay(100);
-
- /*##-7- Master receives aRxBuffer from slave #############################*/
- do
- {
- if(HAL_I2C_Mem_Read_IT(&I2cHandle, (uint16_t)I2C_ADDRESS, 0xA8, I2C_MEMADD_SIZE_8BIT, (uint8_t*)aRxBuffer, RXBUFFERSIZE)!= HAL_OK)
- {
- /* Error_Handler() function is called when error occurs. */
- Error_Handler();
- }
- /* Before starting a new communication transfer, you need to check the current
- state of the peripheral; if it抯 busy you need to wait for the end of current
- transfer before starting a new one.
- For simplicity reasons, this example is just waiting till the end of the
- transfer, but application may perform other tasks while transfer operation
- is ongoing. */
- while (HAL_I2C_GetState(&I2cHandle) != HAL_I2C_STATE_READY)
- {
- }
- /* When Acknowledge failure occurs (Slave don't acknowledge it's address)
- Master restarts communication */
- }
- while(HAL_I2C_GetError(&I2cHandle) == HAL_I2C_ERROR_AF);
- /* Check correctness of received buffer ##################################*/
- if(Buffercmp((uint8_t*)aTxBuffer,(uint8_t*)aRxBuffer,hRxNumData))
- {
- /* Processing Error */
- Error_Handler();
- }
- /* Flush Rx buffers */
- Flush_Buffer((uint8_t*)aRxBuffer,RXBUFFERSIZE);
- /* Toggle LED2 */
- //BSP_LED_Toggle(LED2);
- /* This delay permits to see LED2 toggling */
- HAL_Delay(25);
- }
- #else
- while(1)
- {
- }
- #endif /* MASTER_BOARD */
- }
- /**
- * @brief System Clock Configuration
- * The system Clock is configured as follow :
- * System Clock source = PLL (HSI)
- * SYSCLK(Hz) = 32000000
- * HCLK(Hz) = 32000000
- * AHB Prescaler = 1
- * APB1 Prescaler = 1
- * APB2 Prescaler = 1
- * Flash Latency(WS) = 1
- * Main regulator output voltage = Scale1 mode
- * @retval None
- */
- void SystemClock_Config(void)
- {
- RCC_ClkInitTypeDef RCC_ClkInitStruct ={0};
- RCC_OscInitTypeDef RCC_OscInitStruct = {0};
-
- /* Enable Power Control clock */
- __HAL_RCC_PWR_CLK_ENABLE();
-
- /* The voltage scaling allows optimizing the power consumption when the device is
- clocked below the maximum system frequency, to update the voltage scaling value
- regarding system frequency refer to product datasheet. */
- __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
-
- /* Disable Power Control clock */
- __HAL_RCC_PWR_CLK_DISABLE();
-
- /* Enable HSE Oscillator */
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
- RCC_OscInitStruct.HSIState = RCC_HSI_ON;
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
- RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL4;
- RCC_OscInitStruct.PLL.PLLDIV = RCC_PLL_DIV2;
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct)!= HAL_OK)
- {
- /* Initialization Error */
- while(1);
- }
-
- /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
- clocks dividers */
- RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
- if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1)!= HAL_OK)
- {
- /* Initialization Error */
- while(1);
- }
- }
- /**
- * @brief I2C error callbacks.
- * @param I2cHandle: I2C handle
- * @note This example shows a simple way to report transfer error, and you can
- * add your own implementation.
- * @retval None
- */
- void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *I2cHandle)
- {
- /** Error_Handler() function is called when error occurs.
- * 1- When Slave don't acknowledge it's address, Master restarts communication.
- * 2- When Master don't acknowledge the last data transferred, Slave don't care in this example.
- */
- if (HAL_I2C_GetError(I2cHandle) != HAL_I2C_ERROR_AF)
- {
- Error_Handler();
- }
- }
- /**
- * @brief This function is executed in case of error occurrence.
- * @param None
- * @retval None
- */
- static void Error_Handler(void)
- {
- /* Error if LED2 is slowly blinking (1 sec. period) */
- while(1)
- {
- //BSP_LED_Toggle(LED2);
- HAL_Delay(1000);
- }
- }
- /**
- * @brief Compares two buffers.
- * @param pBuffer1, pBuffer2: buffers to be compared.
- * @param BufferLength: buffer's length
- * @retval 0 : pBuffer1 identical to pBuffer2
- * >0 : pBuffer1 differs from pBuffer2
- */
- static uint16_t Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)
- {
- while (BufferLength--)
- {
- if ((*pBuffer1) != *pBuffer2)
- {
- return BufferLength;
- }
- pBuffer1++;
- pBuffer2++;
- }
- return 0;
- }
- /**
- * @brief Flushes the buffer
- * @param pBuffer: buffers to be flushed.
- * @param BufferLength: buffer's length
- * @retval None
- */
- static void Flush_Buffer(uint8_t* pBuffer, uint16_t BufferLength)
- {
- while (BufferLength--)
- {
- *pBuffer = 0;
- pBuffer++;
- }
- }
- #ifdef USE_FULL_ASSERT
- /**
- * @brief Reports the name of the source file and the source line number
- * where the assert_param error has occurred.
- * @param file: pointer to the source file name
- * @param line: assert_param error line source number
- * @retval None
- */
- void assert_failed(uint8_t* file, uint32_t line)
- {
- /* User can add his own implementation to report the file name and line number,
- ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
- /* Infinite loop */
- while (1)
- {
- }
- }
复制代码
main.h
- #ifndef __MAIN_H
- #define __MAIN_H
- /* Includes ------------------------------------------------------------------*/
- #include "stm32l0xx_hal.h"
- /* Exported types ------------------------------------------------------------*/
- /* Exported constants --------------------------------------------------------*/
- /* User can use this section to tailor I2Cx/I2Cx instance used and associated
- resources */
- /* Definition for I2Cx clock resources */
- #define I2Cx I2C2
- #define RCC_PERIPHCLK_I2Cx RCC_PERIPHCLK_I2C2
- //#define RCC_I2CxCLKSOURCE_SYSCLK RCC_I2C1CLKSOURCE_SYSCLK
- #define I2Cx_CLK_ENABLE() __HAL_RCC_I2C2_CLK_ENABLE()
- #define I2Cx_SDA_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
- #define I2Cx_SCL_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
- #define I2Cx_FORCE_RESET() __HAL_RCC_I2C2_FORCE_RESET()
- #define I2Cx_RELEASE_RESET() __HAL_RCC_I2C2_RELEASE_RESET()
- /* Definition for I2Cx Pins */
- #define I2Cx_SCL_PIN GPIO_PIN_10
- #define I2Cx_SCL_GPIO_PORT GPIOB
- #define I2Cx_SDA_PIN GPIO_PIN_11
- #define I2Cx_SDA_GPIO_PORT GPIOB
- #define I2Cx_SCL_SDA_AF GPIO_AF5_I2C2
- /* Definition for I2Cx's NVIC */
- #define I2Cx_IRQn I2C2_IRQn
- #define I2Cx_IRQHandler I2C2_IRQHandler
- /* Size of Transmission buffer */
- #define TXBUFFERSIZE COUNTOF(aTxBuffer)
- /* Size of Reception buffer */
- #define RXBUFFERSIZE TXBUFFERSIZE
- /* Exported macro ------------------------------------------------------------*/
- #define COUNTOF(__BUFFER__) (sizeof(__BUFFER__) / sizeof(*(__BUFFER__)))
- /* Exported functions ------------------------------------------------------- */
- #endif /* __MAIN_H */
复制代码 stm32l0xx_hal_msp.c
- #include "main.h"
- /** @addtogroup STM32L0xx_HAL_Examples
- * @{
- */
- /** @defgroup HAL_MSP
- * @brief HAL MSP module.
- * @{
- */
- /* Private typedef -----------------------------------------------------------*/
- /* Private define ------------------------------------------------------------*/
- /* Private macro -------------------------------------------------------------*/
- /* Private variables ---------------------------------------------------------*/
- /* Private function prototypes -----------------------------------------------*/
- /* Private functions ---------------------------------------------------------*/
- /** @defgroup HAL_MSP_Private_Functions
- * @{
- */
- /**
- * @brief I2C MSP Initialization
- * This function configures the hardware resources used in this example:
- * - Peripheral's clock enable
- * - Peripheral's GPIO Configuration
- * - DMA configuration for transmission request by peripheral
- * - NVIC configuration for DMA interrupt request enable
- * @param hi2c: I2C handle pointer
- * @retval None
- */
- void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
- RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct;
-
- /*##-1- Configure the I2C clock source. The clock is derived from the SYSCLK #*/
- RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2Cx;
- //RCC_PeriphCLKInitStruct.I2c1ClockSelection = RCC_I2CxCLKSOURCE_SYSCLK;
- HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct);
- /*##-2- Enable peripherals and GPIO Clocks #################################*/
- /* Enable GPIO TX/RX clock */
- I2Cx_SCL_GPIO_CLK_ENABLE();
- I2Cx_SDA_GPIO_CLK_ENABLE();
- /* Enable I2Cx clock */
- I2Cx_CLK_ENABLE();
- /*##-3- Configure peripheral GPIO ##########################################*/
- /* I2C TX GPIO pin configuration */
- GPIO_InitStruct.Pin = I2Cx_SCL_PIN;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
- GPIO_InitStruct.Pull = GPIO_PULLUP;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.Alternate = I2Cx_SCL_SDA_AF;
- HAL_GPIO_Init(I2Cx_SCL_GPIO_PORT, &GPIO_InitStruct);
-
- /* I2C RX GPIO pin configuration */
- GPIO_InitStruct.Pin = I2Cx_SDA_PIN;
- GPIO_InitStruct.Alternate = I2Cx_SCL_SDA_AF;
- HAL_GPIO_Init(I2Cx_SDA_GPIO_PORT, &GPIO_InitStruct);
-
- /*##-4- Configure the NVIC for I2C ########################################*/
- /* NVIC for I2Cx */
- HAL_NVIC_SetPriority(I2Cx_IRQn, 0, 1);
- HAL_NVIC_EnableIRQ(I2Cx_IRQn);
- }
- /**
- * @brief I2C MSP De-Initialization
- * This function frees the hardware resources used in this example:
- * - Disable the Peripheral's clock
- * - Revert GPIO, DMA and NVIC configuration to their default state
- * @param hi2c: I2C handle pointer
- * @retval None
- */
- void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c)
- {
-
- /*##-1- Reset peripherals ##################################################*/
- I2Cx_FORCE_RESET();
- I2Cx_RELEASE_RESET();
- /*##-2- Disable peripherals and GPIO Clocks #################################*/
- /* Configure I2C Tx as alternate function */
- HAL_GPIO_DeInit(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_PIN);
- /* Configure I2C Rx as alternate function */
- HAL_GPIO_DeInit(I2Cx_SDA_GPIO_PORT, I2Cx_SDA_PIN);
-
- /*##-3- Disable the NVIC for I2C ##########################################*/
- HAL_NVIC_DisableIRQ(I2Cx_IRQn);
- }
复制代码
|