[STM8] 搞得快自闭了...STM8使用I2C从机反应奇特(有响应,没数据..

[复制链接]
2893|17
 楼主| zgjzgjkyo 发表于 2019-5-8 17:35 | 显示全部楼层 |阅读模式
本帖最后由 zgjzgjkyo 于 2019-5-8 17:37 编辑


环境为 IAR for STM8。使用寄存器(因为考虑到使用速度和flash有限,只能用寄存器版了)(即使寄存器版本,日常应用程序都快10K了)
主从机使用 STM8L152K4
目前情况是,主机能正常发送地址,也有从机的响应,有时突然能发送数据过去。但从机那边却没有没有产生任何的中断(按理一但响应add地址会产生一个中断的啊),更不用说收到数据了。

首先关键设置是有的,也开了总中断(asm("rim");
QQ截图20190508171237.jpg

奇怪在,地址对时有产生一相关的回复
QQ截图20190508171016.jpg QQ截图20190508172327.jpg

但会突然的置0(按理说要读了SR1再读SR3时,ADDR才会置0,我曾经怀疑过是仿真时先读了寄存器产生了误操作,但我试过不仿真,也会一样突然置0的(用放led程序在里面,没有运行))
QQ截图20190508171054.jpg

如果发送错误的地址,SR2是会有AF没响应置位的。(也就是上面的操作没错阿?)
这里也要说一下,明明是开启了接收广播响应,但下面输入00地址还是没响应,太奇怪了........
QQ截图20190508171311.jpg


主机这边的怪异问题先不说,至少能正常的产生中断,而且发送地址正常得到响应......
但从机那边就要命多了,直接说就是没有任何的响应,按理说主机是收到ACK的,也就是从机那边对了地址,SR1的ADDR会置1并产生中断的阿......事实上没有。
我也试过直接用循环查询SR1、2、3状态寄存器了,除了SR3 检测到有总线外,其余全为0。这下我也真的不知怎么回事了........
QQ截图20190508173145.jpg



这东西我搞了三天了,结果还是完全的一样。主机能正常产生中断,也算能发送地址有回复响应。但从机就完全绝了......

在这里真心求教各位了。


下面程序主从机共用,方便大家查看。(删除大量不相干的,我测试过是可以用的,就是从机没有反应,但主机能收到地址的响应回复.......(如果改成其它地址就没有回复了...证明地址那边是可以的吧?))
  1. #include<iostm8l152k4.h>

  2. /*延时ms*/
  3. void delay(unsigned int ms)
  4. {
  5.         unsigned int x , y;
  6.         for(x = ms; x > 0; x--)           /*  通过一定周期循环进行延时*/
  7.                 for(y = 3000 ; y > 0 ; y--);
  8. }


  9. /*    主函数    */
  10. int main(void)
  11. {
  12.         
  13.         asm("sim");                              //关闭系统总中断
  14.         CLK_CKDIVR = 0x00;                   //采用内部16M高速晶振

  15.         
  16.         /*——————I2C模块初始化——————*/
  17.         CLK_PCKENR1_bit.PCKEN13 = 1;            //使能I2C1时钟                 

  18.         I2C1_CR2_bit.SWRST = 1;                     //复位I2C1寄存器
  19.         asm("nop");
  20.         asm("nop");
  21.         asm("nop");
  22.         asm("nop");
  23.         I2C1_CR2_bit.SWRST = 0;               //清除复位设置
  24.         
  25.         I2C1_FREQR_bit.FREQ = 16;              //Freq = 16M
  26.         
  27.         //标准速度
  28.         I2C1_CCRL = 0x50;        //即为80d,在标准速度100KHz下。1/100,000即为10微秒(含Tlow+Thigh)。
  29.                                                         //因此在1/16MHz=0.0625微秒,乘以80=5微秒
  30.         I2C1_TRISER_bit.TRISE = 0x11;                //即为17d。标准速度下最大允许上升时间为1000ns(1微秒)。
  31.                                                                                                 //因此在16MHz下,1/0.0625=16+1=17d
  32.         
  33.         I2C1_OARH_bit.ADDMODE = 0;                        //设置7位地址响应
  34.         I2C1_OARH_bit.ADDCONF = 1;                        //软件必须配置该位(只能配置成1)
  35.         I2C1_OARL = 0xAE;                                                //设置7位地址为AE

  36.         I2C1_ITR = 0x07;                                                //开启ITBUFEN、ITEVTEN、ITERREN所有事件中断(这里没反应啊~~~~!!!!?)
  37.         
  38.         I2C1_CR2_bit.ACK = 1;                                //应答使能
  39.                
  40.         I2C1_CR1_bit.ENGC = 1;                                //设置为广播呼叫模式(设置了也没有用?主机发送00h地址没响应??)
  41.         I2C1_CR1_bit.PE = 1;                              //打开I2C(使能I2C)
  42.         /*——————I2C模块初始化——————*/
  43.         
  44.         //Key1 按键输入设置(这里根据自己的开发板来写按键检测)
  45.         PD_DDR_bit.DDR4 = 0;      //GPD->PIN4 设置为输入模式
  46.         PD_CR1_bit.C14 = 1;       //GPD->PIN4 带上拉电阻输入
  47.         PD_CR2_bit.C24 = 0;       //GPD->PIN4  禁止外部中断
  48.         
  49.         asm("rim");                                                    //打开系统总中断
  50.         
  51.         while(1)                        //进入死循环,等待发送接收
  52.         {
  53.                 if(PD_IDR_bit.IDR4 == 0)                        //判断按钮1是否被按下
  54.                 {
  55.                         delay(10);                                //先延时进行消抖
  56.                         while(PD_IDR_bit.IDR4 == 0);        //等待按钮1被松开
  57.                         delay(10);                                              //再次延时消抖
  58.                         
  59.                         I2C1_CR2_bit.START = 1;            //I2C发送起始信号
  60.                 }
  61.         }
  62. }



  63. /*    I2C中断事件服务函数(目前情况就是发送有产生中断,接收就什么反应也没有)    */
  64. #pragma vector = I2C_ADDR_vector                //设置I2C中断事件向量号 = 0x1F(相关事件中断向量的地址是一样的?)
  65. __interrupt void I2C_ITEVFEN(void)
  66. {         

  67.         if(I2C1_SR1_bit.SB == 1);                        //产生起始信号
  68.         {
  69.                 I2C1_DR = 0xAE;                                        //发送器件地地址,并清除SB标志位(试了一下,AE和AF均有反应(主机发送和主机接收))
  70.         }
  71.                

  72.         if (I2C1_SR1_bit.ADDR == 1)                //等待器件地址发送完成(主机神奇在这里有收到应答,如果上面地址填写不正确,这里因addr=0变成无限循环死机的)
  73.         {
  74.                 if (I2C1_SR3_bit.MSL == 1)                //主模式
  75.                 {
  76.                         unsigned char i2cSRtemp;        //这里会出现一个“was set but never used”警告,不用理。
  77.                         i2cSRtemp = I2C1_SR1;
  78.                         i2cSRtemp = I2C1_SR3;                                //读状态寄存器1和状态寄存器3清除发送器件地址标志位
  79.                         
  80.                         while(!(I2C1_SR1_bit.TXE == 1));        //等待“发送的数据寄存器”变空
  81.                         
  82.                         I2C1_DR = 'A';                                                        //发送字符给从机(但没有反应,动作都完成。从机没发生中断,也没收到数据)

  83.                         I2C1_CR2_bit.STOP = 1;                           //发送停止信号结束数据传输
  84.                         
  85.                         return;
  86.                         
  87.                 }else        //从模式
  88.                 {
  89.                         //从机就不写了,能进入中断就算成功了,但目前没反应.........
  90.                
  91.                 }
  92.         }
  93.         
  94.         

  95.         if (I2C1_SR1_bit.STOPF == 1)        //检测到停止位
  96.         {
  97.           I2C1_CR2_bit.STOP = 1;        //清除停止位
  98.         }
  99.         
  100.         /*------ 错误处理 ------*/
  101.         if (I2C1_SR2_bit.BERR == 1)                //总线错误
  102.         {
  103.           I2C1_SR2_bit.BERR = 0;        //清零
  104.         }
  105.         else if(I2C1_SR2_bit.ARLO == 1)        //仲裁失败
  106.         {
  107.           I2C1_SR2_bit.ARLO = 0;        //清零
  108.         }
  109.         else if(I2C1_SR2_bit.AF)                        //应答失败
  110.         {
  111.           I2C1_SR2_bit.AF = 0;                //清零
  112.         }
  113.         else if(I2C1_SR2_bit.OVR)                        //上溢、下溢
  114.         {
  115.           I2C1_SR2_bit.OVR =0;                //清零
  116.         }

  117.         I2C1_CR2_bit.STOP = 1;
  118.         
  119. }





 楼主| zgjzgjkyo 发表于 2019-5-8 17:40 | 显示全部楼层
或者那位朋友能提供个主从机的I2C通讯(寄存器版)。我目前网上找到的都是库版(事实我上面的程序基本上就是从库版转过来的)
有试过在I2C的器件正常使用(AT24C02)...但主从机数据传输就不行了......(说实在还真的没搞过从机,以前用IO口模拟I2C也很好做的,想不到这次坑在从机身上了......)
 楼主| zgjzgjkyo 发表于 2019-5-8 17:46 | 显示全部楼层
另外接错线这事应该是没有可能的,我有用万用表测过。PC1接PC1(scl),PC0接PC0(sda)吧....(又不是串口反着接........)
lein2006 发表于 2019-5-8 21:00 | 显示全部楼层
请把
unsigned char i2cSRtemp;            // 这里会出现一个“was set but never used”警告,不用理。
改成
volatile unsigned char i2cSRtemp;   // 试一下
 楼主| zgjzgjkyo 发表于 2019-5-15 10:00 | 显示全部楼层
靠~~!!!!终于找到原因了!!!!!!!要不是有官方函数库,我也不知道原来是那个坑!!!
我猜大家一定是用函数库来写stm8的I2C吧?所以没碰到这个问题。因为我是用寄存器编写的所以才碰到这个问题。
其实问题说白了就是寄存器的输入顺序问题,在PE未置位前,CR1和CR2有部分参数是无法置位的!!!(虽然手册上有说明,但我一直以为是PE产生复位动作那些寄存器才会自动复位,原来是理解错了!!!!)
蝴蝶泉2018 发表于 2019-5-15 10:30 | 显示全部楼层
在这里提个小建议,建议大家初始化时还是用官方的标准外设库(或STM32 的CUBE 库)。如楼上所说,有些设置的细节一开始未必注意到,所以用库就可以避免走弯路。其次,对于代码简化来说,先调通外设,能工作,再参考外设库的代码简化函数至寄存器操作。 再次,注意所使用的编译器的优化设置。这样才能少走弯路,提高效率,少加一点班
 楼主| zgjzgjkyo 发表于 2019-5-15 10:35 | 显示全部楼层
蝴蝶泉2018 发表于 2019-5-15 10:30
在这里提个小建议,建议大家初始化时还是用官方的标准外设库(或STM32 的CUBE 库)。如楼上所说,有些设置 ...

对阿,第一次搞这个程序搞到有心理阴影........以后都是用官方例程运行通过再转寄存器好了。
antusheng 发表于 2019-5-15 22:20 | 显示全部楼层
还是用库吧,至少那是官方验证过的程序
wangjiahao88 发表于 2019-5-16 08:11 | 显示全部楼层
模拟IIC可以吗?
 楼主| zgjzgjkyo 发表于 2019-5-18 14:28 | 显示全部楼层

模拟主机这个容易搞,有非常多的例程搞这个,甚至IO口模拟主机也有的。
但模拟从机的,我查过就相当的少了.....

评论

可以看着I2C协议 自己写一个 XDD  发表于 2019-9-8 00:25
磨砂 发表于 2019-6-12 09:04 | 显示全部楼层
也有可能不是真正的相应 只是一种干扰波
晓伍 发表于 2019-6-12 09:08 | 显示全部楼层
用示波器看看波形
八层楼 发表于 2019-6-12 09:13 | 显示全部楼层
说明极有可能时序不满足要求
观海 发表于 2019-6-12 09:22 | 显示全部楼层
用普通的io口模式试试看
LiuChenghu 发表于 2019-9-6 22:33 | 显示全部楼层
你好版主,我也是同样的问题,从机返回的数据一直是FF,请问你是怎么调试通过的呢,我用的是库函数版本的,能不能发一个例程呢
 楼主| zgjzgjkyo 发表于 2019-9-29 09:55 | 显示全部楼层
LiuChenghu 发表于 2019-9-6 22:33
你好版主,我也是同样的问题,从机返回的数据一直是FF,请问你是怎么调试通过的呢,我用的是库函数版本的, ...

已经不搞I2C了。一怒之下,干脆自己写私有通讯协议,保证其独有的加密性!!!!
zjq985062714 发表于 2019-10-3 13:21 来自手机 | 显示全部楼层
这个官方Demo没有例程吗?应该可以参考一下
您需要登录后才可以回帖 登录 | 注册

本版积分规则

53

主题

213

帖子

4

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