找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

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

單片機(jī)串口如何接收上位機(jī)不斷發(fā)送的數(shù)據(jù)幀,并將該幀的有效數(shù)據(jù)提取出來?

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:49578 發(fā)表于 2018-8-16 17:29 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
各位大蝦:本人菜鳥請(qǐng)教一個(gè)問題,單片機(jī)如何接送串口不斷發(fā)送的數(shù)據(jù)幀,并將該幀的有效數(shù)據(jù)提取出來,請(qǐng)賜教一個(gè)完整程序。
注:我用的是89C52,通信115200已經(jīng)調(diào)試成功,我的思路是先接收一完整幀判斷,然后再進(jìn)行幀數(shù)分析,該幀為02 14 30 57 00 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 17 03 ,幀頭為02,幀尾03,我要提取的數(shù)據(jù)是64。
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:213173 發(fā)表于 2018-8-16 20:21 | 只看該作者
給你一個(gè)PM2.5空氣質(zhì)量檢測模塊的串口測試示例參考,TX-1C實(shí)驗(yàn)板。
//AA 00 10 00 4B 5B FF  用串口助手模擬PM2.5空氣質(zhì)量檢測模塊發(fā)送的數(shù)據(jù)
#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
sbit dula=P2^6;                        //段選
sbit wela=P2^7;                        //位選
uchar code table[]={                //共陰數(shù)碼管0~F數(shù)組
        0x3f,0x06,0x5b,0x4f,
        0x66,0x6d,0x7d,0x07,
        0x7f,0x6f,0x77,0x7c,
        0x39,0x5e,0x79,0x71};
uchar table0[] ="OK\n";        //用于串口助手返回驗(yàn)證
uchar table1[]="ERROR\n";//用于串口助手返回驗(yàn)證
uchar rec_buf[7];                        //緩存
uint V_data;                                //收到的16位有效數(shù)據(jù)變量
uint swan,wan,qian,bai,shi,ge;//數(shù)碼管顯示位
bit flag=0;                                        //接收完成標(biāo)
/*************初始化串口**************/
void InitUART()                //9600bps@11.0592MHz
{
        PCON &= 0x7F;                //波特率不倍速
        SCON = 0x50;                //8位數(shù)據(jù),可變波特率
        TMOD= 0x20;                        //設(shè)定定時(shí)器1為8位自動(dòng)重裝方式
        TL1 = 0xFD;                        //設(shè)定定時(shí)初值
        TH1 = 0xFD;                        //設(shè)定定時(shí)器重裝值
        ET1 = 0;                                //禁止定時(shí)器1中斷
        TR1 = 1;                                //啟動(dòng)定時(shí)器1
        EA = 1;                                //開總中斷
        ES = 1;                                //開串口中斷
}
/**********串口發(fā)送函數(shù)*************/
void SendOneByte(uchar c)
{
    SBUF = c;                //發(fā)送數(shù)據(jù)
    while(!TI);        //等待發(fā)送完成
    TI = 0;                        //發(fā)送中斷請(qǐng)求標(biāo)志位清0
}
/************數(shù)據(jù)解析程序*************/
void analysis()
{
        uchar i,j;                //臨時(shí)變量
        if(flag==1)                //7位數(shù)據(jù)串接收完成
        {
                ES=0;                        //關(guān)串口中斷
                flag=0;                //接收完成標(biāo)志清0
                j=rec_buf[1]+rec_buf[2]+rec_buf[3]+rec_buf[4];//數(shù)據(jù)和
                if(rec_buf[5]==j)//驗(yàn)證數(shù)據(jù)和
                {
                        V_data=(rec_buf[1]<<8)|rec_buf[2];//恢復(fù)16位有效數(shù)據(jù)
                        for(i=0;i<3;i++)
                        SendOneByte(table0[i]);//返回OK
                }
                else for(i=0;i<6;i++)
                        SendOneByte(table1[i]);//返回ERROR
                ES=1;                //開串口中斷
        }
}
/*************數(shù)據(jù)分解***************/
void Transformation()
{
        swan = V_data/100000;                        // 十萬位
        wan  = V_data%100000/10000;                // 萬位
        qian = V_data%10000/1000;                // 千位
        bai  = V_data%1000/100;                        // 百位
        shi  = V_data%100/10;                        // 十位
        ge   = V_data%10;                                        // 個(gè)位
}
/**********6位數(shù)碼管顯示程序************/
void display()
{
        static uchar k=0;                                //分時(shí)顯示變量
        P0=0x00;                                                //消隱
        dula=1;
        dula=0;
        switch(k)
        {
                case 0:
                        P0=0x7e;                                //顯示十萬位碼
                        wela=1;
                        wela=0;
                        P0=table[swan];                        //顯示十萬位段碼
                        dula=1;
                        dula=0;
                        k++;
                 break;       

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

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

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

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

                case 5:
                        P0=0xdf;                                //顯示個(gè)位位碼
                        wela=1;
                        wela=0;
                       
                        P0=table[ge];                        //顯示個(gè)位段碼
                        dula=1;
                        dula=0;
                        k=0;
                 break;       
        }
}
/**************主程序**************/
void main()
{
        InitUART();                //初始化串口
        while(1)
        {
                analysis();        //數(shù)據(jù)解析
                Transformation();//數(shù)據(jù)分解
                display();        //數(shù)碼管顯示
        }
}
/*********串口中斷服務(wù)程序**********/
void UARTInterrupt() interrupt 4
{
        static uchar num=0;                //靜態(tài)計(jì)數(shù)變量
        RI=0;                                        //接收中斷請(qǐng)求標(biāo)志位清0
        rec_buf[num]=SBUF;                //接收到的數(shù)據(jù)串保存在緩存數(shù)組
        if(rec_buf[0]==0xAA)        //驗(yàn)證數(shù)據(jù)頭(起始位)
        {
                num++;
                if(num>=7)
                {
                        flag=1;                        //接收完成標(biāo)志置1
                        num=0;                        //計(jì)數(shù)變量清0
                }
        }
}

評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 回帖助人的獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

板凳
ID:307391 發(fā)表于 2018-8-17 08:25 | 只看該作者
串口接受數(shù)據(jù),把接受的數(shù)據(jù)存進(jìn)數(shù)組,對(duì)比校驗(yàn)的數(shù)據(jù)是否正確,正確的話取出自己需要的數(shù)據(jù)

評(píng)分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

地板
ID:387162 發(fā)表于 2018-8-17 10:40 | 只看該作者
類似狀態(tài)機(jī)的設(shè)計(jì)也可以吧 就是符合條件才進(jìn)入下一個(gè)狀態(tài)

評(píng)分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

5#
ID:303383 發(fā)表于 2018-8-17 23:14 來自觸屏版 | 只看該作者
提示: 作者被禁止或刪除 內(nèi)容自動(dòng)屏蔽
回復(fù)

使用道具 舉報(bào)

6#
ID:49578 發(fā)表于 2018-8-20 15:19 | 只看該作者
wulin 發(fā)表于 2018-8-16 20:21
給你一個(gè)PM2.5空氣質(zhì)量檢測模塊的串口測試示例參考,TX-1C實(shí)驗(yàn)板。
//AA 00 10 00 4B 5B FF  用串口助手模 ...

感謝分享
回復(fù)

使用道具 舉報(bào)

7#
ID:49578 發(fā)表于 2018-8-20 15:20 | 只看該作者

是的  幀頭,幀尾均固定
                                   02                 //幀頭
                                   14                 //數(shù)據(jù)長度: 長度=命令+參數(shù)+效驗(yàn)
                                   30 57 00        //命令
                                   64 00        //找零箱內(nèi)硬幣數(shù)
                                   00 00 00 00 00 00 00 00 00 00 00 00 00 00
                                   17                 //XOR :XOR=長度xor命令xor參數(shù)
                                   03                 //幀尾   
回復(fù)

使用道具 舉報(bào)

8#
ID:49578 發(fā)表于 2018-8-20 15:21 | 只看該作者
ux4123 發(fā)表于 2018-8-17 10:40
類似狀態(tài)機(jī)的設(shè)計(jì)也可以吧 就是符合條件才進(jìn)入下一個(gè)狀態(tài)

請(qǐng)賜教,我不大懂您說的
回復(fù)

使用道具 舉報(bào)

9#
ID:388207 發(fā)表于 2018-8-20 16:33 | 只看該作者
定好協(xié)議,定長發(fā)送,定長接收,存放在rxd_buf[]數(shù)組中,需要的時(shí)候從數(shù)組中取出對(duì)應(yīng)的位就行
回復(fù)

使用道具 舉報(bào)

10#
ID:49578 發(fā)表于 2018-8-29 11:18 | 只看該作者
neuangel 發(fā)表于 2018-8-20 16:33
定好協(xié)議,定長發(fā)送,定長接收,存放在rxd_buf[]數(shù)組中,需要的時(shí)候從數(shù)組中取出對(duì)應(yīng)的位就行

我編寫的主程序中LED無法點(diǎn)亮,硬件電路核查過沒問題,void Data_anlysize()函數(shù)也沒問題,Data_ok能收到,不清楚問題在哪?
#include "reg52.h"                         //此文件中定義了單片機(jī)的一些特殊功能寄存器

#define uint unsigned int         //對(duì)數(shù)據(jù)類型進(jìn)行聲明定義
#define uchar unsigned char


uchar Data_buf[22];          //串口接收數(shù)據(jù)緩存數(shù)組
uint  Data_recieve[22];      //串口接收到完整幀
uint  flag;                                         //串口接收結(jié)束標(biāo)志
uint  Data_ok;                             //有效數(shù)據(jù)提取標(biāo)志

sbit ticket=P1^0;                            //將單片機(jī)的P1.0端口定義為乘客購票檢測
sbit voice=P1^4;                            //將單片機(jī)的P1.4端口定義為語音提示開關(guān)
sbit led=P0^0;                     //將單片機(jī)的P0.0端口定義bug檢測

void UsartInit();            //串口初始化
void Data_anlysize();                 //數(shù)據(jù)分析

/*******************************************************************************
* 函 數(shù) 名       : main
* 函數(shù)功能                 : 主函數(shù)
* 輸    入       : 無
* 輸    出             : 無
*******************************************************************************/
void main()
{        
        UsartInit();                   //串口初始化
        while(1)
        {
                voice=0;
            Data_anlysize();            //數(shù)據(jù)分析
                if(Data_ok==1&&ticket==0)  //判斷乘客有購票行為
                {
                         voice=1;              //開語音提示
                         led=0;
                }        
        }               
}
/*******************************************************************************
* 函數(shù)名         : Usart() interrupt 4
* 函數(shù)功能                 : 串口通信中斷函數(shù)
* 輸入           : 無
* 輸出                  : 無
*******************************************************************************/
void Usart() interrupt 4
{
        static uchar count=0;                //靜態(tài)計(jì)數(shù)變量
    RI=0;                                //接收中斷請(qǐng)求標(biāo)志位清0
    Data_buf[count]=SBUF;                //接收到的數(shù)據(jù)串保存在緩存數(shù)組
    if(Data_buf[0]==0x02)                //驗(yàn)證數(shù)據(jù)頭(起始位)
    {
        count++;
        if(count>=23)
        {
            flag=1;                        //接收完成標(biāo)志置1
            count=0;                        //計(jì)數(shù)變量清0
        }
     }
}
/*******************************************************************************
* 函數(shù)名         :UsartInit()
* 函數(shù)功能                 :串口初始化
* 輸入           : 無
* 輸出                  : 無
*******************************************************************************/
void UsartInit()
{
        SCON=0X50;                        //設(shè)置為串口工作方式1(SM0=0,SM0=1),允許接收 (REN=1)
        T2CON=0X34;                        //設(shè)置T2為波特率發(fā)生器工作方式(TCLK=1,RCLK=1,TR2=1),T2為定時(shí)器(C_T2=0 )
        //T2MOD=0X00;                        //設(shè)置T2為加法計(jì)數(shù)DCEN=0,時(shí)鐘輸出不使能T2OE=0
        TH2=0XFF;                    
        TL2=0XFD;
        RCAP2H=0XFF;
        RCAP2L=0XFD;            //計(jì)數(shù)器T2初始值設(shè)置,波特率115200
        EA=1;                                //打開總中斷
        ES=1;                                //設(shè)置中斷允許控制寄存器IE,允許串行中斷   
}
/*******************************************************************************
* 函數(shù)名         :Data_anlysis()
* 函數(shù)功能                 :串口協(xié)議分析
* 輸入           : 無
* 輸出                  : 無
* 備注                  : 幀結(jié)構(gòu)
                   02                 //幀頭
                                   14                 //數(shù)據(jù)長度: 長度=命令+參數(shù)+效驗(yàn)
                                   30 57 00        //命令
                                   64 00        //找零箱內(nèi)硬幣數(shù)
                                   00 00 00 00 00 00 00 00 00 00 00 00 00 00
                                   17                 //XOR :XOR=長度xor命令xor參數(shù)
                                   03                 //幀尾      
*******************************************************************************/
void Data_anlysize()
{
        uchar i,j;                //臨時(shí)變量
        if(flag==1)               //23位數(shù)據(jù)串接收完成
        {
            ES=0;                 //關(guān)串口中斷
            flag=0;               //接收完成標(biāo)志清0
            j=Data_buf[2]^Data_buf[3]^Data_buf[4]^Data_buf[5]^Data_buf[6]^Data_buf[7]^Data_buf[8]^Data_buf[9]^Data_buf[10]^Data_buf[11]^Data_buf[12]^Data_buf[13]^Data_buf[14]^Data_buf[15]^Data_buf[16]^Data_buf[17]^Data_buf[18]^Data_buf[19]^Data_buf[20];//XOR校驗(yàn)
            if(Data_buf[21]==j)  //校驗(yàn)通過
            {
               for(i=0;i<=22;i++)
                                   Data_recieve=Data_buf;//接收完整幀
                           if(Data_recieve[5]==0x64)
                               Data_ok=1;
            }
            ES=1;                //開串口中斷
          }
}
回復(fù)

