基本搞定了
这种"异常复位"确实会造成I2C死锁.是硬件I2C无法避免的.一旦发生,应先转到IO口方式,用IO口方式发出SCK脉冲.每发一次,检测SDA是否变高.高了就说明解锁了.退出,再转回硬件I2C方式.
简单的代码如下:
void CheckDeadLock(void)
{
DWORD tem= GPIOB->CRL;
int i =0;
I2C_Cmd(I2C1, DISABLE);
RCC->APB1ENR &= ~RCC_APB1Periph_I2C1;
tem = (tem&(~(0x0f<<24)))|(3<<24); // SCK ==> output
tem = (tem&(~(0x0f<<28)))|(4<<28); // SDA ==> input
GPIOB->CRL = tem;
while(1){
GPIOB->BSRR = (0x1UL<<(6+16));
Delay(0x2000);
GPIOB->BSRR = (0x1UL<<6);
Delay(0x2000);
i++;
if(GPIOB->IDR& (0x1UL<<7))
{
printf("释放了%d ", i);
break;
}
else if(i>=9){ // 这里或许应该是8,待研究
}
}
}
我编写的一个程序,不停地读EEPROM,之前一旦复位,基本就死了.现在多次测试,基本OK.之所以说基本,因为几十次还是有一两次,解锁后还是无法跑下去.在这里感谢香版 netjob lut1lut. 以及几位提供了自己代码的网友
如果哪位同学觉得有所帮助,请一起和我奚落一下ST公司的驱动开发能力.
初接触STM32,为它划时代的能力而震撼,深深感觉到这才是21世纪的单片机.再深入,在它提供的驱动包上开始栽跟斗.首先是不同版本的驱动包,同一个结构体,里面的成员变量居然是不同的(名字不同).再后来,发觉很多地方都充满了while(1)这种类型的死循环,一旦硬件出错,软件就死掉了.没有考虑错误的情况.退一步说,即使难以完美处理各种错误,起码也应该在旁边加相应的注释,例如来个fixme提示.让后来者少走弯路.
两个字评论: 业余 三个字:不专业 四个字:有待改进 五个字:望做得更好