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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM