请保留-> 【原文: https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】
(代码仓库地址:https://gitee.com/luobing4365/yie002-explorer
具体参考博客:YIE002开发探索-Gitee代码仓库说明)
在YIE002开发探索05中,我们介绍过RS485一些基本参数。RS485通信协议由RS232协议改进而来,将物理层改为了差分信号进行传输,因此其抗干扰性强、传输距离远,比较广泛地应用于噪声干扰比较大的工业控制环境中。
1 YIE002上的RS485
RS485的电气特性与RS-232不大一样,采用两线的时候为半双工。其基本的特点包括:
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与RS232的编程几乎一样,需要关注的是其半双工的特性(因为开发板上使用的是两线),必须通过使能脚配置其为发送状态或接收状态。
如图1所示,给出了YIE002的RS485部分的线路图。
开发板YIE002采用SP3485作为收发器,其A、B总线接口,用于连接485总线。从图中可以看出,485_TR与STM32F103C8T6的PB0连接,当其电平为低时,RS485接收数据;电平为高时,RS485发送数据。
开发板上使用了串口3实现485,下面将在YIE002开发探索06的基础上,实现RS485的数据收发。
2 YIE002-STM32的串口编程(485)
从软件角度,RS485和RS232的代码是一样的,所要注意的是对RS485接收或发送的使能。因此,本篇的代码编写比较简单,具体步骤如下。
2.1 串口(485)的Cube MX图形配置
如图2所示,在Pinout & Configuration栏的Connectivity中,将USART3的模式设置为异步通信。
在设置中可以看到,USART3旁边有黄色感叹号出现。这是因为用来控制LED灯的PB12、PB13和PB14,分别用于USART3_CK、USART3_CTS和USART3_RTS,导致Cube MX出现了警告提示。在实际应用中,我们并没有用到这些功能,维持原来的引脚配置就可以了。
然后在NVIC的配置界面中,设置串口3的中断优先级,如图3所示。
完成上述配置后,选择GENERATE CODE按钮,生成代码。
2.2 添加应用代码
编写USART3的接收和发送代码,与之前编写USART1的步骤类似。具体如下:
1) 设置USART3的IDLE中断
在main.h中,添加USART3的IDLE中断处理函数的声明。
/* USER CODE BEGIN Includes */
void MyUser_UART1_IDLE_IRQHandler(UART_HandleTypeDef *huart);
void MyUser_UART3_IDLE_IRQHandler(UART_HandleTypeDef *huart);
在stm32f1xx_it.c中,增加对USART3的IDLE中断的调用。
void USART3_IRQHandler(void)
{
/* USER CODE BEGIN USART3_IRQn 0 */
/* USER CODE END USART3_IRQn 0 */
HAL_UART_IRQHandler(&huart3);
/* USER CODE BEGIN USART3_IRQn 1 */
if(__HAL_UART_GET_FLAG(&huart3, UART_FLAG_IDLE) != RESET)
{
__HAL_UART_CLEAR_IDLEFLAG(&huart3);
MyUser_UART3_IDLE_IRQHandler(&huart3);
}
/* USER CODE END USART3_IRQn 1 */
}
在main.c的USART3初始化函数MX_USART3_UART_Init()中,添加对IDLE中断的使能语句。
/* USER CODE BEGIN USART3_Init 2 */
//此处使能IDLE中断
__HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE); //使能IDLE中断
__HAL_UART_CLEAR_IDLEFLAG(&huart3); //清除IDLE挂起标志位
/* USER CODE END USART3_Init 2 */
2) 添加USART3相关的全局变量
#define USART3_REC_LEN 200 //接收的最大字符串长度
uint8_t Usart3PackageFlag; //接收到完整的包的标志,即一串数据接收完毕;
uint8_t bUsart3RxBuff[USART3_REC_LEN]; //接收缓冲,最大USART1_REC_LEN个字节
uint16_t wUsart3RxNumber=0; //接收到的数据字节数
uint8_t bUsart3Buffer[1]; //接收用的暂存缓冲区
//IDLE防抖使用的标志:只有接收到数据后,IDLE才有效,防止抖动
//1:数据接收到了;
uint8_t Usart3DataFlag;
3) 编写USART3的IDLE中断处理函数
在main.c的USER CODE BEGIN 4处,添加函数的实现。
//USART3 IDLE中断
void MyUser_UART3_IDLE_IRQHandler(UART_HandleTypeDef *huart)
{
if(Usart3DataFlag==1) //只有之前接收到数据了,才证明数据包传送完成,主要用来去除空闲中断的抖动
{
Usart3PackageFlag=1;
Usart3DataFlag=0;
}
}
4) 添加USART3的接收中断处理
在main.c的接收中断处理函数HAL_UART_RxCpltCallback()中,添加对USART3数据接收的处理。
if(huart ==&huart3) //串口3-485
{
if(Usart3PackageFlag==0) //上一个包处理完了或初次处理
{
bUsart3RxBuff[wUsart3RxNumber++]=bUsart3Buffer[0];
Usart3DataFlag=1;
if(wUsart3RxNumber>=USART3_REC_LEN)//超过此数目,则认为包已经接收完了
{
Usart3DataFlag=0;
Usart3PackageFlag=1;
}
}
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET); //设置485为接收模式
if(HAL_UART_Receive_IT(&huart3, bUsart3Buffer, 1) != HAL_OK) // receive 1 byte data, and put data
{
Error_Handler();
}
}
5) 添加应用处理代码
在主程序main()中,添加应用所需的代码。
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET); //设置485为接收模式
HAL_UART_Receive_IT(&huart3, bUsart3Buffer, 1); //使能接收中断
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//robin 20210810
if(Usart3PackageFlag==1) //接收到数据包 串口3处理
{
Usart3PackageFlag=0;
rUsart_len=wUsart3RxNumber;
wUsart3RxNumber=0;
for(i=0; i<rUsart_len; i++)
rUsartData[i]=bUsart3RxBuff[i];
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET); //设置485为发送模式
if(HAL_UART_Transmit(&huart3,rUsartData,rUsart_len,5000)!=HAL_OK)
{
Error_Handler();
}
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET); //设置485为接收模式
}
}
/* USER CODE END 3 */
需要注意的是,发送数据的时候采用了阻塞模式的发送函数。主要是因为485有接收和发送模式的使能动作,如果不是发完数据返回,马上就会进入接收模式,导致发送数据失败。
当然,也可以使用非阻塞式的发送模式,那么设置485位接收模式的代码,就不能在此处添加了。应该在发送完成后触发的中断处理函数中,将485设置为接收模式。
2.3 测试
编写完成后,将代码下载至YIE002开发板,就可以进行测试了。
测试的时候,可以使用两个开发板对接,修改应用代码,进行测试。我使用了一个专用的485转USB的工具,直接与PC机进行收发测试。
连接图如图4所示。
将YIE002开发板上的485-A与485转USB工具的A相连,开发板的485-B与485转USB工具的B相连,就完成了硬件连接了。
485转USB工具连接到PC机上,在PC机上运行串口调试助手,就可以进行485的接收发送测试了。
1,430 total views, 2 views today