OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6442|回复: 0

STM32 I2C 做从发送的一点思路

[复制链接]

3

主题

4

帖子

0

精华

新手入门

积分
14
金钱
14
注册时间
2015-10-19
在线时间
3 小时
发表于 2015-11-6 18:29:58 | 显示全部楼层 |阅读模式
这两天一直在琢磨把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,肯定有很多可以吐槽的语法问题。。。先感谢大家的指教了。。。

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-17 18:41

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表