cubemax不定长数据串口接收以及串口重定向

本文介绍了如何在嵌入式系统中通过串口通信实现中断接收,使用HAL库的函数处理数据,以及如何使用printf风格接口发送和接收数据,以及多串口的使用方法。
摘要由CSDN通过智能技术生成

使能串口,设置如下

打开串口中断

 

 预先定义接受数据缓存,rx_buf[MAX_LEN]

在代码开始处使用

HAL_UARTEx_ReceiveToIdle_IT(&huart1,(uint8_t*)rx_buf_1,sizeof(rx_buf_1)-1);

该语句将中断地检测串口总线是否空闲,如果数据传输完成后,总线便会空闲,从而进入回调函数(void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)),由此避开了定长接受的问题。

由于该回调函数是弱定义,所以我们可以在任何地方重写回调函数,重写如下

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if(huart==&huart1)
	{
		rx_buf_1[Size] = '\0';
		osMessageQueuePut(myQueue01Handle,rx_buf_1,NULL,0);
		HAL_UARTEx_ReceiveToIdle_IT(&huart1,(uint8_t*)rx_buf_1,sizeof(rx_buf_1)-1);
	}
}

该回调函数被调用时,会传回该数据流的长度,在数据流末尾处加入‘\0’,形成合法的字符串,

最后再次调用HAL_UARTEx_ReceiveToIdle_IT()函数重新检测总线空闲,继而实现串口接受功能。在此处的osMessageQueuePut函数可以理解为用来像其他任务发送“已经完整接受数据串”的信号,其他任务收到该信号也能开始处理数据串了。

我这里处理数据串是这样写的

if(osMessageQueueGet(myQueue01Handle,buf_1,NULL,10)==osOK)
{
	/*处理数据串*/
}

我这里的消息队列长度为1,单个数据内存占100个字节,所以osMessageQueuePut函数将100个字符放入消息队列,接受时也是将100个字节取出。

下面说一下发送

发送一般就是使用HAL_UART_Transmit或HAL_UART_Transmit_IT.

这里特别说一下重定向,可以直接使用printf进行发送。

在任意处可以加入以下代码

先包含头文件#include"stdio.h",加入以下代码

int fputc(int ch, FILE *f){
	HAL_UART_Transmit(&huart1, (uint8_t *)&ch,1,HAL_MAX_DELAY);
	return ch;
}
int fgetc(FILE *f){
	uint8_t ch;
	HAL_UART_Receive(&huart1, (uint8_t *)&ch,1,HAL_MAX_DELAY);
	return ch;
}

之后勾选USB_MicroLIB

多串口的使用

可以将任意串口当作类似于printf使用

#include <stdarg.h>
void usartx_printf(const char *format,...)
{
  va_list args;
  uint32_t length;
  uint8_t txbuf[MAXLEN] = {0};
  va_start(args, format);
  length = vsnprintf((char *)txbuf, sizeof(txbuf), (char *)format, args);
  va_end(args);
  HAL_UART_Transmit(&huartx, (uint8_t *)txbuf, length, HAL_MAX_DELAY);
  memset(txbuf, 0, MAXLEN);
}

 

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
这段代码是一个线程函数 `do_wstep_thread`,其主要作用是处理一系列事件(`evthead`)并将结果发送到消息队列中。 首先,函数开始时会获取全局变量 `mdata` 和 `evthead`,以及其他所需的变量。然后使用 `osEventFlagsClear` 清除事件标志位。 接下来进入一个无限循环,首先判断是否有可用的事件标志位。如果没有可用的事件标志位,则使用 `osDelay` 函数进行延迟一段时间后继续循环。 如果有可用的事件标志位,则使用 `osEventFlagsWait` 函数等待事件标志位被触发。如果触发的标志位超出了 `EVTFLAGS_MASK` 的范围,则使用 `osDelay` 函数进行延迟一段时间后继续循环。 接下来进入一个 `do-while` 循环,通过调用 `fifo_get` 函数从 `fifo` 队列中获取一个消息。如果获取成功,则将获取到的消息的指针赋值给 `evthead`。接着判断 `evthead` 是否为空,如果为空则跳过当前循环。 接下来使用 `list_for_each_safe` 宏遍历 `evthead->head` 链表中的每个节点。对于每个节点,首先判断节点是否为空,如果为空则跳出当前循环。然后将节点转换为 `wstep_desc` 结构体指针,并调用 `doing_nonblocking` 函数对其进行非阻塞处理。 在处理完所有节点后,将 `evthead` 的指针赋值给 `msg.ptr`,然后使用 `osMessageQueuePut` 函数将消息放入消息队列中。如果放入消息队列失败,则进行错误处理。 最后,更新一些计数器和标志位,并继续下一轮循环。 如果循环结束,则执行 `exit` 标签处的代码,调用 `osThreadExit` 函数退出线程。 总体来说,这段代码的作用是循环等待事件标志位被触发,然后从队列中获取消息并处理,最后将处理结果发送到消息队列中。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值