找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3377|回復(fù): 19
打印 上一主題 下一主題
收起左側(cè)

問一個(gè)單片機(jī)串口通訊數(shù)據(jù)丟位的問題

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
問題說明:我設(shè)置的波特率是9600,然后這個(gè)程序就是筆記本發(fā)送數(shù)據(jù)給單片機(jī),單片機(jī)馬上原封不動(dòng)地發(fā)送回去,但是在發(fā)送回來的時(shí)候發(fā)現(xiàn)缺位了,比如說我發(fā)送了一串?dāng)?shù)字2019060720055905,但是傳回來的時(shí)候有時(shí)候就少了一位數(shù)字成了201906072055905,我想問下這是程序?qū)懙挠惺裁磫栴}嗎,需要延時(shí)還是怎樣?
  1. /*************************************************單純串口通訊程序******************************************************/

  2. 先上程序
  3. #include <reg52.h>

  4. typedef unsigned char uchar;
  5. typedef unsigned int uint;

  6. void SendStr(uchar *s);
  7. void InitUART()

  8. void main()
  9. {
  10.         InitUART();
  11.         SendStr("UART test");
  12.         ES = 1
  13.         while(1)
  14.         {
  15.         }
  16. }

  17. void SendByte(uchar dat)
  18. {
  19.         SBUF = dat;
  20.         while(!TI)
  21.         TI=0;
  22. }

  23. void SendStr(uchar *s)
  24. {
  25.         while(*s != '\0')
  26.         {
  27.                 SendByte(*s);
  28.                 s++;
  29.         }               
  30. }

  31. void InitUART()
  32. {
  33.         SCON = 0x50
  34.         TMOD = 0x20;
  35.         TH1 = 0xFD;
  36.         TR1 = 1;
  37.         EA = 1;
  38. }

  39. void UART_SER() interrupt 4
  40. {
  41.         uchar temp;
  42.         if(RI)
  43.         {
  44.                 RI = 0;
  45.                 temp = SBUF;
  46.                 SBUF = temp;
  47.         }
  48.         if(TI)
  49.         {
  50.                 TI = 0;
  51.         }
  52. }
復(fù)制代碼

/******************************************串口中斷和定時(shí)器中斷**********************************************/