使用道具 舉報(bào)

11#
ID:49578 發(fā)表于 2018-8-29 11:19 | 只看該作者
ux4123 發(fā)表于 2018-8-17 10:40
類似狀態(tài)機(jī)的設(shè)計(jì)也可以吧 就是符合條件才進(jìn)入下一個(gè)狀態(tài)

我編寫的主程序中LED無法點(diǎn)亮,硬件電路核查過沒問題,void Data_anlysize()函數(shù)也沒問題,Data_ok能收到,不清楚問題在哪?
#include "reg52.h"                         //此文件中定義了單片機(jī)的一些特殊功能寄存器

#define uint unsigned int         //對(duì)數(shù)據(jù)類型進(jìn)行聲明定義
#define uchar unsigned char


uchar Data_buf[22];          //串口接收數(shù)據(jù)緩存數(shù)組
uint  Data_recieve[22];      //串口接收到完整幀
uint  flag;                                         //串口接收結(jié)束標(biāo)志
uint  Data_ok;                             //有效數(shù)據(jù)提取標(biāo)志

sbit ticket=P1^0;                            //將單片機(jī)的P1.0端口定義為乘客購票檢測
sbit voice=P1^4;                            //將單片機(jī)的P1.4端口定義為語音提示開關(guān)
sbit led=P0^0;                     //將單片機(jī)的P0.0端口定義bug檢測

void UsartInit();            //串口初始化
void Data_anlysize();                 //數(shù)據(jù)分析

