找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 14388|回复: 24
收起左侧

单片机RS485通讯例程源代码

  [复制链接]
ID:367013 发表于 2018-7-7 20:07 | 显示全部楼层 |阅读模式
0.png

单片机源程序如下:
  1. #include <reg52.h>
  2. #include <intrins.h>

  3. sbit RS485_DIR = P1^7;  //RS485方向选择引脚

  4. bit flagFrame = 0;  //帧接收完成标志,即接收到一帧新数据
  5. bit flagTxd = 0;    //单字节发送完成标志,用来替代TXD中断标志位
  6. unsigned char cntRxd = 0;   //接收字节计数器
  7. unsigned char pdata bufRxd[64];  //接收字节缓冲区

  8. extern void UartAction(unsigned char *buf, unsigned char len);

  9. /* 串口配置函数,baud-通信波特率 */
  10. void ConfigUART(unsigned int baud)
  11. {
  12.     RS485_DIR = 0; //RS485设置为接收方向
  13.     SCON  = 0x50;  //配置串口为模式1
  14.     TMOD &= 0x0F;  //清零T1的控制位
  15.     TMOD |= 0x20;  //配置T1为模式2
  16.     TH1 = 256 - (11059200/12/32)/baud;  //计算T1重载值
  17.     TL1 = TH1;     //初值等于重载值
  18.     ET1 = 0;       //禁止T1中断
  19.     ES  = 1;       //使能串口中断
  20.     TR1 = 1;       //启动T1
  21. }
  22. /* 软件延时函数,延时时间(t*10)us */
  23. void DelayX10us(unsigned char t)
  24. {
  25.     do {
  26.         _nop_();
  27.         _nop_();
  28.         _nop_();
  29.         _nop_();
  30.         _nop_();
  31.         _nop_();
  32.         _nop_();
  33.         _nop_();
  34.     } while (--t);
  35. }
  36. /* 串口数据写入,即串口发送函数,buf-待发送数据的指针,len-指定的发送长度 */
  37. void UartWrite(unsigned char *buf, unsigned char len)
  38. {
  39.     RS485_DIR = 1;  //RS485设置为发送
  40.     while (len--)   //循环发送所有字节
  41.     {
  42.         flagTxd = 0;      //清零发送标志
  43.         SBUF = *buf++;    //发送一个字节数据
  44.         while (!flagTxd); //等待该字节发送完成
  45.     }
  46.     DelayX10us(5);  //等待最后的停止位完成,延时时间由波特率决定
  47.     RS485_DIR = 0;  //RS485设置为接收
  48. }
  49. /* 串口数据读取函数,buf-接收指针,len-指定的读取长度,返回值-实际读到的长度 */
  50. unsigned char UartRead(unsigned char *buf, unsigned char len)
  51. {
  52.     unsigned char i;
  53.    
  54.     if (len > cntRxd)  //指定读取长度大于实际接收到的数据长度时,
  55.     {                  //读取长度设置为实际接收到的数据长度
  56.         len = cntRxd;
  57.     }
  58.     for (i=0; i<len; i++)  //拷贝接收到的数据到接收指针上
  59.     {
  60.         *buf++ = bufRxd[i];
  61.     }
  62.     cntRxd = 0;  //接收计数器清零
  63.    
  64.     return len;  //返回实际读取长度
  65. }
  66. /* 串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔 */
  67. void UartRxMonitor(unsigned char ms)
  68. {
  69.     static unsigned char cntbkp = 0;
  70.     static unsigned char idletmr = 0;

  71.     if (cntRxd > 0)  //接收计数器大于零时,监控总线空闲时间
  72.     {
  73.         if (cntbkp != cntRxd)  //接收计数器改变,即刚接收到数据时,清零空闲计时
  74.         {
  75.             cntbkp = cntRxd;
  76.             idletmr = 0;
  77.         }
  78.         else                   //接收计数器未改变,即总线空闲时,累积空闲时间
  79.         {
  80.             if (idletmr < 30)  //空闲计时小于30ms时,持续累加
  81.             {
  82.                 idletmr += ms;
  83.                 if (idletmr >= 30)  //空闲时间达到30ms时,即判定为一帧接收完毕
  84.                 {
  85.                     flagFrame = 1;  //设置帧接收完成标志
  86.                 }
  87.             }
  88.         }
  89.     }
  90.     else
  91.     {
  92.         cntbkp = 0;
  93.     }
  94. }
  95. /* 串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用 */
  96. void UartDriver()
  97. {
  98.     unsigned char len;
  99.     unsigned char pdata buf[40];

  100.     if (flagFrame) //有命令到达时,读取处理该命令
  101.     {
  102.         flagFrame = 0;
  103.         len = UartRead(buf, sizeof(buf)-2); //将接收到的命令读取到缓冲区中
  104.         UartAction(buf, len);  //传递数据帧,调用动作执行函数
  105.     }
  106. }
  107. /* 串口中断服务函数 */
  108. void InterruptUART() interrupt 4
  109. {
  110.     if (RI)  //接收到新字节
  111.     {
  112.         RI = 0;  //清零接收中断标志位
  113.         if (cntRxd < sizeof(bufRxd)) //接收缓冲区尚未用完时,
  114.         {                            //保存接收字节,并递增计数器
  115.             bufRxd[cntRxd++] = SBUF;
  116.         }
  117.     }
  118.     if (TI)  //字节发送完毕
  119.     {
  120.         TI = 0;   //清零发送中断标志位
  121.         flagTxd = 1;  //设置字节发送完成标志
  122.     }
  123. }
