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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1302|回復: 0
收起左側

單片機RS485程序

[復制鏈接]
ID:735148 發表于 2020-4-23 10:25 | 顯示全部樓層 |閱讀模式

  1. #ifndef __485_C__
  2. #define __485_C__
  3. #include <reg51.h>
  4. #include <string.h>
  5. #define unsigned char uchar
  6. #define unsigned int uint
  7. /*
  8. 通信命令
  9. */
  10. #define __ACTIVE_ 0x01    //
  11. 主機詢問從機是否存在
  12. #define __GETDATA_ 0x02    //
  13. 主機發送讀設備請求
  14. #define __OK_ 0x03    //
  15. 從機應答
  16. #define __STATUS_ 0x04    //
  17. 從機發送設備狀態信息
  18. #define __MAXSIZE 0x08    //
  19. 緩沖區長度
  20. #define __ERRLEN 12    //
  21. 任何通信幀長度超過
  22. 12
  23. 則表示出錯
  24. uchar dbuf[__MAXSIZE];    //
  25. 該緩沖區用于保存設備狀態信息
  26. uchar dev;    //
  27. 該字節用于保存本機設備號
  28. sbit M_DE = P1^0;    //
  29. 驅動器使能,
  30. 1
  31. 有效
  32. sbit M_RE = P1^1;    //
  33. 接收器使能,
  34. 0
  35. 有效
  36. void get_status();    //
  37. 調用該函數獲得設備狀態信息,函數代碼未給出
  38. void send_data(uchar type, uchar len, uchar *buf);    //
  39. 發送數據幀
  40. bit recv_cmd(uchar *type);    //
  41. 接收主機命令,主機請求僅包含命令信息
  42. void send_byte(uchar da);    //
  43. 該函數發送一幀數據中的一個字節,

  44. send_data()

  45. 數調用
  46. void main()
  47. {
  48. uchar type;
  49. uchar len;
  50. /*
  51. 系統初始化
  52. */
  53. P1 = 0xff;    //
  54. 讀取本機設備號
  55. dev = (P1>>2);
  56. TMOD = 0x20; //
  57. 定時器
  58. T1
  59. 使用工作方式
  60. 2
  61. TH1 = 250;    //
  62. 設置初值
  63. TL1 = 250;
  64. TR1 = 1;    //
  65. 開始計時
  66. PCON = 0x80;    // SMOD = 1
  67. SCON = 0x50; //
  68. 工作方式
  69. 1
  70. ,波特率
  71. 9600bps
  72. ,允許接收
  73. ES = 0;    //
  74. 關閉串口中斷
  75. IT0 = 0;    //
  76. 外部中斷
  77. 0
  78. 使用電平觸發模式
  79. EX0 = 1;    //
  80. 開啟外部中斷
  81. 0
  82. EA = 1;    //
  83. 開啟中斷
  84. /*
  85. 主程序流程
  86. */
  87. while(1)    //
  88. 主循環
  89. {
  90.    if(recv_cmd(&type) == 0)    //
  91. 發生幀錯誤或幀地址與本機地址不符,
  92. 丟棄當前幀后
  93. 返回
  94.     continue;
  95.    switch(type)
  96.    {
  97.     case __ACTIVE_:    //
  98. 主機詢問從機是否存在
  99.      send_data(__OK_, 0, dbuf);    //
  100. 發送應答信息,這里
  101. buf
  102. 的內容并未用到
  103.      break;
  104.     case __GETDATA_:
  105.      len = strlen(dbuf);
  106.      send_data(__STATUS_, len, dbuf);    //
  107. 發送設備狀態信息
  108.      break;
  109.     default:
  110.      break;    //
  111. 命令類型錯誤,丟棄當前幀后返回
  112.    }
  113. }
  114. }
  115. void READSTATUS() interrupt 0 using 1    //
  116. 產生外部中斷
  117. 0
  118. 時表示設備狀態發生改
  119. 變,該函數使用寄存器組
  120. 1
  121. {
  122. get_status();    //
  123. 獲得設備狀態信息,并將其存入
  124. dbuf
  125. 指向的存儲區,數據最后一字
  126. 節置
  127. 0
  128. 表示數據結束
  129. }
  130. /*
  131. 該函數接收一幀數據并進行檢測,無論該幀是否錯誤,函數均會返回
  132. *
  133. 函數參數
  134. type
  135. 保存接收到的命令字
  136. *
  137. 當接收到數據幀錯誤或其地址位不為
  138. 0
  139. 時(非主機發送幀),函數返回
  140. 0
  141. ,反之返回
  142. 1
  143. */
  144. bit recv_cmd(uchar *type)
  145. {
  146. bit db = 0;    //
  147. 當接收到的上一個字節為
  148. 0xdb
  149. 時,該位置位
  150. bit c0 = 0;    //
  151. 當接收到的上一個字節為
  152. 0xc0
  153. 時,該位置位
  154. uchar data_buf[__ERRLEN];    //
  155. 保存接收到的幀
  156. uchar tmp;
  157. uchar ecc = 0;
  158. uchar i;
  159. M_DE = 0;    //
  160. 置發送禁止,接收允許
  161. M_RE = 0;
  162. /*
  163. 接收一幀數據
  164. */
  165. i = 0;
  166. while(!c0)    //
  167. 循環直至幀接收完畢
  168. {
  169.    RI = 0;
  170.    while(!RI);
  171.    tmp = SBUF;
  172.    RI = 0;
  173.    if(db == 1)    //
  174. 接收到的上一個字節為
  175. 0xdb
  176.    {
  177.     switch(tmp)
  178.     {
  179.      case 0xdd:
  180.       data_buf[i] = 0xdb;    // 0xdbdd
  181. 表示
  182. 0xdb
  183.       ecc = ecc^0xdb;
  184.       db = 0;
  185.       break;
  186.      case 0xdc
  187.       data_buf[i] = 0xc0;    // 0xdbdc
  188. 表示
  189. 0xc0
  190.       ecc = ecc^0xc0;
  191.       db = 0;
  192.       break;
  193.      default
  194.       return 0;    //
  195. 幀錯誤,返回
  196.     }
  197.     i++;
  198.    }
  199.    switch(tmp)    //
  200. 正常情況
  201.    {
  202.     case 0xc0:    //
  203. 幀結束
  204.      c0 = 1;
  205.      break;
  206.     case 0xdb:    //
  207. 檢測到轉義字符
  208.      db = 1;
  209.      break;
  210.     default:    //
  211. 普通數據
  212.      data_buf[i] = tmp;    //
  213. 保存數據
  214.      ecc = ecc^tmp;    //
  215. 計算校驗字節
  216.      i++;
  217.    }
  218.    if(i == __ERRLEN)    //
  219. 幀超長,錯誤,返回
  220.     return 0;
  221. }
  222. /*
  223. 判斷幀是否錯誤
  224. */
  225. if(i<4)    //
  226. 幀過短,錯誤,返回
  227.    return 0;
  228. if(ecc != 0)    //
  229. 校驗錯誤,返回
  230.    return 0;
  231. if(data_buf[0] != dev)    //
  232. 非訪問本機命令,錯誤,返回
  233.    return 0;
  234. *type = data_buf[1];    //
  235. 獲得命令字
  236. return 1;    //
  237. 函數成功返回
  238. }
  239. /*
  240. 該函數發送一幀數據幀,參數
  241. type
  242. 為命令字、
  243. len
  244. 為數據長度、
  245. buf
  246. 為要發送的數據內

  247. */
  248. void send_data(uchar type, uchar len, uchar *buf)
  249. {
  250. uchar i;
  251. uchar ecc = 0;    //
  252. 該字節用于保存校驗字節
  253. M_DE = 1;    //
  254. 置發送允許,接收禁止
  255. M_RE = 1;
  256. send_byte(dev);    //
  257. 發送本機地址
  258. ecc = dev;
  259. send_byte(type);    //
  260. 發送命令字
  261. ecc = ecc^type;
  262. send_byte(len);    //
  263. 發送長度
  264. ecc = ecc^len;
  265. for(i=0; i<len; i++)    //
  266. 發送數據
  267. {
  268.    send_byte(*buf);
  269.    ecc = ecc^(*buf);
  270.    buf++;
  271. }
  272. send_byte(ecc);    //
  273. 發送校驗字節
  274. TI = 0;    //
  275. 發送幀結束標志
  276. SBUF = 0xc0;
  277. while(!TI);
  278. TI = 0;
  279. }
  280. /*
  281. 該函數發送一個數據字節,若該字節為
  282. 0xdb
  283. ,則發送
  284. 0xdbdd
  285. ,若該字節為
  286. 0xc0
  287. 則,發

  288. 0xdbdc */
  289. void send_byte(uchar da)
  290. {
  291. switch(da)
  292. {
  293.    case 0xdb:    //
  294. 字節為
  295. 0xdb
  296. ,發送
  297. 0xdbdd
  298.     TI = 0;
  299.     SBUF = 0xdb;
  300.     while(!TI);
  301.     TI = 0;
  302.     SBUF = 0xdd;
  303.     while(!TI)
  304.     TI = 0;
  305.     break;
  306.    case 0xc0:    //
  307. 字節為
  308. 0xc0
  309. ,發送
  310. 0xdbdc
  311.     TI = 0;
  312.     SBUF = 0xdb;
  313.     while(!TI);
  314.     TI = 0;
  315.     SBUF = 0xdc;
  316.     while(!TI)
  317.     TI = 0;
  318.     break;
  319.    default:    //
  320. 普通數據則直接發送
  321.     TI = 0;
  322.     SBUF = da;
  323.     while(!TI);
  324.     TI = 0;
  325. }
  326. }
  327. #endif