/*******************************************************************************
* 函 數(shù) 名       : main
* 函數(shù)功能                 : 主函數(shù)
* 輸    入       : 無
* 輸    出             : 無
*******************************************************************************/
void main()
{        
        UsartInit();                   //串口初始化
        while(1)
        {
                voice=0;
            Data_anlysize();            //數(shù)據(jù)分析
                if(Data_ok==1&&ticket==0)  //判斷乘客有購票行為
                {
                         voice=1;              //開語音提示
                         led=0;
                }        
        }               
}
/*******************************************************************************
* 函數(shù)名         : Usart() interrupt 4
* 函數(shù)功能                 : 串口通信中斷函數(shù)
* 輸入           : 無
* 輸出                  : 無
*******************************************************************************/
void Usart() interrupt 4
{
        static uchar count=0;                //靜態(tài)計(jì)數(shù)變量
    RI=0;                                //接收中斷請(qǐng)求標(biāo)志位清0
    Data_buf[count]=SBUF;                //接收到的數(shù)據(jù)串保存在緩存數(shù)組
    if(Data_buf[0]==0x02)                //驗(yàn)證數(shù)據(jù)頭(起始位)
    {
        count++;
        if(count>=23)
        {
            flag=1;                        //接收完成標(biāo)志置1
            count=0;                        //計(jì)數(shù)變量清0
        }
     }
}
/*******************************************************************************
* 函數(shù)名         :UsartInit()
* 函數(shù)功能                 :串口初始化
* 輸入           : 無
* 輸出                  : 無
*******************************************************************************/
void UsartInit()
{
        SCON=0X50;                        //設(shè)置為串口工作方式1(SM0=0,SM0=1),允許接收 (REN=1)
        T2CON=0X34;                        //設(shè)置T2為波特率發(fā)生器工作方式(TCLK=1,RCLK=1,TR2=1),T2為定時(shí)器(C_T2=0 )
        //T2MOD=0X00;                        //設(shè)置T2為加法計(jì)數(shù)DCEN=0,時(shí)鐘輸出不使能T2OE=0
        TH2=0XFF;                    
        TL2=0XFD;
        RCAP2H=0XFF;
        RCAP2L=0XFD;            //計(jì)數(shù)器T2初始值設(shè)置,波特率115200
        EA=1;                                //打開總中斷
        ES=1;                                //設(shè)置中斷允許控制寄存器IE,允許串行中斷   
}
/*******************************************************************************
* 函數(shù)名         :Data_anlysis()
* 函數(shù)功能                 :串口協(xié)議分析
* 輸入           : 無
* 輸出                  : 無
* 備注                  : 幀結(jié)構(gòu)
                   02                 //幀頭
                                   14                 //數(shù)據(jù)長度: 長度=命令+參數(shù)+效驗(yàn)
                                   30 57 00        //命令
                                   64 00        //找零箱內(nèi)硬幣數(shù)
                                   00 00 00 00 00 00 00 00 00 00 00 00 00 00
                                   17                 //XOR :XOR=長度xor命令xor參數(shù)
                                   03                 //幀尾      
*******************************************************************************/
void Data_anlysize()
{
        uchar i,j;                //臨時(shí)變量
        if(flag==1)               //23位數(shù)據(jù)串接收完成
        {
            ES=0;                 //關(guān)串口中斷
            flag=0;               //接收完成標(biāo)志清0
            j=Data_buf[2]^Data_buf[3]^Data_buf[4]^Data_buf[5]^Data_buf[6]^Data_buf[7]^Data_buf[8]^Data_buf[9]^Data_buf[10]^Data_buf[11]^Data_buf[12]^Data_buf[13]^Data_buf[14]^Data_buf[15]^Data_buf[16]^Data_buf[17]^Data_buf[18]^Data_buf[19]^Data_buf[20];//XOR校驗(yàn)
            if(Data_buf[21]==j)  //校驗(yàn)通過
            {
               for(i=0;i<=22;i++)
                                   Data_recieve=Data_buf;//接收完整幀
                           if(Data_recieve[5]==0x64)
                               Data_ok=1;
            }
            ES=1;                //開串口中斷
          }
}
回復(fù)

使用道具 舉報(bào)

12#
ID:382067 發(fā)表于 2018-8-30 16:34 來自觸屏版 | 只看該作者
判斷起始位,如果符合要求,則設(shè)置一個(gè)接收開始的標(biāo)志位,然后直到接收到停止位就可以將接收停止位復(fù)位。如果不設(shè)立停止位,判斷一下接收時(shí)間也可以,大概超過30ms就表示下一個(gè)數(shù)據(jù)就是下一幀的了
回復(fù)

