stm8 调试硬件I2C心得

发布者:一直333最新更新时间:2019-11-12 来源: 51hei关键字:stm8  调试硬件  I2C 手机看文章 扫描二维码
随时随地手机看文章

这次调试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 搞太多!! 想当然啦!没有仔细看官方的文档!
}

关键字:stm8  调试硬件  I2C 引用地址:stm8 调试硬件I2C心得

上一篇:STM8L驱动I2C类型的12864
下一篇:STM8L151x IWDG总结

推荐阅读最新更新时间:2024-11-09 20:32

MSP430F5529 DriverLib 库函数学习笔记(十一)I2C / IIC
平台:Code Composer Studio 10.3.1 MSP430F5529 LaunchPad™ Development Kit (MSP‑EXP430F5529LP) 硬知识 USCI的I2C模式 I2C概述 MSP430单片机的USCI_B模块能够支持I2C通信,能够为MSP430单片机与具有I2C接口的设备互连提供条件。软件上只需要完成I2C功能的配置,硬件能够完全实现I2C通信的功能。相比较利用GPIO软件模拟实现I2C操作,能够减少CPU的负荷。 MSP430单片机I2C模块特征及结构框图 (1)MSP430单片机I2C模块的主要特征  与Philips半导体I2C规范V2.1兼容;  7位
[单片机]
MSP430F5529 DriverLib 库函数学习笔记(十一)<font color='red'>I2C</font> / IIC
【STM32CUBEMX】 I2C Slave 实现
#背景 最近,在使用 STM32F030C8T6 做 I2C Slave 设备接口。在网上查了好多的资料,使用 STM32 硬件 I2C 的例程少之又少,对 STM32 硬件 I2C 的批判巨多,只能硬着头皮,自己一步一步摸索。 实际上,在这次硬件 I2C 调试之前,其实我已经通过 IO 模拟的方式实现了 I2C,但速率仅能实现 Standard-mode(up to 100 kbit/s)。对于 Fast-mode(up to 400 kbit/s),IO 模拟方式简直是无能为力。同时,由于 IO 模拟 I2C 时并没有充分的考虑架构,最终的实现结果是功能单一,客户满意度不好。 #I2C 实现方式 经过多次纠结和考虑,我决定采用
[单片机]
【STM32CUBEMX】 <font color='red'>I2C</font> Slave 实现
STM8单片机定时器驱动的深度解析
上一节给大家介绍了基于标准库STM8单片机GPIO的驱动,本节课主要给大家介绍一下STM8定时器的驱动。 我们先打开STM8L10x单片机的规格书,简单的了解一下STM8L10X单片机的定时器功能。 如果所示,STM8L10x单片机共有3个定时器,分别是TIM2、TIM3、TIM4. 其中TIM2和TIM3是16位的基本定时器,TIM4是8位定时器。 因TIM2和TIM3是16位,所以定时时间更长,功能更加强大,所以我们今天主要给大家介绍一下TIM2和TIM3; 我们以TIM2为例给大家介绍一下定时器功能。 STM8打开标准库文件夹,打开定时器例程 如上图所示,是标准库中定时器2的例程。 我们打开TIM2文件夹
[单片机]
<font color='red'>STM8</font>单片机定时器驱动的深度解析
关于I2C和SPI总线协议
IICvs SPI 现今,在低端数字通信应用领域,我们随处可见IIC (Inter-Integrated Circuit) 和 SPI (Serial Peripheral Interface)的身影。原因是这两种通信协议非常适合近距离低速芯片间通信。Philips(for IIC)和Motorola(for SPI) 出于不同背景和市场需求制定了这两种标准通信协议。 IIC 开发于1982年,当时是为了给电视机内的CPU和外围芯片提供更简易的互联方式。电视机是最早的嵌入式系统之一,而最初的嵌入系统是使用内存映射(memory-mapped I/O)的方式来互联微控制器和外围设备的。要实现内存映射,设备必须并联
[单片机]
关于<font color='red'>I2C</font>和SPI总线协议
IAR STM8工程中断的使用
IAR的工程建立比较简单,直接先建立工作区然后保存,不保存无法调试。把官方的INC放到工程目录下,在C/C++编辑连接包含这个文件的绝对路径(最简单的搞法)。把c文件添加进去就可以了,它的中断很简单你只要写一个如下的.c文件就能用了: #pragma vector=1 __interrupt void TRAP_IRQHandler(void) { } #pragma vector=2 __interrupt void TLI_IRQHandler(void) { } #pragma vector=3 __interrupt void AWU_IRQHandler(void) { } #pragma vector=
[单片机]
LPC_11C14平台I2C分析
1) IIC的初始化:复位IIC,使能IIC时钟单元,设置相应的I0口为IIC功能,清除应答位、起始位、中断位、IIC使能位,设置IIC传输速率,如果是从机的话,设置从机地址,IIC中断使能,最后启动IIC. 2) IIC的启动 uint32_t I2CStart( void ) { uint32_t timeout = 0; uint32_t retVal = FALSE; LPC_I2C- CONSET = I2CONSET_STA //设置起始位 /*循环等待起始位发送,设置超时时间*/ while( 1 )
[单片机]
STM8 普通IO配置模拟串口输出
刚接到上级的需求,由于stm8的串口资源较少,需要在原来工程的基础上加多一个io来输出串口数据。串口在每个学习单片机的人来说都是耳熟能详的东西。没有串口基础的同学建议先去学习串口知识点再来阅读。 首先我们知道串口数据配置里面包含:波特率、流控、数据起始位、数据位、奇偶校验位、停止位。针对本人经常选的配置为: 数据起始位默认都是1。数据实体如下: 由于本人选用波特率为115200 bps ,通过计算器算出每发送一位需要8.68us。这是一个非常低延时的值,这时候就要考虑写一个高精度的短延时的函数。那么问题来了,现在每次一个语句都是以微秒为单位的,任何写多一个语句和写少一个语句都会影响到这个延时函数,计算起来相当复杂。
[单片机]
<font color='red'>STM8</font> 普通IO配置模拟串口输出
51单片机I2C总线协议的实现
//-----------------------函数声明,变量定义------------------------------------------------------- #include reg51.h #include intrins.h sbit SDA=P1^0; // 将p1.0口模拟数据口 sbit SCL=P1^1; // 将p1.1口模拟时钟口 #define NUM 10 // 接收和发送缓存区的深度 #define delayNOP(); {_nop_();_nop_();_nop_();_nop_();}; unsigned char idata sendbuf ; // 数据发送缓冲区
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved