历史上的今天
返回首页

历史上的今天

今天是:2024年11月23日(星期六)

2019年11月23日 | stm8 调试硬件I2C心得

2019-11-23 来源:eefocus

这次调试stm8的硬件真是艰辛,没有想到这样恼火!整整搞啦 我5天的时间,参考网上很多例子和风驰的stm8讲解!和自己的实践,终于搞通啦!特将自己在调试过程中一些心得希望的大家分享。由于本人水平有限也希望大家指出不足和错误的地方!


Stm8不需要专门配置GPIO口,执行初始化就可以啦!有些stm8需要打开EEPROM设置I2C(看官方文档)。


Stm8主要靠SR1和SR3状态寄存器判断I2C的情况(while(!XXXXX)就是出自这里),多半大家调不通!就是卡在这里(需要注意的是 寄存器有些位,只要读寄存器就可以清除,在仿真的时候,最好不要打开寄存器页面)。这里分软故障和硬故障:


首先是硬故障: 一般是stm8芯片IO口坏啦,有些时候stm8能够写程序而且IO别的功能都是好的,单单是I2C用不起!还有就是IO上拉电压不够!我就遇到这样的问题,我IO 加上逻辑分析仪后就可以调通,不加就通不了。这个也搞啦我很久。


软故障: 一般主要是设置CR1和CR2问题,只要按照我的参考程序设置就可以!


我详细的讲讲,寄存器I2c_CR2 应答使能位(位2)ack。首先是理解:官方文档上面说的是ack应答使能,对是使能!很多人包括我自己 开始都认为是发送ack,导致每次stm8收到数据后,我们都手动在每次收到字节后加I2C_AcknowledgeConfig(I2C_ACK_CURR)无任何意义,因为在接收模式下,收到完整字节后,自动发送ack(提前是CR2 ack位使能,不需要专门CR2 ack位置1)   ,都是软件虚拟I2C用多啦!想当然啦!


还有就是使用这个ack!设置ACK都必须在接收字节前,也就是说为个在收到最后一个字节后产生一个NACK 脉冲,在读倒数第二个数据字节之后,必须清除ack位(ack=0)!设置ack同理! 还有需要 主要的地方 如果设置 ack=0; 下次需要重新产生ack的时候!需要手动置位ack!记住在开始接收之前!如果你只有一个字节正确,后面全部是0xFF...可能就是这个问题(切记!切记!很多例子都没有加上这句,包括风驰 的例子!! 不过 他没有加循环! 如果他再循环一次就会出现问题。)


随便说说仿真调试!在调试过程中,最好不要打开I2C寄存器看!因为对寄存器的读,也会造成寄存器有些位重置!直接按Go,然后暂停。进去程序看卡在那里啦。


操作库和寄存器编写程序,其实没有分别!不过为啦更好的理解,我在这里是操作寄存器!网上有人说加入中断会对I2C产生影响,我这里没有加中断。希望有后来人补全!反正我这几天运行没有发现问题!

附录1 主要I2C程序

/*******************************************************************************
* 名称: Read_8816
* 功能: 读取温度数据
* 形参: *pBuffer 返回读取数据指针
         index 温度寄存器地址
         NumByteToRead 需要读取字节数


* 返回: 无
* 说明: 该函数直接操作stm8寄存器!
         寄存器I2c_CR2 应答使能位(位2)ack=1,当stm8接受到数据后,自动发送ACK.不需要手动ack


         为个在收到最后一个字节后产生一个NACK 脉冲,在读倒数第二个数据字节之后,必须清除ack位(ack=0)
         当接收到最后一个字节,需要重新使能ack=1.(如果不设置ack=1,循环开始后,收到第一个字节stm8不会发送ack,造成除每次循环第一个字节正常外,后面收到
         的数据都是0xFF....stm8一直不给ack) 
           
         需要注意的是 寄存器有些位,只要读寄存器就可以清除(不需要专门写入寄存器,在仿真的时候,最好不要打开寄存器页面),
******************************************************************************/

