找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1044|回复: 14
打印 上一主题 下一主题
收起左侧

关于51单片机模拟串行通信协议波形的探讨

[复制链接]
跳转到指定楼层
楼主
本帖最后由 Kituro 于 2022-1-25 01:17 编辑


  1. void I2C_SendOneByte(unsigned char TxValue)
  2. {
  3.         
  4.     unsigned char i, k;

  5.     for(i=0; i<8; i++)
  6.     {
  7.         TxValue <<= 1;               //Data is transferred with MSB first.
  8.         k = CY;
  9.         SDA = k;                         //If MSB is 1, the Carry Flag (CY) will be set to 1 after left logical shift, and vice versa.
  10.         delay();
  11.         SCL = 1;
  12.         delay();  
  13.         SCL = 0;
  14.     }
  15. }
复制代码
使用以上程序发送数据, 波形如下:(端口悬空未连接设备, 探头衰减10X)
单片机型号STC8A8K64S4A12, 输出为准双向口(传统8051模式),启用内部4.1K上拉电阻, IO模式图:









可以看到, 波形有三个阶梯(欠幅), 最下方的波形为0V, 中间的波形为约为2.5v, 最高的波形就是高电平5v
这是为什么? 为什么波形会欠幅?

我有想过可能是变量移位, 取数据等消耗了时间, 但如果这样也不应该欠幅啊, 为什么会有一个2.5v的电压出现?

为什么发送数据的波形会出现欠幅现象?
------------------------------------------------------------------------------------------------------------------------------------------
今天又用Keil的debug功能调试了一下程序, 发现一个问题:先上汇编程序:

整个字节的发送过程太过繁琐, 这里精简一下, 只考虑发送一个bit的情况, 当发送"1"(即高电平)时
当程序运行到SDA = 1时, 输出波形没有预想中被拉高到5v, 反而处于2.5v左右的不确定状态, 有较大波动



但当程序运行至"SCL = 0"处时, SDA才被稳定拉高至5V







整个发送中, 以上过程不断循环, 最终导致了波形产生欠幅现象

综上, 我最搞不清楚的一点是:为什么执行SDA = 1之后SDA管脚会处于不确定状态? 而在执行完与SDA毫不相干的"SCL = 0"语句后SDA又被拉高?
是上拉电阻的原因吗? 但如果是因为没有上拉电阻的话, SDA又为什么能被拉高到5V呢?
本人百思不得其解, 如若得君相助, 定感激不尽!







51hei图片_20220123222634.jpg (3.2 MB, 下载次数: 19)

51hei图片_20220123222634.jpg
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:624769 发表于 2022-1-24 00:06 | 只看该作者
首先,如果是发送  0xff
方法1 是正确发送的,
方法2 发送出去是0xfe

其次,哪种方法简单,你是你以为你看上去觉得简单,而是单片机实际运行起来简单。很明显,单片机执行方法1才是最简单的。

最后, CY 是PSW里的一个位没错,但是就指令来讲,他是直接操作的C寄存器。也是C语言方式下,操纵C寄存器的唯一方式。
从字节中提取位,无论如何都是避不开C寄存器的,所以,直接从C寄存器取值是最理想的一种方式,即便你把C语言代码整的再怎么好看,最后还是要把位变量移到C寄存器然后再从C寄存器赋值给IO,你可以编译后看看编译后的指令,最终还是需要  MOV   xxx,C  来给IO赋值。
回复

使用道具 举报

板凳
ID:739727 发表于 2022-1-24 01:03 | 只看该作者
法2 发送的数据不对的,需要先发送再移位
回复

使用道具 举报

地板
ID:884307 发表于 2022-1-24 11:26 | 只看该作者
AAA_MCU 发表于 2022-1-24 01:03
法2 发送的数据不对的,需要先发送再移位

感谢, 这一点没想到!
回复

使用道具 举报

5#
ID:884307 发表于 2022-1-24 11:26 | 只看该作者
188610329 发表于 2022-1-24 00:06
首先,如果是发送  0xff
方法1 是正确发送的,
方法2 发送出去是0xfe

明白了! 学好汇编还是很重要的, 那为什么波形会呈现阶梯状呢?
回复

使用道具 举报

6#
ID:606226 发表于 2022-1-24 12:15 | 只看该作者
你这个电路是什么样子呢,I2C上有挂什么器件吗
回复

使用道具 举报

