打印

STC8F2K32S2 有 BUG,使用时要注意!

[复制链接]
5754|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
发现问题是在这里:
      https://bbs.21ic.com/forum.php?mod=viewthread&tid=2645540&page=1#pid9993902
和STC方面沟通了一下后,发现是 版本为 DSTC8F2K32S2  ,个人确认这是芯片的bug !
BUG是: I2CSLADR 寄存器没有将从机地址左移一位,也就是没有留出匹配判断位,而直接判断从机地址的最低位是否0或1进行了匹配处理。

相关帖子

沙发
零三翟邢止胃| | 2019-3-21 10:42 | 只看该作者
多谢提醒了啊!!!!!

使用特权

评论回复
板凳
逍遥派掌门|  楼主 | 2019-3-21 17:55 | 只看该作者
本帖最后由 逍遥派掌门 于 2019-3-21 18:01 编辑

后续研究了一下,应该是烧写程序里的范例的注释写错了,写入寄存器的值是 0x5A ,而设备地址则应该是: 0x2D     ( 0x5A >>1 )
这样就能和datasheet对上了。
更悲剧的是:使用从机中断方式,如果不匹配从机地址的话,那就直接惨死! 从机中断接收的数据累计达到16个字节后,IIC功能就瘫痪了!!!!

NND,当了只可悲的小白鼠


使用特权

评论回复
地板
autopccopy| | 2019-3-21 18:11 | 只看该作者
逍遥派掌门 发表于 2019-3-21 17:55
后续研究了一下,应该是烧写程序里的范例的注释写错了,写入寄存器的值是 0x5A ,而设备地址则应该是: 0x2 ...

我没用过STC8F系列,一直用STC8A8K64S4A12, 也没怎么使用硬件IIC, 不过测试了硬件IIC 读写 AT24C系列机iic的OLED 是正常的。建议看看STC8A8K64S4A12的G版本,好像有修正IIC的问题及想官方反映。:)

使用特权

评论回复
5
hwpga| | 2019-3-21 23:57 | 只看该作者
正好做产品,看到了就给你回下
从模式我没试,和主模式基本上没太大区别
但你这程序肯定不行,应答位你都不用起来


没上24波形


上24C波形

使用特权

评论回复
6
hwpga| | 2019-3-22 00:05 | 只看该作者
I2C最最关键的第9位Ack和NoAck你的程序都没有
地址和数据是否接受到或错误
从机是否掉线,全靠第9位来识别

使用特权

评论回复
7
asimeto223| | 2019-3-22 09:08 | 只看该作者
多谢提醒

使用特权

评论回复
8
逍遥派掌门|  楼主 | 2019-3-22 09:29 | 只看该作者
hwpga 发表于 2019-3-22 00:05
I2C最最关键的第9位Ack和NoAck你的程序都没有
地址和数据是否接受到或错误
从机是否掉线,全靠第9位来识别

我用的是从机模式,和主机模式不同,datasheet那里都是单独进行说明的。====================================================

STC8F2K的硬件IIC肯定是有毛病的,STC的datasheet里都列了出来:

上面主要说主机,从机的问题还没有说呢。
=====================================================
有问题找那个技术支持,总是不耐烦的让人去看范例,NND,就看看范例的错误:

把从机地址和赋给寄存器的值混为一谈!坑人啊
======================================================

从机那里不是ACK的问题,我的从机程序是可以工作的,基本是从范例复制过来的。

同一个程序里,将从机地址寄存器设置为匹配时,可以收到上百个正确的字节
而设置为不匹配时,则只能收到16个正确的字节,而且硬件IIC再没有动静了,只能重新上电

使用特权

评论回复
9
hwpga| | 2019-3-22 19:55 | 只看该作者
不想帮STC说话,自己看图


一个字节读取OK的流程,随便写了下程序
从机单片机模拟了下24C
主机写地址0xfc,读地址0xfd,写存储地址0x08,从机返回0xb0

故意改了从机写地址,模拟器件不在线
主机利用Noack终止I2C通信

故意改了器件地址,模拟区间地址错误
主机利用Noack终止I2C通信


故意改了从机读地址,模拟器件地址错误
主机利用Noack终止I2C通信



使用特权

评论回复
10
hwpga| | 2019-3-22 19:57 | 只看该作者
本帖最后由 hwpga 于 2019-3-22 19:59 编辑

你的程序没利用起ack
地址数据发过来你就要了,也不管对错
配合主机定时器超时功能,I2C根本不可能死掉
我用的STC8F2K08S2

使用特权

评论回复
11
xyz549040622| | 2019-3-23 08:16 | 只看该作者
我的意见是,确实有bug,哪怕是楼上说的可以有办法,那也是设计时候没考虑好,我们想要的是和其他芯片一样很简单的就操作。话说这个芯片用过,I2C直接用的是IO模拟,没有上硬件I2C。

使用特权

