STM32Cube系列教程10:STM32CubeIDE工程创建+串口DMA+IDLE+printf重定向+软中断处理串口数据+非阻塞延时任务

news2024/9/20 20:51:26

文章目录

  • 工程配置
    • 配置时钟
    • 配置Debug接口
    • 配置串口外设
    • 配置时钟树
    • 生成代码
  • 配置串口
    • 重定向printf
    • 配置串口,开启IDLE,开启软中断
  • 配置非阻塞延时任务调度函数
    • 编写任务调度函数
    • 延时任务创建
  • 编译,下载与测试
    • 编译
    • 下载
    • 测试

前两天收到了ST社区的NUCLEO-U083RC的评估板,这颗芯片中内置了硬件AES与RNG模块,准备对这两个模块做个测试,今天先配置个工程模板,主要开启串口收发,printf重定向,利用DMA与IDLE中断自动接收不定长的串口数据,在接收完毕后利用软中断触发中断处理串口数据,在编写一个简易的非阻塞延时功能。

全部代码以上传到github:https://github.com/what-sudo/stm32U083

工程配置

配置时钟

打开STM32CubeIDE环境,创建一个新项目,选择对应的芯片,打开STM32CubeMX代码生成工具。
打开System Core -> RCC,分别配置外部高速时钟与外部低速时钟源为晶体振荡器
在这里插入图片描述

打开System Core -> SYS,配置系统时基为SysTick。

vi

配置Debug接口

打开Trace and Debug -> Debug配置选项,选中Serial Wire。打开SWD功能。这里如果不打开,后期将无法使用swd功能烧写程序。
在这里插入图片描述

配置串口外设

打开Connectivity -> LPUART1配置选项,模式设置为异步串行接口,下面波特率设置为115200,检查右侧显示的串口管脚是否与硬件匹配,如果不匹配可重定向到别的管脚。

在这里插入图片描述
配置串口DMA通道
在这里插入图片描述
使能串口中断源
在这里插入图片描述

配置时钟树

为了获取更好的性能,这里选择使用外部时钟,注意设置外部晶体的频率,系统时钟源选择PLLCLK,HCLK时钟配置为48MHz。
在这里插入图片描述

生成代码

点击上方的Project manager,打开Code Generator,选中仅复制使用的库文件,生成单独的.c与.h文件。
在这里插入图片描述
设置完成后,Ctrl + S保存,将自动弹窗提示生成代码,或手动点击上方的小齿轮图标生成代码
在这里插入图片描述

配置串口

重定向printf

打开Core\Src\usart.c文件,在文件前部加入重定向printf的代码。

#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#define GETCHAR_PROTOTYPE int __io_getchar(FILE *f)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#define GETCHAR_PROTOTYPE int fgetc(FILE *f)
#endif /* __GNUC__ */
PUTCHAR_PROTOTYPE
{
  HAL_UART_Transmit(&hlpuart1, (uint8_t *)&ch, 1, 0xFFFF);
  return ch;
}
GETCHAR_PROTOTYPE
{
  uint8_t ch = 0;
  HAL_UART_Receive(&hlpuart1, (uint8_t *)&ch, 1, 0xFFFF);
  if (ch == '\r')
  {
    __io_putchar('\r');
    ch = '\n';
  }
  return __io_putchar(ch);
}

在这里插入图片描述

配置串口,开启IDLE,开启软中断

打开usart.c文件,在文件中定义串口接收buffer,编写串口IDLE中断处理函数,串口DMA发送函数,串口接收数据处理函数,软中断处理函数。

volatile uint8_t rx1_len = 0;  //Received data length
volatile uint8_t rec1_end_flag = 0; //Received data over flag
uint8_t rx1_buffer[BUFFER_SIZE]={0};  //Received data buffer

// IDLE中断处理
void Usart1_IDLE(void)
{
  uint32_t tmp_flag = 0;
  uint32_t temp;

  tmp_flag = __HAL_UART_GET_FLAG(&hlpuart1, UART_FLAG_IDLE);
  if ((tmp_flag != RESET))
  {
    __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);
    HAL_UART_DMAStop(&hlpuart1);
    temp = __HAL_DMA_GET_COUNTER(&hdma_lpuart1_rx);
    rx1_len = BUFFER_SIZE - temp;
    rec1_end_flag = 1;
    EXTI->SWIER1 |= 1 << 0;
  }
}
// 串口发送
int DMA_Usart1_Send(uint8_t *buf, uint8_t len)
{
  if (len == 0)
    return 0;
  HAL_StatusTypeDef sta = HAL_UART_Transmit_DMA(&hlpuart1, buf, len);
  if (sta != HAL_OK)
    return -1;
  return 0;
}
// 串口数据处理
void Usart1_Handle()
{
  if (rec1_end_flag) {
    DMA_Usart1_Send(rx1_buffer, rx1_len);
    rx1_len = 0;
    rec1_end_flag = 0;
    HAL_UART_Receive_DMA(&hlpuart1, rx1_buffer, BUFFER_SIZE);
  }
}
// 软中断处理
void EXTI0_1_IRQHandler(void)
{
  if (EXTI->RPR1 & 1 << 0)
  {
    EXTI->RPR1 |= 1 << 0;
    Usart1_Handle();
  }
}

