• STM32 硬件IIC接口总线


    在网上总看到有人说STM32的硬件IIC不好用,可到底哪不好用,也一直没找到问题点。

    最近有空看了一下STM32的硬件IIC,里面很多EV5/EV6等事件的概念是有些别扭,不过不影响使用。

    写了一个简单的polling模式下的数据读写,也能正常实现功能。但是在单步调试时发现了一些问题,先上代码:

     1 void     STM32F407_IIC_readNByte(u8 addr, u8 * pdata, u8 length)
     2 {
     3     u8 i = 0;
     4     I2C_GenerateSTART(I2C1, ENABLE);
     5     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //EV5
     6 
     7     I2C_Send7bitAddress(I2C1, 0xA0, I2C_Direction_Transmitter);
     8 //    I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);
     9     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));  //EV6
    10     I2C_SendData(I2C1, addr);
    11     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING));        //EV8
    12     I2C_GenerateSTART(I2C1, ENABLE);
    13     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));                //EV5
    14     I2C_Send7bitAddress(I2C1, 0xA0, I2C_Direction_Receiver);
    15     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));    //EV6
    16 
    17     for(i = 0; i < length; i++)
    18     {
    19         if(i == 6)
    20         {
    21             while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));        //EV7_1
    22             *pdata = I2C_ReceiveData(I2C1);
    23             I2C_AcknowledgeConfig(I2C1, DISABLE);
    24             I2C_GenerateSTOP(I2C1, ENABLE);
    25             pdata++;
    26         }
    27         else
    28         {
    29             while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));        //EV7
    30             *pdata = I2C_ReceiveData(I2C1);
    31             pdata++;
    32         }
    33     }
    34     
    35 }

    上述代码第5行是在循环查询EV5事件是否发生,EV5事件是SB==1,可通过先读取SR1,在写DR寄存器来清除SB的状态,单步调试也是如此。
    第9行是在循环查询EV6事件是否发生,EV6事件是ADDR==1,可通过先读取SR1,再读取SR2清除ADDR的状态。但是代码在全速运行时可正常执行,在单步调试时,发现还未读取SR1/SR2,ADDR的状态就已清0,导致第九行的while循环检测不到EV6事件,不知此问题是否是STM32硬件IIC的一个bug,但此问题不影响正常使用

    一般IIC器件的读是可以连续读的,但写时一次最多只能写一个page,写下一个page,需要重新发送起始位,要写入的地址等,经测试,如下代码可实现正常读写(polling模式下):

      1 #include <sys.h>
      2 #include "delay.h"
      3 #include "STM32_IIC.h"
      4 
      5 #define AT24C02_PAGE_SIZE     8
      6 
      7 void STM32F407_IIC_Init()
      8 {
      9     GPIO_InitTypeDef GPIO_InitStructure;
     10     I2C_InitTypeDef I2C_InitStructure;
     11     
     12     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
     13     RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
     14     
     15     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
     16     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
     17     GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
     18     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
     19     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     20     GPIO_Init(GPIOB, &GPIO_InitStructure);
     21 
     22     GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_I2C1);
     23     GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1);
     24 
     25     I2C_InitStructure.I2C_ClockSpeed = 100000;
     26     I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
     27     I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
     28     I2C_InitStructure.I2C_OwnAddress1 = 0x44;
     29     I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
     30     I2C_InitStructure.I2C_DutyCycle = 0;
     31     I2C_Init(I2C1, &I2C_InitStructure);
     32     I2C_AcknowledgeConfig(I2C1, ENABLE);
     33     I2C_StretchClockCmd(I2C1, DISABLE);
     34 }
     35 
     36 u8 STM32F407_IIC_randomReadByte(u8 addr)
     37 {
     38     u8 retvalue = 0;
     39     I2C_GenerateSTART(I2C1, ENABLE);
     40     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
     41     I2C_Send7bitAddress(I2C1, 0xA0, I2C_Direction_Transmitter);
     42     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
     43     I2C_SendData(I2C1, addr);
     44     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING));
     45     I2C_GenerateSTART(I2C1, ENABLE);
     46     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
     47     I2C_Send7bitAddress(I2C1, 0xA0, I2C_Direction_Receiver);
     48     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
     49     I2C_AcknowledgeConfig(I2C1, DISABLE);
     50     while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE));
     51     retvalue = I2C_ReceiveData(I2C1);
     52     I2C_GenerateSTOP(I2C1, DISABLE);
     53     return retvalue;
     54 }
     55 
     56 u8 STM32F407_IIC_readCurrentByte()
     57 {
     58     u8 retvalue = 0;
     59     while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
     60     I2C_GenerateSTART(I2C1, ENABLE);
     61     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
     62     I2C_Send7bitAddress(I2C1, 0xA0, I2C_Direction_Receiver);
     63     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); //EV6
     64     retvalue = I2C_ReceiveData(I2C1);
     65     I2C_AcknowledgeConfig(I2C1, DISABLE);
     66     while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE));
     67     retvalue = I2C_ReceiveData(I2C1);
     68     I2C_GenerateSTOP(I2C1, DISABLE);
     69     return retvalue;
     70 }
     71 
     72 void STM32F407_IIC_randomWriteByte(u8 addr, u8 value)
     73 {
     74     I2C_GenerateSTART(I2C1, ENABLE);
     75     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
     76     I2C_Send7bitAddress(I2C1, 0xA0, I2C_Direction_Transmitter);
     77     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //EV6
     78     I2C_SendData(I2C1, addr);
     79     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));    
     80     I2C_SendData(I2C1, value);
     81     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));    
     82     I2C_GenerateSTOP(I2C1, ENABLE);
     83 }
     84 
     85 void     STM32F407_IIC_readNByte(u8 addr, u8 * pdata, u8 length)
     86 {
     87     u8 i = 0;
     88     I2C_GenerateSTART(I2C1, ENABLE);
     89     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //EV5
     90 
     91     I2C_Send7bitAddress(I2C1, 0xA0, I2C_Direction_Transmitter);
     92     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));  //EV6
     93     I2C_SendData(I2C1, addr);
     94     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING));        //EV8
     95     I2C_GenerateSTART(I2C1, ENABLE);
     96     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));                //EV5
     97     I2C_Send7bitAddress(I2C1, 0xA0, I2C_Direction_Receiver);
     98     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));    //EV6
     99 
    100     for(i = 0; i < length; i++)
    101     {
    102         if(i == length - 2)
    103         {
    104             while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));        //EV7_1
    105             *pdata = I2C_ReceiveData(I2C1);
    106             I2C_AcknowledgeConfig(I2C1, DISABLE);
    107             I2C_GenerateSTOP(I2C1, ENABLE);
    108             pdata++;
    109         }
    110         else
    111         {
    112             while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));        //EV7
    113             *pdata = I2C_ReceiveData(I2C1);
    114             pdata++;
    115         }
    116     }
    117 }
    118 
    119 
    120 /* This function will not roll over if the program address is out of current page boundary */
    121 void     STM32F407_IIC_writePage(u8 addr, u8 *pdata, u8 length)
    122 {
    123     u8 i = 0;
    124     u8 remainToWrite = ((AT24C02_PAGE_SIZE - (addr % 8)) > length) ? length : (AT24C02_PAGE_SIZE - (addr % 8));
    125     
    126     I2C_GenerateSTART(I2C1, ENABLE);
    127     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //EV5
    128     
    129     I2C_Send7bitAddress(I2C1, 0xA0, I2C_Direction_Transmitter);
    130     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));  //EV6
    131     I2C_SendData(I2C1, addr);
    132     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING));        //EV8
    133     for(i = 0; i < remainToWrite; i++)
    134     {
    135         I2C_SendData(I2C1, *pdata);
    136         while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING));        //EV8
    137         pdata++;
    138     }
    139     I2C_GenerateSTOP(I2C1, ENABLE);
    140 }
    141 
    142 
    143 /* This function will roll over if the program address is out of current page boundary */
    144 //void     STM32F407_IIC_writePage(u8 addr, u8 *pdata, u8 length)
    145 //{
    146 //    u8 i = 0;
    147 //    I2C_GenerateSTART(I2C1, ENABLE);
    148 //    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //EV5
    149 //    
    150 //    I2C_Send7bitAddress(I2C1, 0xA0, I2C_Direction_Transmitter);
    151 //    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));  //EV6
    152 //    I2C_SendData(I2C1, addr);
    153 //    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING));        //EV8
    154 //    for(i = 0; i < length; i++)
    155 //    {
    156 //        I2C_SendData(I2C1, *pdata);
    157 //        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING));        //EV8
    158 //        pdata++;
    159 //    }
    160 //    I2C_GenerateSTOP(I2C1, ENABLE);
    161 //}
    162 
    163 void     STM32F407_IIC_writeNByte(u8 addr, u8 *pdata, u8 length)
    164 {
    165     u8 actualWriteByte = 0;
    166     while(length > 0)
    167     {
    168         actualWriteByte = ((AT24C02_PAGE_SIZE - (addr % 8)) > length) ? length : (AT24C02_PAGE_SIZE - (addr % 8));
    169         STM32F407_IIC_writePage(addr, pdata, length);
    170         addr += actualWriteByte;
    171         pdata += actualWriteByte;
    172         length -= actualWriteByte;
    173         delay_ms(5);
    174     }
    175 }
    View Code
  • 相关阅读:
    正则表达式
    python 模块和包
    python面向对象 : 反射和内置方法
    python面向对象 : 属性, 类方法, 静态方法
    python面向对象 : 抽象类(接口类),多态,封装(私有制封装)
    python面向对象 : 继承
    python面向对象:类空间,对象空间, 组合
    python: 面向对象:类和对象调用类中的变量和方法
    lamda匿名函数(与sorted(),filter(),map() 一起用), 递归函数, 二分查找
    python的各种库的用法
  • 原文地址:https://www.cnblogs.com/dwj411024/p/8279933.html
Copyright © 2020-2023  润新知