7#
ID:884307 发表于 2022-1-24 13:01 | 只看该作者
c00156155 发表于 2022-1-24 12:15
你这个电路是什么样子呢,I2C上有挂什么器件吗

没有, 我把SDA映射到P1.4, SCL映射到P1.5, 全部悬空没有挂设备, 我示波器探头开的1X, 输入阻抗相对小, 直接测量P1.5管脚
回复

使用道具 举报

8#
ID:624769 发表于 2022-1-24 13:30 | 只看该作者
Kituro 发表于 2022-1-24 13:01
没有, 我把SDA映射到P1.4, SCL映射到P1.5, 全部悬空没有挂设备, 我示波器探头开的1X, 输入阻抗相对小, 直 ...

如果你是 89C51 的话, 模拟IIC通信, 应当接在P0总线,并且4.7K上拉。
如果是增强型51的话,应该开启IO的开漏模式,并且4.7K上拉。

用准双向口驱动 IIC设备比较容易发生欠幅问题,因为准双向口的内部弱上拉(约50K)和IIC器件内部的弱下拉(约50K),刚好可以形成一个1/2分压电压。
回复

使用道具 举报

9#
ID:884307 发表于 2022-1-24 21:17 | 只看该作者
188610329 发表于 2022-1-24 13:30
如果你是 89C51 的话, 模拟IIC通信, 应当接在P0总线,并且4.7K上拉。
如果是增强型51的话,应该开启IO ...

非常感谢您的回复! 我的帖子更新了一下, 有更详细的描述, 请您看一下, 谢谢!
回复

使用道具 举报

10#
ID:301191 发表于 2022-1-25 19:26 | 只看该作者
顶一下
回复

使用道具 举报

11#
ID:624769 发表于 2022-1-26 03:37 | 只看该作者
Kituro 发表于 2022-1-24 21:17
非常感谢您的回复! 我的帖子更新了一下, 有更详细的描述, 请您看一下, 谢谢!

几点,
首先,代码过于复杂,
你不需要  k = CY; 然后  SDA = k;
而是应该直接  SDA = CY;

之前回复我已经有说,准双向模式, 会在  弱上拉极弱上拉之间切换,所以,是不稳定的,IIC器件都是有内部下拉的,所以IO口,最好是开漏模式 + 4.7K上拉, 既然你用的是 STC8系列, 那么,你也不需要改电路,他是内置有 4.7K上拉的。你翻一下手册,把内置4.7K上拉打开,然后,用开漏模式驱动,应该就能解决这个问题了。
回复

使用道具 举报

12#
ID:884307 发表于 2022-1-26 16:36 | 只看该作者
188610329 发表于 2022-1-26 03:37
几点,
首先,代码过于复杂,
你不需要  k = CY; 然后  SDA = k;

非常感谢帮助, 这个变量k是我在调试的时候用来追踪SDA状态用的, 实际应用不会这么写
使用P1.4口输出波形
我启用了上拉电阻和开漏模式后仍然输出这个波形, 还有救么?









回复

使用道具 举报

13#
ID:624769 发表于 2022-1-26 18:07 | 只看该作者
Kituro 发表于 2022-1-26 16:36
非常感谢帮助, 这个变量k是我在调试的时候用来追踪SDA状态用的, 实际应用不会这么写
使用P1.4口输出波形 ...

IIC 通信,  SDA, SCL 两个引脚都需要上拉,开漏驱动,不是说,设一个就可以的。
假如是控制 DS1307的话,连SWQ引脚都需要上拉。
你虽然SDA的波跳动,但是,很大的可能是因为CLK的上拉不足。
另外,IIC器件的VCC入口一般需要 104电容滤波,如果是类似 TM系列的LED驱动 芯片, 还需要10uf以上的电解电容,不然都可能造成IIC 传输异常。
回复

使用道具 举报

14#
ID:884307 发表于 2022-1-26 19:29 | 只看该作者
188610329 发表于 2022-1-26 18:07
IIC 通信,  SDA, SCL 两个引脚都需要上拉,开漏驱动,不是说,设一个就可以的。
假如是控制 DS1307的话 ...

好吧, 谢谢您的指点!
回复

使用道具 举报

15#
ID:185846 发表于 2022-1-26 22:34 | 只看该作者
你可以在输出时把SDA设置成推挽模式;在读取数据时设置成IO口模式(如果内部上拉电阻足够小的话);最好外部上拉电阻要接上
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表