打开stm32u0xx_it.c文件,找到void USART3_LPUART1_IRQHandler(void)函数,在函数体前部其中加入Usart1_IDLE函数调用。修改如下

/**
  * @brief This function handles USART3 (combined with EXTI 24) + LPUART1 global interrupt (combined with EXTI lines 28).
  */
void USART3_LPUART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART3_LPUART1_IRQn 0 */
  Usart1_IDLE();
  /* USER CODE END USART3_LPUART1_IRQn 0 */
  HAL_UART_IRQHandler(&hlpuart1);
  /* USER CODE BEGIN USART3_LPUART1_IRQn 1 */

  /* USER CODE END USART3_LPUART1_IRQn 1 */
}

打开main.c文件,在main()函数中,加入初始化软中断,开启IDLE中断,开启串口DMA接收的代码

  EXTI->IMR1 |= 1<<0;
  HAL_NVIC_SetPriority(EXTI0_1_IRQn, 3, 0);
  HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);

  __HAL_UART_ENABLE_IT(&hlpuart1, UART_IT_IDLE);
  HAL_UART_Receive_DMA(&hlpuart1,rx1_buffer,BUFFER_SIZE);

在这里插入图片描述

配置非阻塞延时任务调度函数

编写任务调度函数

打开main.c文件,在user code的位置,定义task_scheduling函数。

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t task_scheduling(uint32_t *task, uint32_t time)
{
  uint32_t sys_ms_timer = HAL_GetTick();
  if ((sys_ms_timer > *task) && ((sys_ms_timer - *task) > time))
  {
    *task = sys_ms_timer;
    return 1;
  }
  else if (*task > sys_ms_timer)
  {
    if (((0xffffffff - *task) + sys_ms_timer) > time)
    {
      *task = sys_ms_timer;
      return 1;
    }
  }
  return 0;
}

/* USER CODE END 0 */

延时任务创建

在主循环中,添加一个led灯闪烁的任务,每隔1000ms执行一次。

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    if (task_scheduling(&task1, 1000))
    {
      HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
    }

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

编译,下载与测试

编译

代码编写完成后,点击工具栏的build按钮
在这里插入图片描述

下载

等待控制台完成编译后,控制台输出程序的空间占用,点击工具栏的下载按钮,等待完成下载。
在这里插入图片描述

测试

程序下载完成后,可以看到led灯每隔1s闪烁一下。
打开串口调试工具,发送数据,单片机将接收到的数据返回。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1704128.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C数据结构:二叉树

目录 二叉树的数据结构 前序遍历 中序遍历 后序遍历 二叉树的创建 二叉树的销毁 二叉树的节点个数 二叉树叶子节点个数 二叉树第K层节点个数 二叉树的查找 层序遍历 判断二叉树是否为完全二叉树 完整代码 二叉树的数据结构 typedef char BTDataType; typedef str…

Golang的内存关系

1.Page Golang的Page,在操作系统对虚拟内存管理的MMU定义的物理页有相似的定义,默认的Page为8KB 2.mSpan 多个连续的Page称之为是一个Span&#xff0c;其定义含义有操作系统的管理的页表相似 3.Size Class Size Class: 相当于 一个等级和刻度, 比如 第二等级 就代表 一个Pag…

【C++ ——— 多态】笔记

文章目录 一、多态概念二、多态的定义即实现2.1 多态的构成条件2.2 虚函数2.3虚函数的重写1.虚函数中析构函数的重写2.重载、重写&#xff08;覆盖&#xff09;、重定义&#xff08;隐藏&#xff09;的区别 2.4 C11 override 和 final 三、抽象类3.1抽象类概念3.2 接口继承和实…

中断处理过程介绍

概念 中断 中断源 分类 中断处理过程 中断请求 实现器件 中断判优 软件判优 过程 器件实现 程序实现 硬件判优 链路判优 器件实现 控制器判优 中断响应 中断服务 中断返回

C语言作为计算机行业的基础之一,是否制约了行业本身的发展?

c不是计算机行业的基础啦&#xff0c;你想&#xff0c;c语言出现时已经有一套成熟的计算机体系&#xff0c;有基于内存地址的寻找指令、数据的工作方式&#xff0c;有汇编语言&#xff0c;那搞出c这种高级语言就很正常啊&#xff01;刚好我有一些资料&#xff0c;是我根据网友给…

代码随想录算法训练营第20天 |● 654.最大二叉树 ● 617.合并二叉树 ● 700.二叉搜索树中的搜索 ● 98.验证二叉搜索树

文章目录 前言654.最大二叉树思路方法一 递归法方法一2 老师的优化递归法 617.合并二叉树思路方法一 递归法方法二 迭代法 700.二叉搜索树中的搜索思路方法一 递归法方法二 迭代法 98.验证二叉搜索树思路方法一 使用数组方法二 不使用数组代码注意点&#xff1a; 方法二 使用双…

