IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 【STM32-RS485串口通信踩过的坑】 -> 正文阅读

[嵌入式]【STM32-RS485串口通信踩过的坑】

一、串口初始化 (主控芯片用的GD32f303rct6)

void usart_init()
{
	/* 略 */
}

/*****************  发送一个字节 **********************/
/* 单独调用时要记得先使能485发送引脚,发送后切为接收模式 */
void usart_sendbyte(uint32_t usart_periph, uint8_t ch)
{
	/* 发送一个字节数据到USART */
	usart_data_transmit(usart_periph, ch);	
	/* 等待发送数据寄存器为空 */
	while (usart_flag_get(usart_periph, USART_FLAG_TBE) == RESET);
}

/*****************  发送指定长度的字符串 **********************/
void rs485_send_data(uint8_t *str,uint32_t strlen )
{
	unsigned int k=0;

	rs485_mode_set(1);	//切换为发送
    do 
    {
        usart_sendbyte(USART0, *(str + k));
        k++;
    } while(k < strlen);
		
	///*yehuo de 加短暂延时,保证485发送数据完毕*/
	//Delay(0xFFF);  /* 短延时没用, 导致最后一个字节为0xff, 长延时不能接受 */
	/* yuanzi de 等待发送完成 */
	while (usart_flag_get(USART0, USART_FLAG_TC) == RESET);  /* 有用 */
		
	rs485_mode_set(0);	//切换为接收模式
}

/* _485延时等待,切换收发模式时等待硬件完成 */
void rs485_delay()
{
	__IO uint32_t count = 30;
	for(;count!=0;count--);
}

/* 控制485模块收发模式 0:recv, 1:send*/
void rs485_mode_set(uint8_t mode)
{
	rs485_delay();
	if (mode)
		gpio_bit_reset(GPIOA, GPIO_PIN_5);  /* PA5是rs485收发模式控制引脚 */
	else 
		gpio_bit_set(GPIOA, GPIO_PIN_5);	
	rs485_delay();
}

二、printf重定向到串口

/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
	//rs485_mode_set(1);  不能在里面切模式, 有延时
	usart_data_transmit(USART0, (uint8_t)ch);
    while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
    //rs485_mode_set(0);
    return ch;
}

三、踩到的坑:

1. RS485使用串口输出任意长度字符串, 最后一个字节固定为FF(其他的字节偶尔乱码)

原因显然是最后一个字节没发出去, 网络上的解决方法:

  1. 多发一个空字符.
  2. 发完切模式前加延时, 1ms. 本人实测不同波特率需要不同的延时(1ms), 延时较长并且其他的字符也不稳定.

实际解决方法: 等发送完成标志

while (usart_flag_get(USART0, USART_FLAG_TC) == RESET);  /* 有用 */
2. printf函数规律性乱码

其中一个原因同上, 另一个是: printf重定向问题, 不应该在int fputc(int ch, FILE *f)里面切换RS485收发器工作模式, printf调用此函数每发送一个字符, 会调用4次rs485_dealy(). 解决方法:

  1. 不用printf()函数
  2. 在printf()函数外面切换RS485收发器工作模式 (直观但啰嗦)
rs485_mode_set(1);
printf();  /* 加的log */
rs485_mode_set(0);
  1. 将上面3行代码封装成一个函数, 参数与printf()的一样, 貌似很难实现可变长度参数的传递, 挖坑待填: 可以参考rt-thread的rt_printk()实现原理.
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-12-28 23:05:40  更:2021-12-28 23:06:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/9 16:06:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码