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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 10817|回復: 1
收起左側

51單片機實現的485通訊程序②

[復制鏈接]
ID:71259 發表于 2014-12-30 00:53 | 顯示全部樓層 |閱讀模式
  1. /**********************************************************************************
  2. 一般的單片機多機通訊的情況是:
  3. 1.PC向特定單片機發送命令,該單片機收到后回應PC,也就是說不存在幾個單片機同時向PC發數據的情況。
  4. 2.PC以廣播的形式發送命令,也就是所有單片機都收到命令,在這種情況下一般都是對單片機進行初始設置(此時所有單片機一般都不做應答)
  5. **********************************************************************************/

  6. #include<reg51.h>
  7. #include<string.h>

  8. #define  uchar unsigned char
  9. #define  uint   unsigned int
  10.      
  11. /* 通信命令 */
  12. #define __START_   0x0c    //起始標志位
  13. #define __STOP_    0xc0    //結束標志位
  14. #define __ACTIVE_  0x01    // 主機詢問從機是否存在
  15. #define __GETDATA_ 0x02    // 主機發送讀設備請求
  16. #define __OK_      0x03    // 從機應答
  17. #define __STATUS_  0x04    // 從機發送設備狀態信息

  18. /****************************幀格式****************************
  19.    -目的地址-命令字-數據-校驗碼-      至少4個字節
  20.   主機地址為0x00, 從機地址為1-244,廣播地址255

  21.    轉義字符的處理:
  22.    0xdb 0xdd 代表 0xdb
  23.   0xdb 0xdc 代表 0xc0
  24.   0xdb 0xde 代表 0x0c
  25. *************************************************************/

  26. #define MAXSIZE 0x0a    // 緩沖區長度10
  27. uchar send_buf[MAXSIZE]={0xdb,0x0c,0xc0};    // 該緩沖區用于保存設備狀態信息
  28. //uchar send_buf[MAXSIZE]={0xcd,0xcb,0xbc};
  29. uchar rec_buf1[MAXSIZE];  // 保存接收到的幀
  30. uchar rec_buf2[MAXSIZE];   //保存處理過的幀

  31. uchar dev;    // 該字節用于保存本機設備號
  32. uchar len ;   // 該字節用于保存發送設備信息的長度
  33. uchar type;   // 該字節用于保存命令字

  34. sbit M_DE = P1^0;    // 驅動器使能,1有效
  35. sbit M_RE = P1^1;    // 接收器使能,0有效

  36. void get_status();      // 調用該函數獲得設備狀態信息,函數代碼未給出
  37. void send_data(uchar type, uchar len, uchar *send_buf);    // 發送數據幀
  38. bit recv_cmd(uchar *type);    // 接收主機命令,主機請求僅包含命令信息
  39. void send_byte(uchar da);    // 該函數發送一幀數據中的一個字節,由send_data()函數調用


  40. uchar Recv_Flag,Recv_Over_Flag;  //接受允許標志,接受完成標志
  41. uchar uart_i;    //幀數據計數

  42. void main()
  43. {
  44. /* 系統初始化 */
  45. dev =0xff;  //設備號

  46. TMOD = 0x20; // 定時器T1使用工作方式2
  47. TH1 = 0xfd;    // 設置初值
  48. TL1 = 0xfd;
  49. TR1 = 1;    // 開始計時
  50. PCON = 0x00;    // bps不倍增
  51. SCON = 0x50; // 工作方式1,波特率9600bps,允許接收
  52. ES = 1;    // 開串口中斷
  53. EA = 1;    // 開啟中斷

  54. M_DE = 0;    // 置發送禁止,接收允許
  55. M_RE = 0;


  56. /* 主程序流程 */
  57. while(1)    // 主循環
  58. {
  59.   if(Recv_Over_Flag==1){
  60.       if(recv_cmd(&type) ==1){
  61.       switch(type)
  62.      {
  63.         case __ACTIVE_:    // 主機詢問從機是否存在
  64.             send_data(__OK_, 0, send_buf);    // 發送應答信息,這里buf的內容并未用到
  65.             break;
  66.         case __GETDATA_:
  67.             len=strlen(send_buf);
  68.             send_data(__STATUS_, len, send_buf);    // 發送設備狀態信息
  69.                break;
  70.         default:
  71.         break;    // 命令類型錯誤,丟棄當前幀后返回
  72.             
  73.      }
  74.      Recv_Over_Flag=0;   //一定要清零
  75.      uart_i=0;      //
  76.    }
  77.   }   

  78. }
  79. }


  80. /* 該函數接收一幀數據并進行檢測,無論該幀是否錯誤,函數均會返回
  81. * 函數參數type保存接收到的命令字
  82. * 當接收到數據幀錯誤或其地址位不為0時(非主機發送幀),函數返回0,反之返回1
  83. */

  84. bit recv_cmd(uchar *type)
  85. {
  86. bit db = 0;    // 當接收到的上一個字節為0xdb時,該位置位
  87. bit c0 = 0;    // 當接收到的上一個字節為0xc0時,該位置位



  88. uchar sum = 0;
  89. uchar i,j;

  90. // ES=0;

  91. M_DE = 1;    // 置發送允許,接收禁止
  92. M_RE = 1;

  93. /* 接收一幀數據 */
  94.   for(i=0,j=0;i<uart_i;i++) // 循環直至幀接收完畢  
  95. {
  96.   
  97.     if(db == 1)    // 接收到的上一個字節為0xdb
  98.     {
  99.         switch(rec_buf1[i])
  100.         {
  101.         case 0xdd:
  102.          rec_buf2[j] = 0xdb;    // 0xdbdd表示0xdb
  103.       
  104.          db = 0;
  105.          break;
  106.         case 0xdc:
  107.          rec_buf2[j] = 0xc0;    // 0xdbdc表示0xc0
  108.      
  109.          db = 0;
  110.          break;
  111.       case 0xde:
  112.          rec_buf2[j] = 0x0c;    // 0xdbdc表示0xc0
  113.      
  114.          db = 0;
  115.          break;
  116.         default :
  117.          return 0;    // 幀錯誤,返回
  118.         }
  119.       j++;
  120.     }
  121.    else{
  122.       switch(rec_buf1[i])    // 正常情況
  123.       {
  124.        case 0xdb:    // 檢測到轉義字符
  125.            db = 1;
  126.            break;
  127.        default:    // 普通數據
  128.               rec_buf2[j] = rec_buf1[i];    // 保存數據
  129.                j++;       // 計算校驗字節
  130.          
  131.       }
  132.     }
  133. }
  134.   
  135. /* 判斷幀是否錯誤 */

  136. for(i=0;i<j-1;i++)
  137.   sum+=rec_buf2[i];
  138. sum=sum%256;
  139. if(sum !=rec_buf2[j-1] )    // 校驗錯誤,返回
  140.       return 0;


  141.   if(rec_buf2[0] != dev)    // 非訪問本機命令,錯誤,返回
  142.       return 0;

  143. *type = rec_buf2[1];    // 獲得命令字

  144. return 1;    // 函數成功返回
  145. }


  146. // 該函數發送一幀數據幀,參數type為命令字、len為數據長度、buf為要發送的數據內容
  147. void send_data(uchar type, uchar len, uchar *send_buf)
  148. {

  149. uchar i;
  150. uchar sum = 0;    // 該字節用于保存校驗字節
  151.   
  152. ES=0; //關串口中斷!!!!

  153. M_DE = 1;    // 置發送允許,接收禁止
  154. M_RE = 1;

  155. TI = 0;    // 發送幀開始標志
  156. SBUF = 0x0c;
  157. while(!TI);
  158. TI=0;

  159. send_byte(0x00);    // 發送目的地址
  160. sum+=0x00;  //假設主機地址為0x00
  161. send_byte(type);    // 發送命令字
  162. sum+=type;
  163. //send_byte(len);    // 發送長度

  164. for(i=0; i<len; i++)    // 發送數據
  165. {
  166.     send_byte(*send_buf);
  167.     sum =sum+ (*send_buf);
  168.     send_buf++;
  169. }
  170. sum%=256;
  171. send_byte(sum);    // 發送校驗字節

  172. TI = 0;    // 發送幀結束標志
  173. SBUF = 0xc0;
  174. while(!TI);
  175. TI = 0;

  176. ES=1;  //開串口中斷
  177. }

  178. //該函數發送一個數據字節,若該字節為0xdb,則發送0xdbdd,若該字節為0xc0則,發送0xdbdc
  179. void send_byte(uchar da)
  180. {
  181. switch(da)
  182. {
  183.     case 0xdb:    // 字節為0xdb,發送0xdbdd
  184.         TI = 0;
  185.         SBUF = 0xdb;
  186.         while(!TI);
  187.         TI = 0;
  188.    
  189.         SBUF = 0xdd;
  190.         while(!TI)
  191.         TI = 0;
  192.    
  193.         break;  
  194.     case 0x0c:    // 字節為0x0c,發送0xdbde
  195.      TI = 0;
  196.         SBUF = 0xdb;
  197.         while(!TI);
  198.         TI = 0;
  199.    
  200.         SBUF = 0xde;
  201.         while(!TI)
  202.         TI = 0;
  203.    
  204.         break;

  205.        case 0xc0:    // 字節為0xc0,發送0xdbdc
  206.         TI = 0;
  207.         SBUF = 0xdb;
  208.         while(!TI);
  209.         TI = 0;
  210.    
  211.         SBUF = 0xdc;
  212.         while(!TI)
  213.         TI = 0;
  214.    
  215.         break;  
  216.          
  217.     default:    // 普通數據則直接發送
  218.         TI = 0;
  219.         SBUF = da;
  220.         while(!TI);
  221.         TI = 0;
  222. }
  223. }



  224. void uart( ) interrupt 4          //串口中斷
  225. {
  226. uchar tmp;

  227. if( RI==1 )
  228. {
  229.   RI = 0;
  230.   tmp  = SBUF;  //接收數據
  231.   if(tmp==__START_) //幀起始標志
  232.   {
  233.          uart_i=0;
  234.    Recv_Flag=1;  //接受數據標志
  235.   }
  236.   else if(tmp==__STOP_) //幀結束標志
  237.   {
  238.    if(Recv_Flag==1)
  239.     Recv_Over_Flag=1;
  240.    Recv_Flag=0;
  241.   }
  242.   else if(Recv_Flag==1)  //開始接受幀數據
  243.   {
  244.    rec_buf1[uart_i]=tmp;
  245.    uart_i++;
  246.   }
  247.    if( uart_i >= MAXSIZE )  //超過緩沖區長度
  248.    {
  249.     uart_i = 0;
  250.    Recv_Flag=0;
  251.        Recv_Over_Flag = 1;       //接收一幀數據完畢            
  252.    }
  253. }

  254.   
  255. }
