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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

單片機IO引腳模擬串口程序

[復制鏈接]
跳轉到指定樓層
樓主
ID:299910 發表于 2025-2-18 14:27 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
#include"STC15W4K.H"
#define RECEIVE_MAX_BUTES 1              //最大接收字節數
unsigned char RecvBuf[16];                   //接收數據緩沖區
unsigned char RecvCount=0;                 //接收數據計數器
sbit T_TXD=P3^2;                               //發送數據引腳
sbit R_RXD=P3^3;                               //接收數據引腳
bit RXD_OK;                                        //數據接收完成標志,1接收正確 ,0接收錯誤

void delay104us()
{
   unsigned char i,j,k;
   for(i=1;i>0;i--)         // 注意后面沒分號
   for(j=3;j>0;j--)         // 注意后面沒分號
   for(k=189;k>0;k--);      // 注意后面有分號  
}
void delay52uS()                                      // 起始位結束后52uS采樣數據
{
   unsigned char i,j,k;
   for(i=1;i>0;i--)         // 注意后面沒分號
   for(j=3;j>0;j--)         // 注意后面沒分號
   for(k=93;k>0;k--);       // 注意后面有分號  
}
voidsenbyte(unsigned char dat)
{
  unsigned char i=8;        //發送8位數據
  T_TXD =0;                   //發送起始位
  delay104us();        
  while(i--)
  {
    if(dat&1)  T_TXD=1;
    else T_TXD=0;
    delay104us();
    dat>>=1;
  }
  T_TXD=1;                       //發送停止位
  delay104us();
}

unsigned char recvbyte()
{
  unsigned char i;
  unsigned char dat=0;             //接收到的數據
  RXD_OK=0;                          //字節數據接收正常標志位
  delay52us();                         //數據位中心位置讀取數據
  if(R_RXD==0)                      //確認起始位正常
  {
    delay104us();                     //起始位寬度
    for(i=0;i<8;i++)
    {
      if(R_RXD) dat|=(1<<i);
      delay104us();
    }
    if(R_RXD==1)                //確認停止位正常
    {
      RXD_OK=1;
    }
  }
  return dat;
}

void printfstr(char *pstr)        //串口打印字符串
{
  while(*pstr)
  {
    sendbyte(*pstr++);
  }
}
void main(void)
{
  unsigned char i;
  printfstr("模串口:STC15\r\n");
  while(1)
  {
    if(R_RXD==0)                                               //不斷檢測是否有起始位出現
    {
    recvbuf[recvcount]=recvbyte();
      if(RXD_OK ==1)                                          //一個字節接收正常
      {
        recvcount++;
        if(recvcount>=RECEIVE_MAX_BYTES)
        {
          recvcount=0;
          for(i=0;i<RECEIVE_MAX_BYTES;i++)
        {
          sendbyte( RecvBuf+1);                           //接收到的數據+1后發回
        }
        }
      }
    }
  }
}


這是一個IO引腳模擬串口通信的程序。
接收時先判斷P3.3接收端口是否有起始位低電平出現,如有則按照低位在前的順序接收8位數據,最后判斷是否有停止位高電平出現,如有則完成一個字節的接收,否則繼續等待。P3.2發送。
其中軟件編寫要嚴格按照異步通信的時序進行,每位傳送時間按通信速率9600bps計算為(1/9600)s=104.2us。時鐘:22.1184M。


這個程序也看了很久,重點是發送和接收函數。
發送函數比較好理解,接收函數不太容易。
迷惑的地方是: if(R_RXD) dat|=(1<<i);
                       1.為什么要左移,不是先發送低位的嗎?左移以后先發送的不就成高位了?
                       2.為什么要dat為什么要或1,或1以后接收的值不就變了?


其實是沒看明白這個語句:if(R_RXD) dat|=(1<<i);
                                       這樣的格式很容易讓我忽視if(R_RXD)去只思考dat|=(1<<i);
                                       沒有實踐就沒有發言權,拋棄條件去思考結果,就是耍流氓,肯定是思考不出結果的。
                                       這條語句說的是如果R_RXD==1,那么dat當前為就置1。
                                       另外1<<i,是指1左移i位,而不是i左移1位,同樣的錯誤真的很容易再犯,習慣性思維害人。


