• STM32_HAL_I2C_串行接口


    电气特性

    I2C(Inter-Integrated Circuit)是一种由飞利浦公司(现恩智浦半导体)开发的串行通信协议,用于连接低速外围设备。I2C总线只需要两根线(SDA:串行数据线,SCL:串行时钟线)就可以实现多个设备之间的数据交换。以下是I2C的主要电气特性:

    1. 两线接口

      • SDA(Serial Data Line):用于传输数据。(数据线)
      • SCL(Serial Clock Line):用于同步数据传输。(时钟线)
    2. 多主从结构

      • I2C总线支持多个主设备和一个或多个从设备。在任何时刻,只有一个主设备控制总线。(不能同时存在多个主设备)
    3. 地址编码

      • 每个从设备都有唯一的7位或10位地址,主设备通过地址来选择要通信的从设备。
    4. 时钟同步

      • I2C总线上的所有设备都同步于SCL线上的时钟信号。时钟线由主设备控制
    5. 数据传输速率

      • 标准模式下,时钟频率可达100 kHz。
      • 快速模式下,时钟频率可达400 kHz。
      • 高速模式下,时钟频率可达3.4 MHz。
    6. 起始和停止条件

      • 数据传输开始于起始条件,结束于停止条件。起始条件是SCL为高电平时,SDA由高电平向低电平跳变;停止条件是SCL为高电平时,SDA由低电平向高电平跳变。
    7. 数据有效性

      • 数据在SCL为高电平时保持稳定,在SCL为低电平时改变。
    8. 位的表示

      • I2C使用8位数据传输,每次传输可以是一个字节(8位),也可以是多个字节。
    9. 确认(ACK/NACK)

      • 每个字节传输后,接收方会通过驱动SDA线至低电平来发送一个确认位(ACK),或者通过不驱动SDA线(保持高电平)来发送一个非确认位(NACK)。

    协议

    I²C写操作的详细步骤:

    1. 起始条件:主设备通过将SDA线从高电平拉到低电平,同时保持SCL为高电平,然后释放SCL,使其变为低电平,从而产生起始条件。总线在起始条件后处于忙碌状态。

    2. 发送从设备地址:主设备发送从设备的7位或10位地址,后面跟着一个写操作位(即最低位为0)。所有从设备都会接收这个地址,但只有地址匹配的从设备会响应。

    3. 从设备响应:地址匹配的从设备会发送一个确认(ACK)信号,即在第9个时钟周期时,从设备将SDA线拉低。

    4. 发送数据:主设备开始发送数据字节,每个字节后面都跟着一个时钟周期,用于从设备发送ACK信号。主设备可以发送多个字节,直到发送完所有需要的数据。

    5. 停止条件:当主设备发送完所有数据后,它会发出停止条件,即将SDA线从低电平拉到高电平,同时保持SCL为高电平,然后释放SDA线。

    6. 从设备处理数据:从设备在接收到停止条件后,会处理这些数据,例如存储到内部寄存器或EEPROM中。

    以下是I²C写过程的时序图表示:

    起始条件 -> [设备地址 + W] -> ACK -> [数据1] -> ACK -> [数据2] -> ACK -> ... -> [数据N] -> ACK -> 停止条件
    

    -> 表示时间流动,[] 表示数据字节,R 表示读操作位,ACK 表示主设备发送的确认信号,NACK 表示主设备发送的否定确认信号。

    I²C读操作的详细步骤:

    1. 起始条件:主设备通过将SDA线从高电平拉到低电平,同时保持SCL为高电平,然后释放SCL,使其变为低电平,从而产生起始条件。总线在起始条件后处于忙碌状态。

    2. 发送从设备地址:主设备发送从设备的7位或10位地址,后面跟着一个读操作位(即最低位为1)。所有从设备都会接收这个地址,但只有地址匹配的从设备会响应。

    3. 从设备响应:地址匹配的从设备会发送一个确认(ACK)信号,即在第9个时钟周期时,从设备将SDA线拉低。

    4. 读取数据:从设备开始发送数据字节,主设备在每个字节后面通过发送ACK信号来请求更多的数据,或者通过发送NACK信号来结束读取过程。

    5. 停止条件:当主设备完成数据读取后,它会发出停止条件,即将SDA线从低电平拉到高电平,同时保持SCL为高电平,然后释放SDA线。

    6. 主设备处理数据:主设备接收到数据后,可以根据需要进行处理或存储。

    以下是I²C读过程的时序图表示:

    起始条件 -> [设备地址 + R] -> ACK -> [数据1] -> ACK -> [数据2] -> ACK -> ... -> [数据N] -> NACK -> 停止条件
    

    -> 表示时间流动,[] 表示数据字节,R 表示读操作位,ACK 表示主设备发送的确认信号,NACK 表示主设备发送的否定确认信号。

    I 2 C的功能框图

    STM32CudeMX 

    • Master  features  主模式特性

    • Slave  features  从模式特性

    1. Byte

      • 一个字节(Byte)通常包含8位(bit),这是计算机中最小的可寻址的存储单元。
      • 字节是大多数计算机体系结构中的基本数据单位,用于表示字符、数字和其他数据类型。
      • 在不同的上下文中,字节可以表示不同的含义,例如在数据通信中,它通常指的是传输的一个数据单元。
    2. Half Word

      • 半字(Half Word)通常包含16位(bit),即2个字节。
      • 在16位或更宽的处理器中,半字可能是处理器可以同时处理的数据单位之一。
      • 在一些编程语言和操作系统中,半字用于指定数据类型的大小,例如短整型(short)在某些体系结构上可能是16位的。
    3. Word

      • 一个字(Word)的大小取决于具体的处理器架构,但通常是16位、32位或64位。
      • 在32位处理器中,一个字通常是32位,即4个字节。
      • 在64位处理器中,一个字可能是64位,即8个字节。
      • 字是许多处理器的主要数据单位,用于表示整数、指针和内存地址。

    有哪些函数

    1. 初始化和去初始化

      • HAL_I2C_Init():初始化I2C外设。
      • HAL_I2C_DeInit():去初始化I2C外设。
    2. 配置

      • HAL_I2C_Config():配置I2C的一些参数,如时钟速度、地址等。
    3. 数据传输

      • HAL_I2C_Master_Transmit():作为主设备发送数据到从设备。
      • HAL_I2C_Master_Receive():作为主设备从从设备接收数据。
      • HAL_I2C_Slave_Transmit():作为从设备发送数据到主设备。
      • HAL_I2C_Slave_Receive():作为从设备从主设备接收数据。
    4. 状态和错误处理

      • HAL_I2C_GetState():获取I2C外设的当前状态。
      • HAL_I2C_GetError():获取I2C的错误代码。
    5. 中断处理

      • HAL_I2C_IRQHandler():I2C中断处理函数。
      • HAL_I2C_MasterTxCpltCallback():主设备发送完成回调函数。
      • HAL_I2C_MasterRxCpltCallback():主设备接收完成回调函数。
      • HAL_I2C_SlaveTxCpltCallback():从设备发送完成回调函数。
      • HAL_I2C_SlaveRxCpltCallback():从设备接收完成回调函数。
    6. 其他功能

      • HAL_I2C_IsDeviceReady():检查指定地址的从设备是否就绪。
      • HAL_I2C_Mem_Write():向从设备的内存写入数据。
      • HAL_I2C_Mem_Read():从从设备的内存读取数据。

    代码编写

    检查指定地址的从设备是否就绪。

    1. /* USER CODE BEGIN Header */
    2. /**
    3. ******************************************************************************
    4. * @file : main.c
    5. * @brief : Main program body
    6. ******************************************************************************
    7. * @attention
    8. *
    9. * Copyright (c) 2024 STMicroelectronics.
    10. * All rights reserved.
    11. *
    12. * This software is licensed under terms that can be found in the LICENSE file
    13. * in the root directory of this software component.
    14. * If no LICENSE file comes with this software, it is provided AS-IS.
    15. *
    16. ******************************************************************************
    17. */
    18. /* USER CODE END Header */
    19. /* Includes ------------------------------------------------------------------*/
    20. #include "main.h"
    21. #include "dma.h"
    22. #include "i2c.h"
    23. #include "usart.h"
    24. #include "gpio.h"
    25. /* Private includes ----------------------------------------------------------*/
    26. /* USER CODE BEGIN Includes */
    27. /* USER CODE END Includes */
    28. /* Private typedef -----------------------------------------------------------*/
    29. /* USER CODE BEGIN PTD */
    30. /* USER CODE END PTD */
    31. /* Private define ------------------------------------------------------------*/
    32. /* USER CODE BEGIN PD */
    33. /* USER CODE END PD */
    34. /* Private macro -------------------------------------------------------------*/
    35. /* USER CODE BEGIN PM */
    36. /* USER CODE END PM */
    37. /* Private variables ---------------------------------------------------------*/
    38. /* USER CODE BEGIN PV */
    39. /* USER CODE END PV */
    40. /* Private function prototypes -----------------------------------------------*/
    41. void SystemClock_Config(void);
    42. /* USER CODE BEGIN PFP */
    43. /* USER CODE END PFP */
    44. /* Private user code ---------------------------------------------------------*/
    45. /* USER CODE BEGIN 0 */
    46. /* USER CODE END 0 */
    47. /**
    48. * @brief The application entry point.
    49. * @retval int
    50. */
    51. int main(void)
    52. {
    53. /* USER CODE BEGIN 1 */
    54. /* USER CODE END 1 */
    55. /* MCU Configuration--------------------------------------------------------*/
    56. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    57. HAL_Init();
    58. /* USER CODE BEGIN Init */
    59. /* USER CODE END Init */
    60. /* Configure the system clock */
    61. SystemClock_Config();
    62. /* USER CODE BEGIN SysInit */
    63. /* USER CODE END SysInit */
    64. /* Initialize all configured peripherals */
    65. MX_GPIO_Init();
    66. MX_DMA_Init();
    67. MX_I2C1_Init();
    68. MX_USART1_UART_Init();
    69. /* USER CODE BEGIN 2 */
    70. char I2c_Data[9]={"AA"};
    71. /* USER CODE END 2 */
    72. /* Infinite loop */
    73. /* USER CODE BEGIN WHILE */
    74. while (1)
    75. {
    76. if(HAL_I2C_IsDeviceReady(&hi2c1,0x78,2,500)==HAL_OK){
    77. HAL_UART_Transmit(&huart1,(uint8_t*)I2c_Data,9,1000);
    78. }else{
    79. char a[]={"null"};
    80. HAL_UART_Transmit(&huart1,(uint8_t*)a,5,1000);
    81. }
    82. /* USER CODE END WHILE */
    83. /* USER CODE BEGIN 3 */
    84. }
    85. /* USER CODE END 3 */
    86. }
    87. /**
    88. * @brief System Clock Configuration
    89. * @retval None
    90. */
    91. void SystemClock_Config(void)
    92. {
    93. RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    94. RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    95. /** Initializes the RCC Oscillators according to the specified parameters
    96. * in the RCC_OscInitTypeDef structure.
    97. */
    98. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    99. RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    100. RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
    101. RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    102. RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    103. RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    104. RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
    105. if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    106. {
    107. Error_Handler();
    108. }
    109. /** Initializes the CPU, AHB and APB buses clocks
    110. */
    111. RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
    112. |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    113. RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    114. RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    115. RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
    116. RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    117. if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
    118. {
    119. Error_Handler();
    120. }
    121. }
    122. /* USER CODE BEGIN 4 */
    123. /* USER CODE END 4 */
    124. /**
    125. * @brief This function is executed in case of error occurrence.
    126. * @retval None
    127. */
    128. void Error_Handler(void)
    129. {
    130. /* USER CODE BEGIN Error_Handler_Debug */
    131. /* User can add his own implementation to report the HAL error return state */
    132. __disable_irq();
    133. while (1)
    134. {
    135. }
    136. /* USER CODE END Error_Handler_Debug */
    137. }
    138. #ifdef USE_FULL_ASSERT
    139. /**
    140. * @brief Reports the name of the source file and the source line number
    141. * where the assert_param error has occurred.
    142. * @param file: pointer to the source file name
    143. * @param line: assert_param error line source number
    144. * @retval None
    145. */
    146. void assert_failed(uint8_t *file, uint32_t line)
    147. {
    148. /* USER CODE BEGIN 6 */
    149. /* User can add his own implementation to report the file name and line number,
    150. ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    151. /* USER CODE END 6 */
    152. }
    153. #endif /* USE_FULL_ASSERT */

    注意 

    在I2C(Inter-Integrated Circuit)总线协议中,通常有一个主机(master)和多个从机(slave)。按照I2C协议的设计,所有的数据传输都是在主机控制下进行的。也就是说,在标准的I2C通信中,从机与从机之间不能直接进行通信,所有的数据传输都需要通过主机来控制。

  • 相关阅读:
    Elasticsearch安装
    高效操作Golang字符串实战教程
    Spring Cloud Alibaba微服务第9章之MyBatis-plus
    【数学建模绘图系列教程】绘图模板总结
    centos7配置
    RDS责任羽绒认证标准的作用
    如何用网页绘制一个黑莓9900的键盘效果图
    7-14 整数拆分——递归/推
    react面试题笔记整理
    HTTP/HTTPS TCP/IP
  • 原文地址:https://blog.csdn.net/qq_59527512/article/details/139425720