復制代碼


評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 色女人天堂| 天天射中文| 人人操日日干 | 国产精品久久久久久久久久久久 | 91av在线视频观看 | 亚洲欧美精品久久 | 国产激情视频在线 | 国产精品高潮呻吟久久 | 日韩一区二区三区在线 | 精品欧美一区二区精品久久久 | 日韩欧美一区二区三区免费观看 | 欧美激情视频一区二区三区在线播放 | 中文字幕在线不卡播放 | 久久久久久久久91 | 久久久久av | 黄色a视频 | 日韩综合色 | 国产黄色在线 | 久久久久久久久久久福利观看 | 91成人在线 | 龙珠z国语版在线观看 | 日本aa毛片a级毛片免费观看 | 欧美中文字幕一区二区三区亚洲 | 国产成人亚洲精品 | 一区二区三区四区在线视频 | 国产精品福利在线 | 中文字幕一区二区视频 | 国产一区二区精品在线观看 | 一区二区三区四区免费在线观看 | 午夜精品久久久久久久久久久久 | 欧美aaaaaaaa| 黄免费在线 | 成人免费黄色 | 日韩在线电影 | 久久久久久久久久久久久久国产 | 日韩视频区 | 国产精品激情小视频 | 一区二区三区电影网 | 久久久av一区 | 福利影院在线看 | 精精国产xxxx视频在线播放7 |