打印
[APM32F1]

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

[复制链接]
829|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
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脚。
其中通讯过程中有个等待函数是十分重要的

这个函数每次写完都要进行调用用来判断数据是否写入。
#define             EEPROM_I2Cx                       I2C1
#define             EEPROM_ADDRESS                    0xA0
void MYI2C_Init(void)
{
   GPIO_InitTypeDef GPIO_InitStructure;
        I2C_InitTypeDef I2C_InitStruct;
        RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOB, ENABLE );        //使能GPIOB时钟
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); //使能I2C1时钟
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_OD;   
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
   I2C_DeInit(I2C1);
   I2C_InitStruct.I2C_Ack =I2C_Ack_Enable;
        I2C_InitStruct.I2C_AcknowledgedAddress =I2C_AcknowledgedAddress_7bit ;
        I2C_InitStruct.I2C_ClockSpeed =400000;
        I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2  ;
        I2C_InitStruct.I2C_Mode =I2C_Mode_I2C;
        I2C_InitStruct.I2C_OwnAddress1 =0x00;
        I2C_Init(I2C1,&I2C_InitStruct);
        I2C_Cmd(I2C1,ENABLE);//DISABLE ENABLE
       
}
void I2C_WriteOneByte(u8 RegAddr,u8 date)
{                                  
        while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));
        I2C_GenerateSTART(I2C1,ENABLE);  
        while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));//EV5
        I2C_Send7bitAddress(I2C1,EEPROM_ADDRESS,I2C_Direction_Transmitter);
   while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//EV6
        I2C_SendData(I2C1,RegAddr);
        while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING ));//EV8
        I2C_SendData(I2C1,date);
        while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED ));//EV8—2
        I2C_GenerateSTOP(I2C1,ENABLE);
   I2C_EE_WaitEepromStandbyState();
}
void I2C_WriteLenByte(u8 RegAddr,u8* sbufdate,u8 Len)
{
        while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));
        I2C_GenerateSTART(I2C1,ENABLE);  
        while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));//EV5
        I2C_Send7bitAddress(I2C1,EEPROM_ADDRESS,I2C_Direction_Transmitter);
   while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//EV6发送
        I2C_SendData(I2C1,RegAddr);
        while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED ));//EV8
        while(Len--)
        {
        I2C_SendData(I2C1,*sbufdate);
        while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED ));//EV8
        sbufdate++;
        }
        I2C_GenerateSTOP(I2C1,ENABLE);
        I2C_EE_WaitEepromStandbyState();
}
void I2C_ReadOneByte(u8 RegAddr,u8 *da)
{
          
           while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));
       
                I2C_GenerateSTART(I2C1,ENABLE);
           while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));//EV5       

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


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

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

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

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

}
void I2C_ReadLenByte(u8 RegAddr,u8* sbufdate,u8 len)
{
      while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));

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

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

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

           I2C_GenerateSTART(I2C1,ENABLE);
           while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));//EV5
       
                I2C_Send7bitAddress(I2C1,EEPROM_ADDRESS,I2C_Direction_Receiver );
           while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//EV6 接收

        while(len)
        {
        if(len==1)
         {
         I2C_AcknowledgeConfig(I2C1,DISABLE);//最后有一个数据时关闭应答位
          I2C_GenerateSTOP(I2C1,ENABLE);
         }
        *sbufdate=I2C_ReceiveData(I2C1);
        while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED));
        sbufdate++;         
         len--;
        }

         I2C_AcknowledgeConfig(I2C1,ENABLE);
       
}

void I2C_EE_WaitEepromStandbyState(void)      
{
  vu16 SR1_Tmp = 0;

  do
  {
   
    I2C_GenerateSTART(EEPROM_I2Cx, ENABLE);
  
    SR1_Tmp = I2C_ReadRegister(EEPROM_I2Cx, I2C_Register_SR1);
  
    I2C_Send7bitAddress(EEPROM_I2Cx, EEPROM_ADDRESS, I2C_Direction_Transmitter);
  }while(!(I2C_ReadRegister(EEPROM_I2Cx, I2C_Register_SR1) & 0x0002));
  

  I2C_ClearFlag(EEPROM_I2Cx, I2C_FLAG_AF);


    I2C_GenerateSTOP(EEPROM_I2Cx, ENABLE);
}

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

       
while(1)
{

}

}

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

由上图可知,写入和读取都是正常的,这个程序在极海和STM上都能够正常运行。这就是极海单片机兼容软件的强大之处。小伙伴们好了本次就到这里了

使用特权

评论回复
沙发
鱼香Rose| | 2022-5-31 11:25 | 只看该作者
学习了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

22

帖子

0

粉丝