找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 1313|回復(fù): 0
收起左側(cè)

單片機(jī)RS485程序

[復(fù)制鏈接]
ID:735148 發(fā)表于 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. 主機(jī)詢問從機(jī)是否存在
  12. #define __GETDATA_ 0x02    //
  13. 主機(jī)發(fā)送讀設(shè)備請(qǐng)求
  14. #define __OK_ 0x03    //
  15. 從機(jī)應(yīng)答
  16. #define __STATUS_ 0x04    //
  17. 從機(jī)發(fā)送設(shè)備狀態(tài)信息
  18. #define __MAXSIZE 0x08    //
  19. 緩沖區(qū)長(zhǎng)度
  20. #define __ERRLEN 12    //
  21. 任何通信幀長(zhǎng)度超過
  22. 12
  23. 則表示出錯(cuò)
  24. uchar dbuf[__MAXSIZE];    //
  25. 該緩沖區(qū)用于保存設(shè)備狀態(tài)信息
  26. uchar dev;    //
  27. 該字節(jié)用于保存本機(jī)設(shè)備號(hào)
  28. sbit M_DE = P1^0;    //
  29. 驅(qū)動(dòng)器使能,
  30. 1
  31. 有效
  32. sbit M_RE = P1^1;    //
  33. 接收器使能,
  34. 0
  35. 有效
  36. void get_status();    //
  37. 調(diào)用該函數(shù)獲得設(shè)備狀態(tài)信息,函數(shù)代碼未給出
  38. void send_data(uchar type, uchar len, uchar *buf);    //
  39. 發(fā)送數(shù)據(jù)幀
  40. bit recv_cmd(uchar *type);    //
  41. 接收主機(jī)命令,主機(jī)請(qǐng)求僅包含命令信息
  42. void send_byte(uchar da);    //
  43. 該函數(shù)發(fā)送一幀數(shù)據(jù)中的一個(gè)字節(jié),

  44. send_data()

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

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

  288. 0xdbdc */
  289. void send_byte(uchar da)
  290. {
  291. switch(da)
  292. {
  293.    case 0xdb:    //
  294. 字節(jié)為
  295. 0xdb
  296. ,發(fā)送
  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. 字節(jié)為
  308. 0xc0
  309. ,發(fā)送
  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. 普通數(shù)據(jù)則直接發(fā)送
  321.     TI = 0;
  322.     SBUF = da;
  323.     while(!TI);
  324.     TI = 0;
  325. }
  326. }
  327. #endif
復(fù)制代碼


評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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