新手入门
- 积分
- 14
- 金钱
- 14
- 注册时间
- 2015-10-19
- 在线时间
- 3 小时
|
这两天一直在琢磨把STM32跟一个模拟的I2C设备互联,想让STM32用硬件I2C,当从发送模式,其实参考手册里面关于I2C讲得挺清楚的,但是我这连同C带嵌入式都是刚学,所以看得云里雾里,倒腾了三天,手头又没有逻辑分析仪,,然后看群里,原子哥都说STM32的I2C是个悲剧,唉。。。
这里说说思路吧,网上有个文章,写得挺不错:
http://blog.csdn.net/sljtfyt/article/details/39319045
让我对EV什么的有了点儿认识,但是后来看了一个文章,记不得地址了,里面解释得更清楚,时序图里面的EVx,其实就是可能需要你去响应的东西,比如在中断处理函数中处理一下,或者你要等待一下这个Event的发生。
我用STM32的PB6,7,跟PB10,11这四个脚,两两互联,组成一个实验环境,拿I2C1当主收,I2C2当从发,下一步就是拿个51的板子,写上软件模拟I2C的程序灌进去,跟STM32连起来,来模拟接下来的与其他模块的通讯
这里多一嘴为什么要用STM32当从发,因为我听说软件模拟I2C当从接收更难,而我的数据流是从STM32流去其他模块的,所以STM32必须是个发,为了方便他人,就当了从发,不知道这个路子对不对, 还是请原子哥或者其他高人指点一下。
main文件里面是初始化I2C接口
int main(void ){
u8 testByte=0x00; //为了给要传输的数组造成点儿变化,这里将数组的第一个byte做成会++的
delay_init(); //初始化延时
I2C_Mode_Init(); //模式初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  C_USART_Config(115200); //设置串口波特大率
RCC_Configuration(); //设置系统时钟
NVIC_Configuration(); //设置中断
while(1){
SendTest();
I2C_Buffer_Tx[0]=testByte++;
}
return 1;
}
void SendTest(){
delay_ms(1000);
I2C_AcknowledgeConfig(I2C1,ENABLE); //打开I2C1的ACK,其实前面Init的时候已经打开了, 但是运行过一次之后,ACK会用来触发从机最后一个包的一个中断而关掉,所以这里要打开
printf("I2C1 generate start condition....\n");
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)); //I2C1主机确定为主机模式
I2C_Send7bitAddress(I2C1,I2C2_SLAVE_ADDRESS7, I2C_Direction_Receiver); //主机发送从地址
delay_ms(1000);
}
戏肉是中断处理部分, 因为我是从,同时还有别的事情要处理,所以不能在main里面等他来连我, 只能等主机发送开始信号,并发送7位从机地址,来触发中断进行后面的数据发送。
因为将来我没法控制I2C1,也就是主机, 所以我只能写I2C2的中断处理,就不写I2C1的中断处理了。
void I2C2_EV_IRQHandler(void)
{
switch (I2C_GetLastEvent(I2C2))
{
case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED: //从模式发送地址确认, 意思是主找的就是你!
printf("I2C2: I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED \n"); //打印确认进展
// while(I2C2_EventMaster_Selected_Flag==1);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); //等待主揭你的牌子,好吧,是等待主机确认他现在是主接收模式。
while (Rx_Idx < BufferSize){ //开始发送数据
I2C_SendData(I2C2,I2C_Buffer_Tx[Tx_Idx++]); //发送一个就将索引数++
while(!I2C_CheckEvent(I2C2,I2C_EVENT_SLAVE_BYTE_TRANSMITTED)); //等待主收到你的BYTE,给你扔一个ACK
I2C_Buffer_Rx[Rx_Idx++] =I2C_ReceiveData(I2C1); //将赶紧把主的话记下来
}
printf("%s \n",(u8*)I2C_Buffer_Rx); //打印一下进展
I2C_SendData(I2C2, 0); //发送最后一个字节,这个字节是无关紧要的,目的是让主机收到后,能回应一个NACK,好让发送的从机知道已经完事儿了,触发从机的NACK中断。
Rx_Idx = 0; //将接收索引归零
Tx_Idx = 0;
I2C_AcknowledgeConfig(I2C1,DISABLE); //将主的ACK关掉, 方便回头能触发从机的NACK中断
I2C_GenerateSTOP(I2C1, ENABLE); //让主下线
TransferStatus = Buffercmp(I2C_Buffer_Tx,I2C_Buffer_Rx,BufferSize); //比较一下结果。
printf("resutl is:%d ,Over \n",TransferStatus); //打印结果
break;
case I2C_EVENT_SLAVE_BYTE_TRANSMITTED:
printf("I2C_EVENT_SLAVE_BYTE_TRANSMITTED \n");
// I2C2_Event_Slave_Sent_Flag=1;
break;
case I2C_EVENT_SLAVE_ACK_FAILURE:
// I2C2_EVENT_SLAVE_ACK_FAILURE_Flag=1;
I2C_ClearFlag(I2C2, I2C_FLAG_AF); //将从机的AF清除一下,不然再传数据的时候是没法继续的。
printf("I2C_EVENT_SLAVE_ACK_FAILURE \n");
break;
default:
break;
}
}
基本功能是可以实现的,肯定也还有问题,有高手发现问题的,还请指教,另外刚学C,肯定有很多可以吐槽的语法问题。。。先感谢大家的指教了。。。
|
|