【Linux】Linux的基本指令_3

文章目录 二、基本指令15. date16. cal16. find17. grep18. zip 和 unzip19. tar20. uname 未完待续 二、基本指令 15. date date 命令可以显示当前时间。 常用标记列表&#xff1a; %H : 小时(00…23) %M : 分钟(00…59) %S : 秒(00…61) %X : 相当于 %H:%M:%S %d : 日 (01……

简易计算器

前言 简易计算器&#xff0c;旨在实现一个简单的计算器功能。 整形&#xff0c;浮点型数据的加减乘除运算&#xff1b;数据的统计(如文件中某字符的出现频数)&#xff1b;期望&#xff0c;方程运算&#xff1b;平均数&#xff0c;最小值&#xff0c;最大值&#xff0c;中位数…

C++之“流”-第2课-C++和C标准输入输出同步

为什么C和C的标准输入输出不同步时&#xff0c;数据会混乱&#xff1f;同步会带来多大性能损失&#xff1f;为什么说这个损失通常不用太在乎&#xff1f; 0. 课堂视频 C之“流”-第2课&#xff1a;和C输入输出的同步 1. 理解cin和cout的类型与创建过程 std::cout 是std::ostre…

Css 提高 - 获取DOM元素

目录 1、根据选择器来获取DOM元素 2.、根据选择器来获取DOM元素伪数组 3、根据id获取一个元素 4、通过标签类型名获取所有该标签的元素 5、通过类名获取元素 目标&#xff1a;能查找/获取DOM对象 1、根据选择器来获取DOM元素 语法&#xff1a; document.querySelector(css选择…

C/C++运行时库和UCRT系统通用运行时库总结及问题实例分享

目录 1、概述 2、不同版本的Visual Studio对应的运行时库说明 3、在Windbg10.0安装目录中获取UCRT通用运行时库 4、微软官网对UCRT通用运行时库的相关说明 5、使用Visual Studio 2017开发软件初期遇到的UCRT通用运行时库问题 6、如何查看软件依赖了哪些C/C运行时库&#…

vueRouter路由总结

https://blog.csdn.net/qq_24767091/article/details/119326884

奇门遁甲古籍《烟奇要览》

《烟奇要览》 全书共178页 时间有限&#xff0c;仅上传部分图片&#xff01;

js深入理解对象的 属性(properties)的特殊 特性(attributes)

对象 js对象 // 构造一个对象 let obj {}; let obj new Object(); 我们知道js中一切皆对象&#xff0c;对象是一个键值对集合&#xff08;key: value)&#xff0c;一个键(key)对应一个值(value)&#xff0c;而每个键都是这个对象的属性&#xff0c;我们可以通过对象的属性来…

在CentOS 8上卸载与安装MySQL 8的详细步骤

关键词&#xff1a;MySQL 8安装、CentOS 8、YUM源配置、卸载MySQL、MySQL残留文件删除、首次登录MySQL临时密码、服务状态检查、MySQL社区服务器 阅读建议&#xff1a;本文适合需要在CentOS 8操作系统上部署最新MySQL 8数据库的系统管理员或开发者阅读。文中步骤简洁清晰&#…

ResizeObserver loop completed with undelivered notifications.

报错信息 ResizeObserver loop completed with undelivered notifications. 来源 在用vue3 element-plus写项目的时候报的错&#xff0c;经过排查法&#xff0c;发现是element-plus的el-table组件引起的错误。 经过初步排查&#xff0c;这个错误并不是vue以及element-plus…

springboot投票统计管理系统的设计与实现-计算机毕业设计源码73598

摘 要 随着互联网趋势的到来&#xff0c;各行各业都在考虑利用互联网将自己推广出去&#xff0c;最好方式就是建立自己的互联网系统&#xff0c;并对其进行维护和管理。在现实运用中&#xff0c;应用软件的工作规则和开发步骤&#xff0c;采用Java技术建设投票统计管理系统。 …

最新扣子(Coze)实战教程:扣子​使用基础,完全免费,快来学习吧~

&#x1f9d9;‍♂️ 诸位好&#xff0c;吾乃斜杠君&#xff0c;编程界之翘楚&#xff0c;代码之大师。算法如流水&#xff0c;逻辑如棋局。 &#x1f4dc; 吾之笔记&#xff0c;内含诸般技术之秘诀。吾欲以此笔记&#xff0c;传授编程之道&#xff0c;助汝解技术难题。 &#…

电脑由于ntdll.dlI丢失导致exe崩溃有什么解决办法?解决ntdll.dll丢失问题

相信有一些用户正在面临一个叫做“ntdll.dll丢失”的问题&#xff0c;这种情况多半发生在试图运行某个程序时&#xff0c;系统会提示一条错误消息&#xff1a;“程序无法启动&#xff0c;因为计算机中丢失了ntdll.dll”。那么&#xff0c;为何ntdll.dll文件会丢失&#xff0c;又…