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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

51單片機串口怎么接收數字(不是字符)?

  [復制鏈接]
回帖獎勵 25 黑幣 回復本帖可獲得 5 黑幣獎勵! 每人限 1 次
跳轉到指定樓層
樓主
我使用一個上位機通過串口發送數據給單片機,但是只能發送單個字符才能控制單片機。怎么發送字符串讓單片機接收后,把這個字符串轉為數字?網上找參考程序搞了一個晚上也弄不出來。void Uart_Isr() interrupt 4
{
                                                                    
        uchar receive_data;

        EA = 0;
          if(RI == 1)
        {
                    RI = 0;
                    receive_data = SBUF;
                if(receive_data=='0')
                {
                        LED=0;        
                }
                else if(receive_data=='1')
                {
                        LED=1;               
                }
                else
                {

                               //處理我發送的字符串數據
                   }         
        TI=0;   
        EA = 1;                                                                     
}

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:213173 發表于 2021-5-28 06:15 | 只看該作者
串口一次只能傳輸1個字節,傳輸字符串就是連續傳輸若干字節。傳輸的是數字或字符與串口功能本身無關,是由通信協議確定的。一個最簡單的自定義通信協議通常由若干字節組成一幀數據。串口中斷函數只負責把收到的一幀數據按序保存在緩沖數組中,只發送接收完成標志,不對數據進行處理。在主函數中判斷接收完成后對收到的數據進行解析處理,執行相關任務。

  1. void UARTInterrupt() interrupt 4
  2. {
  3.         static unsigned char num=0;        //靜態變量
  4.         RI=0;                                        //接收中斷請求標志位清0
  5.         rec_buf[num]=SBUF;                //保存SBUF接收到的數據
  6.         if(rec_buf[0]==0xaa)        //驗證數據頭,否則被下一個數據覆蓋
  7.         {
  8.                 num++;
  9.                 if(num>=x)                        //x=字符串長度
  10.                 {
  11.                         flag=1;                        //接收完成標志置1
  12.                         num=0;
  13.                 }
  14.         }
  15. }
復制代碼
回復

使用道具 舉報

板凳
ID:744327 發表于 2021-5-28 08:29 | 只看該作者
串行通信一次只能傳輸1個字節,若傳輸多個字節或傳輸字符串,需要連續傳輸若干字節。
回復

使用道具 舉報

地板
ID:97350 發表于 2021-5-28 08:57 | 只看該作者
#include<reg52.h>

//------------------串口通信的數據包協議-----------------//
/*
    此程序的串口字符串通信使用到下面的一個自定義協議,每次通信都是發送或接收一個數據包,數據包格式解釋如下(長度恒為15):
    例如:A01_fmq_01Off___#
    A--------數據包的開始標記(可以為A到Z,意味著數據包可以有26種)
    01-----設備代號
    fmq_01Off___--------指令(長度恒為10),指令的前4個人字符是指令頭部,指令的后6個字符是指令尾部
    #---------數據包的結束標記

    例如:A02_SenT010250#
    A--------數據包的開始標記(可以為A到Z,意味著數據包可以有26種)
    02-----設備代號
    SenT010250--------指令(長度恒為10),指令的前4個人字符是指令頭部,指令的后6個字符是指令尾部
    #---------數據包的結束標記
*/
char RecvString_buf[16];            //定義數據包長度為15個字符
#define deviceID_1Bit '0'                //用于串口通信時,定義本地設備ID的第1位
#define deviceID_2Bit '2'                //用于串口通信時,定義本地設備ID的第2位
#define datapackage_headflag 'A'        //用于串口通信時,定義數據包頭部的驗證標記

char DataPackage_DS18B20[16]={datapackage_headflag,deviceID_1Bit,deviceID_2Bit,'_','S','e','n','T','X','X','X','X','X','X','#'};    //這個是曾經用來控制溫度傳感模塊(DS18B20)的數據包
char HeartBeat[16]={datapackage_headflag,deviceID_1Bit,deviceID_2Bit,'_','B','e','a','t','X','X','X','X','X','X','#'};            //我隨便定義了一個數據包用來做"心跳包",比如單片機系統向電腦每2秒發送一次該數據包,如果電腦沒有按時接收到,就認為單片機死掉了
//----------------------------------------------//
/*******************************
            串口通信
    MCU:89C52RC        11.0592MHz

//11.0592MHz 0xd0 1200bps
//12MHz 0xcc 1200bps
//11.0592MHz 0xfa 9600bps
//0xf4 11.0592MHz  0xf3 12MHz 4800bps
//均在SMOD=1的情況下(波特率倍增模式)
*******************************/
//串口發送函數
void PutString(unsigned char *TXStr)
{
    ES=0;
     while(*TXStr!=0)
    {
        SBUF=*TXStr;
        while(TI==0);
        TI=0;
        TXStr++;
    }
    ES=1;
}
//串口接收函數
bit ReceiveString()
{
    char * RecStr=RecvString_buf;
    char num=0;
    unsigned char count=0;
    loop:
    *RecStr=SBUF;
    count=0;
    RI=0;
    if(num<14)  //數據包長度為15個字符,嘗試連續接收15個字符
    {
        num++;
        RecStr++;
        while(!RI)
        {
            count++;
            if(count>130)return 0;    //接收數據等待延遲,等待時間太久會導致CPU運算閑置,太短會出現"數據包被分割",默認count=130
        }
        goto loop;
    }
    return 1;
}
//定時器1用作波特率發生器
void Init_USART()
{
    SCON=0x50;  //串口方式1,使能接收
    TMOD|=0x20;  //定時器1工作方式2(8位自動重裝初值)
    TMOD&=~0x10;
    TH1=0xfa;   //9600bps
    TL1=0xfa;
    PCON|=0x80;  //SMOD=1
    TR1=1;
    TI=0;
    RI=0;
    //PS=1;   //提高串口中斷優先級
    ES=1;  //開啟串口中斷使能
}
//比較指令頭部
bit CompareCMD_head(char CMD_head[])
{
    unsigned char CharNum;
    for(CharNum=0;CharNum<4;CharNum++)  //指令長度為10個字符
    {
        if(!(RecvString_buf[CharNum+4]==CMD_head[CharNum]))
        {
            return 0;  //指令頭部匹配失敗
        }
    }
    return 1;        //指令頭部匹配成功
}
//比較指令尾部(start:從哪里開始比較,quality:比較多少個字符,CMD_tail[]:要比較的字符串)
bit CompareCMD_tail(unsigned char start,unsigned char quality,char CMD_tail[])
{
    unsigned char CharNum;
    for(CharNum=0;CharNum<quality;CharNum++)
    {
        if(!(RecvString_buf[start+CharNum]==CMD_tail[CharNum]))
        {
            return 0;
        }
    }
    return 1;
}
bit Deal_UART_RecData()   //處理串口接收數據包函數(成功處理數據包則返回1,否則返回0)
{
    //PutString(RecvString_buf);
    if(RecvString_buf[0]==datapackage_headflag&&buf_string[14]=='#')  //進行數據包頭尾標記驗證
    {
        switch(RecvString_buf[1])        //識別發送者設備ID的第1位數字
        {
            case '0':
                switch(RecvString_buf[2])        //識別發送者設備ID的第2位數字
                {
                    case '3':
                        if(CompareCMD_head("Ligt"))    //判斷指令頭部是否為"Ligt"
                        {
                            //下面是指令尾部分析
                            switch(RecvString_buf[8])
                            {
                                case '0':
                                    switch(RecvString_buf[9])
                                    {
                                        case '0':

                                            return 0;
                                        case '1':
                                            if(CompareCMD_tail(10,3,"Off"))   //判斷整個數據包是否為:A03_Ligt01Off_#
                                            {
                                                //如果是則執行以下代碼
                                                return 1;
                                            }
                                            if(CompareCMD_tail(10,3,"On_"))    //判斷整個數據包是否為:A03_Ligt01On__#
                                            {
                                                //如果是則執行以下代碼
                                                return 1;
                                            }
                                            return 0;
                                        default:
                                            return 0;
                                    }
                                default:
                                    return 0;
                            }
                        }
                        return 0;

                    default:
                        return 0;
                }
            default:
                return 0;
        }
    }
    return 0;
}
/************************
        中斷函數
************************/
//串口中斷服務函數-----------
void USART() interrupt 4   //標志位TI和RI需要手動復位,TI和RI置位共用一個中斷入口
{
    if(ReceiveString())
    {
        //數據包長度正確則執行以下代碼
        Deal_UART_RecData();
    }
    else
    {
        //數據包長度錯誤則執行以下代碼
        //LED1=~LED1;
    }
    RI=0;  //接收并處理一次數據后把接收中斷標志清除一下,拒絕響應在中斷接收忙的時候發來的請求
}
/***************************
        主函數
***************************/
void main()
{
    EA=1;
    Init_USART();    //初始化串口中斷通信,當串口接受完數據包后,如果檢測到數據包包含有效指令,則自動執行對應的代碼,執行完自動返回到主函數,為了盡可能不影響主函數的時序,串口中斷函數的執行代碼不要過復雜
    while(1)
    {
    //下面可以放要經常運行的用戶代碼,使用PutString()函數來發送數據包,如PutString(HeartBeat);    注:空格的ASCLL碼是:0x20,回車是:0x0D


    }
}
回復

使用道具 舉報

5#
ID:277550 發表于 2021-5-28 09:02 | 只看該作者
先理解數據類型,和存儲方法

像int是2個byte、所以串口通訊要傳輸2個字節,接收端收到后、再組合起來
回復

使用道具 舉報

6#
ID:570093 發表于 2021-5-28 09:12 | 只看該作者
wulin 發表于 2021-5-28 06:15
串口一次只能傳輸1個字節,傳輸字符串就是連續傳輸若干字節。傳輸的是數字或字符與串口功能本身無關,是由 ...

那就是串口接收字符串后怎么轉為數字?比如發送“123”,接收到字符串怎么轉為整型數字123?
回復

使用道具 舉報

7#
ID:213173 發表于 2021-5-28 15:27 | 只看該作者
96317 發表于 2021-5-28 09:12
那就是串口接收字符串后怎么轉為數字?比如發送“123”,接收到字符串怎么轉為整型數字123?

0~9數字轉字符ASCII碼+48(0x30),同理0~9字符轉數字-48(0x30)。


回復

使用道具 舉報

8#
ID:570093 發表于 2021-5-28 16:01 | 只看該作者
wulin 發表于 2021-5-28 15:27
0~9數字轉字符ASCII碼+48(0x30),同理0~9字符轉數字-48(0x30)。

這個我知道,但是發送一串字符串的時候就得知道字符串長度,在keil中使用strlen()會報錯說缺少函數原型
回復

使用道具 舉報

9#
ID:213173 發表于 2021-5-28 16:43 | 只看該作者
96317 發表于 2021-5-28 16:01
這個我知道,但是發送一串字符串的時候就得知道字符串長度,在keil中使用strlen()會報錯說缺少函數原型

對于固定字節長度的字符串,這個問題很好處理。對于不固定字節長度的字符串,接收完成時就已知字節長度。如果程序無法知道什么時候接收完成就要開一個定時器中斷,每接收一個字節定時器復位,在達到設定時間沒有收到新的數據定時器中斷發生,就以此判斷為一幀數據接收完成。接收的字節長度當然就知道了。
回復

使用道具 舉報

10#
ID:570093 發表于 2021-6-13 15:54 | 只看該作者
參考了一個藍牙發送的程序,經過測試可以用,比如串口發送“12”可以將其轉成整型數據12,發送字符串“12345”可以轉成整型數字12345。但是發現該程序跳出while()循環后想要使用發送過來的數據有點麻煩。
  1. #include<reg52.h>
  2. #include<intrins.h>
  3. #include <stdio.h>

  4. #define uchar unsigned char
  5. #define uint  unsigned int
  6. #define ulong  unsigned long

  7. uchar uart_receive_buffer[30];  //從串口接收的數據
  8. uint uart_receive_number=0;    //指示串口接收個數
  9. uchar receive_length;                   //串口發送字符串長度
  10. ulong str_to_int=0,int_bit=1;  //字符串轉整型數值、int-bit用來做10的n次方
  11. sbit led=P2^0;

  12. void Delay_1ms(uint i)//1ms延時
  13. {
  14.   uchar x,j;
  15.   
  16.   for(j=0;j<i;j++)
  17.     for(x=0;x<=148;x++);
  18. }

  19. void Com_Int(void) interrupt 4
  20. {
  21.   EA = 0;
  22.   if(RI == 1)
  23.   {  //當硬件接收到一個數據時,RI會置位
  24.     RI = 0;
  25.     uart_receive_buffer[uart_receive_number] = SBUF;  //這里減去48是因為從電腦中發送過來的數據是ASCII碼。
  26.     uart_receive_number++;
  27.   }
  28.   EA = 1;
  29. }

  30. void Com_Init(void) {
  31.   TMOD = 0x20;
  32.   PCON = 0x80;          //波特率加倍
  33.   SCON = 0x50;                                                                  
  34.   TH1=0XF3;                                //計數器初始值設置,注意串口軟件波特率是4800的
  35.   TL1 = 0XF3;
  36.   TR1 = 1;  //啟動定時器1
  37.   ES = 1;  //開串口中斷
  38.   EA = 1;  //開總中斷
  39. }

  40. void PostChar(uchar character)  
  41. {     
  42.             SBUF=character;   //發送單個字符
  43.             while(!TI);           // 等待發送數據完成發送完成TI會置1
  44.                 TI=0;                     //發送完成標志
  45. }



  46. void Main()
  47. {
  48.   uchar uart_receive_number_old=0;
  49.   uchar i=0,j;
  50.   Com_Init();
  51.   
  52.   while(1)
  53.   {
  54.                                                                                                                 
  55.     if(uart_receive_number_old!=uart_receive_number)
  56.         {
  57.       uart_receive_number_old=uart_receive_number;
  58.     }
  59.    
  60.     //如果單片機接收來自HC-xx模塊不少于1字節的串口數據,一定要加延時后再判斷是否
  61.     //還有串口數據在發送,這樣才能完整的接收一幀串口數據
  62.     Delay_1ms(20);
  63.    
  64.     //一段時間之后仍然相等,表示上位機發來的一串數據結束
  65.     if(uart_receive_number_old==uart_receive_number)
  66.         {
  67.       if(uart_receive_number)                 
  68.                 break;      
  69.     }
  70.   }
  71.   
  72. if(uart_receive_number)
  73. {
  74.         //led=~led;         //測試
  75.         receive_length=uart_receive_number;

  76.        
  77.         /*if(receive_length==6)         //////測試串口接收位數,串口軟件如果發送字符串1234,則接收位數為4
  78.                 led=~led;                                         */

  79.         uart_receive_number=0;
  80.     //串口有數據時,該做些什么就做什么吧
  81.         for(i=0;i<receive_length;i++)
  82.         {       
  83.                 PostChar(uart_receive_buffer[i]);//將接收到的數據放入到發送寄存器
  84.                 //Delay_1ms(10);                        //延時,作用為提高發送準確度,可適當調節延時時間
  85.                
  86.                 int_bit=1;
  87.                 for(j=receive_length-i-1;j>=1;j--)
  88.                         int_bit*=10;       
  89.                 str_to_int += (uart_receive_buffer[i]-'0')*int_bit;       
  90.                
  91.                                        
  92.         }
  93.        
  94.         //if(str_to_int==1000000)                //串口軟件發送的字符串要跟這里整形數據一樣才行,不然發送一次后悔一直發送且顯示不正常,暫時找不出原因
  95.         //        led=~led;
復制代碼



回復

使用道具 舉報

11#
ID:937124 發表于 2021-6-13 17:38 | 只看該作者
傳輸數字,可以吧數字拆分成字節,然后按順序傳輸;收到后再恢復就可以了;
回復

使用道具 舉報

12#
ID:937124 發表于 2021-6-13 17:40 | 只看該作者
一般數字,會是16位,32位,或更多位;只要拆封成8位一組,八位八位的傳過去就可以了;因為51,收發寄存器是8位的;
回復

使用道具 舉報

13#
ID:261837 發表于 2021-6-14 13:33 來自手機 | 只看該作者
加幀頭幀尾
回復

使用道具 舉報

14#
ID:883031 發表于 2021-6-15 09:30 | 只看該作者
接收到字符是ASCII碼,數字的話減掉30就是對應的數字。如:1的ASCII碼是31,減掉30就可以了。注意這里是16進制。
回復

使用道具 舉報

15#
ID:844772 發表于 2021-6-15 11:11 | 只看該作者
96317 發表于 2021-6-13 15:54
參考了一個藍牙發送的程序,經過測試可以用,比如串口發送“12”可以將其轉成整型數據12,發送字符串“1234 ...

有些常識還是要知道啊,比如51的int最大65535,不會等于你的1百萬的。還有不控制程序,它會跑飛的,所以都會讓它進死循環,但你讓它跳出了。
回復

使用道具 舉報

16#
ID:81196 發表于 2021-6-15 13:37 | 只看該作者
對于單片機,不管你是傳輸數字還是字符,其傳輸過程中都是16進制表示的.只是在你接收時解析或發送時轉義表示成你的內容對應的十六進制數據即可
回復

使用道具 舉報

17#
ID:811711 發表于 2021-6-16 11:00 | 只看該作者
首先要建議你多看看計算機組成原理,想不出來答案是因為缺少對計算機最本質的理解。
回復

使用道具 舉報

18#
ID:811711 發表于 2021-6-16 11:01 | 只看該作者
其次,你可以自己定義一個數據長度,標志位,或者還有別的思路可以解決這個問題但是還是建議多從計算機思維出發,計算機啥也不是只會遵守規則。
回復

使用道具 舉報

19#
ID:811711 發表于 2021-6-16 11:03 | 只看該作者
數字和字符都是同一種東西啊,只是你翻譯他的方式不一樣
回復

使用道具 舉報

20#
ID:880574 發表于 2021-11-14 12:01 | 只看該作者
lzl12399 發表于 2021-5-28 08:57
#include

//------------------串口通信的數據包協議-----------------//

這個里面的buf_string沒有定義啊
回復

使用道具 舉報

21#
ID:941439 發表于 2021-11-18 20:49 | 只看該作者
我建議你可以把要傳輸的字符串數據先轉換成int型數據,然后串口發送出去應該就可以了
回復

使用道具 舉報

22#
ID:897866 發表于 2021-11-27 18:43 | 只看該作者
可以參考0~9數字轉字符ASCII碼+48(0x30),同理0~9字符轉數字-48(0x30)。
回復

使用道具 舉報

23#
ID:1011216 發表于 2022-4-9 23:48 來自手機 | 只看該作者
我來說說我的思路,上位機把整型數據當做兩個字節發送給單片機,這個其實很好實現,在單片機端用左移八位命令把兩個字節分開,然后合并成原整數,通過實踐,低字節的數據是沒問題的,高字節怎么都不對。單片機做數據接收太不穩定了,不知有啥辦法可以解決這個數據穩定的問題
回復

使用道具 舉報

24#
ID:625730 發表于 2022-4-10 11:29 | 只看該作者
xinwenhyan 發表于 2022-4-9 23:48
我來說說我的思路,上位機把整型數據當做兩個字節發送給單片機,這個其實很好實現,在單片機端用左移八位命 ...

上位機發的都是8位的字符,比如你發12,就是發1和2的字符,單片機接收了以后,要轉換成數字1和2,然后1乘以10,再加2,得到12,要對照ascii碼表進行轉換。
回復

使用道具 舉報

25#
ID:1017168 發表于 2022-4-10 11:47 | 只看該作者
在數據的末尾減去"\0",將對應的字符ascii碼轉換成數字
回復

使用道具 舉報

26#
ID:480627 發表于 2022-4-11 15:35 | 只看該作者
基礎知識不足的弊端啊。。。。什么是二進制,什么是十六進制,怎么用,平時單片機或電腦又是怎么處理數據的。。。
回復

使用道具 舉報

27#
ID:1009420 發表于 2022-4-11 16:32 | 只看該作者
16位,32位,或更多位;只要拆封成8位一組,八位八位的傳過去就可以了
回復

使用道具 舉報

28#
ID:982617 發表于 2022-4-13 17:38 | 只看該作者
先把數據類型都統一了吧
回復

使用道具 舉報

29#
ID:593706 發表于 2022-4-14 08:43 | 只看該作者
用字節發送數組就可以
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 欧美在线一区二区三区 | 国产精品久久久久一区二区三区 | 亚洲二区在线 | 99re国产 | 色婷婷精品国产一区二区三区 | 日本在线中文 | 日本色高清 | 91精品久久久久久久久99蜜臂 | 中文字幕中文字幕 | 久久91精品国产一区二区 | 中文字幕一区二区三区四区五区 | 中国一级大黄大片 | 欧美精品第三页 | 欧美成视频| 免费激情av | 久久国产福利 | 国产一区视频在线 | 日本不卡免费新一二三区 | 欧美成人精品 | 97在线观视频免费观看 | 99re在线视频精品 | 日韩三级精品 | 亚洲性在线 | 99热精品在线 | 精品国产一级 | 久久尤物免费一区二区三区 | 一道本不卡 | 欧美日韩一区二区三区视频 | 欧美日韩在线一区二区三区 | 国产精品免费看 | 日韩国产一区二区三区 | 国产99久久 | 国产精品1区 | 天天玩天天干天天操 | 日韩免费视频一区二区 | 日本黄色高清视频 | 超碰在线人人 | 免费看片国产 | 综合精品久久久 | 久久久久亚洲精品 | 婷婷开心激情综合五月天 |