复制代码

所有资料51hei提供下载:
例程源代码.zip (40.17 KB, 下载次数: 364)

评分

参与人数 1黑币 +5 收起 理由
zalkaer + 5 赞一个!

查看全部评分

回复

使用道具 举报

ID:385149 发表于 2018-8-10 23:13 | 显示全部楼层
谢谢分享。黑币不够了。
回复

使用道具 举报

ID:385160 发表于 2018-8-11 00:49 来自手机 | 显示全部楼层
恩,很好,我也想学学
回复

使用道具 举报

ID:385160 发表于 2018-8-11 00:52 来自手机 | 显示全部楼层
谢谢分享,我也是黑币不够
回复

使用道具 举报

ID:20672 发表于 2018-10-7 15:41 | 显示全部楼层
谢谢分享~~~
回复

使用道具 举报

ID:284846 发表于 2018-10-7 16:23 | 显示全部楼层
学习中,谢谢!
回复

使用道具 举报

ID:63317 发表于 2019-1-24 09:04 | 显示全部楼层
谢谢分享资料
回复

使用道具 举报

ID:151749 发表于 2019-1-28 23:12 来自手机 | 显示全部楼层
谢谢提供
回复

使用道具 举报

ID:63317 发表于 2019-1-29 08:14 | 显示全部楼层
谢谢分享资料
回复

使用道具 举报

ID:9727 发表于 2019-1-29 10:33 | 显示全部楼层
太感谢了
回复

使用道具 举报

ID:470175 发表于 2019-4-17 09:57 | 显示全部楼层
不试一遍,不搭一次硬件我是理解不聊了
回复

使用道具 举报

ID:156532 发表于 2019-4-24 21:06 | 显示全部楼层
谢谢分享  正好要用到RS485进行通讯
回复

使用道具 举报

ID:521831 发表于 2019-4-25 22:28 | 显示全部楼层
请问有不带DIR端的自动控制流向的模块的例程吗?
回复

使用道具 举报

ID:47652 发表于 2019-4-29 20:03 | 显示全部楼层
最好有仿真哦
回复

使用道具 举报

ID:525138 发表于 2019-4-30 14:57 | 显示全部楼层
谢谢分享。
回复

使用道具 举报

ID:526259 发表于 2019-5-13 16:29 | 显示全部楼层
很不错
回复

使用道具 举报

ID:125831 发表于 2019-5-13 19:39 | 显示全部楼层
恩,很好,我也想学学
回复

使用道具 举报

ID:125831 发表于 2019-5-13 19:45 | 显示全部楼层
恩,很好,我也想学学
回复

使用道具 举报

ID:663724 发表于 2019-12-14 13:20 | 显示全部楼层
谢谢分享
回复

使用道具 举报

ID:653902 发表于 2019-12-15 20:07 | 显示全部楼层
正在学习485通讯,非常感谢楼主。
回复

使用道具 举报

ID:283261 发表于 2019-12-25 20:44 | 显示全部楼层
485有点搞不懂,来这里学习来了
回复

使用道具 举报

ID:735148 发表于 2020-4-22 13:29 | 显示全部楼层
很好,赞一个,正好需要这个
回复

使用道具 举报

ID:735148 发表于 2020-4-24 16:36 | 显示全部楼层
有没有人知道这个程序的视频讲解
回复

使用道具 举报

ID:308785 发表于 2021-1-22 16:14 | 显示全部楼层
可以借鉴,楼主复制不容易
回复

使用道具 举报

ID:886629 发表于 2021-2-26 12:09 | 显示全部楼层
可以借鉴
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表