復制代碼


回復

使用道具 舉報

ID:136238 發表于 2016-9-10 21:21 | 顯示全部樓層
請問是主機程序。還是從機,我不懂
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 狠狠影院 | 色爱综合网 | 成人激情视频在线播放 | 毛片一区| 久久精品二区亚洲w码 | 性在线| 国产精品久久久久免费 | 国产精品久久久久久久久久久久冷 | 一级片在线观看 | 999久久久国产精品 欧美成人h版在线观看 | 亚洲一区二区久久久 | 老司机深夜福利网站 | 欧美日韩精品一区二区天天拍 | 国产日韩欧美 | 成人欧美一区二区三区黑人孕妇 | 欧美综合国产精品久久丁香 | 国产91综合一区在线观看 | 男人天堂av网站 | 国产精品视频久久久久 | 亚欧精品一区 | 日韩精品久久久 | 99精品久久久 | 91精品国产手机 | 久久网站免费视频 | 国产精品美女久久久久久免费 | 精品九九| 99re66在线观看精品热 | 欧洲性生活视频 | 99热这里 | 亚洲国产成人精品久久久国产成人一区 | 午夜国产一区 | 国产免费一区 | 精品国产综合 | 电影91久久久 | 国产精品国产精品国产专区不蜜 | 亚洲一区毛片 | 久久久久网站 | 一区二区三区在线播放 | 国产精品区二区三区日本 | 国产免费一区二区三区免费视频 | 国产精品综合色区在线观看 |