每日一言
别怕起点低,持续向前的人,终会抵达山顶。
串口通信02_发送一个字符串给pc
复习一下:C 语言中没有专门的字符串类型,而是通过char类型的数组存储字符串,末尾以 空字符\0 作为结束标志。字符串本质上是由字符(char)组成的数组,而数组名在作为参数传递时会 “退化为” 指向数组首元素的指针。因此在你的代码中,sendString(char *str)函数接收指针类型的参数是正确的
char myStr[] = "helloworld";
sendString(myStr);
等价于 sendString("helloworld");
传进去的是 "h" 的指针。"helloworld" 在内存中是连续存储的,传指针其实就是告诉函数从哪里开始读取字符串。函数通过这个指针先找到 "h",然后顺着内存地址依次读取后续字符,直到碰到 '\0' 结束,这样就能完整发送 "helloworld"
其实就是把helloworld 中的h的指针传到char *str
介绍一下TI这个是发送中断请求标志位,他里面有一个特性叫做在停止位开始发送的时候由内部硬件置位,T1会由0置位变成1,但是位结束后,要软件将T1复位为0
- 当硬件完成最后一个停止位的发送时,才会将TI置 1。
- 因此,while(!TI)实际上是在等待整个 10 位帧的传输完成,而不仅仅是 8 位数据位。
- 一帧数据有10位 1个起始位,8位 数据位1个停止位
意思就是每次要等10位的最后一位结束的时候这个h
那么我们就会发现不应该是这样啊,因为我们串口助手返回到是helloworld,我们根据代码应该是h一个e一个l一个l一个0一个这样一个一个的但是实际却不是这样,所以百思不得其解????
解答:
串口调试助手连续显示 helloworld 的原因可以从 通信协议、软件实现 和 人类感知 三个层面来解释:
一、通信协议层面:字符是逐个发送的,但间隔极短
波特率决定传输速度
代码中设置的波特率为 9600bps,即每秒传输 9600 位。
发送一个字符(10 位 / 帧)所需时间为:
- 9600位/秒10位≈1.04毫秒
发送 "helloworld" 共 10 个字符,理论耗时约 10.4 毫秒。
字符间的实际间隔
每次发送完一个字符后,代码会:
-
- 等待 TI 置 1(约 1.04ms)
- 执行 TI=0 和 str++(几微秒,可忽略)
- 立即发送下一个字符
因此,字符间的间隔仅为 1.04ms,几乎是连续发送的。
二、软件实现层面:调试助手的显示机制
缓冲区与刷新策略
调试助手通常采用 行缓冲 或 实时刷新 模式:
-
- 行缓冲:收到换行符 \n(或特定长度)才显示。但你的代码未发送 \n,仍能显示,说明采用的是:
- 实时刷新:每收到一个字符就立即显示,并追加到已有内容末尾。
显示延迟
计算机屏幕的刷新频率通常为 60Hz(每 16.7ms 刷新一次)。
10.4ms 的传输时间远小于屏幕刷新间隔,因此:
-
- 所有字符在 一次屏幕刷新周期内 就已全部到达
- 人类视觉系统无法分辨如此短的时间间隔,感知为 “同时显示”
五、关键结论
- 硬件层面:字符是 串行、逐个发送 的,每个字符间有 1.04ms 间隔。
- 软件层面:调试助手 实时追加显示 每个收到的字符。
sendString 中的 while 循环本身执行很快,每个字符间隔仅 1.04ms,但由于人类视觉暂留效应和调试助手的刷新机制,你会感觉整个字符串是 “同时出现” 的,主要就是串口助手的刷新机制哈。
字符确实是逐个发送的,但由于调试助手的刷新机制和人类视觉的局限性,我们会看到 “连续显示” 的效果。这种现象本质上是时序差异造成的错觉,而非数据在 SBUF 中累积。
这个也非常好证实,关于串口的刷新率16ms,我们这样将,helloworld的长度读取远远超过一次串口刷新的频率16ms,那么就会有这样的效果,1s内有两条数据,因为误差的关系每条数据长度也不一样,16 X 2ms的话可存放的数据是远大于我写的字符串长度的,所以显示两条
解决疑惑了开心了