欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

標題: 請教單片機串口通信方面的問題,希望做過這一方面的大佬能解答一下 [打印本頁]

作者: mdzzlsf    時間: 2018-4-23 15:47
標題: 請教單片機串口通信方面的問題,希望做過這一方面的大佬能解答一下
最近正在用51單片機做串口通信,已經完成了基本的發送接收。想做更深入一點:1.對接收到的數據能進行解析,比如串口助手發送了一組電壓電流數據:V1012A0022,要把它還原成電壓1.012伏,電路0.022A,用兩數碼管顯示出來。
2.發送數據能不用中斷嗎?現在用的是interrupt 0(外部中斷0),能不能不用中斷,用單片機上任意的一個口控制發送。


作者: 小貓貓愛吃魚    時間: 2018-4-23 17:28
你好!如果用任意一個口做串口發送,是可以做到的,用軟件模擬串口就行。
作者: wulin    時間: 2018-4-23 19:37
你可以自定義通訊協議,比如:數據頭0xff,電壓整數0x01,電壓小數0x0c,電流整數0x00,電流小數0x16,數據尾為有效數據和0x23,0xff 0x01 0x0c 0x00 0x16 0x23,由6組8位數據組成一個數據串,下位機收到數據串后保存在緩存中,根據數據頭尾判斷數據傳輸正確后對有效數據解析,提供給顯示模塊。
作者: 緒爺    時間: 2018-4-23 19:58
發數據不需要中斷接收需要
作者: mdzzlsf    時間: 2018-4-24 12:11
wulin 發表于 2018-4-23 19:37
你可以自定義通訊協議,比如:數據頭0xff,電壓整數0x01,電壓小數0x0c,電流整數0x00,電流小數0x16,數據 ...

通過狀態機實現么?能否給一個大概的代碼框架么,因為剛接觸這方面,個人編程也不熟練,沒法直接根據您提供的思路搭建出來。
作者: wulin    時間: 2018-4-24 14:41
mdzzlsf 發表于 2018-4-24 12:11
通過狀態機實現么?能否給一個大概的代碼框架么,因為剛接觸這方面,個人編程也不熟練,沒法直接根據您提 ...

沒有你想的那么復雜,給你寫一個示例程序參考,經TX-1C實驗板與串口助手驗證無誤。
#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
sbit dula=P2^6;                        //段選
sbit wela=P2^7;                        //位選
uchar code table[]={                //共陰數碼管0~F、U數組
        0x3f,0x06,0x5b,0x4f,
        0x66,0x6d,0x7d,0x07,
        0x7f,0x6f,0x77,0x7c,
        0x39,0x5e,0x79,0x71,0x3e};
