STM32之I2C
来源:互联网 发布:海军知耻 陆军马鹿 编辑:程序博客网 时间:2024/05/23 01:16
对于STM32,说道I2C都比较头疼。有人说硬件有缺陷,有的人说不稳定。总之就是不好用。
但是对于某些情况,又必须要使用I2C,无奈之余,只能凑合用了。
I2C从模式上分为主发,主收,从发,从收。
主发送模式:
I2C_ERR_E I2C_Send(BYTE* data, BYTE addr, int len)
{
int count, cycle = 0,err;
u32 event;
I2C_ERR_E error = I2C_ERR_OK;
I2C_AcknowledgeConfig(I2C2, ENABLE);
/* Send START condition */
if(I2C2->SR2 & 0x02) //检测busy位,如果为“1”,则I2C不能正常使用,重启I2C
{
goto I2C_RESET;
}
I2C_GenerateSTART(I2C2, ENABLE);
count = I2C_TIMEOUT; //设置超时时限
while(--count && !I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));
if(count == 0) //发送开始条件失败(总线忙),可能因为总线被占用,重启I2C
{
I2C_GenerateSTOP(I2C2, ENABLE);
error = I2C_ERR_TIMEOUT;
goto I2C_RESET;
}
count = I2C_TIMEOUT;
I2C_Send7bitAddress(I2C2,addr,I2C_Direction_Transmitter);
while(--count && !I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
if(count == 0) //发送地址无应答,直接返回。此处不需要重启,可能是因为地址没有匹配。
{
error = I2C_ERR_TIMEOUT;
return error;
}
while(len -- ){
count = I2C_TIMEOUT;
I2C_SendData(I2C2, *data);
data++;
while(--count && !(I2C2->SR1 & 0x80));
if(count == 0) //发送失败,退出发送
{
error = I2C_ERR_TIMEOUT;
break;
}
}
I2C_GenerateSTOP(I2C2, ENABLE);
count= I2C_TIMEOUT;
while (--count && I2C2->SR2 & 0x02); //检测停止条件是否发送成功
if(count == 0)
{
goto I2C_RESET;
}
return I2C_ERR_OK;
I2C_RESET: //对于异常,重启I2C(对于主机的I2C异常,重启能解决,但是若从机占用了I2C,那么需要重启从机I2C才能解决)
I2C_SoftwareResetCmd(I2C2, ENABLE);
I2C_SoftwareResetCmd(I2C2, DISABLE);
I2C_Config();
return I2C_ERR_TIMEOUT;
}
主接受模式:
I2C_ERR_E I2C_Recv(BYTE addr, I2C_frame_t *frame)
{
int count = I2C_TIMEOUT;
int index = 0 ,len;
u32 event;
u8 crc;
I2C_ERR_E error = I2C_ERR_OK;
I2C_Lock();
if(I2C2->SR2 & 0x02)
{
error = I2C_ERR_FAIL;
goto i2c_recv_ret;
}
I2C_AcknowledgeConfig(I2C2,ENABLE);
I2C_GenerateSTART(I2C2, ENABLE);
while(--count && !I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));
if(count == 0)
{
error = I2C_ERR_TIMEOUT;
goto end;
}
count = I2C_TIMEOUT;
I2C_Send7bitAddress(I2C2,addr,I2C_Direction_Receiver);
while(--count && !I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
if(count == 0)
{
error = I2C_ERR_TIMEOUT;
goto end;
}
count = I2C_TIMEOUT;
while(--count && !I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED));
if(count == 0)
{
error = I2C_ERR_TIMEOUT;
goto end;
}
frame->cmd = I2C_ReceiveData(I2C2); //cmd
count = I2C_TIMEOUT;
while(--count && !I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED));
if(count == 0)
{
error = I2C_ERR_TIMEOUT;
goto end;
}
frame->len = len = I2C_ReceiveData(I2C2); //len
if(len > 0 && len <= 64){
while(len -- ){
count = I2C_TIMEOUT;
while(--count && !I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED));
if(count == 0)
{
error = I2C_ERR_TIMEOUT;
goto end;
}
frame->data[index] = I2C_ReceiveData(I2C2);
index ++;
}
}
I2C_AcknowledgeConfig(I2C2,DISABLE);
I2C_GenerateSTOP(I2C2, ENABLE);
count = I2C_TIMEOUT;
while(--count && !I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED));
if(count == 0)
{
error = I2C_ERR_TIMEOUT;
goto end;
}
frame->crc = I2C_ReceiveData(I2C2); //len
crc = CRC8_Table(frame->data, frame->len);
if(frame->crc != crc)
{
error = I2C_ERR_CRC;
}
goto i2c_recv_ret;
end:
I2C_GenerateSTOP(I2C2, ENABLE);
count= I2C_TIMEOUT;
while (count-- && I2C2->SR2 & 0x02);
if(count == 0)
{
return I2C_ERR_TIMEOUT;
}
i2c_recv_ret:
return error;
}
从发,从収使用中断来响应:
void I2C2_EV_IRQHandler(void)
{
u32 SR1Register,SR2Register;
SR1Register = I2C2->SR1;
SR2Register = I2C2->SR2;
/* If I2C1 is slave (MSL flag = 0) */
if ((SR2Register &0x0001) != 0x0001)
{
/* If ADDR = 1: EV1 */
if ((SR1Register & 0x0082) == 0x0082)
{
/* Clear SR1Register and SR2Register variables to prepare for next IT */
SR1Register = 0;
SR2Register = 0;
/* Initialize the transmit/receive counters for next transmission/reception
using Interrupt */
Tx_Counter = 0;
status = 2;
Time5_Init();
}else if((SR1Register & 0x0082) == 0x0002)
{
SR1Register = 0;
SR2Register = 0;
/* Initialize the transmit/receive counters for next transmission/reception
using Interrupt */
Rx_Counter = 0;
status = 1;
Time5_Init();
}
/* If TXE = 1: EV3 */
if ((SR1Register & 0x0080) == 0x0080)
{
/* Write data in data register */
I2C2->DR = I2C1_Buffer_Tx[Tx_Counter++];
SR1Register = 0;
SR2Register = 0;
}
/* If RXNE = 1: EV2 */
if ((SR1Register & 0x0040) == 0x0040)
{
/* Read data from data register */
I2C1_Buffer_Rx[Rx_Counter++] = I2C2->DR;
SR1Register = 0;
SR2Register = 0;
}
/* If STOPF =1: EV4 (Slave has detected a STOP condition on the bus */
if (( SR1Register & 0x0010) == 0x0010)
{
//处理帧
SR1Register = 0;
SR2Register = 0;
}
} /* End slave mode */
}
- STM32学习之I2C
- STM32之I2C
- STM32之I2C
- STM32之I2C
- Arduino与上STM32之I2C
- STM32---------- I2C
- STM32学习之路:I2C的基本读写
- STM32--硬件I2C-2402
- STM32-寄存器I2C--2402
- STM32-I2C-appcat延时
- stm32 I2C问题 I2C_CheckEvent()
- STM32 I2C 难点
- STM32 I2C读写
- stm32 I2C问题 I2C_CheckEvent()
- STM32--硬件I2C-2402
- STM32-寄存器I2C--2402
- STM32-I2C-appcat延时
- STM32 I2C 难点
- PHP 从数据库中取出数据并存为Json数据
- C\C++把TXT文件读入内存
- Reacjs学习笔记
- lombok如何做的冗余代码消除。
- 优秀工具资料网站
- STM32之I2C
- struts2的体系结构
- 【mysql】mysql 小数转换成百分数查出(保留两位小数百分数)以及怎么使select中嵌套if的使用
- Oracle 11.2.0.1.0 静默安装
- Scala 数据类型的协变、逆变、上边界、下边界
- OC与Swift混编
- UVA 253 Cube painting
- 什么理论?人与人之间的关系
- 利用Oracle分析函数实现多行数据合并为一行