久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1824|回復: 16
打印 上一主題 下一主題
收起左側

51單片機UART通信-不理解接收程序 求分析

[復制鏈接]
跳轉到指定樓層
樓主
不理解邏輯。
單片機是通過010101這種的高低電平模擬二級制記錄數據的,這里是接收數據部分,PIN_RXD引腳的高低電平這里是如何控制的?

#include <reg52.h>

sbit PIN_RXD = P3^0;
sbit PIN_TXD = P3^1;

bit RxdEnd = 0;  //接收數據完成標記位
bit RxdOrTxd = 0;   //發送 和接收狀態標記位
unsigned char RxdBuf = 0;//接收數據緩沖區
unsigned char TxdBuf = 0;//發送數據緩沖區

void ConfigUART(unsigned int baud);
void StartRXD();
void StartTXD(unsigned char dat);

void main()
{
     EA = 1;
           ConfigUART(9600);
        
           while(1)
                 {
                   while(PIN_RXD);
                         StartRXD();
                         while(!RxdEnd);
                         StartTXD(RxdBuf+1);
                         while(!TxdEnd);
                 }
}

void ConfigUART(unsigned int baud)
{

   TMOD &= 0XF0;
         TMOD |= 0X02; //模式2 ,自動重裝模式
         TH0 = 256 - 11059200 / 12 / baud ;
         
}

void StartRXD()
{
   TL0 = 256 - ((256 - TH0)>>1);
         ET0 = 1;
         TR0 = 1;
         RxdEnd = 0;
         RxdOrTxd = 0;
}

void StartTXD(unsigned  char dat)
{

   TxdBuf = dat;
         TL0 = TH0; //發送整個數據
         ET0 = 1;
         TR0 = 1;
         PIN_TXD = 0;
         TxdEnd = 0;
         RxdOrTxd = 1;
}

void InterruptTimer0() interrupt 1
{
   static unsigned char cnt = 0;
        
         if(RxdOrTxd)
         {
            cnt ++ ;
                  if(cnt <= 8)
                        {
                           PIN _TXD = TxdBuf & 0x01;
                                 TxdBuf >>= 1;
                                 
                        }
                        else if(cnt == 9)
                        {
                          PIN _ TXD = 1;// STOP BIT
                        }
                        else
                        {
                           cnt = 0;
                                 TR0 = 0;
                                 TxdEnd = 1;
                        }
         }
         else //接收狀態
         {
            if(cnt == 0)
                        {
                           if(!PIN_RXD) // 確認是起始位
                                 {
                                    RxdBuf = 0; //接收RxdBuf清空
                                          cnt++;
                                 }
                                 else // 不是低電平,是干擾信號
                                 {
                                    TR0 = 0; //關中斷
                                 }
                        }
                        else if(cnt <= 8)
                        {
                            RxdBuf >>= 1; //接收數據是一位一位的接收
                                  if(PIN_RXD)
                                        {
                                          RxdBuf |= 0x80;
                                        }
                                        cnt ++;
                        }
      else
                        {
                            cnt = 0;
                                  TR0 = 0;
                                  if(PIN_RXD)
                                        {
                                          RxdEnd = 1;            
                                        }
                        }                                
         }

}

對于如下的:              RxdBuf >>= 1;
                                  if(PIN_RXD)
                                        {
                                          RxdBuf |= 0x80;
                                        }
                                        cnt ++;
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:1078938 發表于 2023-6-4 20:36 | 只看該作者
沙發,詳情見下面回復
回復

使用道具 舉報

板凳
ID:1078938 發表于 2023-6-4 20:48 | 只看該作者
我理解如下:
PIN_RXD是接收數據的引腳,1就是高,0就是低。
以接收 1010 0101為例子舉例。
1 . 數據確定是從起始位開始后,RxdBuf  = 0;
2.1  RxdBuf = 0 ,
       PIN_RXD這時候接收為高電平,RxdBuf |= 1000 0000 ===> RxdBuf = 1000 0000
2.2 PIN_RXD 接收低電平 ,RxdBuf = 0100 0000 (右移了一位)
2.3 PIN_Rxd接收高電平  , RxdBuff >>=  0010 0000  ==>1010 0000
2.4 PIN_Rxd低, RxdBuf  ==> 0101 0000
2.5 Pin_Rxd為低 , RxdBuf ==> 0010 1000
2.6 Pin_Rxd高, Rxdbuf ===>1001 0100
2.7 Pin_Rxd低,RxdBuf ===> 0100 1010
2.8 Pin_Rxd高, RxdBuf ==> 1010 0101