使用道具 舉報(bào)

13#
ID:213173 發(fā)表于 2018-8-31 19:42 | 只看該作者
本帖最后由 wulin 于 2018-9-1 17:39 編輯
zfeng45 發(fā)表于 2018-8-29 11:18
我編寫的主程序中LED無法點(diǎn)亮,硬件電路核查過沒問題,void Data_anlysize()函數(shù)也沒問題,Data_ok能收到 ...

給你把程序改了,你試試
#include "reg52.h"           //此文件中定義了單片機(jī)的一些特殊功能寄存器

#define uint unsigned int    //對(duì)數(shù)據(jù)類型進(jìn)行聲明定義
#define uchar unsigned char

uchar Data_buf[23];          //串口接收數(shù)據(jù)緩存數(shù)組
uint  Data_recieve[23];      //串口接收到完整幀
uint  flag;                  //串口接收結(jié)束標(biāo)志
uint  Data_ok;               //有效數(shù)據(jù)提取標(biāo)志

//sbit ticket=P1^0;            //將單片機(jī)的P1.0端口定義為乘客購票檢測
//sbit voice=P1^4;             //將單片機(jī)的P1.4端口定義為語音提示開關(guān)
//sbit led=P0^0;               //將單片機(jī)的P0.0端口定義bug檢測

sbit ticket=P3^4;            //按鍵開關(guān)模擬乘客購票檢測
sbit voice=P1^4;             //LED顯示模擬語音提示
sbit led=P1^0;               //LED顯示

void UsartInit();            //串口初始化
void Data_anlysize();        //數(shù)據(jù)分析
void delayms(uint k);
/*-------------------------------
  1ms延時(shí)子程序
-------------------------------*/
void delayms(uint k)
{
        uint i,j;
        for(i=k;i>0;i--)
                for(j=110;j>0;j--);
}
/*******************************************************************************
* 函 數(shù) 名       : main
* 函數(shù)功能       : 主函數(shù)
* 輸    入       : 無
* 輸    出       : 無
*******************************************************************************/
void main()
{        
        UsartInit();                   //串口初始化
        while(1)
        {

                Data_anlysize();            //數(shù)據(jù)解析
                if((Data_ok==1)&&(ticket==0))  //判斷乘客有購票行為
                {
                        voice=0;              //開語音提示
                        led=0;                                                //LED亮
/********延時(shí)觀察LED********************/
                        delayms(1000);                                //延時(shí)1秒,
                        voice=1;              //關(guān)語音提示
                        led=1;                                                //LED熄
                        Data_ok=0;                                //有效數(shù)據(jù)提取標(biāo)志復(fù)位
                }        
        }               
}
/*******************************************************************************
* 函數(shù)名         : Usart() interrupt 4
* 函數(shù)功能                 : 串口通信中斷函數(shù)
* 輸入           : 無
* 輸出                  : 無
*******************************************************************************/
void Usart() interrupt 4
{
        static uchar count=0;                //靜態(tài)計(jì)數(shù)變量
        uchar i;
        RI=0;                                //接收中斷請(qǐng)求標(biāo)志位清0
        Data_buf[count]=SBUF;                //接收到的數(shù)據(jù)串保存在緩存數(shù)組
        if(Data_buf[0]==0x02)                //驗(yàn)證數(shù)據(jù)頭(起始位)
        {
                count++;
                if(count>=23)
                {
                        if(Data_buf[22]==0x03)                        //驗(yàn)證數(shù)據(jù)尾(結(jié)束位)
                                flag=1;                    //接收完成標(biāo)志置1
                        else
                                for(i=0;i<23;i++)
                                        Data_buf=0x00;                        //緩存數(shù)組清0
                        count=0;                      //計(jì)數(shù)變量清0
                }
        }
}
/*******************************************************************************
* 函數(shù)名         :UsartInit()
* 函數(shù)功能       :串口初始化
* 輸入           : 無
* 輸出           : 無
*******************************************************************************/
void UsartInit()        //晶振頻率11.0592MHz
{
        SCON=0X50;      //設(shè)置為串口工作方式1(SM0=0,SM0=1),允許接收 (REN=1)
        T2CON=0X34;     //設(shè)置T2為波特率發(fā)生器工作方式(TCLK=1,RCLK=1,TR2=1),T2為定時(shí)器(C_T2=0 )
        //T2MOD=0X00;   //設(shè)置T2為加法計(jì)數(shù)DCEN=0,時(shí)鐘輸出不使能T2OE=0
        TL2 = RCAP2L =0XFD;//計(jì)數(shù)器T2初始值設(shè)置,波特率115200
        TH2 = RCAP2H =0XFF;                     
        EA=1;           //打開總中斷
        ES=1;           //設(shè)置中斷允許控制寄存器IE,允許串行中斷   
}
/*******************************************************************************
* 函數(shù)名         :Data_anlysis()
* 函數(shù)功能       :串口協(xié)議分析
* 輸入           : 無
* 輸出           : 無
* 備注           : 幀結(jié)構(gòu)
                   02           //幀頭
                   14           //數(shù)據(jù)長度: 長度=命令+參數(shù)+效驗(yàn)
                   30 57 00     //命令
                   64 00        //找零箱內(nèi)硬幣數(shù)
                   00 00 00 00 00 00 00 00 00 00 00 00 00 00
                   17           //XOR :XOR=長度xor命令xor參數(shù)
                   03           //幀尾      
*******************************************************************************/
void Data_anlysize()
{
        uchar i,j;                //臨時(shí)變量
        if(flag==1)               //23字節(jié)數(shù)據(jù)串接收完成
        {
                ES=0;                 //關(guān)串口中斷
                flag=0;               //接收完成標(biāo)志清0
                j=0;
                for(i=0;i<20;i++)
                        j=j^Data_buf[i+1];//XOR校驗(yàn)
                if(Data_buf[21]==j)  //校驗(yàn)通過
                {
                        for(i=0;i<23;i++)
                                Data_recieve=Data_buf;//接收完整幀
                        if(Data_recieve[5]==0x64)
                                Data_ok=1;
                        for(i=0;i<23;i++)
                                Data_buf=0x00;                        //緩存數(shù)組清0
                }
                ES=1;                //開串口中斷
        }
}
//02 14 30 57 00 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 17 03

