2.硬件设计 D1指示灯用来提示系统运行状态,K_UP按键用来控制24C02的数据写入,K_DOWN按键用来控制24C02的数据读取,数据的写入与读取信息通过串口1打印出来
指示灯D1 USART1串口
AT24C02
K_UP和K_DOWN按键
3.软件设计 3.1 STM32CubeMX设置 ➡️ RCC设置外接HSE,时钟设置为72M ➡️ PC0设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平 ➡️ USART1选择为异步通讯方式,波特率设置为115200Bits/s,传输数据长度为8Bit,无奇偶校验,1位停止位 ➡️ PA0设置为GPIO输入模式、下拉模式;PE3设置为GPIO输入模式、上拉模式 ➡️ 激活I2C2,选择标准传输模式,选择7位寻址地址,其余默认设置 ➡️输入工程名,选择路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码
3.2 MDK-ARM软件编程 ➡️ 在i2c.c文件下可以看到I2C初始化函数 - void MX_I2C2_Init(void){
- hi2c2.Instance = I2C2;
- hi2c2.Init.ClockSpeed = 100000;
- hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
- hi2c2.Init.OwnAddress1 = 0;
- hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
- hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
- hi2c2.Init.OwnAddress2 = 0;
- hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
- hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
- if (HAL_I2C_Init(&hi2c2) != HAL_OK){
- Error_Handler();
- }
- }
- void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle){
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- if(i2cHandle->Instance==I2C2){
- __HAL_RCC_GPIOB_CLK_ENABLE();
- /**I2C2 GPIO Configuration
- PB10 ------> I2C2_SCL
- PB11 ------> I2C2_SDA*/
- GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
- HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
- /* I2C2 clock enable */
- /*网上看到很多资料说此处的I2C时钟初始化函数应该放在GPIO
- 初始化之前,但是这里没有调整也能够正常读写EEPROM*/
- __HAL_RCC_I2C2_CLK_ENABLE();
- }
复制代码
[color=rgba(0, 0, 0, 0.9)]➡️ 创建按键驱动文件key.c 和相关头文件key.h,参考[color=var(--weui-LINK)]按键输入例程 [color=rgba(0, 0, 0, 0.9)]➡️ 创建AT24C02驱动文件24cxx.c和24cxx.h - #define ADDR_24CXX_WRITE 0XA0
- #define ADDR_24CXX_READ 0XA1
- void AT24CXX_Init(void){
- MX_I2C2_Init();
- while(AT24CXX_Check()){
- printf("AT24C02 Checked Failed!\r\n");
- HAL_Delay(500);
- }
- printf("AT24C02 Checked Sucessed!\r\n");
- }
- uint8_t AT24CXX_Check(void){
- uint8_t temp;
- HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,255,I2C_MEMADD_SIZE_8BIT,&temp,1,0xff);
- if(temp==0x36)
- return 0;
- else{
- uint8_t data = 0x36;
- HAL_I2C_Mem_Write(&hi2c2,ADDR_24CXX_WRITE,255,I2C_MEMADD_SIZE_8BIT,&data,1,0xff);
- HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,255,I2C_MEMADD_SIZE_8BIT,&temp,1,0xff);
- if(temp==0x36)
- return 0;
- }
- return 1;
- }
复制代码
➡️ 在main.c文件下编写I2C测试代码 AT24C02的2Kbit分为32页,每页8个字节。而EEPROM也可以按页写入,本例使用了按页写入的方式,分32次写入。注意每次写入完毕需要延时5ms,是AT24C02芯片的要求;读取数据没有页的限制,可以一次全部读取256个字节 - /* USER CODE BEGIN PV */
- #define ADDR_24CXX_WRITE 0XA0
- #define ADDR_24CXX_READ 0XA1
- uint8_t WriteBuf[256];
- uint8_t ReadBuf[256];
- uint16_t i,j;
- /* USER CODE END PV */
- int main(void){
- uint8_t key;
- HAL_Init();
- SystemClock_Config();
- MX_GPIO_Init();
- MX_I2C2_Init();
- MX_USART1_UART_Init();
- /* USER CODE BEGIN 2 */
- AT24CXX_Init(void);
- printf("\r\n*********STM32CubeMX I2C AT24C02 Example*********\r\n");
- for(i = 0;i < 256; i++){ //初始化写数据缓冲区
- WriteBuf = i;
- }
- /* USER CODE END 2 */
- while (1){
- key = KEY_Scan(0);
- if(key == KEY_UP_PRES){
- for(j = 0;j < 32;j++){ //按页写入EEPROM,分32次写入
- if(HAL_I2C_Mem_Write(&hi2c2,ADDR_24CXX_WRITE,8*j,I2C_MEMADD_SIZE_8BIT,WriteBuf+8*j,8,0xFF) == HAL_OK){
- printf("\r\nEEPROM 24C02 Write Test OK!\r\n");
- HAL_Delay(5);
- }
- else{
- printf("\r\nEEPROM 24C02 Write Test False!\r\n");
- HAL_Delay(5);
- }
- }
- }
- //EEPROM读取没有页限制,可以一次读取256个字节
- if(key == KEY_DOWN_PRES){
- HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,0,I2C_MEMADD_SIZE_8BIT,ReadBuf,256,0xFF);
- for(i=0;i<256;i++){
- printf("0x%02X ",ReadBuf);
- }
- //通过内存比较,判断读取和写入的数据是否相同
- if(memcmp(WriteBuf,ReadBuf,256) == 0){
- printf("\r\nEEPROM 24C02 Read Test OK!\r\n");
- }
- else{
- printf("\r\nEEPROM 24C02 Read Test False!\r\n");
- }
- }
- HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);
- HAL_Delay(500);
- }
- }
复制代码
4.下载验证 编译无误下载到开发板后,可以看到D1指示灯不断闪烁,当按下K_UP按键后数据写入到24C02芯片内,当按下K_DOWN按键后读取24C02芯片的值,同时串口打印出相应信息
|