3.發送停止位
回復

使用道具 舉報

地板
ID:1078938 發表于 2023-6-4 21:18 | 只看該作者
為何串口發送1 ,接收81??

Snipaste_2023-06-04_21-17-35.jpg (166.51 KB, 下載次數: 38)

Snipaste_2023-06-04_21-17-35.jpg
回復

使用道具 舉報

5#
ID:1078938 發表于 2023-6-4 22:16 | 只看該作者
用邏輯分析儀抓波形,數據傳輸是對的,不理解為何是81?

Snipaste_2023-06-04_22-16-04.jpg (75.74 KB, 下載次數: 31)

Snipaste_2023-06-04_22-16-04.jpg
回復

使用道具 舉報

6#
ID:624769 發表于 2023-6-5 00:13 | 只看該作者
你接收程序有問題, 接收到起始位后,要 錯位 半個時間位才能 正確收到數據,即要在收到起始位后,經過1.3~ 1.5個位 的時間后 才開始接收 第一位數據。所以,廣泛會用 3分波特率 或4分波特率方式。
回復

使用道具 舉報

7#
ID:1078938 發表于 2023-6-5 00:16 | 只看該作者
但是如果使用51單片機的串口模塊,發送數據和接收數據是正確的。
#include <reg52.h>

void ConfigUART(unsigned int baud);

void main()
{
         EA = 1;
   ConfigUART(9600);
       
         while(1)
         {
          
         }
}

void ConfigUART(unsigned int baud)
{
   SCON = 0X50; //模式1  REN = 1 ,允許軟件接收
         TMOD &= 0X0F; //定時器1
         TMOD |= 0X20;//模式2
         TH1 = 256 - (11059200/12/32)/baud;
         TL1 = TH1;
         ET1 = 0; //T1只能做波特率發生器,關閉定時器1中斷
         TR1 = 1;
         ES = 1; //打開串口中斷
}

void InterruptUART() interrupt 4
{
   if(RI)
         {
           RI = 0;
                 SBUF = SBUF + 1;
         }
         if(TI)
         {
           TI = 0;
         }
}

Snipaste_2023-06-05_00-16-12.jpg (172.64 KB, 下載次數: 30)

Snipaste_2023-06-05_00-16-12.jpg
回復

使用道具 舉報

8#
ID:1078938 發表于 2023-6-5 01:30 | 只看該作者
188610329 發表于 2023-6-5 00:13
你接收程序有問題, 接收到起始位后,要 錯位 半個時間位才能 正確收到數據,即要在收到起始位后,經過1.3~ ...

接收部分,是從每個比特位的中間部分接收的,不太理解如何從1.3-1.5接收
回復

使用道具 舉報

9#
ID:213173 發表于 2023-6-5 06:05 | 只看該作者
哈蘭德 發表于 2023-6-4 20:48
我理解如下:
PIN_RXD是接收數據的引腳,1就是高,0就是低。
以接收 1010 0101為例子舉例。

