嵌入式技术william hill官网
直播中

向日葵的花季

8年用户 1225经验值
擅长:电源/新能源
私信 关注
[问答]

RT-Thread UART接口接收多个字节出错这是什么原因?

使用官方给的UART例程移植到自己板子上,使用uart2,调试口使用jlinkRtt,mcu stm32f103zet6

软件环境:rt_thread studio2.2.5

硬件环境:自己做的板子上暂时跑一个uart2连接金升阳TD321S485模块,

实验现象:用官方给的例子实现接收和发送,在不加485模块时,接收多少个数据,即可发出多少个,但是接上485之后,在接收一个字节时,发出的数据正确,接收多个字节,发出数据报错,这是什么原因?

/*

Copyright (c) 2006-2022, RT-Thread Development Team

SPDX-License-Identifier: Apache-2.0

Change Logs:

Date Author Notes

2022-09-13 RT-Thread first version

/

#include <rtthread.h>

#include <drivers/pin.h>

#include <rtdbg.h>

#include <led.h>

#include <rtdevice.h>

#include "gpio.h"

#include "usart.h"

//#include <serial.h

#define SAMPLE_UART_NAME "uart2"

static struct rt_semaphore rx_sem;

static rt_device_t serial;

#define RS485_TX_EN 1

struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* 初始化配置参数 */

int RS485_TX(void)

{

rt_pin_write(RS485_TX_EN, PIN_LOW);

return 0;

}

int RS485_RX(void)

{

rt_pin_write(RS485_TX_EN, PIN_HIGH);

return 0;

}

int RS485_INIT(void)

{

rt_pin_mode(RS485_TX_EN, PIN_MODE_OUTPUT);

RS485_RX();

return 0;

}

/* 接收数据回调函数 */

static rt_err_t uart_input(rt_device_t dev, rt_size_t size)

{

/* 串口接收到数据后产生中断,调用此回调函数,然后发送接收信号量 */

rt_sem_release(&rx_sem);

return RT_EOK;

}

static void serial_thread_entry(void *parameter)

{

char ch;

while (1)

{

/* 从串口读取一个字节的数据,没有读取到则等待接收信号量 */

while (rt_device_read(serial, -1, &ch, 1) != 1)

{

/* 阻塞等待接收信号量,等到信号量后再次读取数据 */

rt_sem_take(&rx_sem, RT_WAITING_FOREVER);

}

/* 读取到的数据通过串口错位输出 */

ch = ch;

RS485_TX();

rt_device_write(serial, 0, &ch, 1);

RS485_RX();

}

}

static int uart_sample()

{

rt_err_t ret=RT_EOK;

char uart_name[RT_NAME_MAX];

char str[]="this a rtthread example!\r\n";

/* if (argc == 2)

{

rt_strncpy(uart_name, argv[1], RT_NAME_MAX);

}

else

{

rt_strncpy(uart_name, SAMPLE_UART_NAME, RT_NAME_MAX);

}*/

serial=rt_device_find(SAMPLE_UART_NAME);

if(!serial)

{

rt_kprintf("find %s failed!\n",uart_name);

return RT_ERROR;

}

config.baud_rate=BAUD_RATE_9600;

if(RT_EOK != rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config))

{

rt_kprintf("配置串口设备失败\n");

return RT_ERROR;

}

rt_kprintf("配置串口设备成功!\n");

RS485_INIT();

rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);

rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);

rt_device_set_rx_indicate(serial, uart_input);

RS485_TX();

rt_device_write(serial, 0, str, (sizeof(str)-1));

RS485_RX();

rt_thread_t thread =rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);

if(thread!=RT_NULL)

{

rt_thread_startup(thread);

}

else {

ret=RT_ERROR;

}

return ret;

}

int main(void)

{

uart_sample();

led_init();

while (1)

{

led_toggle();

rt_thread_mdelay(1000);

}

return RT_EOK;

}

图1用UART直接发送,用uart转usb接到电脑显示如下

1.jpg

图2,用485直接发送,用485转usb接到电脑显示如下

1.jpg

回帖(4)

李辉

2022-10-24 14:32:22
在测试485的时候,你是不是一下子使用串口调试助手发送多个数据,根据你的代码,收一个发一个。
因为 485 是半双工的,你串口调试助手一次发多个,正常的逻辑单片机一侧应该接收完再发送,但是你的逻辑是收一个发一个,这样在发送第一个收到的字节时,串口调试助手已经在发送第二个第三个了,这样你单片机一侧就会丢数据,所以看起来就是首发的结果不一致,但是全双工的就不会影响。
举报

李辉

2022-10-24 14:32:28
应该修改为一直接收,接收完成后再发送
举报

李莉

2022-10-24 14:32:37
接收的数据对吗,使用485得考虑你发送的数据和接收的都要过485芯片。然后还要考虑485芯片的通信频率。
举报

夏日余晖

2022-10-24 14:33:13
启动发送前拉低rs485的收发使能需要延时一下,发送完成后也要延时下再拉低收发使能脚
举报

更多回帖

发帖
×
20
完善资料,
赚取积分