串口RS485通信
一、RS485的介绍? ? ? ??
????????485(一般称作 RS485/EIA-485)是隶属于 OSI 模型物理层的电气特性规定为 2 线,半双工,多点通信的标准。它的电气特性和 RS-232 大不一样。用缆线两端的电压差值来表示传递信号。RS485 仅仅规定了接受端和发送端的电气特性。它没有规定或推荐任何数据协议。
RS485 的特点包括:
????????1) 接口电平低,不易损坏芯片。RS485 的电气特性:逻辑“1”以两线间的电压差为+(2~6)V
表示;逻辑“0”以两线间的电压差为-(2~6)V 表示。接口信号电平比 RS232 降低了,
不易损坏接口电路的芯片,且该电平与 TTL 电平兼容,可方便与 TTL 电路连接。
????????2) 传输速率高。10 米时,RS485 的数据最高传输速率可达 35Mbps,在 1200m 时,传输
速度可达 100Kbps。
????????3) 抗干扰能力强。RS485 接口是采用平衡驱动器和差分接收器的组合,抗共模干扰能力
增强,即抗噪声干扰性好。
????????4) 传输距离远,支持节点多。RS485 总线最长可以传输 1200m 以上(速率≤100Kbps)
一般最大支持 32 个节点,如果使用特制的 485 芯片,可以达到 128 个或者 256 个节点,
最大的可以支持到 400 个节点。
二、RS485收发器
?SP3485 作为收发器,该芯片支持 3.3V 供电,最大传输速度可达10Mbps,支持多达 32 个节点,并且有输出短路保护。图中 A、B 总线接口,用于连接 485 总线。RO 是接收输出端,DI 是发送数据收入端,RE是接收使能信号(低电平有效),DE 是发送使能信号(高电平有效)。可以将RE和DE用同一个线连接,然后控制该脚的电平信号来确定是发送还是接收模式
三、实现代码
1)rs485.h?
#ifndef __RS485_H
#define __RS485_H
#include "head.h"
#define RX_MAX_LEN 64
#define RS485_TX_MODE gpio_bit_set(GPIOA, GPIO_PIN_8) //U-NCA3485是半双工RS485收发器,将RS485设置为发送模式
#define RS485_RX_MODE gpio_bit_reset(GPIOA, GPIO_PIN_8)//将RS485设置为接收模式
void RS485_Init(void);
void RS485_Send_Data(UCHAR *buf,UCHAR len);
void RS485_Receive_Data(UCHAR *buf,UCHAR *len);
extern UCHAR RS485_RX_BUF[RX_MAX_LEN]; //接收缓冲,最大64个字节
extern UCHAR RS485_RX_CNT; //接收到的数据长度
extern USART_RX_FLAG rs485_recvFlag;
#endif
2)rs485.c
#include "rs485.h"
UCHAR RS485_RX_BUF[RX_MAX_LEN]; //接收缓冲,最大64个字节
UCHAR RS485_RX_CNT=0; //接收到的数据长度
USART_RX_FLAG rs485_recvFlag=FLASE;
void USART0_IRQHandler(void)
{
UCHAR res;
if(RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE))
{
res=usart_data_receive(USART0);
if(RS485_RX_CNT<RX_MAX_LEN)
{
RS485_RX_BUF[RS485_RX_CNT]=res; //记录接收到的值
RS485_RX_CNT++; //接收数据增加1
}
usart_interrupt_flag_clear(USART2, USART_INT_FLAG_RBNE); //清中断标志
}
else if (RESET != usart_interrupt_flag_get(USART2, USART_INT_FLAG_IDLE))
{
usart_interrupt_flag_clear(USART2, USART_INT_FLAG_IDLE);
usart_data_receive(USART2); /* 清除接收完成标志位 */
rs485_recvFlag = TRUE; //事件通知接收完成
}
}
void RS485_Init(void)
{
rcu_periph_clock_enable(RCU_GPIOA); //enable GPIO clock
rcu_periph_clock_enable(RCU_USART0);// enable USART clock
gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8); //RS485-RE0
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); //RS485-TX0(USARTx_Tx)
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10);//RS485-RX0(USARTx_Rx)
usart_deinit(USART0); //USART configure
usart_baudrate_set(USART0, 115200); //设置波特率
usart_word_length_set(USART0, USART_WL_8BIT); //设置数据位
usart_parity_config(USART0, USART_PM_NONE); //设置奇偶校验位
usart_stop_bit_set(USART0, USART_STB_1BIT); //设置停止位
usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE); //禁用rts
usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE); //无硬件数据流控制
usart_receive_config(USART0, USART_RECEIVE_ENABLE); //使能接收器
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE); //使能发送器
nvic_irq_enable(USART0_IRQn, 0, 0);//配置NVIC分组,初始化NVIC分组4
usart_interrupt_enable(USART0, USART_INT_RBNE);//使能接收中断
usart_interrupt_enable(USART0, USART_INT_IDLE);
usart_enable(USART0);//使能串口
RS485_RX_MODE; //默认为接收模式
}
void RS485_Send_Data(UCHAR *buf,UCHAR len)
{
UINT i;
RS485_TX_MODE; //设置为发送模式
for(i=0;i<len;i++) //循环发送数据
{
while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));//等待发送区为空
usart_data_transmit(USART0,buf[i]);
}
while(RESET == usart_flag_get(USART0, USART_FLAG_TC)); //发送完成中断
RS485_RX_CNT=0;
RS485_RX_MODE; //设置为接收模式
}
void RS485_Receive_Data(UCHAR *buf,UCHAR *len)
{
UCHAR rxlen=RS485_RX_CNT;
UCHAR i=0;
*len=0;
delay_1ms(10); //等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束,然后读取数据
if(rxlen==RS485_RX_CNT&&rxlen)//接收到了数据,且接收完成了
{
for(i=0;i<rxlen;i++)
{
buf[i]=RS485_RX_BUF[i];
}
*len=RS485_RX_CNT; //记录本次数据长度
RS485_RX_CNT=0; //清零
}
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!