另:
#define RECEIVE_MAX_BUTES 1              //最大接收字節數


這條宏語句的值改成2后,輸出的結果并不是想像的那樣。
例如我輸入11 22 點擊發送,我認為會回復:12 23;實際上第一次點擊發送時串口助手是沒有接收信息的(接收窗口空白),點擊第二次才會接收到正確回復。
這是因為         
    for(i=0;i<RECEIVE_MAX_BYTES;i++)
        {
          sendbyte( RecvBuf+1);                           //接收到的數據+1后發回        }
這條語句的原因。

改成條件語句:
        SendByte(RecvBuf+1);           // 接收到得數據+1后發回
                                                i++;
                                                if(i>=RECEIVE_MAX_BYTES)
                                                {
                                                        i=0;
                                                }
自認為會完成改善,其實結果是點擊一次發送,接收到的只有一個字節的內容,第一次接收到12,第二次接收到23,再點就是12,再是23。

經思考:如果想點擊一次發送,接收到所有發送內容,需要增加發送數組函數,調用現有發送函數將發送內容存儲到數組中,main()函數中調用發送數組函數。語句沒有寫,所以暫時只用語言描述。
                                       
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:299910 發表于 2025-2-19 09:30 | 只看該作者
模擬串口就是把串口協議的幀格式用程序語句表達出來,然后放到IO口上去。這里說的幀格式就是信號在固定波特率的高低電平變化,即1,0的變化和波形寬度。幀格式還包含幀內每部分信號的含義,如起始位,數據,校驗,停止位,當然也都是1,0的變化和波形寬度。該程序沒有校驗部分。
回復

使用道具 舉報

板凳
ID:1096929 發表于 2025-2-20 15:22 | 只看該作者
jackduan2018 發表于 2025-2-19 09:30
模擬串口就是把串口協議的幀格式用程序語句表達出來,然后放到IO口上去。這里說的幀格式就是信號在固定波特 ...

解讀的非常好!
回復

使用道具 舉報

地板
ID:624769 發表于 2025-3-5 10:30 | 只看該作者
你既然用的 STC 單片機, IO 模擬串口,還是看 STC 官方例程吧, 你手上這個,不說毫無實用性吧,還會把編程思路帶歪,將來寫程序,只會單線程思考。
回復

使用道具 舉報

5#
ID:446156 發表于 2025-3-10 11:33 | 只看該作者
不建議用IO模擬串口時序,更不建議應用到項目中,純粹是吃飽了找罪受
回復

使用道具 舉報

6#
ID:108361 發表于 2025-4-17 13:25 | 只看該作者
稍微復雜的程序,實時性要求上來一點,這個IO模擬串口就容易翻車,現在串口成本很低了,不再是那個MCS51的時代了,需要與時俱進一點
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产精品99久久久久久大便 | 欧美三区| www.久久久.com | 亚洲精品一区二区久 | 亚洲精品9999久久久久 | 伊人网国产 | 999视频 | 日韩精品在线一区 | 亚洲视频免费在线观看 | 成人综合视频在线观看 | 国产精品久久久久久久模特 | 99re国产精品| 中文字幕亚洲精品在线观看 | 91视频在线 | 九九激情视频 | 欧美在线a| 国产精品96久久久久久 | 521av网站 | 性高朝久久久久久久3小时 av一区二区三区四区 | 二区成人 | 97日日碰人人模人人澡分享吧 | 欧美一区二区三区在线看 | 国产片侵犯亲女视频播放 | 福利av在线 | 成人小视频在线观看 | 欧美不卡在线 | 亚洲一区二区三区免费 | www.夜夜草| 国产乱码久久久久久 | 亚洲一区二区欧美 | 一区二区精品视频 | 精品二区 | 中文字幕亚洲无线 | 欧美日韩视频在线播放 | 精品国产乱码久久久久久闺蜜 | 美国一级黄色片 | 成人一区av | 欧美精品一区二区三 | 自拍偷拍第一页 | 亚洲一区二区三区四区五区午夜 | 亚洲 精品 综合 精品 自拍 |