版权声明:本文为博主原创文章,转载请附上原文出处链接。
文章目录
前言
今天介绍下STC8A8K64S4A12系列MCU串行口原理,掌握RS485总线通信的硬件原理,了解RS485总线通信的软件协议。
一、硬件设计
1.开发板串口硬件电路
STC8A8K64S4A12开发板上设计了RS485电路(RS485接口芯片选择的是MAX485),具体电路及实物接口如下。
RS485电路占用的单片机的引脚如下表:
☆注:独立GPIO表示开发板没有其他的电路使用这个GPIO。
2.RS485电气性能
RS485接口是一个物理接口,将多个RS485接口通过一定方式连接起来,可形成RS485总线。将多个RS485接口连接起来的方式有多种,一般不支持星型、树型或环型网络。下图是总线型连接的RS485系统通信框图,也是被最广泛应用的一种连接方式。
☆注:RS485系统通信时有几点注意事项:
1)连接电脑(主机)和RS485总线的可以不选择USB转RS485模块,如果电脑有RS232接口,也可选择RS232转RS485模块。
2)RS485总线如果需要加终端电阻,最好的效果是总线的首尾两端各加一个。
RS485总线是一种常规的通信总线,他不能做总线的自动仲裁,也就是不能同时发送数据以避免总线竞争,所以整个系统的通信效率必然较低,数据冗余量较大,对于速度要求高的应用场所不适应用RS485总线。同时由于RS485总线上通常只有一台主机,所以这种总线方式是典型的集中——分散型控制系统。
概括一下,RS485接口或者说RS485总线具有以下电气性能:
- 传输方式:主从式,半双工。
- 传输速率:可配置(最高传输速率为10Mbps)。
- 最大挂接节点数:一般最大支持32个节点(如果使用特制的RS485芯片,可以达到128个或者256个节点,最大的可以支持到400个节点)。
- 最大传输距离(不加中继):受传输速率、通信电缆是否双绞、通信电缆芯线截面积等因素影响,一般在100Kbps的传输速率下,才可以达到最大的通信距离约为1219米。
3.RS485通信协议
RS485接口本身只是硬件接口,硬件通信接口建立后,在进行数据传输的设备之间需要约定一个数据协议,以使接收端能够解析收到的数据,这便是“协议”的概念。
通信协议按照有无统一的标准来划分,可分成两种:
- 标准通信协议。此有统一标准的协议格式,如“ModBus”协议,标准的协议内容全面,包含的内容很多,但不易理解。
- 自定义通信协议或者说私有通信协议。用户可根据自已的需求,灵活定义一种协议,简单实用,这便是“自定义协议”。
☆注:“ModBus”协议也有ASCII模式和RTU模式两种,这两种又有很大差别,用户需根据自已实际需求来选择最合适自己的协议。
4.RS485电路设计
RS485电路总体上可以分为隔离型与非隔离型。隔离型比非隔离型在抗干扰、系统稳定性等方面都有更出色的表现,但有一些场合也可以用非隔离型。
非隔离型的电路非常简单,只需一个RS485芯片直接与MCU的串行通信口和一个GPIO控制口连接就可以。(开发板使用的就是最简单的非隔离型电路)
在某些工业控制领域,由于现场情况十分复杂,各个节点之间存在很高的共模电压。虽然RS485接口采用的是差分传输方式,具有一定的抗共模干扰的能力,但当共模电压超过RS485接收器的极限接收电压,即大于+12V或小于-7V时,接收器就再也无法正常工作了,严重时甚至会烧毁芯片和仪器设备。
解决此类问题的方法是通过DC-DC将系统电源和RS485收发器的电源隔离;通过隔离器件将信号隔离,彻底消除共模电压的影响。
实现隔离型RS485电路设计的方案可分为:
- 传统方式:用高速光耦、带隔离的DC-DC、RS485芯片构筑电路。
- 使用二次集成芯片,如ADM2483、ADM257E等。
☆注:隔离型RS485具体电路不在此介绍,还是那句话,根据自己的需求和成本来定方案。
二、软件设计
RS485通信本质还是异步串行通信,这和UART通信一样,不同之处是,RS485接收和发送需要专用使能引脚控制,软件设计时需要注意。(软件控制MAX485芯片RE引脚切换为接收或发送模式时,注意软件适当延时,以满足硬件切换的时间需求。)
1.RS485总线数据收发实验(串口4)
1.1.工程需要用到的c文件
本例需要用到的c文件如下表所示,工程需要添加下表中的c文件。
1.2.头文件引用和路径设置
■ 需要引用的头文件
#include "delay.h"
#include "uart.h"
■ 需要包含的头文件路径
本例需要包含的头文件路径如下表:
MDK中点击魔术棒,打开工程配置窗口,按照下图所示添加头文件包含路径。
1.3.编写代码
首先,在uart.c文件中编写串口4的初始化函数Uart4_Init,代码如下。
程序清单:串口4初始化函数
/***************************************************************************
* 描 述 : 串口4初始化函数
* 入 参 : 无
* 返回值 : 无
备注:波特率9600bps 晶振11.0592MHz
**************************************************************************/
void Uart4_Init(void)
{
P_SW2|=S4_S; //选择P5.2、P5.3为串口4使用
S4CON |= 0x10; //启动串行接收器
S4CON &= 0x30; //8位数据,可变波特率,串口4选择定时器2为波特率发生器
AUXR |= 0x04; //定时器2时钟为Fosc,即1T
T2L = 0xE0; //设定定时初值
T2H = 0xFE; //设定定时初值
AUXR |= 0x10; //启动定时器2
IE2 |= 0x10; // 串口4中断打开
}
然后,编写串口4发送数据函数,把要发送的字节存放于数据缓存寄存器中,直到数据发送完成,代码如下。
程序清单:数据发送函数函数
/***************************************************************************
* 描 述 : 串口4发送数据函数
* 入 参 : uint8 数据
* 返回值 : 无
**************************************************************************/
void SendDataByUart4(uint8 dat)
{
S4BUF = dat; //写数据到UART数据寄存器
while(!(S4CON&S4TI)); //在停止位没有发送时,S4TI为0即一直等待
S4CON&=~S4TI; //清除S4CON寄存器对应S4TI位(该位必须软件清零)
}
之后,编写串口4的中断服务函数,将接收的数据存放到用户自定义变量uart4temp中,代码如下。
程序清单:中断服务函数
/***************************************************************************
* 描 述 : 串口4中断服务函数
* 入 参 : 无
* 返回值 : 无
**************************************************************************/
void Uart4() interrupt 18 using 1
{
IE2 &= 0xEF; //串口4中断关闭
Flag=TRUE; //接收到数据,接收标识符有效
if (S4CON & S4RI) //串行接收到停止位的中间时刻时,该位置1
{
S4CON &= ~S4RI; //清除S4CON寄存器对应S4RI位(该位必须软件清零)
uart4temp = S4BUF; //把串口4缓存SBUF寄存器数据存放到数组temp1中
}
if (S4CON & S4TI) //在停止位开始发送时,该位置1
{
S4CON &= ~S4TI; //清除S4CON寄存器对应S4TI位(该位必须软件清零)
}
IE2 |= 0x10; //串口4中断打开
}
最后,用户定义一个自定义函数UART4_Tx485_Puts,该函数将接收的数据原样返回去并加上回车符,注意RS485发送完后要将RE引脚控制为接收模式,切换引脚发送还是接收时有软件延时。主函数main在主循环中调用该函数。具体代码如下。
代码清单:用户函数UART4_Tx485_Puts
/**************************************************************************************
* 描 述 : RS485接收到数据后发送出去
* 入 参 : 无
* 返回值 : 无
**************************************************************************************/
void USART4_Tx485_Puts(void)
{
if(Flag) //有新数据通过串口被接收到
{
rs485_dr=1; //控制485发送
delay_ms(1); //延时1ms,不可省去
IE2 &= 0xEF; //串口4中断关闭
SendDataByUart4(uart4temp); //发送字符
SendDataByUart4(0x0D); //发送换行符
SendDataByUart4(0x0A); //发送换行符
IE2 |= 0x10; //串口4中断打开
delay_ms(1); //延时1ms,不可省去
rs485_dr=0; //控制485接收
Flag=FALSE; //清除接收标识符
}
}
代码清单:主函数
int main()
{
P5M1 &= 0xFB; P5M0 &= 0xFB; //设置P5.2为准双向口
P5M1 &= 0xF7; P5M0 |= 0x08; //设置P5.3为推挽输出
rs485_dr=0; //控制485接收
Uart4_Init(); //串口4初始化
EA = 1; //总中断打开
while(1)
{
USART4_Tx485_Puts(); //RS485接收到1个字符后返回该字符
}
}
1.4.硬件连接
本实验需要用到USB转RS485转换器,以实现开发板通过RS485接口与PC通信,实验连接图如下。
总结
以上就是今天要讲的内容,希望对你有帮助!