利用51单片机实现与RS485通讯,接收数据

这篇具有很好参考价值的文章主要介绍了利用51单片机实现与RS485通讯,接收数据。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、研究背景

二、硬件准备

三、软件准备

 四、实验原理

五、单片机代码

 六、Python读取串口处理数据

七、开发总结


一、研究背景

         学院给了14天的时间,一枚专业课紧的大三狗匆忙做出来。探索出一种研究阳极氧化工艺电解液中金属离子浓度在线测量和监控的设备和方式

二、硬件准备

          阳极氧化工艺电解液金属离子浓度在线监控仪,主要由高精度耐腐蚀溶液密度传感器探头、显示控制器、声光提醒装置、通讯端口、单片机以及控制PC组成。    

利用51单片机实现与RS485通讯,接收数据

利用51单片机实现与RS485通讯,接收数据利用51单片机实现与RS485通讯,接收数据 

三、软件准备

         除了Keil5、Pycharm还有ISP-STC软件,考虑到会同时使用单片机和Pycharm读取串口,因此还需要额外准备虚拟串口软件MX虚拟串口。

利用51单片机实现与RS485通讯,接收数据

 四、实验原理

       (1)RS485原理

        RS-485是串口通讯标准,常用于工业、自动化、汽车和建筑物管理等领域。相比于RS232总线, RS485总线采用AB双线进行差分传输,弥补了通信距离短且速率低下的特点。

        长距离布线传输时会有信号衰减,且噪声和干扰很大,传输线上的电压幅度变化体现这一点。但是采用AB线差分传输时,以A线作为信号传输线,以B线为传输参考线,利用运算元件进行差值相减可以排除干扰,输出正确的信号,这种方式叫做共模抑制,其原理如图

利用51单片机实现与RS485通讯,接收数据

         RS485总线有两线制和四线制两种接线方式,四线制只能支持一对一之间的通信,现实中生活生产中多采用两线制度。如图7所示,RS485总线支持单主机单从机模式以及单主机多从机这两种通信结构,本项目实践采用的是单主机单从机结构。

利用51单片机实现与RS485通讯,接收数据          

        RS485通信设备需要使用单片机上MX485模块,如图8所示,为一个MCU控制RS485通信的示意图。如图9和图10,根据《A7双核开发板原理图》需要将RXD2与P3.0、TXD2与P3.1以及485_RE与P1.1相连。AB接口为总线,RXD2为接收器输入,TXD2为发送器输出。485_RE控制485模块的工作方式,当485_RE为1时,设置为接收器;当485_RE为0时,设置为发送器。

利用51单片机实现与RS485通讯,接收数据

利用51单片机实现与RS485通讯,接收数据利用51单片机实现与RS485通讯,接收数据

        主机发送给从机或从机发送给主机时都会占用AB总线,所以RS485多采用半双工模式。主机通过485_RE引脚控制MX485为发送模式,从PC端串口向MX485的TXD2引脚发送一个字节,MX485将该字节数据转化为差分信息流通过AB线进行传输。当数据发送完毕时,主机立即设置MX485为接收模式。从机的信息传输与主机类似。

        (2)Modbus通讯协议

        泽耀科技数传电台,可以通过RS485总线进行通信,通信协议是Modbus协议。

        Modbus通信协议分为“03”、“04”“06”和“10”功能码,“03”表示读多路寄存输入,输出电台采用即为“03”功能码模式。如表1和表2所示,表1为主机发送报文,表2为从机回复报文,参考数传电台说明书,得到相应的寄存器说明,如图11所示。主机和从机之间发送的字节均为bytes格式.

        利用51单片机实现与RS485通讯,接收数据

利用51单片机实现与RS485通讯,接收数据

利用51单片机实现与RS485通讯,接收数据

        (3)单片机与PC串口通讯

        如图12和图13所示所示,51单片机内部自带UART(Universal Asynchronous Receiver Transmitter,通用异步收发器),可以实现单片机的单向或双向串口通讯。