评论回复
12
逍遥派掌门|  楼主 | 2019-3-25 11:18 | 只看该作者
hwpga 发表于 2019-3-22 19:57
你的程序没利用起ack
地址数据发过来你就要了,也不管对错
配合主机定时器超时功能,I2C根本不可能死掉

这个BUG 和程序有没有利用ACK是没有关系的。
ACK和NACK,在STC硬件I2C里都是STC的内部处理的,用户程序干涉不了。
再说,如果是ACK,NACK不正确,哪里还可以正确收到数据呢? 我这里是可以收到正确数据,不存在ACK等问题。
STC从机中断里也没有什么可以控制的了,只是地址寄存器里设置了地址为不要匹配(这个是硬件处理的,用户程序干涉不了),工作一小会就挂了。
注意:是能工作一小会。我这里是成功发起了8次I2C事件,一共接收16个字节,然后才挂的。
对于STC硬件I2C的,官方的datasheet都承认是有BUG的。不过在datasheet里,说是信号受到干扰就要重新上电。(太文雅了,直说就是死机了,挂了)
在我测试这里完全说不通。我设置了地址要匹配,那么一直接收到6K多数据仍在工作;而设置地址不匹配,马上就不正常了。(除了设置地址匹配的寄存器外,程序没有改动)。如果说是干扰,这干扰也太智能太能挑事了,还能识别寄存器的设置?
下面是有关STC的硬件I2C的官方说明:

使用特权

评论回复
13
逍遥派掌门|  楼主 | 2019-3-28 10:37 | 只看该作者
跟踪了地址匹配模式下的接收信号,问题出在这里了:


隔一次I2C事件就出错一次,地址没有识别出来。

地址不匹配模式就不想再浪费力气去跟踪了。

STCF2Kxxx  的I2C的从机模式,就是有BUG。

使用特权

评论回复
14
hwpga| | 2019-3-28 16:37 | 只看该作者
本帖最后由 hwpga 于 2019-3-28 17:15 编辑

                                                                                                                        if(I2C.ucSLSta>0)  
                                                                                                                                    {
                                                                                                                                                  if((I2CSLST&0x20)>0)
                                                                                                                                                  {
                                                                                                                                                       I2CSLST&=~0x20;                  
                                                                                                                                                        if(I2CRXD==0xfc)      //从机地址匹配
                                                                                                                                                                 {
                                                                                                                                                                         I2CSLST=0x00;      //从机发送Ack
                                                                                                                                                                         I2C.ucGetStep=1;
                                                                                                                                                                 }
                                                                                                                                                                 else                  //地址不匹配
                                                                                                                                                                 {
                                                                                                                                                                         I2CSLST=0x01;      //从机发送Noack                                                                                                                                                                          
                                                                                                                                                                         I2C.ucSLSta=0;
                                                                                                                                                                         I2CSLCR=0x01;    //复位I2C,从机退出Busy
                                                                                                                                                                         I2CSLCR=0x40;    //使能Sta,等待下一个新的起始
                                                                                                                                                                 }        
                                                                                                                                                 }            
                                                                                                                                        }
                                                                                                                                        else
                                                                                                                                        {
                                                                                                                                                 if((I2CSLST&0x40)>0)   //起始
                                                                                                                                                 {
                                                                                                                                                         I2CSLST&=~0x40;   //清除Sta标志位
                                                                                                                                                         I2C.ucSLSta=1;
                                                                                                                                                         I2CSLCR=0x20;    //使能Rx接收中断,禁止Sta中断
                                                                                                                                                 }        
                                                                                                                                        }
                                                                                                                                        break;


地址识别的,别的我就不发了
I2CSLST最低位写0,从机返回主机ack
I2CSLST最低位写1, 从机返回主机Noack
主机写0011命令到后, MSACK1读回从机返回的是ack或Noack
MSACK1位为0,主机继续通信
MSACK1位为1,主机要发送Stop命令,会清除Busy并结束通信
我也不是STC的人,也没义务帮谁
主机超时大概这样,每次通信主机写个I2CCFG|=0x80;
每次通信计时用完了,I2C就自动关掉
void  I2C_TimeOut()
{
                if((I2CCFG&0x80)>0)     //I2C使能下,主机通信计时xxxMS
                 {
                          if(++I2C.xxxCnt>=5)
                          {
                                  I2C.xxxCnt=0;
                                  I2CCFG&=~0x80;   //主机退出I2C模式
                                  Rst_I2C();
                          }                     
                   }
}






使用特权

评论回复
15
bear1| | 2019-3-28 17:37 | 只看该作者
路上本满是坑,填的人多了,路也就平了。

使用特权

评论回复
16
bear1| | 2019-3-28 17:38 | 只看该作者
hwpga 发表于 2019-3-22 19:55
不想帮STC说话,自己看图

波形好漂亮,你这是什么工具看的波形图?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

14

主题

524

帖子

2

粉丝