void Read_8816(u8 *pBuffer, u8 index, u8 NumByteToRead) 
{  
  
  while(I2C->SR3 & 0x02);  //等待总线空闲   检测i2c-SR3 busy位  
  
  
  //以下见stm8s中文数据手册P251(图96主设备发送模式发送序列图)
  
  //S 起始条件
  I2C->CR2 |= 0x01;  //产生起始位            CR2 start位       
  //EV5:SB=1,读SR1 然后将地址写入DR寄存器将清除该标志。
  while(!(I2C->SR1 & 0x01));  //等待START发送完 E5
  
  //ADDRESS (发送模式)
  I2C->DR = 0x00;  //发送MLX90615器件地址(最后一位是0,表示发送)
  

  while(!(I2C->SR1 & 0x02));  //等特7位器件地址发送完并且收到ack,ADDR置1
  
//EV6:ADDR 在软件读取SR1后,对SR3寄存器读操作 将清除改位
I2C->SR1; //见P251 读SR1 (实验证明可以不要)
I2C->SR3; //然后读SR3 清  ADDR(等于库函数I2C_ClearFlag(I2C_FLAG_ADDRESSSENTMATCHED))


  //DATA 发送寄存器地址
  I2C->DR = (u8)(index); 
  
  //EV8_2 TxE=1 ,BTF=1,产生停止条件时由硬件清除。
  while(!(I2C->SR1 & 0x84));  //检测SR1 TXE1 BTF位置(只有当stm8收到ack,TxE才会置1,其实这句相当于判断收到ack没有?)
  
  
  
  //在发送地址和清除ADDR 之后,I2C接口进入主设备接收模式。以下见stm8s中文数据手册P252(图97主设备接收模式接收序列图)
  
  //S 重复起始条件
  I2C->CR2 |= 0x01;  //产生重复起始位
  //EV5:SB=1,读SR1 然后将地址写入DR寄存器将清除该标志。
  while(!(I2C->SR1 & 0x01));  //等待START发送完
  
  //ADDRESS (接收)
  I2C->DR = 0x01;  //发送MLX90615器件地址(最后一位是1,表示接收),发送完后自动发送ack(提前是CR2 ack位使能)

  
  //EV6:ADDR 在软件读取SR1后,对SR3寄存器读操作 将清除改位
  while(!(I2C->SR1 & 0x02));  //等特7位器件地址发送完并且收到ack,ADDR置1
I2C->SR1; //见P251 读SR1 (实验证明可以不要)
I2C->SR3; //然后读SR3 清  ADDR(等于库函数I2C_ClearFlag(I2C_FLAG_ADDRESSSENTMATCHED)) 

//循环读取数据
  while(NumByteToRead)  
  {
      //EV7_1 :RxNE=1 ,读DR寄存器清除该标志。设置ACK=0和STOP 请求。(在接收最后一个字节前) 
        if(NumByteToRead == 1) //实验证明在最后一个字节前后都一样
    { 
      I2C->CR2 &= ~0x04; //ack使能
      
      I2C->CR2 |= 0x02;  //停止位产生stop
    
    } 
      
    
      ///测试EV7 RxNE=1(收到一个字节后RxNE置1) ,判断DR寄存器有数据
    if(I2C->SR1 & 0x40)
    {    
       *pBuffer=I2C->DR;//在接收模式下,收到完整字节后,自动发送ack(提前是CR2 ack位使能,不需要专门CR2 ack位置1)
              //在风驰里面例子,在每次收到字节后加I2C_AcknowledgeConfig(I2C_ACK_CURR)无任何意义,
       pBuffer++;  
       NumByteToRead--;      
    } 
      
  }
   
I2C->CR2 |= 0x04;//为一下循环开始 设置 ack使能,上面 EV7_1设置ack=0发送stop后;需要手动设置ack=1使能,必要在接收数据之前

//切记!切记!很多例子都没有加上这句,包括风驰 的例子!! 不过 他没有加循环! 如果他在循环一次就会出现问题。CR2 ack位其实就是使能的意思!!很多人都理解成需要手动设置!
// 都是软件模拟I2C 搞太多!! 想当然啦!没有仔细看官方的文档!
}


推荐阅读

史海拾趣

ASM公司的发展小趣事

ASM公司的创始人阿瑟·德尔·普拉多(Arthur del Prado)在移居美国后,遇到了半导体产业的蓬勃发展。他敏锐地洞察到了这一行业的巨大潜力,并决定投身其中。起初,他只有有限的资源和500美元的资金,但他凭借着对市场的深刻理解和不懈的努力,成功地在欧洲市场打开了局面。1964年,他在荷兰创立了先进半导体材料公司(ASM),这标志着ASM公司的正式诞生。

Everett Charles Technologies (ECT)公司的发展小趣事

1965年,Everett Charles Technologies (ECT) 公司正式成立,标志着其在电子测试系统硬件与软件领域的起点。ECT的创始人凭借对电子技术的深刻理解和市场需求的敏锐洞察,成功开发出了一系列符合工业标准的产品,包括POGO探针、ValuGrid测试治具等。这些产品的推出,不仅奠定了ECT在电子测试领域的基础,也为公司的后续发展提供了强大的动力。

ESTEK公司的发展小趣事

在电子行业竞争日益激烈的背景下,ESTEK公司也面临着诸多挑战和危机。然而,公司始终保持着清醒的头脑和坚定的信心。在面对市场波动、原材料价格上涨等挑战时,ESTEK公司迅速调整战略、优化生产流程、降低成本等措施,成功度过了危机。在危机中,ESTEK公司展现出了强大的韧性和生命力,为公司未来的发展奠定了坚实基础。

昭华(CHA)公司的发展小趣事