我這里需要串口給單片機(jī)傳時(shí)間數(shù)據(jù),也需要定時(shí)器定時(shí)給數(shù)碼管掃描顯示數(shù)據(jù),但是串口傳給單片機(jī)的數(shù)據(jù)好像也不對(duì),數(shù)碼管顯示的時(shí)間也不對(duì),所以我覺得是不是兩個(gè)中斷會(huì)相互干擾,因?yàn)榇谥袛鄡?yōu)先級(jí)比定時(shí)器0中斷低,所以我特別設(shè)置了IP = 0x10,但是也沒什么用,所以想來問下這其中到底有什么問題。下面是串口程序和定時(shí)器0程序。
  1. /**************串口程序***************/

  2. #include "UART.h"

  3. bit SetFlag;
  4. uchar time_buf2[16];

  5. void UART_Init()
  6. {
  7.         SCON = 0X50;// SCON:模式1, 8-bit UART,
  8.         TMOD |= 0x20;//TMOD: timer 1, mode 2, 8-bit
  9.         TH1  = 0xFD; // TH1:波特率 9600 2
  10.         TR1 = 1;
  11.         EA = 1;
  12.         ES = 1;
  13.         
  14. }


  15. void UART() interrupt 4
  16. {
  17.         uchar temp;
  18.         static uchar i;
  19.         if(RI)
  20.         {
  21.                 RI = 0;
  22.                 temp = SBUF;
  23.                 time_buf2[i] = temp;
  24.                 i++;
  25.                 if(i == 16)
  26.                 {
  27.                         i = 0;
  28.                         SetFlag = 1;
  29.                 }
  30.                 SBUF = temp;
  31.         }
  32.         if(TI)
  33.         {
  34.                 TI = 0;
  35.         }
  36. }

  37. /*************定時(shí)器0程序***************/

  38. #include "Display.h"
  39. #include "Delay.h"

  40. uchar code DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
  41. uchar code WeiMa[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
  42. uchar TempData[8];

  43. void Display(uchar firstbit, uchar num)
  44. {
  45.         static uchar i = 0;
  46.         
  47.         DataPort=0;   //Çå¿Õ¶ÎËø′æÖDμÄêy¾Y£¬·àÖ1óD½»ìæÖØó°
  48.         Seg_Latch = 1;
  49.         Seg_Latch = 0;
  50.         
  51.         DataPort = WeiMa[i+firstbit];
  52.         Bit_Latch = 1;
  53.         Bit_Latch = 0;
  54.                
  55.         DataPort = TempData[i];
  56.         Seg_Latch = 1;
  57.         Seg_Latch = 0;
  58.         
  59.         i++;
  60.         if(i == num)
  61.         {
  62.                 i = 0;
  63.         }
  64. }

  65. void Init_Timer0()
  66. {
  67.         TMOD |= 0x01;
  68.         TH0 = (65535-2000)/256;
  69.         TL0 = (65535-2000)%256;
  70.         EA = 1;
  71.         ET0 = 1;
  72.         TR0 = 1;
  73. }

  74. void Timer0() interrupt 1
  75. {
  76.         static uchar  num;
  77.         TH0 = (65535-500)/256;
  78.         TL0 = (65535-500)%256;
  79.         Display(0,8);
  80.         num++;
  81.         
  82.         if(num == 50)
  83.         {
  84.                 num = 0;
  85.                 ReadTimeFlag = 1;
  86.         }
  87.         
  88. }
復(fù)制代碼

下面就是串口通訊的錯(cuò)誤結(jié)果


        


question.png (12.26 KB, 下載次數(shù): 62)

question.png
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

來自 2#
ID:207421 發(fā)表于 2019-6-8 12:37 | 只看該作者
哪里抄的代碼,代碼中很多錯(cuò)誤
串口通信注意的是:
1. 晶振的誤差會(huì)導(dǎo)致數(shù)據(jù)發(fā)生錯(cuò)誤
2. 發(fā)送速度的快慢, 一個(gè)巴掌扇過去,那個(gè)人還沒來得及回復(fù)你,你又一個(gè)巴掌,他做啞巴得了,你白問了.
3. 沒有對(duì)數(shù)據(jù)進(jìn)行校驗(yàn)的函數(shù)
4. 接收或發(fā)送數(shù)據(jù)時(shí),  沒有進(jìn)行ES或EA處理,不就存在BUG了么
回復(fù)

使用道具 舉報(bào)

來自 3#
ID:557163 發(fā)表于 2019-6-8 22:57 | 只看該作者
這么改
1. 漏了個(gè)分號(hào)
void SendByte(uchar dat)
{
        SBUF = dat;
        while(!TI);  // 這里加上分號(hào)
        TI=0;
}

2.  中斷服務(wù)程序的收發(fā)看似沒問題,當(dāng)單片機(jī)的波特率比電腦略低時(shí),有一定的概率上一個(gè)字節(jié)發(fā)送還沒完下一個(gè)字節(jié)就收到了,簡單粗暴的改法是
把   SBUF=temp;
改為  SendByte(temp);
回復(fù)

使用道具 舉報(bào)

地板
ID:523537 發(fā)表于 2019-6-7 20:36 | 只看該作者
下面就是串口通訊的錯(cuò)誤結(jié)果
回復(fù)

使用道具 舉報(bào)

5#
ID:523537 發(fā)表于 2019-6-8 06:14 | 只看該作者
懇請各位大佬指點(diǎn)
回復(fù)

使用道具 舉報(bào)

6#
ID:94031 發(fā)表于 2019-6-8 08:35 | 只看該作者
發(fā)送雙方都要給對(duì)方留出處理信息的時(shí)間。
回復(fù)

使用道具 舉報(bào)

7#
ID:557425 發(fā)表于 2019-6-8 11:42 | 只看該作者

發(fā)送雙方都要給對(duì)方留出處理信息的時(shí)間。



回復(fù)

使用道具 舉報(bào)

8#
ID:259083 發(fā)表于 2019-6-8 17:09 | 只看該作者
可能是兩個(gè)單片機(jī)的波特率誤差導(dǎo)致的,你可以換幾組波特率試試,如果還是不行,最好加CRC 校驗(yàn)等校驗(yàn)?zāi)J竭M(jìn)行校驗(yàn),也可以考慮采用糾錯(cuò)碼來糾正誤碼!
回復(fù)

使用道具 舉報(bào)

9#
ID:93224 發(fā)表于 2019-6-8 17:30 | 只看該作者
數(shù)碼管用定時(shí)器0,串口的用定時(shí)器1
回復(fù)

使用道具 舉報(bào)

10#
ID:523537 發(fā)表于 2019-6-8 19:14 | 只看該作者
lwh999995 發(fā)表于 2019-6-8 12:37
哪里抄的代碼,代碼中很多錯(cuò)誤
串口通信注意的是:
1. 晶振的誤差會(huì)導(dǎo)致數(shù)據(jù)發(fā)生錯(cuò)誤

這個(gè)代碼是我參照例子寫的。首先我用的是11.0592MHz的晶振,波特率9600,我想問下需要延時(shí)要在哪里加_nop_()函數(shù)呢?另外我這個(gè)因?yàn)槭请娔X和單片機(jī)通訊,為了簡單一點(diǎn)所以沒有校驗(yàn),最后接受和發(fā)送數(shù)據(jù)的時(shí)候要關(guān)閉總中斷來避免多個(gè)中斷干擾數(shù)據(jù)傳輸嗎?
回復(fù)

使用道具 舉報(bào)

