一、串口初始化 (主控芯片用的GD32f303rct6)
void usart_init()
{
}
void usart_sendbyte(uint32_t usart_periph, uint8_t ch)
{
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);
while (usart_flag_get(USART0, USART_FLAG_TC) == RESET);
rs485_mode_set(0);
}
void rs485_delay()
{
__IO uint32_t count = 30;
for(;count!=0;count--);
}
void rs485_mode_set(uint8_t mode)
{
rs485_delay();
if (mode)
gpio_bit_reset(GPIOA, GPIO_PIN_5);
else
gpio_bit_set(GPIOA, GPIO_PIN_5);
rs485_delay();
}
二、printf重定向到串口
int fputc(int ch, FILE *f)
{
usart_data_transmit(USART0, (uint8_t)ch);
while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
return ch;
}
三、踩到的坑:
1. RS485使用串口输出任意长度字符串, 最后一个字节固定为FF(其他的字节偶尔乱码)
原因显然是最后一个字节没发出去, 网络上的解决方法:
- 多发一个空字符.
- 发完切模式前加延时, 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() . 解决方法:
- 不用printf()函数
- 在printf()函数外面切换RS485收发器工作模式 (直观但啰嗦)
rs485_mode_set(1);
printf();
rs485_mode_set(0);
- 将上面3行代码封装成一个函数, 参数与
printf() 的一样, 貌似很难实现可变长度参数的传递, 挖坑待填: 可以参考rt-thread的rt_printk() 实现原理.
|