为了满足市场的不断增长的需求,昭华公司在2016年成立了昭华智硕东莞工厂。这座工厂拥有先进的生产设备和完善的生产流程,能够大幅提高公司的生产效率和产品质量。同时,昭华公司还不断优化供应链管理,加强与供应商的合作,确保原材料的稳定供应。这些举措不仅提高了公司的产能,还降低了生产成本,增强了公司的市场竞争力。

All Sensors公司的发展小趣事

All Sensors在传感器技术领域一直保持着世界领先的地位。公司掌握着核心的MEMS传感器技术,如独有的CoBeam2 TM传感器技术等。这些技术的应用使得All Sensors的传感器在精度、稳定性和寿命等方面都达到了行业领先水平。同时,公司还不断投入研发,推出更多创新产品,满足不断变化的市场需求。

Avalon Photonics公司的发展小趣事

随着Avalon Photonics的不断发展壮大,公司开始更加关注社会责任和可持续发展。公司积极参与公益活动,支持教育事业和科技创新。同时,Avalon也致力于研发更加环保、节能的产品,为推动电子行业的可持续发展贡献力量。通过积极履行社会责任,Avalon Photonics不仅赢得了社会各界的认可,也为公司的长远发展奠定了坚实的基础。


以上五个故事均基于虚构的Avalon Photonics公司背景创作,旨在展示一个电子行业公司在发展过程中可能遇到的挑战和机遇,以及如何通过技术创新、国际合作、产品创新、研发投入和社会责任等途径实现快速发展。这些故事均遵循了只描述事实、不做褒贬的原则。

问答坊 | AI 解惑

中国所有的车牌你们都知道吗?

北京市(京)   京A、京C、京E、京F、北京市(城区),京G 北京市(远郊区), 京B 出租车,京O警察 天津市(津)   津A、津B、津C、天津市 ,津E 出租车 上海市(沪)   沪A、沪B、沪D 上海市区,沪C 远郊区 重庆市(渝)   渝A 重庆市 ...…

查看全部问答>

vxworks的使用

int t1,t2; printf(\"please input 1:\"); scanf(\"%d\\n\",&t1); switch(t1) { case 1:{printf(\"case1\\n\"); scanf(\"%d\",&t2);printf(\"t2=%d\\n\",t2); break;} } ------------------------------------------- 在屏幕上: 我输入1 ...…

查看全部问答>

串口通信的问题

我最近碰到2个问题,实在搞不懂,所以请教一下各位大哥。。。 1、我通过我的硬件键盘,按键,然后在串口调试助手上显示相应的键值,但是上面显示的数值前面,总有一些诡异的符号。比如我按6,就会显示66666。    我希望只显示出一 ...…

查看全部问答>

关于WINCE下MFC的工具栏的问题

我想在单文档MFC里面实现可移动和停靠的工具栏(就和打开我的设备里面的工具栏一样,前面有2个竖杠),可是CE下CToolBar没有EnableDocking这个方法,请问下是怎么实现的? 还有一个问题,在设置工具栏图标的时候,我是通过下面代码实现的,其中有 ...…

查看全部问答>

MC55 没有收到网络上发来的数据

在调试中,我的AT命令是 AT^SICS=0,conType,GPRS0↙ //选择GPRS工作模式 AT^SICS=0,user,gprs↙ //用户名称 AT^SICS=0,passwd,gprs↙ //密码 AT^SICS=0,apn,cmnet↙ //网络运营商 AT^SISS=1,srvType,socket↙ //服务类型为socket   ...…

查看全部问答>

上网iesimple提问

我在网上看到有人写CE的浏览器程序时,他的代码为: extern \"C\" DWORD __stdcall SetProcPermissions(DWORD); extern \"C\" DWORD __stdcall GetCurrentPermissions(); CWnd *pWnd = NULL; HWND hWnd; hWnd = ::FindWindow(NULL, _T(\"\\\ ...…

查看全部问答>

这样写那里错了?

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriObj,IN PUNICODE_STRING pRegPath) {   ...   //Attach Device   status = IoAttachDevice(g_DevObj,&DevName,&g_OldDevObj);   ... } NTSTATUS Tdi ...…

查看全部问答>

怎样可以使McBSP的FSX频率与CLKX同步

各位大虾,请问怎么使2812的FSX频率和CLKX频率不同步,我现在能够调出FSX频率,但是CLKX频率与FSX频率一直同步,就是同升同降。可是所需的芯片要求他们两个不同步,该怎么设置呢?谢谢各位了!!…

查看全部问答>

AD 9下 库等窗口的设置

     AD9下窗口设置在 察看->工作区面板->system路径下,有剪切板,元件库等选项,在窗口前打上对号即可在主界面下显示。…

查看全部问答>

各位大哥 能帮看下这段程序啥意思

module demux(         input clk_108m,         input clk_27m,         input[7:0] vin_data,         output reg[7:0] vout_data_ch0,     &n ...…

查看全部问答>