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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索

51單片機串口收發代碼排錯

查看數: 1148 | 評論數: 14 | 收藏 1
關燈 | 提示:支持鍵盤翻頁<-左 右->
    組圖打開中,請稍候......
發布時間: 2024-9-14 18:28

正文摘要:

PC發送hex  5A A5 03 01 02 03;解析出03(數據包的長度),第一次解析正常,03改變后解析還是03, 哪位幫忙分析一下代碼出錯 void main(){         UartInit(); ...

回復

ID:1073939 發表于 2024-9-19 10:01
samxon 發表于 2024-9-18 17:16
謝謝你熱情給力的解析,還把代碼增加了注釋。非常感謝。希望占用您寶貴時間幫我看看下面的代碼。給點思路 ...

感覺協議制定得不太合理,putCmd()應該能解決你的第3個難點。
  1. char putchar(char c) // 發1個
  2. {
  3.         while (!TI)
  4.                 ; // 注意uart初始化時要TI = 1;
  5.         TI = 0;
  6.         SBUF = c;
  7.         return c;
  8. }
  9. void putBuff(unsigned char *buf, unsigned char len) // 發多個
  10. {
  11.         while (len--)
  12.                 putchar(*buf++);
  13. }
  14. /*
  15. */
  16. void putCmd(unsigned char cmd, unsigned short var_add, const unsigned char *dat, unsigned char len)
  17. {
  18.         putchar(Pack_Head >> 8);
  19.         putchar(Pack_Head);
  20.         putchar(len + 3);
  21.         putchar(cmd);
  22.         putchar(var_add >> 8);
  23.         putchar(var_add);
  24.         putBuff(dat, len);
  25. }
復制代碼


putCmd()使用示范
  1. #define CMD_1_ADD 0x1200
  2. #define CMD_2_ADD 0x1350
  3. #define CMD_3_ADD 0x1400
  4. code unsigned char CMD_1[] = {0x06, 0x1b};                                         // 寫入電壓
  5. code unsigned char CMD_2[] = {0x34, 0x35, 0x57, 0x00};                 // 寫入測試標識
  6. code unsigned char CMD_3[] = {0x50, 0x41, 0x53, 0x53, 0x00}; // 寫入測試結果(pass或fail)
  7. void putCmd_demo()
  8. {
  9.         putCmd(WriteCmd, CMD_1_ADD, CMD_1, sizeof(CMD_1));
  10.         putCmd(WriteCmd, CMD_2_ADD, CMD_2, sizeof(CMD_2));
  11.         putCmd(WriteCmd, CMD_3_ADD, CMD_3, sizeof(CMD_3));
  12.         putCmd(WriteCmd, 1234, "1234567890", sizeof("1234567890")-1);
  13. }
復制代碼


簡化你之前的Uart_send_data()
  1. void Uart_send_data()
  2. {
  3.         // unsigned char m;
  4.         if (REC_COMPLETED)
  5.         {
  6.                 REC_COMPLETED = 0;
  7.                 putBuff(USART_RX_BUF, DATA_LENGTH);
  8.                 // for (m = 0; m < DATA_LENGTH; m++)
  9.                 // {
  10.                 //         SBUF = USART_RX_BUF[m];
  11.                 //         while (!TI)
  12.                 //                 ;
  13.                 //         TI = 0;
  14.                 // }
  15.         }
  16. }
復制代碼



ID:705846 發表于 2024-9-19 09:41
samxon 發表于 2024-9-18 17:16
謝謝你熱情給力的解析,還把代碼增加了注釋。非常感謝。希望占用您寶貴時間幫我看看下面的代碼。給點思路 ...

一個一個來搞,請各位幫忙把關代碼。如有更好優化,請賜教。
添加數據包長度代碼
void Join_Test_Parameter(unsigned char cmd,unsigned short var_add,unsigned short jdata){
        unsigned char temp_buf[15],par_buf[16],i,par_buf_size,cnt=0;
        temp_buf[cnt++]= (Pack_Head&0xFF00)>>8;         //0
        temp_buf[cnt++]= Pack_Head&0xFF;                                        //1
        temp_buf[cnt++]=        cmd;                                                                                //2
        temp_buf[cnt++]=(var_add&0xFF00)>>8;                        //3
        temp_buf[cnt++]=var_add&0xFF;                                                        //4
        temp_buf[cnt++]=(jdata&0xFF00)>>8;                  //5
        temp_buf[cnt++]=jdata&0xFF;                                                        //6       
        for(i=0;i<10;i++){
                if(i<2){
                        par_buf=temp_buf;
                }else if(i==2){
                        par_buf=cnt-3; //將長度直接添加到數組下標2的位置。
                }else{
                        par_buf=temp_buf[i-1];
                }       
        }
        Send_Test_Parameter(par_buf,cnt+1);
}
ID:705846 發表于 2024-9-18 17:16

謝謝你熱情給力的解析,還把代碼增加了注釋。非常感謝。希望占用您寶貴時間幫我看看下面的代碼。給點思路和辦法我。謝謝。

遇到的難點:
1) 如何把len這個長度字段插入到數據包的第3個字節。
2)由于有效數據部分是不確定的。可能有時是3個字節,也有可能是四個字節。如何把這些直接傳遞給Join_Test_Parameter函數來正確的產生一個數據包。
3)也許可用一個數組把想要的參數一次全部打包丟給Join_Test_Parameter這個函數處理吧。可是我不知道怎么實現。
謝謝大家,特別是謝謝這個ydatou友情幫忙

