由于需要调试一个IIC从器件,期间插拔线或者接触不好经常出现死机,后来发现是卡在IIC通讯上面。
硬件IIC的库函数很多地方是while(。。。),没有长时间无返回就退出机制,因此很容易挂掉。
新思路是:在IIC while(。。。)等待里面再加一个变量iic_time,使用定时器去改变此变量值
在while(。。。)里面除了判断状态参数外还要判断时间,这里设了5ms,只要到了5ms,不管接没接收到状态数据都退出while。
这样可以保证不会死机。
程序可参考如下:
void TIM3_start(void)
{
iic_time=1;
TIM_DeInit(TIM3);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_Period=5000;//定时5ms
TIM_TimeBaseInitStructure.TIM_Prescaler=71;//1M时钟
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3,& TIM_TimeBaseInitStructure);
TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标示位
TIM_ITConfig(TIM3,TIM_IT_Update, ENABLE );//使能中断
TIM_Cmd(TIM3, ENABLE);//开始计数
}
void TIM3_stop(void)
{
iic_time=1;
TIM_Cmd(TIM3, DISABLE);//停止计数
TIM_ITConfig(TIM3,TIM_IT_Update, DISABLE );//停止转换
TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标示位
}
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
iic_time=0;
}
}
void I2C2_WriteByte(u8 id,u8 write_address, u8 datal)//写一个字节
{
TIM3_start();
while((I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY))&(iic_time==1));
TIM3_stop();
I2C_AcknowledgeConfig(I2C1, ENABLE);
I2C_GenerateSTART(I2C2,ENABLE);
TIM3_start();
while((!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))&(iic_time==1)); //等待ACK
TIM3_stop();
I2C_Send7bitAddress(I2C2,id,I2C_Direction_Transmitter);//发送设备地址
TIM3_start();
while((!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))&(iic_time==1));//等待ACK
TIM3_stop();
I2C_SendData(I2C2, write_address);//寄存器地址
TIM3_start();
while((!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED))&(iic_time==1));//等待ACK
TIM3_stop();
I2C_SendData(I2C2, datal);//发送数据
TIM3_start();
while((!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED))&(iic_time==1));//发送完成
TIM3_stop();
I2C_GenerateSTOP(I2C2, ENABLE);//产生结束信号
}
|