軟件模擬串口示例
  1. #include "reg51.h"

  2. typedef unsigned char uchar;
  3. typedef unsigned int uint;

  4. sbit RXB = P3^0;         //定義UART TX/RX端口
  5. sbit TXB = P3^1;

  6. uchar TBUF,RBUF;
  7. uchar TDAT,RDAT;
  8. uchar TCNT,RCNT;
  9. uchar TBIT,RBIT;
  10. bit TING,RING;
  11. bit TEND,REND;
  12. uchar t, r;
  13. uchar buf[16];

  14. //初始UART模塊
  15. void UART_INIT()
  16. {
  17.         TING = 0;
  18.         RING = 0;
  19.         TEND = 1;
  20.         REND = 0;
  21.         TCNT = 0;
  22.         RCNT = 0;
  23.         TMOD = 0x02;   //8位自動重載12T模式
  24.         TL1 = 0xE8;                //設定定時初值(波特率1200)
  25.         TH1 = 0xE8;                //設定定時器重裝值
  26. //        TMOD = 0x00;   // 16位自動重載模式中的Time0
  27. //        AUXR = 0x80;   // 1T工作模式
  28. //        TL0 = BAUD;
  29. //        TH0 = BAUD>>8; // 初始Time0和設置重載值
  30.         TR0  = 1;      // tiemr0開始運行
  31.         ET0  = 1;      // 啟用Time0中斷
  32.         PT0  = 1;      // 提高定時中斷優先級
  33.         EA   = 1;      // 打開全局中斷開關
  34. }
  35. //
  36. void main()
  37. {
  38.         UART_INIT();   //初始UART模塊
  39.         while (1)
  40.         {              //用戶功能
  41.                 if (REND)   //接收完成標志為真
  42.                 {
  43.                         REND = 0;//接收完成標志清0
  44.                         buf[r++ & 0x0f] = RBUF;//保存在緩存中
  45.                 }
  46.                 if (TEND)
  47.                 {
  48.                         if (t != r)
  49.                         {
  50.                                 TEND = 0;
  51.                                 TBUF = buf[t++ & 0x0f];//發送緩存中數據
  52.                                 TING = 1;
  53.                         }
  54.                 }
  55.         }
  56. }
  57. //UART定時器中斷例程
  58. void tm0() interrupt 1 using 1
  59. {
  60.         if (RING)
  61.         {
  62.                 if (--RCNT == 0)
  63.                 {
  64.                         RCNT = 3;                   //重置發送波特率計數器
  65.                         if (--RBIT == 0)
  66.                         {
  67.                                 RBUF = RDAT;            //將數據保存到RBUF
  68.                                 RING = 0;               //停止接收
  69.                                 REND = 1;               //設置接收完成標志
  70.                         }
  71.                         else
  72.                         {
  73.                                 RDAT >>= 1;
  74.                                 if (RXB) RDAT |= 0x80;  //將RX數據轉換為RX緩沖區
  75.                         }
  76.                 }
  77.         }
  78.         else if (!RXB)
  79.         {
  80.                 RING = 1;                       //設置開始接收標志
  81.                 RCNT = 4;                       //初始接收波特率計數器
  82.                 RBIT = 9;                       //initial receive bit number (8 data bits + 1 stop bit)
  83.         }                                                                                          //初始接收比特數(8個數據位+ 1個停止位)
  84.         if (--TCNT == 0)
  85.         {
  86.                 TCNT = 3;                       //重置發送波特率計數器
  87.                 if (TING)                       //判斷是否發送
  88.                 {
  89.                         if (TBIT == 0)
  90.                         {
  91.                                 TXB = 0;                //發送起始位
  92.                                 TDAT = TBUF;            //加載數據 TBUF 到 TDAT
  93.                                 TBIT = 9;               //initial send bit number (8 data bits + 1 stop bit)
  94.                         }                                                                        //初始發送比特數(8個數據位+ 1個停止位)
  95.                         else
  96.                         {
  97.                                 TDAT >>= 1;             //將數據轉換到CY
  98.                                 if (--TBIT == 0)
  99.                                 {
  100.                                         TXB = 1;
  101.                                         TING = 0;           //停止發送
  102.                                         TEND = 1;           //設置發送完成標志
  103.                                 }
  104.                                 else
  105.                                 {
  106.                                         TXB = CY;           //將CY寫入TX端口
  107.                                 }
  108.                         }
  109.                 }
  110.         }
  111. }
復制代碼
回復

使用道具 舉報

10#
ID:195496 發表于 2023-6-5 09:25 | 只看該作者
用硬件接收,看你的狀態,還沒有完全搞明白串口通信與接收的采樣位關系。先用硬件串口吧,軟件要實現一時半會你可能調試不出結果。
回復

使用道具 舉報

11#
ID:1064915 發表于 2023-6-5 10:16 | 只看該作者
有邏輯分析儀,厲害
回復

使用道具 舉報

12#
ID:1078938 發表于 2023-6-5 10:32 | 只看該作者
大漠落日 發表于 2023-6-5 09:25
用硬件接收,看你的狀態,還沒有完全搞明白串口通信與接收的采樣位關系。先用硬件串口吧,軟件要實現一時半 ...

就是接收部分的    TL0 = 256 - ((256 - TH0)>>1);  不理解怎么改
回復

使用道具 舉報

13#
ID:1064915 發表于 2023-6-5 10:35 | 只看該作者
wulin 發表于 2023-6-5 06:05
軟件模擬串口示例

TL1 = 0xE8; T0可以用嗎
回復

使用道具 舉報

14#
ID:1078938 發表于 2023-6-5 10:39 | 只看該作者
wulin 發表于 2023-6-5 06:05
軟件模擬串口示例

