[APM32F1] STM32F103硬件II2C存储EEPROM在极海同系列板子上的实现

[复制链接]
 楼主| BDW杜兰特 发表于 2022-5-27 17:00 | 显示全部楼层 |阅读模式
#申请原创# #有奖活动# #技术资源# 用II2C通讯,我们首先要知道硬件II2C和软件II2C的区别
(1)所谓硬件I2C对应芯片上的I2C外设,有相应I2C驱动电路,其所使用的I2C管脚也是专用的;
        软件I2C一般是用GPIO管脚,用软件控制管脚状态以模拟I2C通信波形。
(2)硬件I2C的效率要远高于软件的,而软件I2C由于不受管脚限制,接口比较灵活。
(3)硬件i2c程序员只要调用i2c的控制函数即可,不用直接的去控制SCL,SDA高低电平的输出。但是有些单片机的硬件i2c不太稳定,调试问题较多。
(4) 硬件IIC速度比模拟快,并且可以用DMA。
项目中一般要用DMA的话,还是硬件II2C用的较多。本次实验是用硬件II2C实现对EEPROM进行读写操作
烧录用的是J-LINK
下面是II2C读写EEPROM部分,本次用的是PB6和PB7脚。
其中通讯过程中有个等待函数是十分重要的

这个函数每次写完都要进行调用用来判断数据是否写入。
  1. #define             EEPROM_I2Cx                       I2C1
  2. #define             EEPROM_ADDRESS                    0xA0
  3. void MYI2C_Init(void)
  4. {
  5.    GPIO_InitTypeDef GPIO_InitStructure;
  6.         I2C_InitTypeDef I2C_InitStruct;
  7.         RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOB, ENABLE );        //使能GPIOB时钟
  8.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); //使能I2C1时钟
  9.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
  10.         GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_OD;   
  11.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  12.         GPIO_Init(GPIOB, &GPIO_InitStructure);
  13.    I2C_DeInit(I2C1);
  14.    I2C_InitStruct.I2C_Ack =I2C_Ack_Enable;
  15.         I2C_InitStruct.I2C_AcknowledgedAddress =I2C_AcknowledgedAddress_7bit ;
  16.         I2C_InitStruct.I2C_ClockSpeed =400000;
  17.         I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2  ;
  18.         I2C_InitStruct.I2C_Mode =I2C_Mode_I2C;
  19.         I2C_InitStruct.I2C_OwnAddress1 =0x00;
  20.         I2C_Init(I2C1,&I2C_InitStruct);
  21.         I2C_Cmd(I2C1,ENABLE);//DISABLE ENABLE
  22.        
  23. }
  24. void I2C_WriteOneByte(u8 RegAddr,u8 date)
  25. {                                  
  26.         while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));
  27.         I2C_GenerateSTART(I2C1,ENABLE);  
  28.         while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));//EV5
  29.         I2C_Send7bitAddress(I2C1,EEPROM_ADDRESS,I2C_Direction_Transmitter);
  30.    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//EV6
  31.         I2C_SendData(I2C1,RegAddr);
  32.         while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING ));//EV8
  33.         I2C_SendData(I2C1,date);
  34.         while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED ));//EV8—2
  35.         I2C_GenerateSTOP(I2C1,ENABLE);
  36.    I2C_EE_WaitEepromStandbyState();
  37. }
  38. void I2C_WriteLenByte(u8 RegAddr,u8* sbufdate,u8 Len)
  39. {
  40.         while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));
  41.         I2C_GenerateSTART(I2C1,ENABLE);  
  42.         while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));//EV5
  43.         I2C_Send7bitAddress(I2C1,EEPROM_ADDRESS,I2C_Direction_Transmitter);
  44.    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//EV6发送
  45.         I2C_SendData(I2C1,RegAddr);
  46.         while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED ));//EV8
  47.         while(Len--)
  48.         {
  49.         I2C_SendData(I2C1,*sbufdate);
  50.         while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED ));//EV8
  51.         sbufdate++;
  52.         }
  53.         I2C_GenerateSTOP(I2C1,ENABLE);
  54.         I2C_EE_WaitEepromStandbyState();
  55. }
  56. void I2C_ReadOneByte(u8 RegAddr,u8 *da)
  57. {
  58.           
  59.            while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));
  60.        
  61.                 I2C_GenerateSTART(I2C1,ENABLE);
  62.            while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));//EV5       

  63.                 I2C_Send7bitAddress(I2C1,EEPROM_ADDRESS,I2C_Direction_Transmitter);
  64.       while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//EV6


  65.            I2C_SendData(I2C1,RegAddr);
  66.            while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED ));//EV8

  67.            I2C_GenerateSTART(I2C1,ENABLE);
  68.            while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));//EV5

  69.                 I2C_Send7bitAddress(I2C1,EEPROM_ADDRESS,I2C_Direction_Receiver );
  70.            while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//EV6 接收

  71.            I2C_AcknowledgeConfig(I2C1,DISABLE);//最后有一个数据时关闭应答位
  72.            I2C_GenerateSTOP(I2C1,ENABLE);
  73.                 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED));//
  74.            *da=I2C_ReceiveData(I2C1);
  75.                
  76. //                delay_ms(10);
  77. //                I2C_AcknowledgeConfig(I2C1,ENABLE);

  78. }
  79. void I2C_ReadLenByte(u8 RegAddr,u8* sbufdate,u8 len)
  80. {
  81.       while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));

  82.                 I2C_GenerateSTART(I2C1,ENABLE);
  83.            while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));//EV5       

  84.                 I2C_Send7bitAddress(I2C1,EEPROM_ADDRESS,I2C_Direction_Transmitter);
  85.            while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//EV6发送

  86.            I2C_SendData(I2C1,RegAddr);
  87.            while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED ));//EV8

  88.            I2C_GenerateSTART(I2C1,ENABLE);
  89.            while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));//EV5
  90.        
  91.                 I2C_Send7bitAddress(I2C1,EEPROM_ADDRESS,I2C_Direction_Receiver );
  92.            while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//EV6 接收

  93.         while(len)
  94.         {
  95.         if(len==1)
  96.          {
  97.          I2C_AcknowledgeConfig(I2C1,DISABLE);//最后有一个数据时关闭应答位
  98.           I2C_GenerateSTOP(I2C1,ENABLE);
  99.          }
  100.         *sbufdate=I2C_ReceiveData(I2C1);
  101.         while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED));
  102.         sbufdate++;         
  103.          len--;
  104.         }

  105.          I2C_AcknowledgeConfig(I2C1,ENABLE);
  106.        
  107. }

  108. void I2C_EE_WaitEepromStandbyState(void)      
  109. {
  110.   vu16 SR1_Tmp = 0;

  111.   do
  112.   {
  113.    
  114.     I2C_GenerateSTART(EEPROM_I2Cx, ENABLE);
  115.   
  116.     SR1_Tmp = I2C_ReadRegister(EEPROM_I2Cx, I2C_Register_SR1);
  117.   
  118.     I2C_Send7bitAddress(EEPROM_I2Cx, EEPROM_ADDRESS, I2C_Direction_Transmitter);
  119.   }while(!(I2C_ReadRegister(EEPROM_I2Cx, I2C_Register_SR1) & 0x0002));
  120.   

  121.   I2C_ClearFlag(EEPROM_I2Cx, I2C_FLAG_AF);


  122.     I2C_GenerateSTOP(EEPROM_I2Cx, ENABLE);
  123. }

下面是主函数中代码
  1. u8 sbuf[9];
  2. u8 buf[9]={3,1,2,8,4,4,5,6,6};       
  3. int main (void)
  4. {
  5. u8 i;
  6. u8 *dat;
  7. MYI2C_Init();
  8. Usart_Init();
  9.         dat=sbuf;
  10.         for(i=0;i<9;i++)
  11.         {
  12.                 I2C_WriteOneByte(i,buf[i]);
  13.                 I2C_ReadOneByte(i,dat++);
  14.                 printf("%d \r\n",sbuf[i]);
  15.         }

  16.        
  17. while(1)
  18. {

  19. }

  20. }

我设置的是一个9位数组,写入一个9位数组,然后设置了一个指针利用for循坏,调用II2C写函数将数组当中的一个个变量写入,然在将SBUF的地址通过指针赋值给DAT,然后读出DAT的值,这样就可以判断II2C读写是否正常了。

由上图可知,写入和读取都是正常的,这个程序在极海和STM上都能够正常运行。这就是极海单片机兼容软件的强大之处。小伙伴们好了本次就到这里了
鱼香Rose 发表于 2022-5-31 11:25 | 显示全部楼层
学习了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

22

帖子

0

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