[应用相关] STM32外设驱动篇——AT24C02(I2C接口)

[复制链接]
2467|3
 楼主| 玛尼玛尼哄 发表于 2016-8-8 17:54 | 显示全部楼层 |阅读模式

SOC:STM32F103RCT6

软件平台:STM官方库V3.5.0

开发工具:Keil


1. 摘要

  本**将给出STM32F103RCT6控制AT24C02的代码。如有疑问和错误,欢迎留言告之。


2.硬件连接

AT24C02使用I2C进行数据访问,板子上使用STM32的I2C控制器2和AT24C02进行连接。

具体来说,PB10作为SCL和AT24C02相连,PB11作为SDL和AT24C02相连。

这里就不给出硬件连接图了,比较简单。


3. AT24C022C访问代码(轮询)

I2C这里使用轮询方法,不是中断,请留意。

首先,给出I2C控制器的初始化代码,和读写代码,一共三个函数,对应三个功能。

注意:这里是使用I2C控制器2。



 楼主| 玛尼玛尼哄 发表于 2016-8-8 17:55 | 显示全部楼层
  1. #include "stm32f10x.h"
  2. #include "stm32f10x_i2c.h"
  3. #include <stdio.h>

  4. void I2C2_Init(I2C_InitTypeDef* I2C_InitStruct)
  5. {
  6.         GPIO_InitTypeDef GPIO_InitStruct;

  7.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);       
  8.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);        
  9.        
  10.         /* 配置IO管脚 */
  11.         GPIO_InitStruct.GPIO_Pin =  GPIO_Pin_10 | GPIO_Pin_11;            
  12.         GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;            
  13.         GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
  14.         GPIO_Init(GPIOB, &GPIO_InitStruct);
  15.    
  16.            I2C_Init(I2C2, I2C_InitStruct);
  17.         I2C_Cmd(I2C2, ENABLE);
  18.        
  19.         // 配置NVIC
  20. /*        NVIC_InitStructure.NVIC_IRQChannel = I2C2_EV_IRQn   ;                                //I2C事件中断
  21.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;        //抢占优先级1
  22.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;                        //子优先级2
  23.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                        //使能中断通道
  24.         NVIC_Init(&NVIC_InitStructure);                                                            //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 */

  25.         //I2C_ITConfig(I2C2, I2C_IT_EVT, ENABLE); //打开事件中断
  26. }

  27. /* i2c 写一个字节*/
  28. /* Byte Write */
  29. void I2C2_WriteByte(uint8_t DeviceAddress, uint8_t MemoryAddress, uint8_t Data)
  30. {
  31.         while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY));           //等待I2C空闲

  32.         //start
  33.         I2C_GenerateSTART(I2C2, ENABLE);
  34.         while( I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS );
  35.        
  36.         //device address
  37.         I2C_Send7bitAddress(I2C2, DeviceAddress, I2C_Direction_Transmitter); //写模式
  38.         while( I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS );        
  39.         //printf("address over\r\n") ;

  40.         //memory address
  41.         I2C_SendData(I2C2, MemoryAddress);
  42.         while( I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS );
  43.                        
  44.         //data
  45.            I2C_SendData(I2C2, Data);
  46.         while( I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS );        

  47.         //stop
  48.         I2C_GenerateSTOP(I2C2, ENABLE);
  49. }

  50. /* i2c 读一个字节*/
  51. /* Random Read */
  52. uint8_t I2C2_ReadByte(uint8_t DeviceAddress, uint8_t MemoryAddress)
  53. {
  54.         uint8_t        Data;
  55.        
  56.         while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY));           //等待I2C空闲  
  57.         //start
  58.         I2C_GenerateSTART(I2C2, ENABLE);
  59.         while( I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS ); //ev5

  60.         //device address
  61.         I2C_Send7bitAddress(I2C2, DeviceAddress, I2C_Direction_Transmitter);  //写模式
  62.         while( I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS );         //ev6
  63.          
  64.         //memory address
  65.         I2C_SendData(I2C2,  MemoryAddress);
  66.         while( I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS ) ;
  67.                                                                                                                                                   
  68.         //start
  69.         I2C_GenerateSTART(I2C2, ENABLE);
  70.         while( I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS ) ;        

  71.         //device address
  72.         I2C_Send7bitAddress(I2C2, DeviceAddress, I2C_Direction_Receiver); //读模式
  73.         while( I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) != SUCCESS ) ;
  74.        
  75.         /* 按照manual的图273,先读取数据,关闭ACK应答,最后发出STOP*/          
  76.         while( I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS );         /* 等待读取事件,再读取数据 */
  77.            Data = I2C_ReceiveData(I2C2);
  78.         I2C_AcknowledgeConfig(I2C2, DISABLE); //关闭应答和停止条件产生  
  79.         printf("received\r\n");
  80.         I2C_GenerateSTOP(I2C2, ENABLE);
  81.        
  82.         I2C_AcknowledgeConfig(I2C2, ENABLE);

  83.         return Data;
  84. }
接着给出相应的AT24C02访问代码
  1. #include "stm32f10x.h"
  2. #include "stm32f10x_i2c.h"
  3. #include "i2c.h"
  4. #include "delay.h"
  5. #include <stdio.h>

  6. /* 从AT24CXX的指定地址开始读出一个字节 */
  7. uint8_t AT24CXX_ReadByte(uint8_t ReadAddr)
  8. {
  9.         return I2C2_ReadByte(0xA0, ReadAddr);
  10. }  

  11. /* 向AT24CXX的指定地址开始写入一个字节 */
  12. void AT24CXX_WriteByte(uint8_t WriteAddr, uint8_t Data)
  13. {
  14.         I2C2_WriteByte(0xA0, WriteAddr, Data);
  15. }

  16. void AT24CXX_test(void)
  17. {
  18.         uint8_t i;
  19.            I2C_InitTypeDef I2C_InitStructure;

  20.         I2C_InitStructure.I2C_ClockSpeed         =  200000;           //200kHZ
  21.            I2C_InitStructure.I2C_Mode                         =  I2C_Mode_I2C;
  22.            I2C_InitStructure.I2C_DutyCycle         =  I2C_DutyCycle_2;        //根据datasheet,Tlow/Thigh = 2
  23.            I2C_InitStructure.I2C_OwnAddress1         =  0xA0;                
  24.            I2C_InitStructure.I2C_Ack                          =  I2C_Ack_Enable;
  25.            I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  26.        
  27.         I2C2_Init(&I2C_InitStructure);

  28.         for(i = 0; i < 10; i++){       
  29.                 AT24CXX_WriteByte(i, 100 + i);
  30.                 /* NOTE: 根据datasheet,两次字节写之间必须延迟5ms,也就是stop和start之间的间隔时间*/
  31.                 delay_ms(6);  
  32.         }
  33.         printf("Write completed \r\n");

  34.         for(i = 0; i < 10; i++){       
  35.                 printf("%d ", AT24CXX_ReadByte(i));
  36.             delay_ms(6);
  37.         }
  38.         printf("\r\n");
  39. }


 楼主| 玛尼玛尼哄 发表于 2016-8-8 17:56 | 显示全部楼层
注意:两次访问间隔必须大于5ms,这是datasheet规定的。
如果不加延时,第二次写入时候,写入设备地址后,无法接受到ACK,程序陷入死循环。
 楼主| 玛尼玛尼哄 发表于 2016-8-8 18:45 | 显示全部楼层
以上内容是我从网上找来的,应该是没问题的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

196

主题

3261

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部