品牌建设完整版,关键词点击优化工具,企业网站建设新站,mvc做的网站如何发布访问485(一般称作 RS485/EIA-485)隶属于 OSI 模型物理层#xff0c;是串行通讯的一种。电气特性规定 为 2 线#xff0c;半双工#xff0c;多点通信的类型。它的电气特性和 RS-232 大不一样。用缆线两端的电压差值 来表示传递信号。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 推荐使用在点对点网络中比如线型总线型网络等而不能是星型环型网络。 理想情况下 RS485 需要 2 个终端匹配电阻其阻值要求等于传输电缆的特性阻抗一般为 120 Ω。没有特性阻抗的话当所有的设备都静止或者没有能量的时候就会产生噪声而且线移需 要双端的电压差。没有终接电阻的话会使得较快速的发送端产生多个数据信号的边缘导致 数据传输出错。485 推荐的一主多从连接方式如图 36.1.1 所示
在上面的连接中如果需要添加匹配电阻我们一般在总线的起止端加入也就是主机和 设备 4 上面各加一个 120Ω的匹配电阻。
由于 RS485 具有传输距离远、传输速度快、支持节点多和抗干扰能力更强等特点所以 RS485有很广泛的应用。实际多设备时收发器有范围为-7V到12V的共模电压为了稳定传输 也有使用 3 线的布线方式即在原有的 A、B 两线上多增加一条地线。4 线制使用全双工通讯 方式这种也叫 RS422由于布线的难度和通讯局限相对使用得比较少
TP8485E/SP3485 可作为 RS485 的收发器该芯片支持 3.3V~5.5V 供电最大传输速度可 达 250Kbps支持多达 256 个节点(单位负载为 1/8 的条件下)并且支持输出短路保护。该芯片的框图如图 36.1.2 所示 图中 A、B 总线接口用于连接 485 总线。RO 是接收输出端DI 是发送数据收入端RE 是接收使能信号低电平有效DE 是发送使能信号高电平有效。
代码
rs485.h
#ifndef __RS485_H
#define __RS485_H#include ./SYSTEM/sys/sys.h/******************************************************************************************/
/* RS485 引脚 和 串口 定义 */
#define RS485_RE_GPIO_PORT GPIOD
#define RS485_RE_GPIO_PIN GPIO_PIN_7
#define RS485_RE_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOD_CLK_ENABLE(); }while(0) /* PD口时钟使能 */#define RS485_TX_GPIO_PORT GPIOA
#define RS485_TX_GPIO_PIN GPIO_PIN_2
#define RS485_TX_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */#define RS485_RX_GPIO_PORT GPIOA
#define RS485_RX_GPIO_PIN GPIO_PIN_3
#define RS485_RX_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */#define RS485_UX USART2
#define RS485_UX_IRQn USART2_IRQn
#define RS485_UX_IRQHandler USART2_IRQHandler
#define RS485_UX_CLK_ENABLE() do{ __HAL_RCC_USART2_CLK_ENABLE(); }while(0) /* USART2 时钟使能 *//******************************************************************************************//* 控制RS485_RE脚, 控制RS485发送/接收状态* RS485_RE 0, 进入接收模式* RS485_RE 1, 进入发送模式*/
#define RS485_RE(x) do{ x ? \HAL_GPIO_WritePin(RS485_RE_GPIO_PORT, RS485_RE_GPIO_PIN, GPIO_PIN_SET) : \HAL_GPIO_WritePin(RS485_RE_GPIO_PORT, RS485_RE_GPIO_PIN, GPIO_PIN_RESET); \}while(0)#define RS485_REC_LEN 64 /* 定义最大接收字节数 64 */
#define RS485_EN_RX 1 /* 使能1/禁止0RS485接收 */extern uint8_t g_RS485_rx_buf[RS485_REC_LEN]; /* 接收缓冲,最大RS485_REC_LEN个字节 */
extern uint8_t g_RS485_rx_cnt; /* 接收数据长度 */void rs485_init( uint32_t baudrate); /* RS485初始化 */
void rs485_send_data(uint8_t *buf, uint8_t len); /* RS485发送数据 */
void rs485_receive_data(uint8_t *buf, uint8_t *len);/* RS485接收数据 */#endifrs485.c
#include ./BSP/RS485/rs485.h
#include ./SYSTEM/delay/delay.hUART_HandleTypeDef g_rs458_handler; /* RS485控制句柄(串口) */#ifdef RS485_EN_RX /* 如果使能了接收 */uint8_t g_RS485_rx_buf[RS485_REC_LEN]; /* 接收缓冲, 最大 RS485_REC_LEN 个字节. */
uint8_t g_RS485_rx_cnt 0; /* 接收到的数据长度 */void RS485_UX_IRQHandler(void)
{uint8_t res;if ((__HAL_UART_GET_FLAG(g_rs458_handler, UART_FLAG_RXNE) ! RESET)) /* 接收到数据 */{HAL_UART_Receive(g_rs458_handler, res, 1, 1000);if (g_RS485_rx_cnt RS485_REC_LEN) /* 缓冲区未满 */{g_RS485_rx_buf[g_RS485_rx_cnt] res; /* 记录接收到的值 */g_RS485_rx_cnt; /* 接收数据增加1 */}}
}#endif/*** brief RS485初始化函数* note 该函数主要是初始化串口* param baudrate: 波特率, 根据自己需要设置波特率值* retval 无*/
void rs485_init(uint32_t baudrate)
{/* IO 及 时钟配置 */RS485_RE_GPIO_CLK_ENABLE(); /* 使能 RS485_RE 脚时钟 */RS485_TX_GPIO_CLK_ENABLE(); /* 使能 串口TX脚 时钟 */RS485_RX_GPIO_CLK_ENABLE(); /* 使能 串口RX脚 时钟 */RS485_UX_CLK_ENABLE(); /* 使能 串口 时钟 */GPIO_InitTypeDef gpio_initure;gpio_initure.Pin RS485_TX_GPIO_PIN;gpio_initure.Mode GPIO_MODE_AF_PP;gpio_initure.Pull GPIO_PULLUP;gpio_initure.Speed GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(RS485_TX_GPIO_PORT, gpio_initure); /* 串口TX 脚 模式设置 */gpio_initure.Pin RS485_RX_GPIO_PIN;gpio_initure.Mode GPIO_MODE_AF_INPUT;HAL_GPIO_Init(RS485_RX_GPIO_PORT, gpio_initure); /* 串口RX 脚 必须设置成输入模式 */gpio_initure.Pin RS485_RE_GPIO_PIN;gpio_initure.Mode GPIO_MODE_OUTPUT_PP;gpio_initure.Pull GPIO_PULLUP;gpio_initure.Speed GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(RS485_RE_GPIO_PORT, gpio_initure); /* RS485_RE 脚 模式设置 *//* USART 初始化设置 */g_rs458_handler.Instance RS485_UX; /* 选择485对应的串口 */g_rs458_handler.Init.BaudRate baudrate; /* 波特率 */g_rs458_handler.Init.WordLength UART_WORDLENGTH_8B; /* 字长为8位数据格式 */g_rs458_handler.Init.StopBits UART_STOPBITS_1; /* 一个停止位 */g_rs458_handler.Init.Parity UART_PARITY_NONE; /* 无奇偶校验位 */g_rs458_handler.Init.HwFlowCtl UART_HWCONTROL_NONE; /* 无硬件流控 */g_rs458_handler.Init.Mode UART_MODE_TX_RX; /* 收发模式 */HAL_UART_Init(g_rs458_handler); /* HAL_UART_Init()会使能UART2 */#if RS485_EN_RX /* 如果使能了接收 *//* 使能接收中断 */__HAL_UART_ENABLE_IT(g_rs458_handler, UART_IT_RXNE); /* 开启接收中断 */HAL_NVIC_EnableIRQ(RS485_UX_IRQn); /* 使能USART2中断 */HAL_NVIC_SetPriority(RS485_UX_IRQn, 3, 3); /* 抢占优先级3子优先级3 */
#endifRS485_RE(0); /* 默认为接收模式 */
}/*** brief RS485发送len个字节* param buf : 发送区首地址* param len : 发送的字节数(为了和本代码的接收匹配,这里建议不要超过 RS485_REC_LEN 个字节)* retval 无*/
void rs485_send_data(uint8_t *buf, uint8_t len)
{RS485_RE(1); /* 进入发送模式 */HAL_UART_Transmit(g_rs458_handler, buf, len, 1000); /* 串口2发送数据 */g_RS485_rx_cnt 0;RS485_RE(0); /* 进入接收模式 */
}/*** brief RS485查询接收到的数据* param buf : 接收缓冲区首地址* param len : 接收到的数据长度* arg 0 , 表示没有接收到任何数据* arg 其他, 表示接收到的数据长度* retval 无*/
void rs485_receive_data(uint8_t *buf, uint8_t *len)
{uint8_t rxlen g_RS485_rx_cnt;uint8_t i 0;*len 0; /* 默认为0 */delay_ms(10); /* 等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束 */if (rxlen g_RS485_rx_cnt rxlen) /* 接收到了数据,且接收完成了 */{for (i 0; i rxlen; i){buf[i] g_RS485_rx_buf[i];}*len g_RS485_rx_cnt; /* 记录本次数据长度 */g_RS485_rx_cnt 0; /* 清零 */}
}main.c
#include ./SYSTEM/sys/sys.h
#include ./SYSTEM/usart/usart.h
#include ./SYSTEM/delay/delay.h
#include ./BSP/LED/led.h
#include ./BSP/LCD/lcd.h
#include ./BSP/KEY/key.h
#include ./BSP/RS485/rs485.hint main(void)
{uint8_t key;uint8_t i 0, t 0;uint8_t cnt 0;uint8_t rs485buf[5];HAL_Init(); /* 初始化HAL库 */sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */delay_init(72); /* 延时初始化 */usart_init(115200); /* 串口初始化为115200 */led_init(); /* 初始化LED */lcd_init(); /* 初始化LCD */key_init(); /* 初始化按键 */rs485_init(9600); /* 初始化RS485 */lcd_show_string(30, 50, 200, 16, 16, STM32, RED);lcd_show_string(30, 70, 200, 16, 16, RS485 TEST, RED);lcd_show_string(30, 90, 200, 16, 16, ATOMALIENTEK, RED);lcd_show_string(30, 110, 200, 16, 16, KEY0:Send, RED); /* 显示提示信息 */lcd_show_string(30, 130, 200, 16, 16, Count:, RED); /* 显示当前计数值 */lcd_show_string(30, 150, 200, 16, 16, Send Data:, RED); /* 提示发送的数据 */lcd_show_string(30, 190, 200, 16, 16, Receive Data:, RED);/* 提示接收到的数据 */while (1){key key_scan(0);if (key KEY0_PRES) /* KEY0按下,发送一次数据 */{for (i 0; i 5; i){rs485buf[i] cnt i; /* 填充发送缓冲区 */lcd_show_xnum(30 i * 32, 170, rs485buf[i], 3, 16, 0X80, BLUE); /* 显示数据 */}rs485_send_data(rs485buf, 5); /* 发送5个字节 */}rs485_receive_data(rs485buf, key);if (key) /* 接收到有数据 */{if (key 5)key 5; /* 最大是5个数据. */for (i 0; i key; i){lcd_show_xnum(30 i * 32, 210, rs485buf[i], 3, 16, 0X80, BLUE); /* 显示数据 */}}t;delay_ms(10);if (t 20){LED0_TOGGLE(); /* LED0闪烁, 提示系统正在运行 */t 0;cnt;lcd_show_xnum(30 48, 130, cnt, 3, 16, 0X80, BLUE); /* 显示数据 */}}
}