论坛» 嵌入式开发» STM32

【炫Q-STM32】NUCLEO-G070RB边玩边学(三)-串口大杂烩

专家
2021-02-07 20:59 1楼

正好这周讲串口,就先做串口吧,因为今天订的配件到了,所以考虑是做小灯的作业还是做串口,一番纠结后决定先把串口记录下来,灯不一定能点亮,串口已经通了,在忘了之前记录下来,虽然还不是很稳定。

005.png

好吧,言归正传,串口,期间网上搜了不少资料也用了不少时间来学习,来尝试,最终结论,还是S老师的帖子给力,期间主要参考了


第八篇:STM32G070RB探测8-串口点灯

第九篇:STM32G070RB探测9-串口不定长接收(中断方式接收中断空闲中断)

第十篇:STM32G070RB探测10-串口不定长接收(DMA接收空闲中断)

最终结果,压力测试,有误码,但不算多,这块就算过吧,有发现代码问题的老师,欢迎指出问题,谢谢啦!


专家
2021-02-07 21:13 2楼

首先是准备工作

建立一个叫Echo的工程,打开串口中断,确认115200-N-8-1,还得打开debuger的自动reset and run

usart.h引用

#include "stdio.h"

usart.c增加

int fputc(int ch, FILE *f) { HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF); return ch; }

main.c测试

printf("Hello EEPW ^_^!\r\n");

运行显示

Hello EEPW ^_^!


专家
2021-02-07 21:28 3楼

然后普通串口中断回显

main.c中定义缓存变量

uint8_t recv_buf;

启动接收

HAL_UART_Receive_IT(&huart2, &recv_buf, 1);

定义中断处理函数

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart ->Instance == USART2){ printf("%c",recv_buf); HAL_UART_Receive_IT(&huart2, &recv_buf, 1); } }

经测试3个字节间隔10ms发送,接收问题不大,再长会丢失不再接收


专家
2021-02-07 21:41 4楼

空闲中断

main.h中定义

#define RX_BUF_MAX_LEN 512 typedef struct { uint8_t rx_buff[RX_BUF_MAX_LEN]; uint16_t len; uint8_t flag; } USRAT_RX;

main.c中定义

#include "string.h" USRAT_RX usart_rx; uint8_t recv_buf;

stm32g0xx_it.c中定义

extern uint8_t recv_buf; extern USRAT_RX usart_rx;

直接修改中断函数

if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_RXNE) != RESET) { /* USER CODE END USART2_IRQn 0 */ HAL_UART_IRQHandler(&huart2); /* USER CODE BEGIN USART2_IRQn 1 */ usart_rx.rx_buff[usart_rx.len++] = recv_buf; if(usart_rx.len>RX_BUF_MAX_LEN){ usart_rx.flag = 1; } } if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE) != RESET) { __HAL_UART_CLEAR_IDLEFLAG(&huart2); usart_rx.flag = 1; if(usart_rx.len==0){ usart_rx.flag = 0; } } HAL_UART_Receive_IT(&huart2,&recv_buf,1);

main.c中初始化

memset(&usart_rx, 0, sizeof(USRAT_RX)); HAL_UART_Receive_IT(&huart2,&recv_buf,1); __HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE);

while中添加

if(usart_rx.flag){ printf("%s",usart_rx.rx_buff); memset(&usart_rx, 0, sizeof(USRAT_RX)); }

测试10个字节10ms发送基本没有问题


专家
2021-02-07 21:54 5楼

最后DMA+空闲

先选择RX的DMA选项

然后初始化

memset(&usart_rx, 0, sizeof(USRAT_RX)); __HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE); HAL_UART_Receive_DMA(&huart2, (uint8_t*)usart_rx.rx_buff, RX_BUF_MAX_LEN);

修改中断

if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE) != RESET) { __HAL_UART_CLEAR_IDLEFLAG(&huart2); HAL_UART_DMAStop(&huart2); usart_rx.len = RX_BUF_MAX_LEN - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx); usart_rx.flag = 1; if(usart_rx.len == 0){ usart_rx.flag = 0; HAL_UART_Receive_DMA(&huart2, (uint8_t*)usart_rx.rx_buff, RX_BUF_MAX_LEN); HAL_UART_DMAResume(&huart2); } }

循环输出

if(usart_rx.flag){ printf("%s",usart_rx.rx_buff); memset(&usart_rx, 0, sizeof(USRAT_RX)); HAL_UART_Receive_DMA(&huart2, (uint8_t*)usart_rx.rx_buff, RX_BUF_MAX_LEN); HAL_UART_DMAResume(&huart2); }

效果似乎还不如纯空闲,不知道为啥


院士
2021-02-07 22:35 6楼

在串口中这么早就清中断标识,会不会串口中断还未执行完就被别的中断打断了?

工程师
2021-02-07 23:03 7楼

十分不错的产品

专家
2021-02-08 09:50 8楼
谢谢
工程师
2021-02-08 23:39 9楼

感谢分享

工程师
2021-02-08 23:44 10楼

总结的非常不错

共20条 1/2 1 2 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册]