STM32 硬件I2C的使用:中断方式 无DMA 无最高优先级

2019-07-21 08:56发布

STM32的硬件I2C和RTC一样,一直以来都是STM32的一大败笔,我也曾经在想,这么好的片子I2C是这个样子。。。真想骂两句。。。呵呵! 不过对其有了深入了解之后,哪怕不用勘误手册上的办法(DMA或优先级最高)也是可以的。估计有很多人是知道办法的,我在这里就当是把问题重新提一下,大家讨论一下,共同学习了!
关于STM32乃至STM8的I2C,估计应该是专利的问题,所以故意做的不同,其不同点就在于无论是发送还是接收,都多了一个缓存寄存器,发送时先写缓存,缓存复制到移位寄存器,缓冲空了,可以再写一个字节,也就是当第一个字节还没发完的时候就可以再写一个字节,可以视作一次性写了2个字节;接收的时候移位寄存器先收到一个字节,复制到缓冲,移位寄存器空,然后可以接收下一个字节,可以视作一次性可接2个字节。这样的结构看似美好,其实问题就出在这里,具体的错误过程我就不在这里分析了(其实我也搞得不是很清楚,希望清楚的同志赐教),如何克服这一缺点呢。
具体做法:只使能事件中断 而不使能缓冲区中断,这样做的目的是把发送或接收的2个寄存器当成一个来用,一次只发或接一个字节,当BTF中断来临时去判断是RXE还是TXE,这样一来STM32的I2C结构就和其他单片机一样了。
这样就能做到硬件I2C中断方式 无DMA 无最高优先级了!
呵呵!分享,快乐!

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
20条回答
zhengbingyan
1楼-- · 2019-07-22 21:05
中断的处理可以更优
youngme
2楼-- · 2019-07-23 02:06
回复【9楼】whjambo:
---------------------------------
只使能事件中断 而不使能缓冲区中断,是什么意思啊?IIC只有事件中断和错误中断,我不知道缓存的中断标志有什么用。求解
peteropendev
3楼-- · 2019-07-23 02:24
回复【16楼】peteropendev:
---------------------------------
void c02_write_data(void)
{
 while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
 
WRITE_FLAG=1;
 I2C_GenerateSTART(I2C1, ENABLE);
 
// while(i2c_plan!=20);
 //while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY));
 //delay_ms(5);

}

void c02_read_data()
{
 while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
WRITE_FLAG=0;
STEP1=1;
STEP2=1;
 I2C_GenerateSTART(I2C1, ENABLE);

 
}





/*********************************************zhongduan**********************/
void DebugMon_Handler(void)
{
}
/**
  * @brief  This function handles Debug Monitor exception.
  * @param  None
  * @retval None
  */
void I2C1_EV_IRQHandler(void)
{
uint32_t lastevent=  I2C_GetLastEvent(I2C1);
switch (lastevent)
{
case I2C_EVENT_MASTER_MODE_SELECT://EV5
if(WRITE_FLAG==1)
{
I2C_Send7bitAddress(I2C1, 0X50, I2C_Direction_Transmitter);
if((STEP1==1)&&(STEP2==1))
{
STEP1=0;
}
}
else
{
 I2C_Send7bitAddress(I2C1, 0X50, I2C_Direction_Receiver);
 STEP2=0;
}
 break;
 case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED://EV6fa
if(WRITE_FLAG==1)
 I2C_SendData(I2C1, WRITE_OFFSET);
else
 I2C_SendData(I2C1, READ_OFFSET);
 break;
 case I2C_EVENT_MASTER_BYTE_TRANSMITTED://EV8
 if(WRITE_FLAG==1)
 {
I2C_SendData(I2C1, I2c_Buf_Write[WRITE_OFFSET]);
  WRITE_OFFSET++;
  if(WRITE_OFFSET!=0xff)
I2C_GenerateSTART(I2C1, ENABLE);
else
I2C_GenerateSTOP(I2C1, ENABLE);
 }
 else
 {
  I2C_GenerateSTOP(I2C1, ENABLE);
  I2C_GenerateSTART(I2C1, ENABLE);
 }
 break;
 case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED://EV6SHOU
 break;
 case I2C_EVENT_MASTER_BYTE_RECEIVED://ev7
 I2c_Buf_Read[READ_OFFSET] = I2C_ReceiveData(I2C1);
 if(READ_OFFSET!=0xff)
  I2C_GenerateSTART(I2C1, ENABLE);
 else
  I2C_GenerateSTOP(I2C1, ENABLE);
 break;
}
}
我根据楼主写的改编的,可用
墨染卿卿
4楼-- · 2019-07-23 08:06
回复【18楼】墨染卿卿:
---------------------------------
你好,我遇到了这个问题,参照你的代码进行了改进,发现还是不行,可否参照一下你的完整源代码?谢谢
墨染卿卿
5楼-- · 2019-07-23 08:59
 精彩回答 2  元偷偷看……
caoting1104@gma
6楼-- · 2019-07-23 12:33
其实这个飞利浦IIC专利过期了,现在不存在专利问题了,所以兆易创新国产GD32修改了STM32这个BUG

一周热门 更多>