这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » 【炫Q-STM32】NUCLEO-G070RB边玩边学(三)-串口大杂烩

共20条 1/2 1 2 跳转至

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

专家
2021-02-07 20:59:02     打赏

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

005.png

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


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

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

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

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




专家
2021-02-07 21:13:26     打赏
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:17     打赏
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:03     打赏
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:02     打赏
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:56     打赏
6楼

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


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

十分不错的产品


专家
2021-02-08 09:50:26     打赏
8楼
谢谢

工程师
2021-02-08 23:39:19     打赏
9楼

感谢分享


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

总结的非常不错


共20条 1/2 1 2 跳转至

回复

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