极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 12674|回复: 8

串口函数print首字母重复问题

[复制链接]
发表于 2015-2-11 19:54:04 | 显示全部楼层 |阅读模式
我自己写了个用于51的串口显示函数,工作还可以,有个头痛的问题,首字母重复。
  1. void serialprint(char  code  MESSAGE[])
  2. {
  3.         unsigned int a;
  4.         a=0;
  5.         while(MESSAGE[a] != '\0')
  6.         {
  7.                 SBUF = MESSAGE[a];                
  8.                 while(!TI);                               
  9.                 TI = 0;                                       
  10.                 ++a;                                            
  11.         }  
  12. }
复制代码

当我调用serialprint("Program start\n");
结果输出PProgram start

能用的办法都用过了
大家有遇到过吗?欢迎一起讨论
回复

使用道具 举报

发表于 2015-2-12 09:13:33 | 显示全部楼层
可以尝试在最后添加一个小延时
回复 支持 反对

使用道具 举报

发表于 2015-2-12 09:26:41 | 显示全部楼层
我對 51 不熟悉, 但邏輯上好像有點問題, 是否應該先測試輸出是否 ready, 然後才輸出?

  1. void serialprint(char  code  MESSAGE[])
  2. {
  3.         unsigned int a;
  4.         a=0;
  5.         while(MESSAGE[a] != '\0')
  6.         {
  7.                 while(!TI);                                
  8.                 SBUF = MESSAGE[a];               
  9.                 TI = 0;                                       
  10.                 ++a;                                            
  11.         }  
  12. }
复制代码

回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-2-12 16:30:48 | 显示全部楼层
加饭 发表于 2015-2-12 09:13
可以尝试在最后添加一个小延时

原来有个delay(10),调试的时候发现没什么用,才删掉的,前后没看到什么影响
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-2-12 16:31:29 | 显示全部楼层
Super169 发表于 2015-2-12 09:26
我對 51 不熟悉, 但邏輯上好像有點問題, 是否應該先測試輸出是否 ready, 然後才輸出?

void serialprint( ...

这句应该就是吧while(!TI);
回复 支持 反对

使用道具 举报

发表于 2015-2-12 17:12:21 | 显示全部楼层
Hackerpro 发表于 2015-2-12 16:31
这句应该就是吧while(!TI);


從網上的例子看, TI==1 是就代表 serial is ready.
所以, 我猜 while(!TI); 的作用, 應該是等待 serial ready.
但我不知道如果在 TI==0 時, 進行 串口輸出, SBUF = MESSAGE[a]; , 會有什麼後果.
我覺得,  while(!TI); 應該是放在 SBUF = MESSAGE[a]; 之前, 看來比較合理.
回复 支持 反对

使用道具 举报

发表于 2015-2-12 17:37:44 | 显示全部楼层
Hackerpro 发表于 2015-2-12 16:30
原来有个delay(10),调试的时候发现没什么用,才删掉的,前后没看到什么影响

delay(10) 好像太大了, 一般輸出的程式很少會加上 delay, 反而是接收的會.
因為有時接收程式是以停止了輸入去測試完結訊息, 當傳輸速度比較慢時, 會有可能因為下一個 byte 未送到而誤當作完結, 所以有可能會加上 1 ms 的 delay, 確保有足夠時間接收.  例如要用 9600 bps 發送 一個 byte, 單以理論速度去字計算, 就要 8/9600 ~ 1ms 了.  但再慢的也不會用到 10ms 吧 (除非你還在用 1200bps 或以下的傳輸速度).

但在發出訊號的一方, 比較少會加入 delay, 因為會造成訊號不連續, 而且增加傳輸時間.  就以 9600bps 為例, 用 1ms 發出一個 byte 再等 10ms, 原本用 100ms 可以發出 100 個 byte 的訊號, 就變成要 1.1s 了, 實在太不合理.
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-2-14 22:28:21 | 显示全部楼层
Super169 发表于 2015-2-12 17:12
從網上的例子看, TI==1 是就代表 serial is ready.
所以, 我猜 while(!TI); 的作用, 應該是等待 seria ...

有道理
不过这段程序的流程,这样写
SBUF = MESSAGE[a];//
while(!TI);//等待数据发送成功
TI = 0;//清楚数据传送标志
++a;
这只是输出,程序循环执行,应该还算合理吧?
有问题的话,可以详细讲一下吗?
多谢
回复 支持 反对

使用道具 举报

发表于 2015-2-15 19:11:59 | 显示全部楼层
Hackerpro 发表于 2015-2-14 22:28
有道理
不过这段程序的流程,这样写
SBUF = MESSAGE[a];//

由於我自己沒用過 51, 只好好奇看看, 如果有理解錯的地方, 請見諒.

我也明白你的思維是測試發送是否完成, 但問題在於第一個要發送的資料, 在發送之前並沒有做任何測試.
我在網上看到的解說 指 TI==1 代表 serial ready.
我的理解為  TI=0, 是告訴系統有資料要發送.  是在 SBUF 設定了數值後, 發送資料用.

在你的例子中, 發送完一個 byte 後, 再檢測 while (!TI);  待 TI 為 1 時, 再把它設定為 0, 就有可能出現第一個 char 重覆了.

假設在啟動時, serial 未 ready, TI 為 0, 由於你沒有檢查 TI 值就把第一個 byte 放到 SBUF, 然後等待.  
結果系統就會把第一個 byte 發出去.
之後把 TI 設為 0, 當時 SUBF 不會被清除, 還是保留了第一個 byte 的值, 就會把它再發一次出去了.
之後在第一個 byte 重發後, 才去到再設定第二個 byte, 然後再一直執行下去.  就會得出第一個 byte 重複了的後果.

以上只是我憑空想像, 沒有驗證過的.  
由於某止 arduino 板也有 serial 延遲的現象, 需要等待一下才可以使用, 所以我懷疑你的問題也可能相類似, 只是給果是多發了一次.

你有嘗試跟我的寫法把次序改變嗎?  看看是否可解決問題.
回复 支持 反对

使用道具 举报

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

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-17 12:00 , Processed in 0.045595 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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