標(biāo)題: 單片機(jī)任意I/O口模擬串口的程序,有一句代碼不明白 [打印本頁(yè)]

作者: 1017038201    時(shí)間: 2023-12-23 23:24
標(biāo)題: 單片機(jī)任意I/O口模擬串口的程序,有一句代碼不明白
請(qǐng)高人幫忙指點(diǎn),小弟勝感激
/****************《51單片機(jī)輕松入門(mén)-基于STC15W4K系列》配套例程 *************
/*  任意I/O口模擬串口,22.1184MHZ, 內(nèi)部R/C時(shí)鐘,9600bps  */

#include "STC15W4K.H"            // 包含 "STC15W4K.H"寄存器定義頭文件  
#define RECEIVE_MAX_BYTES  1     // 最大接收字節(jié)數(shù)

unsigned char RecvBuf[16];       // 接收數(shù)據(jù)緩沖區(qū)
unsigned char RecvCount=0;       // 接收數(shù)據(jù)計(jì)數(shù)器

sbit T_TXD=P3^2;                 // 發(fā)送數(shù)據(jù)的引腳
sbit R_RXD=P3^3;                 // 接收數(shù)據(jù)的引腳
bit RXD_OK;                         // 數(shù)據(jù)接收完成標(biāo)志,1(接收正確),0(接收錯(cuò)誤)
//******************************************/
void delay104uS()
{
  unsigned char i,j,k;
  for(i=1;i>0;i--)         // 注意后面沒(méi)分號(hào)
  for(j=3;j>0;j--)         // 注意后面沒(méi)分號(hào)
  for(k=189;k>0;k--);      // 注意后面有分號(hào)  
}
void delay52uS()               // 起始位結(jié)束后52uS采樣數(shù)據(jù)
{
  unsigned char i,j,k;
  for(i=1;i>0;i--)         // 注意后面沒(méi)分號(hào)
  for(j=3;j>0;j--)         // 注意后面沒(méi)分號(hào)
  for(k=93;k>0;k--);       // 注意后面有分號(hào)  
}
void SendByte(unsigned char Dat)
{
       unsignedchar i=8;      // 發(fā)送8 位數(shù)據(jù)
       T_TXD=0;                        // 發(fā)送起始位
       delay104uS();
       while(i--)
       {
              if(Dat&1)T_TXD=1;
              elseT_TXD=0;
              delay104uS();
              Dat>>=1;
       }
       T_TXD=1;                        // 發(fā)送停止位
       delay104uS();           // 延時(shí)   
}

unsigned char RecvByte()
{
       unsignedchar i;      
       unsignedchar Dat=0;            // 接收到的數(shù)據(jù)
       RXD_OK=0;                              // 字節(jié)數(shù)據(jù)接收正常標(biāo)志,0——錯(cuò)誤,1——正常
       delay52uS();                   // 數(shù)據(jù)位中心位置讀數(shù)據(jù)   
       if(R_RXD==0)                     // 確認(rèn)起始位正常
       {   
              delay104uS();               // 起始位寬度            
              for(i=0;i<8;i++)
              {
                     if(R_RXD)     Dat|=(1<<i);  /這一句不懂,求高人講解。
                     delay104uS();
              }   
              if(R_RXD==1)                // 確認(rèn)停止位正常
              {
                     RXD_OK=1;
              }
       }  
       returnDat;
}

//功能:串口打印字符串
//*****************************************/
void PrintfStr(char * pstr)
{
       while(*pstr)   
       {
              SendByte(*pstr++);
       }
}

//功能:函數(shù)主體
//******************************************/
void main(void)
{  
       unsignedchar i;     
       PrintfStr("模擬串口:STC15\r\n");
       while(1)                  
       {
              if(R_RXD==0)      // 死循環(huán)不斷檢測(cè)R_RXD是否有起始位出現(xiàn)
              {
                     RecvBuf[RecvCount]=RecvByte();
                     if(RXD_OK==1)                                     // 一個(gè)字節(jié)接收正常
                     {  
                            RecvCount++;
                            if(RecvCount>=RECEIVE_MAX_BYTES)
                            {
                                   RecvCount=0;
                                   for(i=0;i<RECEIVE_MAX_BYTES;i++)
                                   {
                                          SendByte(RecvBuf[ i]+1);        // 接收到得數(shù)據(jù)+1后發(fā)回
                                   }
                            }
                     }            
              }
       }
}