利用51单片机实现与RS485通讯,接收数据   利用51单片机实现与RS485通讯,接收数据

        SCON寄存器

        SCON寄存器格式如图14所示,其中SM0和SM1控制串口的工作方式,如图15所示。SM2:允许方式2或方式3多机通信控制位;REN:允许/禁止穿行接收控制位。由软件置位REN,REN=1为允许串行接收状态,可启动串行接收器RxD,开始接收信息;软件复位REN,即REN=0,则禁止接收;

        TI: 发送中断请求标志位。在方式0,当串行发送数据第8位结束时,由内部硬件自动置位,即TI=1,向主机请求中断,响应中断后必须用软件复位,即TI=0。在其他方式中,则在停止位开始发送时由内部硬件置位,必须用软件复位;

        RI:接收中断请求标志位。在方式0,当串行接收到第8位结束时由内部硬件自动置位RI=1,向主机请求中断,响应中断后必须用软件复位,即RI=0。在其他方式中,串行接收到停止位的中间时刻由内部硬件置位,即RI=1(例外情况见SM2说明),必须由软件复位,即RI=0。

        利用51单片机实现与RS485通讯,接收数据

利用51单片机实现与RS485通讯,接收数据         

        PCON寄存器

       PCON寄存器的格式如图16所示,SMOD作为波特率选择位。当用软件置位SMOD,即SMOD=1,则使串行通信方式1、2、3的波特率加倍;当SMOD=0,则各工作方式的波特率不加倍。复位时SMOD=0。

利用51单片机实现与RS485通讯,接收数据

        TMOD寄存器

        TMOD寄存器的格式如图17所示,分为定时器1 T1和定时器0 T0。定时器的工作方式由M1和M0决定,如图18所示。

利用51单片机实现与RS485通讯,接收数据

        利用51单片机实现与RS485通讯,接收数据

五、单片机代码

        首先用Keil对485头文件设置

#include <reg52.h>
#include "intrins.h"
typedef unsigned int u16;
typedef unsigned char u8;

sbit RS485DIR=P1^1;//为0时处于接收状态,为1时处于发送状态
bit flagFrame = 0;  //帧接收完成标志,即接收到一帧新数据
bit flagTxd = 0;    //单字节发送完成标志,用来替代TXD中断标志位
unsigned char cntRxd = 0;   //接收字节计数器
unsigned char pdata bufRxd[64];  //接收字节缓冲区

extern void UartAction(u8 *buf, u8 len);
void ConfigUart(u16 baud)//串口初始化
{
	  RS485DIR = 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
}
void delay10us(u16 i)//延时10us函数
{
	do
	{
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
	}while(--i);
}
void RS485_write(u8 *buf,u8 len)//发送请求读取命令
{
	RS485DIR=1;//RS485设置为发送状态
	while(len--)//循环发送所有字节
	{
		flagTxd=0;//清零发送标志
		SBUF=*buf++;//发送一个字节数据
		while(!flagTxd);//等待该字节发送完成
	}
	delay10us(5);//等待停止位完成
	RS485DIR=0;//RS485设置为接收状态
}
unsigned char RS485_read(u8 *buf,u8 len)//接收数据命令
{
	u8 i;
	RS485DIR=0;//RS485设置为接收状态
	
	if(len>cntRxd)//指定读取长度大于实际接收的长度时
	{
		len=cntRxd;
	}
	for(i=0;i<len;i++)//拷贝接收到的数据到接收指针上
	{
		*buf++=bufRxd[i];
	}
	cntRxd=0;//接收计数器清零
	RS485DIR=1;//RS485设置为接收状态
	return len;//返回实际读取长度
}
void RS485Monitor(u8 ms)//串口接收监控,由于空闲时间判定帧结束,需在定时中断中调用,ms定时间间隔
{
	static u8 cntbkp=0;
	static u8 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 RS485_Driver()//串口驱动函数,监测数据帧数的接收
{
	unsigned char len;
	unsigned char pdata buf[40];
	if(flagFrame)//有点命令到达时,读取处理命令
	{
		flagFrame=0;
		len=RS485_read(buf,sizeof(buf)-2);//将接收到的命令读取到缓冲区中
		UartAction(buf,len);//传递数据帧数,调用动作执行函数
	}
}
void InteruptRS485() interrupt 4//串口中断服务函数
{
	if(RI)//接收到新字节
	{
		RI=0;//清零接收中断标志
		if(cntRxd<sizeof(bufRxd))//接收缓冲区尚未用完时,
		{
			bufRxd[cntRxd++]=SBUF;
		}
	}
	if(TI)//字节发送完毕
	{
		TI=0;//清零发送中断标志位
		flagTxd=1;//设置字节发送完成标志
	}
	
}


         接着是主程序的设置。

#include <reg52.h>
#include "485测试.h"
#include "intrins.h"
unsigned char T0RH = 0;  //T0重载值的高字节
unsigned char T0RL = 0;  //T0重载值的低字节

void ConfigTimer0(unsigned int ms);
extern void RS485_Driver();
extern void ConfigUart(unsigned int baud);
extern void Rs485Monitor(unsigned char ms);
extern void RS485_write(unsigned char *buf, unsigned char len);

void main()
{
    EA = 1;              //开总中断
    ConfigTimer0(1);   //配置T0定时1ms
    ConfigUart(9600);  //配置波特率为9600
    while (1)
    {
        RS485_Driver();  //调用串口驱动
    }

}
void UartAction(unsigned char *buf, unsigned char len)//串口动作函数
{
   
   RS485_write(buf, len);
	 //RS485_read(buf,len);
}

void ConfigTimer0(unsigned int ms)//配置启动t0,ms为定时时间
{
    unsigned long tmp;  //临时变量
    tmp = 11059200 / 12;       //定时器计数频率
    tmp = (tmp * ms) / 1000;  //计算所需的计数值
    tmp = 65536 - tmp;         //计算定时器重载值
    tmp = tmp + 33;            //补偿中断响应延时造成的误差
    T0RH = (unsigned char)(tmp>>8);  //定时器重载值拆分为高低字节
    T0RL = (unsigned char)tmp;
    TMOD &= 0xF0;   //清零T0的控制位
    TMOD |= 0x01;   //配置T0为模式1
    TH0 = T0RH;     //加载T0重载值
    TL0 = T0RL;
    ET0 = 1;        //使能T0中断
    TR0 = 1;        //启动T0
}
void InterruptTimer0() interrupt 1/* T0中断服务函数,执行串口接收监控 */
{
    TH0 = T0RH;  //重新加载重载值
    TL0 = T0RL;
    RS485Monitor(1);  //串口接收监控

}

         将程序生成的Hex文件通过isp烧入51单片机中。所示连接好接线方式。然后将文件通过ISP烧录给单片机,启动单片机,向串口助手输入01 03 00 01 00 05 f5 cb,每1s自动发送一次,请求比重浓度、波美度、百分比浓度、温度、状态运行码。如图20所示,当串口助手接受区有从机回复数据接收(01 03 0a 27 03 00 00 00 00 00 d0 00 01 40 cf),电台红绿交替闪烁,证明单片机代码可以成功实现控制数据接收的功能。

利用51单片机实现与RS485通讯,接收数据  利用51单片机实现与RS485通讯,接收数据

 六、Python读取串口处理数据

        由于要一个串口只能被一个程序范围,而COM6端口要同时被单片机和Pycharm访问,所以需要使用一个虚拟串口软件。

利用51单片机实现与RS485通讯,接收数据

        保密一部分,嘿嘿~反正都能前面485通讯那么难的都做完了,用Python写个读串口还不简简单单?直接上图!

利用51单片机实现与RS485通讯,接收数据

七、开发总结

        事实上,我刚做这个项目就上网遍历了一下,几乎没有人做普中51单片机与485通讯的案例。于是想着应该是创新,就没有用Arduino或者STM32来做。于是踩了个比较大的坑,你也看到了,看法过程中足足用了4个软件,改bug的过程中相当繁琐,然后这个UI做得也不行。这个方案不是没有人做,而是太麻烦了导致没有人做。我的方案有效代码拢共500多行,而且还时不时报错;我同组有Arduino开发的同学也就300多行的代码就解决了。

         下次加把劲用Arduino ESP32 试一下。感谢你的阅读!文章来源地址https://www.toymoban.com/news/detail-466197.html

到了这里,关于利用51单片机实现与RS485通讯,接收数据的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【单片机】UART、I2C、SPI、TTL、RS232、RS422、RS485、CAN、USB、SD卡、1-WIRE、Ethernet等常见通信方式

    在单片机开发中,UART、I2C、RS485等普遍在用,这里做一个简单的介绍 UART口指的是一种物理接口形式(硬件)。 UART是异步(指不使用时钟同步,依靠帧长进行判断),全双工(收发可以同时进行)串口总线。它比同步串口复杂很多。有两根线,一根TXD用于发送,一根RXD用于接收

    2024年02月11日
    浏览(39)
  • 基于51单片机利用中断实现100以内的按键计数(Proteus仿真)

    https://mp.weixin.qq.com/s?__biz=Mzg4Mzc3NDUxOQ==mid=2247484090idx=3sn=ed67cb438e25cc13b32ac6c48ccebecbchksm=cf4307e2f8348ef424109aacc5bb64a6f20d53581d57f15377ec67383e01a69e7a0292b500f6token=3445295lang=zh_CN#rd https://mp.weixin.qq.com/s?__biz=Mzg4Mzc3NDUxOQ==mid=2247484090idx=3sn=ed67cb438e25cc13b32ac6c48ccebecbchksm=cf4307e2f8348ef424109aacc5bb64a6f20d535

    2024年02月04日
    浏览(40)
  • Proteus基于51单片机利用虚拟串口实现主从机的通信

    最近在学校做单片机课程实验时,需要在Proteus上实现串口的通信,具体要求如下: 在此记录一下本人的解题方案,首先Proteus中的原理图绘制如下 其中虚拟串口可在元件库中搜索COMPIM获得。 将原件按上图连接完毕后,将各个虚拟串口的收发波特率设置为19200,并分别赋予CO

    2024年02月08日
    浏览(38)
  • 基于51单片机的通讯聊天系统

    通过编写51单片机通讯聊天程序,掌握51单片机的各个模块的知识点和运用C语言编写51单片机的能力。 用51单片机与口袋开发板设计实现一个单片机与电脑串口助手实现通讯功能的程序。程序的主要功能如下: 1 OLED初始化显示Welcome to Bluetooth communication! 字符串。 2 程序开始时

    2023年04月08日
    浏览(29)
  • STC8G1K08单片机接收485发送的不等长混合数据

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 提示:以下是本篇文章正文内容,下面案例可供参考 这里以芯力特的485芯片为例如图1: 引脚功能: 1.接收器输出端(接单片机的RXD引脚) 2.接收器输出使能控制(接收器输出使能控制。当/RE 接低电平

    2024年02月16日
    浏览(36)
  • c51单片机串口通信(中断方式接收数据)(单片机--单片机通信)示例代码 附proteus图

         单片机一般采用中断方式接受数据,这样便于及时处理 其中发送数据段采用的是查询方式,接收端采用了中断方式, 要注意的地方有: 在中断处理函数int_0()内,处理数据前要先关闭中断,否则中断可能会不断传过来, EA=0; 然后退出中断处理函数前恢复中断处理能力:

    2024年02月13日
    浏览(60)
  • 电脑通过串口助手和51单片机串口通讯

    今天有时间把电脑和51单片机之间的串口通讯搞定了,电脑发送的串口数据,单片机能够正常接收并显示到oled屏幕上,特此记录一下,防止后面自己忘记了怎么搞得了。 先来两个图片看看结果吧! 下面是串口3.c的文件全部内容: 下面是oled.h的全部内容: 下面是oled.c的全部内

    2024年02月07日
    浏览(53)
  • Proteus8仿真:51单片机使用串口进行双机通讯

    元器件 名称 电阻 RES 51单片机 AT89C51 电容 CAP 晶振 CRYSTAL BCD数码管 7SEG-BCD 串口初始化: 首先根据相关的串口寄存器编写对应的初始化代码: STC89C51单片机设有两个定时器/计数器,因定时器1有4种工作方式,而常选用定时器1的工作方式2(8位自动重装)作为波特率的溢出率。 串口

    2024年02月04日
    浏览(42)
  • 利用51单片机进行LED 跑马灯设计

    题目:         使用单片机驱动8个LED,2个按键并实现跑马灯功能。         当按下按键1时,LED 从左至右依次点亮,全亮后再从右至左依次熄灭,全灭后再从左至右依次点亮,依次循环下去。        当按下按键2 时,LED 从右至左依次点亮,全亮后再从左至右依次熄

    2024年02月07日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包