标题:
单片机RS485通讯例程源代码
[打印本页]
作者:
luyun
时间:
2018-7-7 20:07
标题:
单片机RS485通讯例程源代码
0.png
(43.52 KB, 下载次数: 92)
下载附件
2018-7-8 01:04 上传
单片机源程序如下:
#include <reg52.h>
#include <intrins.h>
sbit RS485_DIR = P1^7; //RS485方向选择引脚
bit flagFrame = 0; //帧接收完成标志,即接收到一帧新数据
bit flagTxd = 0; //单字节发送完成标志,用来替代TXD中断标志位
unsigned char cntRxd = 0; //接收字节计数器
unsigned char pdata bufRxd[64]; //接收字节缓冲区
extern void UartAction(unsigned char *buf, unsigned char len);
/* 串口配置函数,baud-通信波特率 */
void ConfigUART(unsigned int baud)
{
RS485_DIR = 0; //RS485设置为接收方向
SCON = 0x50; //配置串口为模式1
TMOD &= 0x0F; //清零T1的控制位
TMOD |= 0x20; //配置T1为模式2
TH1 = 256 - (11059200/12/32)/baud; //计算T1重载值
TL1 = TH1; //初值等于重载值
ET1 = 0; //禁止T1中断
ES = 1; //使能串口中断
TR1 = 1; //启动T1
}
/* 软件延时函数,延时时间(t*10)us */
void DelayX10us(unsigned char t)
{
do {
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
} while (--t);
}
/* 串口数据写入,即串口发送函数,buf-待发送数据的指针,len-指定的发送长度 */
void UartWrite(unsigned char *buf, unsigned char len)
{
RS485_DIR = 1; //RS485设置为发送
while (len--) //循环发送所有字节
{
flagTxd = 0; //清零发送标志
SBUF = *buf++; //发送一个字节数据
while (!flagTxd); //等待该字节发送完成
}
DelayX10us(5); //等待最后的停止位完成,延时时间由波特率决定
RS485_DIR = 0; //RS485设置为接收
}
/* 串口数据读取函数,buf-接收指针,len-指定的读取长度,返回值-实际读到的长度 */
unsigned char UartRead(unsigned char *buf, unsigned char len)
{
unsigned char i;
if (len > cntRxd) //指定读取长度大于实际接收到的数据长度时,
{ //读取长度设置为实际接收到的数据长度
len = cntRxd;
}
for (i=0; i<len; i++) //拷贝接收到的数据到接收指针上
{
*buf++ = bufRxd[i];
}
cntRxd = 0; //接收计数器清零
return len; //返回实际读取长度
}
/* 串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔 */
void UartRxMonitor(unsigned char ms)
{
static unsigned char cntbkp = 0;
static unsigned char idletmr = 0;
if (cntRxd > 0) //接收计数器大于零时,监控总线空闲时间
{
if (cntbkp != cntRxd) //接收计数器改变,即刚接收到数据时,清零空闲计时
{
cntbkp = cntRxd;
idletmr = 0;
}
else //接收计数器未改变,即总线空闲时,累积空闲时间
{
if (idletmr < 30) //空闲计时小于30ms时,持续累加
{
idletmr += ms;
if (idletmr >= 30) //空闲时间达到30ms时,即判定为一帧接收完毕
{
flagFrame = 1; //设置帧接收完成标志
}
}
}
}
else
{
cntbkp = 0;
}
}
/* 串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用 */
void UartDriver()
{
unsigned char len;
unsigned char pdata buf[40];
if (flagFrame) //有命令到达时,读取处理该命令
{
flagFrame = 0;
len = UartRead(buf, sizeof(buf)-2); //将接收到的命令读取到缓冲区中
UartAction(buf, len); //传递数据帧,调用动作执行函数
}
}
/* 串口中断服务函数 */
void InterruptUART() interrupt 4
{
if (RI) //接收到新字节
{
RI = 0; //清零接收中断标志位
if (cntRxd < sizeof(bufRxd)) //接收缓冲区尚未用完时,
{ //保存接收字节,并递增计数器
bufRxd[cntRxd++] = SBUF;
}
}
if (TI) //字节发送完毕
{
TI = 0; //清零发送中断标志位
flagTxd = 1; //设置字节发送完成标志
}
}
复制代码
所有资料51hei提供下载:
例程源代码.zip
(40.17 KB, 下载次数: 368)
2018-7-7 20:06 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
yzchendlei
时间:
2018-8-10 23:13
谢谢分享。黑币不够了。
作者:
haorizi
时间:
2018-8-11 00:49
恩,很好,我也想学学
作者:
haorizi
时间:
2018-8-11 00:52
谢谢分享,我也是黑币不够
作者:
wdliming
时间:
2018-10-7 15:41
谢谢分享~~~
作者:
a9069776
时间:
2018-10-7 16:23
学习中,谢谢!
作者:
WFX777888
时间:
2019-1-24 09:04
谢谢分享资料
作者:
bruck
时间:
2019-1-28 23:12
谢谢提供
作者:
WFX777888
时间:
2019-1-29 08:14
谢谢分享资料
作者:
yasi666
时间:
2019-1-29 10:33
太感谢了
作者:
黄焖鸡米饭1
时间:
2019-4-17 09:57
不试一遍,不搭一次硬件我是理解不聊了
作者:
jyf123
时间:
2019-4-24 21:06
谢谢分享 正好要用到RS485进行通讯
作者:
pannnnnda
时间:
2019-4-25 22:28
请问有不带DIR端的自动控制流向的模块的例程吗?
作者:
榆林上校
时间:
2019-4-29 20:03
最好有仿真哦
作者:
hili210
时间:
2019-4-30 14:57
谢谢分享。
作者:
Wanyling
时间:
2019-5-13 16:29
很不错
作者:
15808190021
时间:
2019-5-13 19:39
恩,很好,我也想学学
作者:
15808190021
时间:
2019-5-13 19:45
恩,很好,我也想学学
作者:
460984528
时间:
2019-12-14 13:20
谢谢分享
作者:
rotga
时间:
2019-12-15 20:07
正在学习485通讯,非常感谢楼主。
作者:
中原
时间:
2019-12-25 20:44
485有点搞不懂,来这里学习来了
作者:
饮酒作乐
时间:
2020-4-22 13:29
很好,赞一个,正好需要这个
作者:
饮酒作乐
时间:
2020-4-24 16:36
有没有人知道这个程序的视频讲解
作者:
suph007
时间:
2021-1-22 16:14
可以借鉴,楼主复制不容易
作者:
1294433629
时间:
2021-2-26 12:09
可以借鉴
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1