作者: wdgao    時(shí)間: 2023-12-24 01:19
這里要實(shí)現(xiàn)的是把串行收到的數(shù)一位一位地接收下來(lái)轉(zhuǎn)成并行的8位數(shù),這里只考慮收到是1的情況,沒(méi)考慮收到0的情況,應(yīng)該是少了一句程序。
作者: wulin    時(shí)間: 2023-12-24 07:30
Dat變量初始為0,用2進(jìn)制表示:00000000 8位都是0
當(dāng)for循環(huán),if(R_RXD)判斷R_RXD為真,也就是1,
Dat|=(1<<i); 等同Dat=Dat|(1<<i),結(jié)果一樣寫(xiě)法不同,
這段代碼就是把由低到高收到的1按位插入Dat。
例如:
Dat初始=0000 0000
收到字節(jié)1010 0101
逐次按位相或后Dat=1010 0101=0xa5
作者: 人中狼    時(shí)間: 2023-12-24 08:32
功能如樓上所說(shuō),不過(guò)DAT初始化為0,所以不考慮接收0的情況
作者: dream2023    時(shí)間: 2023-12-24 09:52
表示接收的數(shù)據(jù)或等于1右移i位
作者: bsjzb    時(shí)間: 2023-12-24 10:49
這段代碼是使用單片機(jī)STC15W4K模擬串口通信的程序。它通過(guò)模擬IO口實(shí)現(xiàn)了串口的發(fā)送和接收功能。  代碼中定義了一個(gè)接收數(shù)據(jù)緩沖區(qū)RecvBuf和一個(gè)接收數(shù)據(jù)計(jì)數(shù)器RecvCount。接收到的數(shù)據(jù)存儲(chǔ)在RecvBuf數(shù)組中,并根據(jù)接收計(jì)數(shù)器進(jìn)行處理。  在主函數(shù)main中,先發(fā)送一條初始化信息"模擬串口:STC15\r\n",然后進(jìn)入死循環(huán)不斷檢測(cè)R_RXD引腳是否有起始位出現(xiàn)。如果檢測(cè)到起始位,則調(diào)用RecvByte函數(shù)接收一字節(jié)數(shù)據(jù),并判斷接收是否正常。  如果接收正常,將接收到的數(shù)據(jù)存儲(chǔ)在RecvBuf數(shù)組中,并遞增接收計(jì)數(shù)器RecvCount。當(dāng)接收計(jì)數(shù)器達(dá)到最大接收字節(jié)數(shù)RECEIVE_MAX_BYTES時(shí),將接收到的數(shù)據(jù)加1后通過(guò)SendByte函數(shù)發(fā)送回去。  整個(gè)程序的功能是模擬串口通信,接收到的數(shù)據(jù)加1后再發(fā)送回去。  需要注意的是,這段代碼只是單片機(jī)的程序,無(wú)法在此環(huán)境中直接運(yùn)行。如果需要運(yùn)行,請(qǐng)將代碼下載到STC15W4K單片機(jī)開(kāi)發(fā)板上,并根據(jù)硬件連接情況進(jìn)行相應(yīng)的配置。
作者: rayin    時(shí)間: 2023-12-24 11:16
如果R_RXD=1, 就把Dat=Dat第0 到7 bit(根據(jù)i的循環(huán)置0-7)置1.
作者: 1017038201    時(shí)間: 2023-12-24 19:00
wulin 發(fā)表于 2023-12-24 07:30
Dat變量初始為0,用2進(jìn)制表示:00000000 8位都是0
當(dāng)for循環(huán),if(R_RXD)判斷R_RXD為真,也就是1,
Dat|=( ...

非常感謝這位老師的回復(fù)!
只是我感覺(jué)這句代碼有問(wèn)題,如果改動(dòng)一下就對(duì)了,也好理解。
if(R_RXD)
Dat |=(i<<1);
作者: man1234567    時(shí)間: 2023-12-25 08:16
1017038201 發(fā)表于 2023-12-24 19:00
非常感謝這位老師的回復(fù)!
只是我感覺(jué)這句代碼有問(wèn)題,如果改動(dòng)一下就對(duì)了,也好理解。
if(R_RXD)

沒(méi)有任何改動(dòng)哈,回車(chē)和縮進(jìn)對(duì)機(jī)器可有可無(wú)只是方便人類(lèi)閱讀罷了。
將多行放在一行是可行的,只要多行能正常運(yùn)行放在同一行也一樣行。
作者: Graves    時(shí)間: 2023-12-28 13:55
1017038201 發(fā)表于 2023-12-24 19:00
非常感謝這位老師的回復(fù)!
只是我感覺(jué)這句代碼有問(wèn)題,如果改動(dòng)一下就對(duì)了,也好理解。
if(R_RXD)

不知道是你復(fù)制錯(cuò)了還是故意改的,Dat |=(i<<1);不能這樣改,邏輯上錯(cuò)了,還得原本的Dat |=(1<<i);




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1