11#
ID:523537 發(fā)表于 2019-6-8 19:15 | 只看該作者
xuyaqi 發(fā)表于 2019-6-8 08:35
發(fā)送雙方都要給對(duì)方留出處理信息的時(shí)間。

那需要在哪里加延時(shí)函數(shù)呢?
回復(fù)

使用道具 舉報(bào)

12#
ID:523537 發(fā)表于 2019-6-8 19:16 | 只看該作者
lele5211314 發(fā)表于 2019-6-8 17:30
數(shù)碼管用定時(shí)器0,串口的用定時(shí)器1

我數(shù)碼管確實(shí)用的是定時(shí)器0,串口用的是定時(shí)器1啊
回復(fù)

使用道具 舉報(bào)

13#
ID:519141 發(fā)表于 2019-6-8 19:34 | 只看該作者
數(shù)據(jù)傳輸開始和完成都需要有確認(rèn)語句,方可進(jìn)行下一步的操作
回復(fù)

使用道具 舉報(bào)

14#
ID:523537 發(fā)表于 2019-6-9 14:06 | 只看該作者
he_37 發(fā)表于 2019-6-8 22:57
這么改
1. 漏了個(gè)分號(hào)
void SendByte(uchar dat)

分號(hào)是我復(fù)制粘貼上來的時(shí)候不小心刪掉了,不過我想了下你的改法應(yīng)該是對(duì)的,后面我嘗試了下也確實(shí)是對(duì)的,沒有出現(xiàn)過一次丟包,不過我又有了一個(gè)新問題,我先把代碼復(fù)制上來吧。void UART_SER() interrupt 4{
        uchar temp;
        if(RI)
        {
                RI = 0;
                temp = SBUF;
                SBUF = temp;
                /*下面兩個(gè)語句就是SendByte(uchar dat)的功能*/
                while(!TI);
                TI = 0;
        }
}


我是這么想的,電腦發(fā)送了一個(gè)8位數(shù)據(jù)過來,單片機(jī)接收端的SBUF接收了,然后我把數(shù)據(jù)轉(zhuǎn)給了發(fā)送端的SBUF,然后就是while(!TI);等待單片機(jī)發(fā)送完,但是我的串口中斷還是開的,那么當(dāng)單片機(jī)數(shù)據(jù)發(fā)送完TI置1,那么就會(huì)觸發(fā)中斷,然后又從中斷函數(shù)開頭uchar temp;開始,那么而且我也把TI=0;語句刪了,那么按道理就是應(yīng)該無限循環(huán)啊,為啥還會(huì)完整把整個(gè)數(shù)據(jù)接收完呢?我現(xiàn)在也搞不懂了。
回復(fù)

使用道具 舉報(bào)

15#
ID:523537 發(fā)表于 2019-6-9 14:12 | 只看該作者
he_37 發(fā)表于 2019-6-8 22:57
這么改
1. 漏了個(gè)分號(hào)
void SendByte(uchar dat)

更有意思的是我整個(gè)串口中斷程序沒有把TI置0也可以進(jìn)行串口通訊,只是也有丟位。
void UART_SER() interrupt 4
{
        uchar temp;
        if(RI)
        {
                RI = 0;
                temp = SBUF;
                SBUF = temp;
                /*下面兩個(gè)語句就是SendByte(uchar dat)的功能*/
                while(!TI);
        }
}

回復(fù)

使用道具 舉報(bào)

16#
ID:552783 發(fā)表于 2019-6-9 21:13 | 只看該作者
我覺得可以加個(gè)校驗(yàn)
回復(fù)

使用道具 舉報(bào)

17#
ID:222006 發(fā)表于 2019-6-10 01:01 | 只看該作者
波特率和檢驗(yàn)的問題,小老弟串口不要用人家的源碼呀,bug多得嚇?biāo)廊藛,還占資源
回復(fù)

使用道具 舉報(bào)

18#
ID:523537 發(fā)表于 2019-6-10 09:55 | 只看該作者
闊愛的釗釗 發(fā)表于 2019-6-10 01:01
波特率和檢驗(yàn)的問題,小老弟串口不要用人家的源碼呀,bug多得嚇?biāo)廊藛眩占資源

自己也是剛學(xué),很多東西都不太懂,只好在源碼上做簡單修改
回復(fù)

使用道具 舉報(bào)

19#
ID:243060 發(fā)表于 2019-6-10 11:39 | 只看該作者
串口通訊的時(shí)間是最主要的,要保證兩個(gè)通訊的頻率是一樣的,其次對(duì)于發(fā)射和接受的延時(shí)等待時(shí)間也要一致
回復(fù)

使用道具 舉報(bào)

20#
ID:523537 發(fā)表于 2019-6-11 00:03 | 只看該作者
yumer 發(fā)表于 2019-6-10 11:39
串口通訊的時(shí)間是最主要的,要保證兩個(gè)通訊的頻率是一樣的,其次對(duì)于發(fā)射和接受的延時(shí)等待時(shí)間也要一致

嗯嗯,確實(shí)是這樣,多謝指教了!
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表