BDW杜兰特 发表于 2022-5-27 17:00

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

#申请原创# #有奖活动# #技术资源# 用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脚。
其中通讯过程中有个等待函数是十分重要的
https://thumbnail1.baidupcs.com/thumbnail/5c219f578q8930b85886315af9171c77?fid=1103639223936-250528-145379792756363&time=1653638400&rt=yt&sign=FDTAER-DCb740ccc5511e5e8fedcff06b081203-4a0V4wu9cGwadBEk9ZkHFTH**c%3D&expires=24h&chkv=0&chkbd=0&chkpc=&dp-logid=3568921846&dp-callid=0&size=c1536_u864&quality=90&vuk=-&ft=video&autopolicy=1
这个函数每次写完都要进行调用用来判断数据是否写入。
#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;
u8 buf={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);
                I2C_ReadOneByte(i,dat++);
                printf("%d \r\n",sbuf);
        }

       
while(1)
{

}

}
我设置的是一个9位数组,写入一个9位数组,然后设置了一个指针利用for循坏,调用II2C写函数将数组当中的一个个变量写入,然在将SBUF的地址通过指针赋值给DAT,然后读出DAT的值,这样就可以判断II2C读写是否正常了。
https://thumbnail5.baidupcs.com/thumbnail/acf06477ftbfaa8e7f20fe5a0b843916?fid=1103639223936-250528-59331414599681&time=1653638400&rt=yt&sign=FDTAER-DCb740ccc5511e5e8fedcff06b081203-1XS96Uvmp1XsttGnxvVAU3hS9Eg%3D&expires=24h&chkv=0&chkbd=0&chkpc=&dp-logid=3565777948&dp-callid=0&size=c1536_u864&quality=90&vuk=-&ft=video&autopolicy=1
由上图可知,写入和读取都是正常的,这个程序在极海和STM上都能够正常运行。这就是极海单片机兼容软件的强大之处。小伙伴们好了本次就到这里了

鱼香Rose 发表于 2022-5-31 11:25

学习了
页: [1]
查看完整版本: STM32F103硬件II2C存储EEPROM在极海同系列板子上的实现