void Join_Test_Parameter(unsigned char len,unsigned char cmd,unsigned short var_add,unsigned short jdata){
        unsigned char par_buf[15],cnt=0;
        par_buf[cnt++]= (Pack_Head&0xFF00)>>8;       
        par_buf[cnt++]= Pack_Head&0xFF;       
        par_buf[cnt++]=len;
        par_buf[cnt++]=        cmd;
        par_buf[cnt++]=(var_add&0xFF00)>>8;
        par_buf[cnt++]=var_add&0xFF;
        par_buf[cnt++]=(jdata&0xFF00)>>8;
        par_buf[cnt++]=jdata&0xFF;
        Send_Test_Parameter(par_buf,cnt);
}

void Get_Test_Gear(){          
        if(REC_COMPLETED){
        REC_COMPLETED=0;       
        if(USART_RX_BUF[1]==0x31){
        switch(USART_RX_BUF[2]){
             case 0x00: TEST_GEAR=0;
                Join_Test_Parameter(0x05,WriteCmd,0x1200,0x61B); //寫入電壓
                Join_Test_Parameter(0x05,WriteCmd,0x1250,0x145); //寫入電流
                Join_Test_Parameter(0x05,WriteCmd,0x1300,0x1fb); //寫入功率
                Join_Test_Parameter(0x07,WriteCmd,0x1350,0x34 0x35 0x57 0x00); //寫入測試標識
                Join_Test_Parameter(0x08,WriteCmd,0x1400,0x50 0x41 0x53 0x53 0x00);        //寫入測試結果(pass或fail)
                Join_Test_Parameter(0x05,WriteCmd,0x1653,0x0400);        //改變字體顏色
                Join_Test_Parameter(0x05,WriteCmd,0x1500,0x1455); //寫入最大值
                Join_Test_Parameter(0x05,WriteCmd,0x1200,0x13F1);        //寫入平均值
                Join_Test_Parameter(0x05,WriteCmd,0x1200,0x1389);        //寫入最小值
                break;
             case 0x10: TEST_GEAR=1;
                ........
                }
        }
}

ID:1073939 發表于 2024-9-18 12:00
  1. /*
  2. 和樓主代碼比優點如下:
  3. 占用ram資源少。
  4. 可連續多幀處理,不會掉幀。
  5. 多幀之間摻雜其他數據,不會掉幀。
  6. */
  7. #define MAX_LENGTH 32//最大數據長度
  8. idata unsigned char USART_RX_BUF[MAX_LENGTH];//xdata
  9. unsigned char DATA_LENGTH;//當前數據長度,只有REC_COMPLETED為1時才有效
  10. bit REC_COMPLETED;

  11. void Uart() interrupt 4
  12. {
  13.         unsigned char d;
  14.         static unsigned char ccnt = 0;
  15.         if (RI)
  16.         {
  17.                 RI = 0;
  18.                 d = SBUF;

  19.                 if (ccnt == 0)
  20.                 {
  21.                         if (d == 0x5A)
  22.                                 ccnt = 1;
  23.                 }
  24.                 else if (ccnt == 1)
  25.                 {
  26.                         if (d == 0xA5)
  27.                                 ccnt = 2;
  28.                         else if (d != 0x5A)//連續多個5A也能正常接收,不掉幀。
  29.                                 ccnt = 0;
  30.                 }
  31.                 else if (ccnt == 2)
  32.                 {
  33.                         if (d > 0 && d <= MAX_LENGTH)//數據長度檢查,防止溢出。
  34.                         {
  35.                                 DATA_LENGTH = d;
  36.                                 ccnt = 3;
  37.                         }
  38.                         else if (d == 0x5A)//連續多個5A也能正常接收,不掉幀。
  39.                                 ccnt = 1;
  40.                         else
  41.                                 ccnt = 0;
  42.                 }
  43.                 else
  44.                 {
  45.                         unsigned char i = ccnt - 3;
  46.                         if (i < MAX_LENGTH)
  47.                         {
  48.                                 USART_RX_BUF[i] = d;
  49.                                 ccnt++;
  50.                                 if (i == DATA_LENGTH - 1)
  51.                                 {
  52.                                         REC_COMPLETED = 1;
  53.                                         //要盡快(<=2個字符時間)處理使REC_COMPLETED = 0
  54.                                         //9600波特率下,2個字符時間約2ms。
  55.                                         ccnt = 0;
  56.                                 }
  57.                         }
  58.                         else
  59.                                 ccnt = 0;
  60.                 }
  61.         }
  62.         if (TI)
  63.         {
  64.                 // TI=0;
  65.         }
  66. }
  67. void Uart_send_data()
  68. {
  69.         unsigned char m;
  70.         if (REC_COMPLETED)
  71.         {
  72.                 REC_COMPLETED = 0;
  73.                 for (m = 0; m < DATA_LENGTH; m++)
  74.                 {
  75.                         SBUF = USART_RX_BUF[m];
  76.                         while (!TI)
  77.                                 ;
  78.                         TI = 0;
  79.                 }
  80.         }
  81. }
復制代碼
ID:1073939 發表于 2024-9-18 11:08
samxon 發表于 2024-9-17 08:18
能不等講一下,我看到很多都是用指針傳送接收數組uartx_Rx_buf的值。直接傳遞和用指針傳區別在哪里。直接 ...

這段代碼不能在51下工作。
51的ram最多只有256字節,單Buf[300]都不夠。
51的臨時變量不是分配在堆棧上,函數一般不支持再入。一個函數假如在某個中斷中有調用,那么它就不適合在其它中斷中和非中斷中調用。
用指針傳遞更靈活方便,但占用ram資源多些。用全局變量傳遞,占用ram資源少,使用限制多。
ID:287147 發表于 2024-9-17 23:18



感謝壇子高工,問題已經解決,增加else條件。
void Uart() interrupt 4
{
        static unsigned char ccnt,bufccnt,recd_temp[5];
        if(RI && REC_COMPLETED==0){
                RI=0;
                if(ccnt<3){
                recd_temp[ccnt++]=SBUF;                       
                }else{
                        if(recd_temp[0]==0x5A && recd_temp[1]==0xA5){
                                DATA_LENGTH=recd_temp[2];
                                USART_RX_BUF[bufccnt++]=SBUF;                              
                                        if(bufccnt==DATA_LENGTH){  //5A A5 02 03 04   0>03,1;1>04,2
                                                REC_COMPLETED=1;
                                                bufccnt=0;
                                                ccnt=0;
                                                ES=0;
                                        }
                  }else{
                                ccnt=0;
                        }      
                }
        }      
if(TI){}      
}

void Uart_send_data(){
        static unsigned char m;               
        if(REC_COMPLETED){
                for(m=0;m<DATA_LENGTH;m++){
                        SBUF=USART_RX_BUF[m];
                        while(!TI);
                        TI=0;
                }
                DATA_LENGTH=0;
                REC_COMPLETED=0;
                m=0;
                ES=1;
        }
}
ID:705846 發表于 2024-9-17 08:18
ydatou 發表于 2024-9-16 15:35
這段代碼還有問題。
1.串口是可以同時收發的。 if(RI && REC_COMPLETED==0)會使發送期間數據接收出錯。
...

能不等講一下,我看到很多都是用指針傳送接收數組uartx_Rx_buf的值。直接傳遞和用指針傳區別在哪里。直接傳程序看起來不是更好清晰嗎。謝謝解答。

void Encode_Receive(uint8_t bytedata)
{
        static uint8_t step=0;//狀態變量初始化為0 在函數中必須為靜態變量
        static uint8_t cnt=0,Buf[300],len,cmd,*data_ptr;
        static uint16_t crc16;
        //進行數據解析 狀態機
        switch(step)
        {
            case 0://接收幀頭1狀態
                if(bytedata== 0xAF)
                {
                    step++;
                    cnt = 0;
                    Buf[cnt++] = bytedata;
                }break;
            case 1://接收幀頭2狀態
                if(bytedata== 0xFA)
                {
                    step++;
                    Buf[cnt++] = bytedata;
                }
                else if(bytedata== 0XAF)
                {
                    step = 1;
                }
                else
                {
                    step = 0;
                }
                break;
            case 2://接收數據長度字節狀態
                step++;
                Buf[cnt++] = bytedata;
                len = bytedata;
                break;
            case 3://接收命令字節狀態
                step++;
                Buf[cnt++] = bytedata;
                cmd = bytedata;
                data_ptr = &Buf[cnt];//記錄數據指針首地址
                if(len == 0)step++;//數據字節長度為0則跳過數據接收狀態
                break;
            case 4://接收len字節數據狀態
                Buf[cnt++] = bytedata;
                if(data_ptr + len == &Buf[cnt])//利用指針地址偏移判斷是否接收完len位數據
                {
                    step++;
                }
                break;
            case 5://接收crc16校驗高8位字節
                step++;
                crc16 = bytedata;
                break;
            case 6://接收crc16校驗低8位字節
                crc16 <<= 8;
                crc16 += bytedata;
                if(crc16 == CRC16_Check(Buf,cnt))//校驗正確進入下一狀態
                {
                    step ++;
                }
                else if(bytedata == 0xAF)
                {
                    step = 1;
                }
                else
                {
                    step = 0;
                }
                break;
            case 7://接收幀尾
                if(bytedata== 0xFF)//幀尾接收正確
                {
                        Encode_Handle(cmd,data_ptr,len);//數據解析
                    step = 0;
                }
                else if(bytedata == 0xAF)
                {
                    step = 1;
                }
                else
                {
                    step = 0;
                }
                break;
            default:step=0;break;//多余狀態,正常情況下不可能出現
        }
}
ID:705846 發表于 2024-9-16 22:17
ydatou 發表于 2024-9-16 15:35
這段代碼還有問題。
1.串口是可以同時收發的。 if(RI && REC_COMPLETED==0)會使發送期間數據接收出錯。
...

非常感謝,這個是狀態機的思想寫的代碼。當然最好。值得擁有。
ID:1073939 發表于 2024-9-16 15:35
samxon 發表于 2024-9-16 09:31
感謝壇子高工,問題已經解決,增加else條件。
void Uart() interrupt 4
{

這段代碼還有問題。
1.串口是可以同時收發的。 if(RI && REC_COMPLETED==0)會使發送期間數據接收出錯。
2.錯誤檢查有漏洞。數據長度要做范圍檢查。
3.浪費了太多全局變量,51的ram資源又比較少。

請參考我的代碼。
  1. #define MAX_LENGTH 32
  2. unsigned char USART_RX_BUF[MAX_LENGTH];
  3. unsigned char DATA_LENGTH;
  4. bit REC_COMPLETED;

  5. void Uart() interrupt 4
  6. {
  7.         unsigned char d;
  8.         static unsigned char ccnt=0;
  9.         if (RI)
  10.         {
  11.                 RI = 0;
  12.                 d = SBUF;

  13.                 if (ccnt==0){
  14.                         if(d==0x5A)
  15.                                 ccnt=1;
  16.                 }
  17.                 else if (ccnt==1){
  18.                         if(d==0xA5)
  19.                                 ccnt=2;
  20.                         else
  21.                                 ccnt=0;
  22.                 }
  23.                 else if (ccnt==2){
  24.                         if(d>0 && d<=MAX_LENGTH){
  25.                                 DATA_LENGTH=d;
  26.                                 ccnt=3;
  27.                         }
  28.                         else
  29.                                 ccnt=0;
  30.                 }
  31.                 else {
  32.                         unsigned char i=ccnt-3;
  33.                         if(i<MAX_LENGTH){
  34.                                 USART_RX_BUF[i] = d;
  35.                                 ccnt++;
  36.                                 if(i==DATA_LENGTH-1) {
  37.                                         REC_COMPLETED = 1;
  38.                                         ccnt=0;
  39.                                 }
  40.                         }
  41.                         else
  42.                                 ccnt=0;
  43.                 }
  44.         }
  45.         if (TI)
  46.         {
  47.                 // TI=0;
  48.         }
  49. }
  50. void Uart_send_data()
  51. {
  52.         unsigned char m;
  53.         if (REC_COMPLETED)
  54.         {
  55.                 REC_COMPLETED = 0;
  56.                 for (m = 0; m < DATA_LENGTH; m++)
  57.                 {
  58.                         SBUF = USART_RX_BUF[m];
  59.                         while (!TI)
  60.                                 ;
  61.                         TI = 0;
  62.                 }
  63.         }
  64. }
復制代碼
ID:705846 發表于 2024-9-16 09:31


感謝壇子高工,問題已經解決,增加else條件。
void Uart() interrupt 4
{
        static unsigned char ccnt,bufccnt,recd_temp[5];
        if(RI && REC_COMPLETED==0){
                RI=0;
                if(ccnt<3){
                recd_temp[ccnt++]=SBUF;                       
                }else{
                        if(recd_temp[0]==0x5A && recd_temp[1]==0xA5){
                                DATA_LENGTH=recd_temp[2];
                                USART_RX_BUF[bufccnt++]=SBUF;                               
                                        if(bufccnt==DATA_LENGTH){  //5A A5 02 03 04   0>03,1;1>04,2
                                                REC_COMPLETED=1;
                                                bufccnt=0;
                                                ccnt=0;
                                                ES=0;
                                        }
                  }else{
                                ccnt=0;
                        }       
                }
        }       
if(TI){}       
}

void Uart_send_data(){
        static unsigned char m;               
        if(REC_COMPLETED){
                for(m=0;m<DATA_LENGTH;m++){
                        SBUF=USART_RX_BUF[m];
                        while(!TI);
                        TI=0;
                }
                DATA_LENGTH=0;
                REC_COMPLETED=0;
                m=0;
                ES=1;
        }
}

ID:705846 發表于 2024-9-15 12:20
發表于 2024-9-15 09:51
if(bufccnt=DATA_LENGTH)這句是不是應該用兩個等于號==

修正,情況依舊,可能還是數組上面的問題。但沒有排查的思路
ID:878061 發表于 2024-9-15 09:51
if(bufccnt=DATA_LENGTH)這句是不是應該用兩個等于號==

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 麻豆a级片 | 欧美aⅴ在线观看 | 日韩在线观看中文字幕 | 国产一级片在线播放 | 久久国产成人 | 一区二区三区亚洲视频 | 日韩欧美一区二区三区四区 | 色偷偷噜噜噜亚洲男人 | 三级黄色大片网站 | 在线观看中文字幕一区二区 | 欧美一级三级在线观看 | 日日骚网 | 午夜日韩 | 蜜桃传媒一区二区 | 精品亚洲一区二区三区 | 欧美乱淫视频 | 欧美激情精品久久久久久变态 | a免费观看 | 国产精品久久久久永久免费观看 | 国产精品一区二区视频 | 草草影院ccyy| 一级黄色毛片 | 91人人视频在线观看 | 亚洲狠狠 | www国产成人免费观看视频,深夜成人网 | 99久久精品免费看国产四区 | www.久| 青草久久免费视频 | 精品国产91| 久久久久久亚洲精品 | 亚洲在线一区二区 | 免费观看毛片 | 精品久久久久久久久久 | 夜夜艹 | 色在线免费视频 | 国产精品精品久久久 | 日韩精品一区二区三区第95 | 91影院在线观看 | 亚洲第一av网站 | 91久久久久| 日韩伦理电影免费在线观看 |