確實可以,把波特率改為1200就可以。

Snipaste_2023-06-05_14-51-58.jpg (144.69 KB, 下載次數: 50)

Snipaste_2023-06-05_14-51-58.jpg
回復

使用道具 舉報

15#
ID:123289 發表于 2023-6-5 10:43 | 只看該作者
【PIN_RXD引腳的高低電平這里是如何控制的?】
由發送方進行控制。
控制的邏輯依據串行協議。
接收方由單片機內部嵌入的UART硬件完成,當然也會按照同樣的協議進行解碼。
回復

使用道具 舉報

16#
ID:624769 發表于 2023-6-5 11:26 來自手機 | 只看該作者
哈蘭德 發表于 2023-6-5 01:30
接收部分,是從每個比特位的中間部分接收的,不太理解如何從1.3-1.5接收

參考9樓給你的代碼,這是典型的3分波特率,每個位的間隔為3次中斷,收到起始信號時為4個時間中斷,就是從1.333的位置開始接受。
回復

使用道具 舉報

17#
ID:1078938 發表于 2023-6-6 09:43 | 只看該作者
wulin 發表于 2023-6-5 06:05
軟件模擬串口示例
  1.   if (RING)
  2.         {
  3.                 if (--RCNT == 0)
  4.                 {
  5.                         RCNT = 3;                   //重置發送波特率計數器
  6.                         if (--RBIT == 0)
  7.                         {
  8.                                 RBUF = RDAT;            //將數據保存到RBUF
  9.                                 RING = 0;               //停止接收
  10.                                 REND = 1;               //設置接收完成標志
  11.                         }
  12.                         else
  13.                         {
  14.                                 RDAT >>= 1;
  15.                                 if (RXB) RDAT |= 0x80;  //將RX數據轉換為RX緩沖區
  16.                         }
  17.                 }
  18.         }
  19.         else if (!RXB)
  20.         {
  21.                 RING = 1;                       //設置開始接收標志
  22.                 RCNT = 4;                       //初始接收波特率計數器
  23.                 RBIT = 9;                       //initial receive bit number (8 data bits + 1 stop bit)
  24.         }                                                                                          //初始接收比特數(8個數據位+ 1個停止位)
復制代碼

我的理解:         波特率就是傳輸二進制的速率,這里選用的是1200,每秒傳送1200個比特位,1 / 1200 = 833 us,833us傳輸一個比特位。每次溢出后進入中斷,代表已經時間已經達到一個碼元位,如果向下面理解那么傳輸的比特不應該是對的????

接收代碼的理解:
    1.當遇到低電平RXB的時候,代表UART通信開始接收,先把RING = 1 , 比特計數器RCNT = 4 , 比特數RBIT = 9。
    2.下次再進入中斷,RCNT自動減1,經過4次中斷進入后,直到RCNT = 0,然后賦值RCNT = 3,比特數RBT減少一位,這時候認為數據是有效的,把RXB電平的數據記錄到RDAT中。
    3. 每個比特位都需要RCNT減3次后才把RXB的數據賦值給RDAT。同時,把RBIT數據也減1,直到等于0就代表接收完畢,然后恢復RING = 0。








回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 午夜视频在线播放 | 天天干天天爽 | 综合久久av | 午夜理伦三级理论三级在线观看 | 欧美精产国品一二三区 | 欧美日韩一区二区在线观看 | 九色在线观看 | 日韩欧美中文字幕在线观看 | 99国内精品久久久久久久 | 久久国产精品首页 | 成人亚洲精品久久久久软件 | 免费看黄色视屏 | 蜜桃精品在线 | 成人av网站在线观看 | 国内精品视频在线 | 中国一级特黄毛片大片 | 九九久久精品视频 | 中文字幕中文字幕 | av资源网站 | 天天操天天干天天透 | 欧美男人天堂 | 久久久视 | 欧美日韩国产精品 | 日本精品国产 | h片在线播放 | 国产精品视频网址 | 久久麻豆精品 | 四虎影院在线播放 | 国产免费拔擦拔擦8x高清 | 91秦先生艺校小琴 | 亚洲三级在线 | 大象视频一区二区 | 欧美日韩在线观看一区 | 国产一区二区成人 | 国产福利91精品一区二区三区 | 亚洲国产精品suv | 成人av网页| 日韩一区在线播放 | 国产第一页在线播放 | 成人久久18免费网站图片 | 精品久久国产 |