uchar table0[] ="OK\n";        //用于串口助手返回驗證
uchar table1[]="ERROR\n";//用于串口助手返回驗證
uchar rec_buf[6];                        //緩存
uint swan,wan,qian,bai,shi,ge;//數碼管顯示位
bit flag=0;                                        //接收完成標
/*************初始化串口**************/
void InitUART()                //9600bps@11.0592MHz
{
        PCON &= 0x7F;                //波特率不倍速
        SCON = 0x50;                //8位數據,可變波特率
        TMOD= 0x20;                        //設定定時器1為8位自動重裝方式
        TL1 = 0xFD;                        //設定定時初值
        TH1 = 0xFD;                        //設定定時器重裝值
        ET1 = 0;                                //禁止定時器1中斷
        TR1 = 1;                                //啟動定時器1
        EA = 1;                                //開總中斷
        ES = 1;                                //開串口中斷
}
/**********串口發送函數*************/
void SendOneByte(uchar c)
{
    SBUF = c;                //發送數據
    while(!TI);        //等待發送完成
    TI = 0;                        //發送中斷請求標志位清0
}
/************數據解析函數*************/
void analysis()
{
        uchar i;                        //臨時變量
        if(flag==1)                //一幀數據串接收完成
        {
                ES=0;                        //關串口中斷
                flag=0;                //接收完成標志清0
                if(rec_buf[5]==rec_buf[1]+rec_buf[2]+rec_buf[3]+rec_buf[4])//驗證數據和,超出8位溢出舍棄
                {
                        for(i=0;i<3;i++)
                        SendOneByte(table0);//返回OK
                }
                else
                {
                        for(i=0;i<6;i++)
                                SendOneByte(table1);//返回ERROR
                        rec_buf[0]=rec_buf[1]=rec_buf[2]=rec_buf[3]=rec_buf[4]=rec_buf[5]=0;//清除緩存數據
                }
                ES=1;                //開串口中斷
        }
}
/*************數據分解***************/
void Transformation()
{
        static uint i=0;
        static bit j=0;
        i++;
        if(i==7500)                //計數延時切換顯示內容
        {
                i=0;
                j=~j;
        }
        if(j==0)                        //換算電壓
        {
                swan = rec_buf[1]%100/10;                        // 十萬位
                wan  = rec_buf[1]%10;                                // 萬位
                qian = rec_buf[2]%1000/100;                // 千位
                bai  = rec_buf[2]%100/10;                        // 百位
                shi  = rec_buf[2]%10;                                // 十位
                ge   = 16;                                                                // 個位"V"
        }
        else                        //換算電流
        {
                swan = rec_buf[3]%100/10;                        // 十萬位
                wan  = rec_buf[3]%10;                                // 萬位
                qian = rec_buf[4]%1000/100;                // 千位
                bai  = rec_buf[4]%100/10;                        // 百位
                shi  = rec_buf[4]%10;                                // 十位
                ge   = 10;                                                                // 個位"A"
        }
}
/**********6位數碼管顯示程序************/
void display()
{
        static uchar k=0;                        //分時顯示變量
        switch(k)
        {
                case 0:
                   dula=0;
                   P0=table[swan];                //顯示十萬位段碼
                   dula=1;
                   dula=0;
               
                   wela=0;
                   P0=0x7e;                                                //顯示十萬位碼
                   wela=1;
                   wela=0;
                        k++;
                 break;       

                case 1:
                   dula=0;
                   P0=table[wan]|0x80;                //顯示萬位段碼+小數點
                   dula=1;
                   dula=0;
               
                   wela=0;
                   P0=0x7d;                                                //顯示萬位位碼
                   wela=1;
                   wela=0;
                        k++;
                 break;       

                case 2:
                   P0=table[qian];                        //顯示千位段碼
                   dula=1;
                   dula=0;
               
                   P0=0x7b;                                                //顯示千位位碼
                   wela=1;
                   wela=0;
                        k++;
                 break;       

                case 3:
                   P0=table[bai];                        //顯示百位段碼
                   dula=1;
                   dula=0;
               
                   P0=0x77;                                                //顯示百位位碼
                   wela=1;
                   wela=0;
                        k++;
                 break;       

                case 4:
                   P0=table[shi];                        //顯示十位段碼
                   dula=1;
                   dula=0;
               
                   P0=0xef;                                                //顯示十位位碼
                   wela=1;
                   wela=0;
                        k++;
                 break;       

                case 5:
                   P0=table[ge];                        //顯示個位段碼
                   dula=1;
                   dula=0;
               
                   P0=0xdf;                                                //顯示個位位碼
                   wela=1;
                   wela=0;
                        k=0;
                 break;       
        }
}
/**************主程序**************/
void main()
{
        InitUART();                //初始化串口
        while(1)
        {
                analysis();        //數據解析
                Transformation();//數據分解
                display();        //數碼管顯示
        }
}
/*********串口中斷服務程序**********/
void UARTInterrupt() interrupt 4
{
        static uchar num=0;        //靜態計數變量
        RI=0;                                                //接收中斷請求標志位清0
        rec_buf[num]=SBUF;        //接收到的數據串保存在緩存數組
        if(rec_buf[0]==0xff)        //驗證數據頭(起始位)
        {
                num++;
                if(num>=6)
                {
                        flag=1;                        //接收完成標志置1
                        num=0;                        //計數變量清0
                }
        }
}
//0xff 0x01 0x0c 0x00 0x16 0x23



作者: sirf3    時間: 2018-4-24 16:16
接收要用中斷,因為接收緩沖區只有一個字節,不停下手頭的事去接收,SBUF會被下一個字節改變。
發送不用中斷。

將發送的數據包裝成一個個的數據幀,加上幀頭和校驗,一般還是很可靠的。
作者: mdzzlsf    時間: 2018-4-25 11:40
wulin 發表于 2018-4-24 14:41
沒有你想的那么復雜,給你寫一個示例程序參考,經TX-1C實驗板與串口助手驗證無誤。
#include
#define  ...

謝謝您的解答!
作者: ttaniscy    時間: 2019-9-5 10:36
謝謝LZ分享,借鑒下
作者: dzq123    時間: 2019-9-7 20:17
緒爺 發表于 2018-4-23 19:58
發數據不需要中斷接收需要

請教一下怎么發送?我每次發送數據都上位機都亂碼了




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