回復(fù)

使用道具 舉報(bào)

14#
ID:49578 發(fā)表于 2018-9-4 08:29 | 只看該作者
wulin 發(fā)表于 2018-8-31 19:42
給你把程序改了,你試試
#include "reg52.h"           //此文件中定義了單片機(jī)的一些特殊功能寄存器

...

非常感謝
回復(fù)

使用道具 舉報(bào)

15#
ID:283332 發(fā)表于 2021-12-18 15:41 | 只看該作者
我將"給你一個(gè)PM2.5空氣質(zhì)量檢測模塊的串口測試示例參考,TX-1C實(shí)驗(yàn)板"的程序作了部分移植,總體沒什么問題,在analysis()函數(shù)內(nèi)調(diào)用發(fā)送 SendOneByte(table0[i]),應(yīng)放在ES=1 之后
回復(fù)

使用道具 舉報(bào)

16#
ID:883242 發(fā)表于 2021-12-18 16:22 | 只看該作者
上位機(jī)實(shí)時(shí)性太差了,我定義通訊協(xié)議都是用ASCII碼的形式,比如冒號(hào)是幀頭標(biāo)志,\r\n是幀尾標(biāo)志,中間數(shù)字是'0'~'9','A'~'Z'的可打印字符。

單片機(jī)之間的通訊,因?yàn)閷?shí)時(shí)性好,可以定成總線空閑3.5字節(jié)的時(shí)間,下面來的第一個(gè)字符就是幀頭,不需要特殊字符來區(qū)別。
回復(fù)

使用道具 舉報(bào)

17#
ID:811253 發(fā)表于 2021-12-18 16:23 | 只看該作者
一般都是把數(shù)據(jù)封裝成具有一定格式的數(shù)據(jù)包來發(fā)送,收發(fā)雙方按協(xié)議打包或是解釋數(shù)據(jù)。
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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