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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

51單片機(jī)實現(xiàn)的485通訊程序②

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:71259 發(fā)表于 2014-12-30 00:53 | 只看該作者 回帖獎勵 |正序瀏覽 |閱讀模式
  1. /**********************************************************************************
  2. 一般的單片機(jī)多機(jī)通訊的情況是:
  3. 1.PC向特定單片機(jī)發(fā)送命令,該單片機(jī)收到后回應(yīng)PC,也就是說不存在幾個單片機(jī)同時向PC發(fā)數(shù)據(jù)的情況。
  4. 2.PC以廣播的形式發(fā)送命令,也就是所有單片機(jī)都收到命令,在這種情況下一般都是對單片機(jī)進(jìn)行初始設(shè)置(此時所有單片機(jī)一般都不做應(yīng)答)
  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    //起始標(biāo)志位
  13. #define __STOP_    0xc0    //結(jié)束標(biāo)志位
  14. #define __ACTIVE_  0x01    // 主機(jī)詢問從機(jī)是否存在
  15. #define __GETDATA_ 0x02    // 主機(jī)發(fā)送讀設(shè)備請求
  16. #define __OK_      0x03    // 從機(jī)應(yīng)答
  17. #define __STATUS_  0x04    // 從機(jī)發(fā)送設(shè)備狀態(tài)信息

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

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

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

  31. uchar dev;    // 該字節(jié)用于保存本機(jī)設(shè)備號
  32. uchar len ;   // 該字節(jié)用于保存發(fā)送設(shè)備信息的長度
  33. uchar type;   // 該字節(jié)用于保存命令字

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

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


  40. uchar Recv_Flag,Recv_Over_Flag;  //接受允許標(biāo)志,接受完成標(biāo)志
  41. uchar uart_i;    //幀數(shù)據(jù)計數(shù)

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

  46. TMOD = 0x20; // 定時器T1使用工作方式2
  47. TH1 = 0xfd;    // 設(shè)置初值
  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;    // 置發(fā)送禁止,接收允許
  55. M_RE = 0;


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

  78. }
  79. }


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

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



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

  90. // ES=0;

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

  93. /* 接收一幀數(shù)據(jù) */
  94.   for(i=0,j=0;i<uart_i;i++) // 循環(huán)直至幀接收完畢  
  95. {
  96.   
  97.     if(db == 1)    // 接收到的上一個字節(jié)為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:    // 檢測到轉(zhuǎn)義字符
  125.            db = 1;
  126.            break;
  127.        default:    // 普通數(shù)據(jù)
  128.               rec_buf2[j] = rec_buf1[i];    // 保存數(shù)據(jù)
  129.                j++;       // 計算校驗字節(jié)
  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)    // 非訪問本機(jī)命令,錯誤,返回
  142.       return 0;

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

  144. return 1;    // 函數(shù)成功返回
  145. }


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

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

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

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

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

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

  172. TI = 0;    // 發(fā)送幀結(jié)束標(biāo)志
  173. SBUF = 0xc0;
  174. while(!TI);
  175. TI = 0;

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

  178. //該函數(shù)發(fā)送一個數(shù)據(jù)字節(jié),若該字節(jié)為0xdb,則發(fā)送0xdbdd,若該字節(jié)為0xc0則,發(fā)送0xdbdc
  179. void send_byte(uchar da)
  180. {
  181. switch(da)
  182. {
  183.     case 0xdb:    // 字節(jié)為0xdb,發(fā)送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:    // 字節(jié)為0x0c,發(fā)送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:    // 字節(jié)為0xc0,發(fā)送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:    // 普通數(shù)據(jù)則直接發(fā)送
  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;  //接收數(shù)據(jù)
  231.   if(tmp==__START_) //幀起始標(biāo)志
  232.   {
  233.          uart_i=0;
  234.    Recv_Flag=1;  //接受數(shù)據(jù)標(biāo)志
  235.   }
  236.   else if(tmp==__STOP_) //幀結(jié)束標(biāo)志
  237.   {
  238.    if(Recv_Flag==1)
  239.     Recv_Over_Flag=1;
  240.    Recv_Flag=0;
  241.   }
  242.   else if(Recv_Flag==1)  //開始接受幀數(shù)據(jù)
  243.   {
  244.    rec_buf1[uart_i]=tmp;
  245.    uart_i++;
  246.   }
  247.    if( uart_i >= MAXSIZE )  //超過緩沖區(qū)長度
  248.    {
  249.     uart_i = 0;
  250.    Recv_Flag=0;
  251.        Recv_Over_Flag = 1;       //接收一幀數(shù)據(jù)完畢            
  252.    }
  253. }

  254.   
  255. }
復(fù)制代碼


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

相關(guān)帖子

回復(fù)

使用道具 舉報

沙發(fā)
ID:136238 發(fā)表于 2016-9-10 21:21 | 只看該作者
請問是主機(jī)程序。還是從機(jī),我不懂
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

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

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