使用RT-Thread的串口空闲+DMA收发数据

RT-Thread的串口空闲+DMA目前发现一个问题,对于没有任何格式的串口帧来说,有时候用空闲中断是最方便的处理方,。因为每次接收过来的就是完整的一帧,而不用判断帧格式。但是RT底层会向中间件层推送数据,导致应用层接收的数据会被拆包。

解决方法:见注释部分(位于drv_usart.c)针对RT版本:v4.0.2

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    struct stm32_uart *uart;
    RT_ASSERT(huart != NULL);
    uart = (struct stm32_uart *)huart;
    //dma_isr(&uart->serial);
}

void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
{
    struct stm32_uart *uart;
    RT_ASSERT(huart != NULL);
    uart = (struct stm32_uart *)huart;
    //dma_isr(&uart->serial);
}

验证工程:将每次收到的字节数量打印到recv_count数组里观察。

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#include <ulog.h>

#define UART2_485_PIN    GET_PIN(A, 1)

static struct rt_messagequeue rx_mq;
rt_thread_t led_thread;
static rt_device_t serial2; 
struct serial_configure uart2_config = RT_SERIAL_CONFIG_DEFAULT;
static char msg_pool[256];

struct rx_msg
{
    rt_device_t dev;
    rt_size_t size;
};
int recv_count[50];
char rx_buffer[200];
static rt_err_t uart2_dma_callback(rt_device_t dev, rt_size_t size)
{
		static int recv_tick=0;
    struct rx_msg msg;
    rt_err_t result;
    msg.dev = dev;
    msg.size = size;
		recv_count[recv_tick]=msg.size;
		recv_tick++;
		result = rt_mq_send(&rx_mq, &msg, sizeof(msg));
    if ( result == -RT_EFULL)
    {
        rt_kprintf("message queue full!\n");
    }
    return result;
}

static void serial_thread_entry(void *parameter)
{
    struct rx_msg msg;
    rt_err_t result;
    rt_uint32_t rx_length;
    static char rx_buffer[RT_SERIAL_RB_BUFSZ + 1];

    while (1)
    {
        rt_memset(&msg, 0, sizeof(msg));
        result = rt_mq_recv(&rx_mq, &msg, sizeof(msg), RT_WAITING_FOREVER);
        if (result == RT_EOK)
        {
            rx_length = rt_device_read(msg.dev, 0, rx_buffer, msg.size);
            rx_buffer[rx_length] = '\0';
            rt_device_write(serial2, 0, rx_buffer, rx_length);
            rt_kprintf("%s\n",rx_buffer);
        }
    }
}

int main(void)
{
		rt_err_t ret = RT_EOK;
		rt_pin_mode(GET_PIN(A, 1), PIN_MODE_OUTPUT);
		rt_mq_init(&rx_mq, "rx_mq",msg_pool,sizeof(struct rx_msg),sizeof(msg_pool),RT_IPC_FLAG_FIFO);
		serial2=rt_device_find("uart2");
		if(RT_NULL==serial2)
		{
			rt_kprintf("uart2 find failed !\n");
		}
		else
		{
			uart2_config.baud_rate = BAUD_RATE_115200;        
			uart2_config.data_bits = DATA_BITS_8;          
			uart2_config.stop_bits = STOP_BITS_1;         
			uart2_config.bufsz     = 128;                  
			uart2_config.parity    = PARITY_NONE;        
			rt_device_control(serial2, RT_DEVICE_CTRL_CONFIG, &uart2_config);
			ret=rt_device_open(serial2, RT_DEVICE_FLAG_DMA_RX);
			rt_device_set_rx_indicate(serial2, uart2_dma_callback);
		}
		rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);
    if (thread != RT_NULL)
    {
        rt_thread_startup(thread);
    }

    return RT_EOK;
}


可以看到,每次接收到的长度都为40,与发送长度保持一致。并且收发正常。

  • 10
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值