[STM8] stm8硬件I2C 主机/从机 发送/接收 完全解决测试验证通过

[复制链接]
3516|6
 楼主| capturesthe 发表于 2016-11-27 19:33 | 显示全部楼层 |阅读模式
网上都说STM8的硬件I2C 不好用 有BUG之类的。而我因为项目需要,用stm8硬件 I2C 中断方式 发送/接收数据,经过查阅手册和反复验证,已经完成了,话不多说,上代码。主机主函数:
  1. I2C_MASTERMODE_Init(STANDARDSPEED);
  2.   I2C_ITConfig(I2C_IT_ERR|I2C_IT_EVT|I2C_IT_BUF,ENABLE);
  3.   rim();
  4.   delay_ms(6000);
  5. // while (I2C_GetFlagStatus(I2C_FLAG_BUSBUSY));
  6. // I2C_GenerateSTART(ENABLE);
  7.   while(1)
  8.   {
  9.     //I2C_Write(0x40,0x50,0x64);
  10.    //I2C_EEPROM_WriteOneByte(0x42,Cnt);
  11.    //I2C_Write(0x40,Cnt,0x58);
  12.    // Cnt++;
  13.     while (I2C_GetFlagStatus(I2C_FLAG_BUSBUSY));
  14.     I2C_ITConfig(I2C_IT_ERR|I2C_IT_EVT|I2C_IT_BUF,ENABLE);
  15.     I2C_AcknowledgeConfig(I2C_ACK_CURR);
  16.     I2C_TXCnt=0;
  17.     I2C_RXCnt=0;
  18.     I2C_GenerateSTART(ENABLE);
  19.     delay_ms(3000);
  20.   }

  21.    主机中断部分:
  22.     unsigned char Nuse;
  23.   unsigned char Event;                                 
  24.   Event=I2C->SR1;                                               //数据无错位  
  25.   Nuse=I2C->SR3;
  26.   if(I2C_TX)                                                   //主发送
  27.   {
  28.     switch(Event)
  29.     {
  30.       case 0X01:                                                  //起始条件已经发送
  31.           I2C_Send7bitAddress(SLAVE_ADDRESS, I2C_DIRECTION_TX);   //发送从机地址
  32.           break;
  33.       case 0x80:                         //发送区空  
  34.           I2C->DR=I2C_TXBuffer[I2C_TXCnt++];
  35.           if(I2C_TXCnt>=14)
  36.           {
  37.             I2C_TXCnt=0;
  38.             I2C_ITConfig(I2C_IT_BUF, DISABLE);
  39.           }
  40.           break;
  41.       case 0X82:                             // 地址发送结束   
  42.          // Nuse=I2C->SR3;
  43.           I2C_TXCnt=0;
  44.           I2C->DR=I2C_TXBuffer[I2C_TXCnt++];
  45.           break;
  46.       case 0x84:
  47.           I2C_GenerateSTOP(ENABLE);
  48.           I2C_ITConfig(I2C_IT_EVT, DISABLE);   //不能少
  49.          
  50.           break;
  51.       default:
  52.           break;   
  53.     }
  54.   }
  55.   else                                                        //主接收
  56.   {
  57.     switch(Event)
  58.     {
  59.       case 0X01:                                                  //起始条件已经发送
  60.           I2C_Send7bitAddress(SLAVE_ADDRESS, I2C_DIRECTION_RX);   //发送从机地址
  61.           break;
  62.       case 0x40:                                          //接收区满
  63.           I2C_RXBuffer[I2C_RXCnt++]=I2C->DR;   
  64.           if(I2C_RXCnt==13)
  65.           {           
  66.             I2C_AcknowledgeConfig(I2C_ACK_NONE);
  67.             I2C_GenerateSTOP(ENABLE);
  68.           }
  69.           if(I2C_RXCnt>=14)
  70.           {
  71.             I2C_RXCnt=0;
  72.           }
  73.           break;
  74.       case 0X42:                             // 地址发送结束   
  75.          // Nuse=I2C->SR3;
  76.           I2C_RXCnt=0;
  77.           Nuse=I2C->DR;
  78.           break;
  79.       case 0x44:
  80.           //I2C_GenerateSTOP(ENABLE);
  81.           I2C_ITConfig(I2C_IT_EVT, DISABLE);   //不能少
  82.       default:
  83.           break;   
  84.     }
  85.   }


 楼主| capturesthe 发表于 2016-11-27 19:33 | 显示全部楼层
从机中断:
  1. unsigned char Add;
  2.   unsigned char Nuse;
  3.   static unsigned char RX_Cnt=0;
  4.   
  5.   if(I2C->SR2&0X0F)           //I2C 出现错误
  6.   {
  7.     I2C->SR2&=0xf0;
  8.     //I2C->CR2|=1<<7;
  9.     //I2C->CR2&=~(1<<7);
  10.     RX_Cnt=0;
  11.     I2C_Tx_Idx=0;
  12.   }
  13.   
  14.    if(I2C->SR1&0X02)      //地址匹配
  15.   {
  16.     (void)(I2C->SR3);  //先读I2C_SR1,再读I2C_SR3,就可以清除ADDR
  17.      // I2C->DR = 0X00;
  18.     I2C_Tx_Idx=0;
  19.     I2C_Rx_Idx=0;
  20.     I2C->DR = Slave_Buffer_Tx[I2C_Tx_Idx++];
  21.   }
  22.   if(I2C->SR1&0X10)         //停止条件
  23.   {
  24.     Nuse = I2C->CR2;
  25.     nop();
  26.     I2C->CR2 = Nuse;
  27.   }
  28.   if(I2C->SR1&0X04)
  29.   {
  30.     Nuse=I2C->DR;
  31.    // I2C->DR=Nuse;
  32.   }
  33.    if(I2C->SR1 & 0x40)
  34.    {
  35.       Slave_Buffer_Rx[I2C_Rx_Idx++]=I2C->DR;
  36.       if(I2C_Rx_Idx>=14)
  37.       {
  38.         I2C_Rx_Idx=0;
  39.       }   
  40.    }
  41.   if(I2C->SR1 & 0x80)
  42.   {
  43.     //将发送的数据放入DR寄存器,清除TX
  44.     //   I2C->DR = Slave_Buffer_Tx[I2C_Tx_Idx++];
  45.      //  if(I2C_Tx_Idx>=14)I2C_Tx_Idx=0;
  46.    
  47.     I2C->DR = Slave_Buffer_Tx[I2C_Tx_Idx++];
  48.     if(I2C_Tx_Idx>=14)I2C_Tx_Idx=0;
  49.   }


734774645 发表于 2016-11-27 21:04 | 显示全部楼层
正需要这个,以前都用IO来搞,学习一下楼主的方法。
hclin 发表于 2017-1-18 20:11 | 显示全部楼层
有完整的源码可供编译、测试吗?
hudi008 发表于 2017-1-18 23:06 | 显示全部楼层
hclin 发表于 2017-1-18 20:11
有完整的源码可供编译、测试吗?

这个iic不是有代码吗
18814303937 发表于 2019-3-7 16:53 | 显示全部楼层
你好,iic中断的产生条件是怎么样的?是不是做从机时,当时候有iic信号过来,就会产生中断?

评论

当addr =1的时候 有开中断的话,是会产生一个中断的  发表于 2019-3-11 10:23
您需要登录后才可以回帖 登录 | 注册

本版积分规则

22

主题

136

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部