匿名
未登录
登录
丢石头百科
搜索
查看“STM32CubeMX系列教程9:内部集成电路(I2C)”的源代码
来自丢石头百科
名字空间
页面
讨论
更多
更多
页面选项
查看
查看源代码
历史
←
STM32CubeMX系列教程9:内部集成电路(I2C)
因为以下原因,您没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:
用户
您可以查看与复制此页面的源代码。
<b style="background-color: inherit;">1.I2C总线简介</b> I2C(Inter-Integrated Circuit ,内部集成电路)总线是一种由飞利浦Philip公司开发的串行总线。是两条串行的总线,它由一根数据线(SDA)和一根 时钟线(SDL)组成。I2C总线上可以接多个I2C设备,每个器件都有一个唯一的地址识别。同一时间只能有一个主设备,其他为从设备。通常MCU作为主设备控制,外设作为从设备。 <b style="background-color: inherit;">2.I2C硬件电路</b> <b style="background-color: inherit;"> </b> I2C总线为漏极开路结构(OD),因此它们必须接有上拉电阻,阻值常为 4k7 或 10k ;当总线空闲时,两根线均为高电平。OD门与其它任意数量的OD与OC门成"线与"关系,即当总线上的任一器件输出的低电平,都将使总线的信号变低。 [[File:145023c79id39wzwd9uj9r.png]] <b style="background-color: inherit;">3.I2C协议</b> <b style="background-color: inherit;"> </b> I2C有三种状态信号:开始信号、结束信号和应答信号 开始信号:SCL为高电平时,SDA由高电平转变为低电平跳变,表示开始通信。 结束信号:SCL为高电平时,SDA由低电平转变为高电平跳变,结束结束通信。 应答信号:接收数据的IC在接收到一个字节数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。 [[File:145024o730doq7dnn379br.png]] 在数据传输过程中,SCL时钟为主设备控制,SCL为高的时候读取数据SDA的数据,SCL为低的时候,主设备改变SDA的数据准备传输下一位。数据从高位开始传输,当传输8位后,主设备会释放SDA总线。如果从设备正确接收到数据,则从设备会拉低SDA总线,则产生一个应答信号。如果从设备出错,不拉低SDA总线,由于上拉电阻的作用,SDA的电平会变为高电平,即为非应答信号。数据传输总是以开始信号开始传输,以结束信号终止传输,中间可以传输多个字节的数据。 <b style="background-color: inherit;">4.AT24Cxx</b> <b style="background-color: inherit;"> </b> AT24C系列为美国ATMEL公司推出的串行COMS型E<sup style="background-color: inherit;">2</sup>PROM。芯片型号后两位表示芯片容量,例如ATC24C02为2K。引脚图中A0、A1、A2为器件地址引脚,GND为地,VCC为正电源,WP为写保护,SCL为串行时钟线,SDA为串行数据线。 [[File:145024s1cl6ukmvahag16m.png]] [[File:145024zx7316z77g78axnu.png]] AT24C设备地址为如下,前四位固定为1010,A2~A0为由管脚电平。AT24CXX EEPROM Board模块中默认为接地。A2~A0为000,最后一位表示读写操作。所以AT24Cxx的读地址为0xA1,写地址为0xA0。 [[File:145025w801gmhg7bpglugu.png]] 写字节操作MCU先发送一个开始信号(START),然后发送器件写操作地址(DEVICE ADDRESS),E<sup>2</sup>PROM接收到地址后,如果地址和自身的地址一样,E<sup>2</sup>PROM就会回一个应答信号(ACK)。MCU接收到应答信号后,再发送要操作的内存地址(WORD ADDRESS),得到应答后再传输写入的数据(DATA)。再次等待E<sup>2</sup>PROM应答后发送结束信号(STOP)结束传输。 [[File:145025k53tq37kmc3m113t.png]] E<sup>2</sup>PROM支持连续写操作,操作和单个字节类似,先发送设备写操作地址(DEVICE ADDRESS),然后发送内存起始地址(WORD ADDRESS),然后不断传输数据。E<sup>2</sup>PROM的地址指针会自动递增,数据会依次保存在内存中。 [[File:145025aeio40tq40n03xox.png]] E<sup>2</sup>PROM读字节操作如下,先发送设备写操作地址(DEVICE ADDRESS),然后发送要读取内存的地址(WORD ADDRESS)。然后重新发送开始信号(START),发送设备读操作地址(DEVICE ADDRESS)对E<sup>2</sup>PROM进行读操作。此时MCU释放SDA数据线,E<sup>2</sup>PROM控制SDA数据总线,将内存地址中对应的数据发送给MCU。 [[File:145025k2xg2zk6gbiglllu.png]] 同理,E<sup>2</sup>PROM可以连续读操作,在读一个字节后,MCU会回应一个应答信号(ACK)后,E<sup>2</sup>PROM会继续传输下一个地址的数据,MCU不断回应应答信号可以不断读取内存的数据,不应答发送结束信号后终止传输。 [[File:145026jrwr57z0fg3f325x.png]] 注意:每次操作都是由MCU先发送开始信号,然后发送器件地址,写操作发送写设备地址,读操作发送读设备地址,然后再传输数据。 <b style="background-color: inherit;">5.示例程序</b> <b style="background-color: inherit;"> </b> 本章程序在串口printf工程的基础上修改,复制串口printf的工程,修改文件夹名。击STM32F746I.ioc打开STM32cubeMX的工程文件重新配置。I2C1选择I2C模式,PB8,PB9管脚分别配置为I2C1_SDA,I2C2_SCL。 [[File:145026to2bp7fs7isgwgst.png]] [[File:145026wj4zdkmz4o0mutri.png]] I2C为默认设置不作修改。只需注意一下,I2C为标准模式,I2C传输速率(I2C Speed Frequency)为100KHz。 [[File:145026q92zp05b7t2hl1lj.png]] 生成报告以及代码,编译程序。在i2c.c文件中可以看到ADC初始化函数。在stm32f7xx_hal_i2c.h头文件中可以看到I2C的操作函数。分别对应轮询,中断和DMA三种控制方式。 [[File:145027bau62t4ti5ck665z.png]] 在mian.c文件前面声明两个输出存储读写数据,宏定义E<sup>2</sup>PROM读写地址以及缓存数据长度。 <syntaxhighlight lang="python"> /* USER CODE BEGIN PV */ /* Private variables ---------------------------------------------------------*/ #define ADDR_24LCxx_Write 0xA0 #define ADDR_24LCxx_Read 0xA1 #define BufferSize 0x100 uint8_t WriteBuffer[BufferSize],ReadBuffer[BufferSize]; uint16_t i; /* USER CODE END PV */</syntaxhighlight> <syntaxhighlight lang="python"> </syntaxhighlight>在mian()函数里面添加应用程序读写E<sup style="font-family: 'Times New Roman';">2</sup>PROM。 <syntaxhighlight lang="python"> /* USER CODE BEGIN 2 */ printf("\r\n***************I2C Example*******************************\r\n"); for(i=0; i<256; i++) WriteBuffer[i]=i; /* WriteBuffer init */ /* wrinte date to EEPROM */ if(HAL_I2C_Mem_Write(&hi2c1, ADDR_24LCxx_Write, 0, I2C_MEMADD_SIZE_8BIT,WriteBuffer,BufferSize, 0x10) == HAL_OK) printf("\r\n EEPROM 24C02 Write Test OK \r\n"); else printf("\r\n EEPROM 24C02 Write Test False \r\n"); /* read date from EEPROM */ HAL_I2C_Mem_Read(&hi2c1, ADDR_24LCxx_Read, 0, I2C_MEMADD_SIZE_8BIT,ReadBuffer,BufferSize, 0x10); for(i=0; i<256; i++) printf("0x%02X ",ReadBuffer[i]); if(memcmp(WriteBuffer,ReadBuffer,BufferSize) == 0 ) /* check date */ printf("\r\n EEPROM 24C02 Read Test OK\r\n"); else printf("\r\n EEPROM 24C02 Read Test False\r\n"); /* USER CODE END 2 */</syntaxhighlight> 程序中先初始化写数据缓存。然后调用HAL_I2C_Mem_Write()函数将数据写入E<sup>2</sup>PROM中。根据函数返回值判断写操作是否正确。在I2C中可以找到内存写函数说明。第一个参数为I2C操作句柄。第二个参数为E<sup>2</sup>PROM的写操作设备地址。第三个参数为内存地址,第二个参数为内存地址长度,E<sup>2</sup>PROM内存长度为8bit,第四个参数为数据缓存的起始地址,第五个参数为传输数据的大小,第六个参数为操作超时时间。 <syntaxhighlight lang="python"> /** * @brief Write an amount of data in blocking mode to a specific memory address * @param hi2c : Pointer to a I2C_HandleTypeDef structure that contains * the configuration information for the specified I2C. * @param DevAddress: Target device address * @param MemAddress: Internal memory address * @param MemAddSize: Size of internal memory address * @param pData: Pointer to data buffer * @param Size: Amount of data to be sent * @param Timeout: Timeout duration * @retval HAL status */ HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)</syntaxhighlight> <syntaxhighlight lang="python"> <code style="font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace !important; color: black !important; font-size: 1em !important; background-color: inherit;"> </syntaxhighlight>调用HAL_I2C_Mem_Read()函数读取E<sup>2</sup>PROM中刚才写入的数据。</code>HAL_I2C_Mem_Read()函数描述如下。第一个参数为I2C操作句柄。第二个参数为E<sup>2</sup>PROM的读操作设备地址。第三个参数为内存地址,第二个参数为内存地址长度,第四个参数为读取数据存储的起始地址,第五个参数为传输数据的大小,第六个参数为操作超时时间。 <syntaxhighlight lang="python"> /** * @brief Read an amount of data in blocking mode from a specific memory address * @param hi2c : Pointer to a I2C_HandleTypeDef structure that contains * the configuration information for the specified I2C. * @param DevAddress: Target device address * @param MemAddress: Internal memory address * @param MemAddSize: Size of internal memory address * @param pData: Pointer to data buffer * @param Size: Amount of data to be sent * @param Timeout: Timeout duration * @retval HAL status */ HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)</syntaxhighlight> 程序最后调用memcmp()函数判断读写的两个缓存的数据是否一致。memcmp()是比较内存区域是否相等,标准库里面的函数,在main.c前面添加string.h头文件。 <syntaxhighlight lang="python"> /* USER CODE BEGIN Includes */ #include <string.h> /* USER CODE END Includes */</string.h></syntaxhighlight> <syntaxhighlight lang="python"> </syntaxhighlight> <syntaxhighlight lang="python"> <code style="font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace !important; color: rgb(0, 130, 0) !important; font-size: 1em !important; background-color: inherit;">将</syntaxhighlight>AT24CXX EEPROM Board模块插入到Open746I开发板I2C1中,编译程序并下载到开发板。打开串口调试助手。设置波特率为115200。串口助手上会显示如下信息。 [[File:145027cyii0f0ek0kk6hfe.png]] </code>
返回至
STM32CubeMX系列教程9:内部集成电路(I2C)
。
导航
导航
首页
最近更改
随机页面
MediaWiki帮助
首页
首页
树莓派
主机
配件包
外壳
键鼠
电源
扩展板
显示屏
墨水屏
摄像模块
通信模块
继电器
电机驱动板
游戏机
产品分类
树莓派
Arduino
micro:bit
STM32
Espressif
WiFi模块
蓝牙模块
无线模块
LoRa模块
4G模块
GSM
GPRS
以太网
导航模块
北斗卫星
GPS
LCD
墨水屏
OLED
摄像头
USB模块
串口模块
RS232
RS485
CAN
传感器
温度模块
湿度模块
气压模块
继电器
电机模块
指纹模块
电平转换
音频模块
编程器
Wiki工具
Wiki工具
特殊页面
页面工具
页面工具
用户页面工具
更多
链入页面
相关更改
页面信息
页面日志