【蓝桥杯嵌入式】六、真题演练(三)-2研究篇:第13届第一场真题

温馨提示:

        真题演练分为模拟篇和研究篇。本专栏的主要作用是记录我的备赛过程,我打算先自己做一遍,把遇到的问题和不同之处记录到演练篇,然后再返回来仔细研究一下,找到最佳的解题方法记录到研究篇。题目在:https://pan.quark.cn/s/fc121e80dbff

本文可能不会重复之前提到的内容,如需查看,请参考附录

【蓝桥杯嵌入式】附录

目录

演练时发现的问题

题目分析与计划

设计规范 

浏览题目

详细阅读与分析

整体流程设计和对应代码

一、外设配置与代码框分析

二、软件配置

按照分析配置外设

USART1

TIM

三、保存结果


演练时发现的问题

  1. LED的闪烁问题(之前没有注意到),不可以使用Toggle函数;因为LCD会对引脚的状态产生影响。应该使用标志变量,或利用奇偶数来实现状态切换。
  2. 不知道为什么,我的开发板上一打开TIM就会产生一次超时中断;解决方法是设置一个计数变量为0,只要调用中断服务函数就自增1,当计数为2时再实现计划的功能。
  3. 在LED驱动函数中包含关闭所有LED灯的,只需要在进入while前关闭一次LED,不用每次都关闭LED了。
  4. 重要!!题目要求按键响应小于100ms,那我们就设置为90ms。
  5. 有时需要在中断中清屏,但是中断的位置不确定;所以要设置一个全局标志,在中断改变标志,然后在需要清屏的地方判断标志位来清屏。
  6. 串口接收信号后要延时50ms。

题目分析与计划

设计规范 

       我自己设计的时候没有章法,从而设计的有点潦草,浪费了很多时间。设计的时候要冷静、全面、要遵守一个确定的顺序。

        现在我要确定一个章法,这是第一版,以后更新的版本请在附录中查看。

  1. 浏览一遍题目,有一个整体印象。
  2. 仔细读题目,综合考虑如何配置外设和实现功能。
    1. 确定需要的外设和功能。约定圆形为外设分析、三角型为功能分析,图形中的数字来区分不同的模块。
  3. 设计流程,主循环前做什么、主循环中做什么。
    1. 确定主循环前打开需要的外设
    2. 根据题目一步一步的设计流程,不要遗漏,字不要写的太大,而且要留有足够的空间用来修改。
      1. 流程包括一条主线任务,调用函数就是支线任务。
    3. 同时在另一张草稿纸上写下需要的变量,按照外设或题目中的信息命名,要有特征性和区分度。
  4. 这样设计下来最多1小时,按照设计配置外设和写程序最多2小时,检查和优化1小时,最多4个小时就完成了。
  5. 全局变量定义:

    经验规则:

    标志变量:uint8_t ,只取个位数或0,1

    与计算有关或者需要显示:uint32_t

    浮点型:float

浏览题目

得到的信息:PWM输出、串口、LED2个、KEY4个、LCD2种界面。

详细阅读与分析

硬件要求:

①USART1,9600,需要接收信息

②PWM输出,PA1,2k或1k,占空比可调10%。PCBTimer设置位40MHz,周期设置为199(频率1k);占空值设置为19。

功能要求:

、通过串口改密码、密码错误3次以上LD2闪烁。

常用功能:

三角形1:验证密码

三角形2:改变输入的密码

三角形3:串口接收后的处理(中断服务函数)

三角形4:密码正确的操作(包含在三角形1中)

需要的定时器的功能:

三角形1密码正确后:TIM6

三角形1密码3次以上错误后:TIM7

整体流程设计和对应代码

提示:自己写设计流程草稿的时候要按照自己的习惯简写,我这里是为了方便描述才写这么多的。

  • 这里密码只用于确定是否正确而且位数确定,所以密码直接用字符类型的数组来存储密码更方便。
  • 软件方式启动PA1进行PWM输出的定时器,和通道;DMA方式启动串口接收。
  • 主循环中轮询检测按键、LED状态标志
  • 当LCD_show=0时为PSD模式;
    • 按下按键,对应的密码值B[x]就加一
    • 按下B4→三角形1:验证密码
      • (支线)三角形1:验证密码
        • 尝试次数 tryTime 加一
        • 若密码正确:LED_show=1;清屏;tryTime清零;PWM周期设置为99;占空值设置为19; LD1_f标志置1;打开TIM6。
          //验证密码
          void KEY_Try()
          {if(KEY[0]==B[0]&&KEY[1]==B[1]&&KEY[2]==B[2]){LCD_show=1;LCD_Clear(Black);LD1_f=1;tryTime=0;__HAL_TIM_SET_COUNTER(&htim2,99);__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,19);HAL_TIM_Base_Start_IT(&htim6);}else{tryTime++;B[0]='@',B[1]='@',B[2]='@';if(tryTime>=3){LD2_f=1;HAL_TIM_Base_Start_IT(&htim7);}}
          }
          
           
          • TIM6:5s后第二次调用服务函数时:LED_show=0;PWM周期变设置为199; LD1_f标志置0;清屏标志clear_f置1;关闭TIM6。
  • 当LCD_show=1时为STA模式;
    • 显示频率和周期,题目中没有读取操作,设置周期后频率确定,这里频率是定值2000;占空比可以用“(读取占空比+1)/2”计算,其实也是定值,这里象征性的计算一下。
  • 其他支线
    • (支线)三角形2:密码值变化,输入一个char*变量,改变值,如果是‘@’或‘9’,就变为‘0’。
      //密码值改变
      void KEY_Change(char* Bx)
      {if(*Bx=='@'||*Bx=='9')*Bx='0';else*Bx=*Bx+1;
      }

    • (支线)三角形3:串口接收后的处理(中断服务函数):如果指令的前三位是密码,那就把密码改为指令的4~6为新密码
      void DMA1_Channel1_IRQHandler(void)
      {/* USER CODE BEGIN DMA1_Channel1_IRQn 0 *//* USER CODE END DMA1_Channel1_IRQn 0 */HAL_DMA_IRQHandler(&hdma_usart1_rx);/* USER CODE BEGIN DMA1_Channel1_IRQn 1 */HAL_Delay(50);if(KEY[0]==rxBuf[0]&&KEY[1]==rxBuf[1]&&KEY[2]==rxBuf[2]){KEY[0]=rxBuf[4];KEY[1]=rxBuf[5];KEY[2]=rxBuf[6];}/* USER CODE END DMA1_Channel1_IRQn 1 */
      }

主循环函数部分:

/* USER CODE BEGIN WHILE */HAL_TIM_Base_Start(&htim2);HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);HAL_UART_Receive_DMA(&huart1,(uint8_t*)rxBuf,sizeof(rxBuf));LED_swicth(LED1_Pin|LED2_Pin|LED3_Pin|LED4_Pin|LED5_Pin|LED6_Pin|LED7_Pin|LED8_Pin,GPIO_PIN_SET);while (1){keyScan();LED_State();if(LCD_show==0){if(clear_f==1){LCD_Clear(Black);clear_f=0;}LCD_DisplayStringLine(Line2,(uint8_t*)"       PSD");sprintf(LCD_str,"    B1:%c",B[0]);LCD_DisplayStringLine(Line4,(uint8_t*)LCD_str);sprintf(LCD_str,"    B2:%c",B[1]);LCD_DisplayStringLine(Line5,(uint8_t*)LCD_str);sprintf(LCD_str,"    B3:%c",B[2]);LCD_DisplayStringLine(Line6,(uint8_t*)LCD_str);}else if(LCD_show==1){LCD_DisplayStringLine(Line2,(uint8_t*)"       STA");sprintf(LCD_str,"    F:%dHz",STA_F);LCD_DisplayStringLine(Line4,(uint8_t*)LCD_str);STA_D=__HAL_TIM_GET_COMPARE(&htim2,TIM_CHANNEL_2)+1/2;sprintf(LCD_str,"    D:%d%c",STA_D,'%');LCD_DisplayStringLine(Line5,(uint8_t*)LCD_str);}/* USER CODE END WHILE */

按键响应:

//按键响应
void B1_fun()
{if(LCD_show!=0)return;KEY_Change(&B[0]);
}void B2_fun()
{if(LCD_show!=0)return;KEY_Change(&B[1]);
}void B3_fun()
{if(LCD_show!=0)return;KEY_Change(&B[2]);
}void B4_fun()
{if(LCD_show!=0)return;KEY_Try();
}

中断函数: 


void DMA1_Channel1_IRQHandler(void)
{HAL_DMA_IRQHandler(&hdma_usart1_rx);HAL_Delay(50);if(KEY[0]==rxBuf[0]&&KEY[1]==rxBuf[1]&&KEY[2]==rxBuf[2]){KEY[0]=rxBuf[4];KEY[1]=rxBuf[5];KEY[2]=rxBuf[6];}
}void TIM6_DAC_IRQHandler(void)
{HAL_TIM_IRQHandler(&htim6);tim6++;if(tim6==2){clear_f=1;tim6=0;LCD_show=0;LD1_f=0;__HAL_TIM_SET_COUNTER(&htim2,199);LED_swicth(LED1_Pin,GPIO_PIN_SET);B[0]='@',B[1]='@',B[2]='@';HAL_TIM_Base_Stop_IT(&htim6);}
}void TIM7_IRQHandler(void)
{HAL_TIM_IRQHandler(&htim7);LD2_tim++;if(LD2_tim==50){LD2_tim=0;HAL_TIM_Base_Stop_IT(&htim7);}else {if(LD2_tim%2==0)LED_swicth(LED2_Pin,GPIO_PIN_RESET);elseLED_swicth(LED2_Pin,GPIO_PIN_SET);}
}

一、外设配置与代码框分析

LED:锁存器操作包装函数,直接在main.c实现

//LED控制
void LED_swicth(uint16_t GPIO_pin,GPIO_PinState PinState)
{HAL_GPIO_WritePin(LED_LE_GPIO_Port,LED_LE_Pin,GPIO_PIN_SET);HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin|LED2_Pin|LED3_Pin|LED4_Pin|LED5_Pin|LED6_Pin|LED7_Pin|LED8_Pin,GPIO_PIN_SET);HAL_GPIO_WritePin(LED1_GPIO_Port,GPIO_pin,PinState);HAL_GPIO_WritePin(LED_LE_GPIO_Port,LED_LE_Pin,GPIO_PIN_RESET);
}

KEY:扫描函数、长按操作

按键扫描函数框架:所有的按键引发事件的操作都在这里实现

//按键1响应函数
void B1Fun()
{
}//按键2响应函数
void B2Fun()
{
}//按键3响应函数
void B3Fun()
{
}//按键4响应函数
void B4Fun()
{
}//按键扫描
void KeyScan()
{uint32_t keyDelay=50;if(HAL_GPIO_ReadPin(B1_GPIO_Port,B1_Pin)==GPIO_PIN_RESET){HAL_Delay(keyDelay);if(HAL_GPIO_ReadPin(B1_GPIO_Port,B1_Pin)==GPIO_PIN_RESET){B1Fun();}}if(HAL_GPIO_ReadPin(B2_GPIO_Port,B2_Pin)==GPIO_PIN_RESET){HAL_Delay(keyDelay);if(HAL_GPIO_ReadPin(B2_GPIO_Port,B2_Pin)==GPIO_PIN_RESET){B2Fun();}}if(HAL_GPIO_ReadPin(B3_GPIO_Port,B3_Pin)==GPIO_PIN_RESET){HAL_Delay(keyDelay);if(HAL_GPIO_ReadPin(B3_GPIO_Port,B3_Pin)==GPIO_PIN_RESET){B3Fun();}}if(HAL_GPIO_ReadPin(B4_GPIO_Port,B4_Pin)==GPIO_PIN_RESET){HAL_Delay(keyDelay);if(HAL_GPIO_ReadPin(B4_GPIO_Port,B4_Pin)==GPIO_PIN_RESET){B4Fun();}}
}

长按操作: 按下按键后打开定时器,定时器计时2s,如果定时器正在运行,就轮询检测按键是否松开,如果松开就是短按。如果定时器计时完成就关闭定时器,等待按键松开,就是长按。

//PWM_C初始化为1,在定时器超时后PWM_C=0判定为长按
if(PWM_C==1)//长按
{HAL_TIM_Base_Start_IT(&htim6);while(HAL_TIM_Base_GetState(&htim6)==HAL_TIM_STATE_BUSY)//定时器正在运行{if(HAL_GPIO_ReadPin(B4_GPIO_Port,B4_Pin)==GPIO_PIN_SET)//按键提前松开,就是短按{HAL_TIM_Base_Stop_IT(&htim6);return;}}//如果是长按就等待按键松开if(PWM_C==0)while(HAL_GPIO_ReadPin(B4_GPIO_Port,B4_Pin)==GPIO_PIN_RESET);
}
else//短按PWM_C=1;

LCD:各种界面的设计,在主循环中实现

PWM输出:

  • 通过设置 Prescaler             来设置定时器频率 
  • 通过设置 Counter Period   来设置周期(计数值)
  • 通过设置 Pulse                   来设置占空比
  • 通过设置 CH Polarity         来设置极性
  • PWM波的频率设置计算公式:

预分频系数 = (APB1 Timer/PWM波的频率 )-1;

周期 = 定时器频率/PWM波的频率

预分频系数 = (APB1 Timer/定时器频率 )-1;

  • 根据题目确定配置,如果要配置%的占空比,周期就设置为100的倍数。然后根据题目和便于计算原则,设置预分频系数。
  • 在程序中修改预分频系数、周期、占空比的函数如下,读取函数就是把SET改为GET。
    __HAL_TIM_SET_COUNTER()    //设置计数值,即周期
    __HAL_TIM_SET_PRESCALER()  //设置预分频系数
    __HAL_TIM_SET_COMPARE(设备句柄地址,通道号,脉宽值);    //设置占空比

USART1:Asynchronous模式、频率设置为9600。

二、软件配置

参考附录的内容,建立名为“ ”的项目。

按照分析配置外设

时钟配置:

 LED

KEY

PWM输出

USART1

将PA9和PA10,用作USART1的引脚。

TIM

TIM6:

TIM7:

生成项目文件后,打开MDK;

导入LCD驱动程序文件,编译。

三、保存结果

打包Core文件中所有文件,还有Gxxxxxxxx.hex文件。

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

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

相关文章

远程过程调用(远程调用)

远程过程调用(远程调用) 1、什么是分布式计算 在计算机科学中,分布式计算(英语:Distributed computing),又译为分散式运算。这个研究领域,主要研究分布式系统(Distribu…

学习周报:文献阅读+Fluent案例+水力学理论学习

目录 摘要 Abstract 文献阅读:物理信息的神经网络与湍流传质的非封闭机制模型相结合 文献摘要 提出问题 提出方案 实验设置 所需方程介绍 雷诺时均方程(RANS) K-epsilon两方程模型 神经网络框架 DNN部分 损失函数定义 PINN部分…

Francek Chen 的128天创作纪念日

目录 Francek Chen 的128天创作纪念日机缘收获日常成就憧憬 Francek Chen 的128天创作纪念日 Francek Chen 的个人主页 机缘 不知不觉的加入CSDN已有两年时间了,最初我第一次接触CSDN技术社区是在2022年4月的时候,通过学长给我们推荐了几个IT社区平台&a…

【Python】还在用print进行调试,你Out了!!!

1. 引言 Python 中最常用的函数是什么?像在大多数编程语言中,print() 函数是最常用的。我相信大多数开发者都会像我一样,在开发过程中多次使用它将信息进行打印。 当然,没有其他方法可以完全取代print()函数。不过,当…

c++算法学习笔记 (20) 哈希表

1.模拟散列表 // 拉链法 #include <bits/stdc.h> using namespace std; const int N 100003; int h[N]; int e[N], ne[N], idx; // 存链void insert(int x) {int k (x % N N) % N; // 让负数的余数变成正数(若直接加N,则可能溢出)e[idx] x;ne[idx] h[k];h[k] idx;…

传动设计选型

一. 齿轮选型 1齿轮传动概述 齿轮传动首先自然是一对对的&#xff0c;故也叫齿轮副。原理其实大家基本都知道&#xff0c;很多玩具中都会有齿轮传动的身影&#xff0c;比如小时候玩的四驱车。就是两齿轮互相啮合互相推动&#xff0c;然后输出旋转动力或者改变传递动力的方向&…

基于SpringBoot Vue学生信息管理

一、&#x1f4dd;功能介绍 基于SpringBoot Vue学生信息管理 角色&#xff1a;管理员、学生、教师 管理员&#xff1a;管理员进入主页面&#xff0c;主要功能包括对系统首页、个人中心、学生管理、教师管理、公告通知管理、课程类型管理、课程信息管理、选课信息管理、课程成…

使用STM32实现 蓝牙插座

硬件介绍 蓝牙模块HC-01 蓝牙模块&#xff0c;又叫做蓝牙串口模块 串口透传技术&#xff1a;透传即透明传送&#xff0c;是指在数据的传输过程中&#xff0c;通过无线的方式这组数据不发生任何形式的改变&#xff0c;仿佛传输过程是透明的一样&#xff0c;同时保证传输的质量&…

农业地物反演采用卫星影像技术方法

一、引言 随着空间技术的快速发展&#xff0c;卫星影像已经成为一种重要的工具&#xff0c;用于提供全球尺度的数据收集和分析。在农业领域&#xff0c;卫星影像被广泛应用于植物反演&#xff0c;以获取关于作物生长和健康的实时信息。本文旨在全面概述卫星影像在农业植物反演中…

baseline SE SP YI是什么?

SE、SP和YI是评估分类模型性能时常用的几个统计指标&#xff0c;特别是在医学影像处理、疾病诊断等领域&#xff0c;这些指标帮助了解模型对于正负类样本的识别能力。 SE (Sensitivity)&#xff0c;也称为真正率&#xff08;True Positive Rate, TPR&#xff09;或召回率&#…

鸿蒙ArkUI实例:【自定义组件】

组件是 OpenHarmony 页面最小显示单元&#xff0c;一个页面可由多个组件组合而成&#xff0c;也可只由一个组件组合而成&#xff0c;这些组件可以是ArkUI开发框架自带系统组件&#xff0c;比如 Text 、 Button 等&#xff0c;也可以是自定义组件&#xff0c;本节笔者简单介绍一…

hive词频统计---文件始终上传不来

目录 准备工作&#xff1a; 文件内容&#xff1a; 创建数据库及表 将文件上传到&#xff1a;上传到/user/hive/warehouse/db1.db/t_word目录下 hive里面查询&#xff0c;始终报错&#xff1a;&#xff08;直接查询也是不行&#xff09; 解决方案&#xff1a; 准备工作&am…

OPC UA遇见chatGPT

最近opc 基金会将召开一个会议&#xff0c;主题是”OPC UA meets IT“。由此可见&#xff0c;工业自动化行业也开始研究和评估chatGPT带来的影响了。 本文谈谈本人对OPC UA 与chatGPT结合的初步实验和思考。 构建OPC UA 信息模型 chatGPT 的确非常强大了&#xff0c;使用自然…

Stable Diffusion文生图技术详解:从零基础到掌握CLIP模型、Unet训练和采样器迭代

文章目录 概要Stable Diffusion 底层结构与原理文本编码器&#xff08;Text Encoder&#xff09;图片生成器&#xff08;Image Generator&#xff09; 那扩散过程发生了什么&#xff1f;stable diffusion 总体架构主要模块分析Unet 网络采样器迭代CLIP 模型 小结 概要 Stable …

C++设计模式:装饰器模式(四)

1、定义与动机 装饰器模式定义&#xff1a;动态&#xff08;组合&#xff09;地给一个对象增加一些额外的职责。就增加功能而言&#xff0c;Decorator模式比生成子类&#xff08;继承&#xff09;更为灵活&#xff08;消除重复代码 & 减少子类个数&#xff09;。 在某些情…

如何理解CDN?说说实现原理?

文章目录 一、是什么二、原理分析负载均衡系统缓存代理 三、总结参考文献 一、是什么 CDN (全称 Content Delivery Network)&#xff0c;即内容分发网络 构建在现有网络基础之上的智能虚拟网络&#xff0c;依靠部署在各地的边缘服务器&#xff0c;通过中心平台的负载均衡、内…

成为一个ATE工程师是什么体验?

当你成为ATE工程师&#xff0c;是什么感受&#xff1f; 按照业内资深工程师的玩笑话来说&#xff1a;整的是比劳斯莱斯还贵的设备&#xff0c;更高端的机台顶得起上海几套房。 1、什么是ATE测试&#xff1f; 一颗芯片的生命周期始于市场需求&#xff0c;从产品的定义与设计&…

蓝桥杯-dfs搜索模板题(一)

蓝桥杯-dfs搜索模板题&#xff08;一&#xff09; P2089 烤鸡P1088 火星人P1149 火柴棒等式P2036 PERKETP1135 奇怪的电梯结语 P2089 烤鸡 对于每个位置枚举数字 #include<bits/stdc.h>using namespace std;const int N1010;int n;int arr[N];//临时方案 int res0;//方案…

163 Linux C++ 通讯架构实战17,本地套接字整理对比,IPC:pipe,fifo,mmap,信号,本地套

IPC&#xff1a; Linux环境下&#xff0c;进程地址空间相互独立&#xff0c;每个进程各自有不同的用户地址空间。任何一个进程的全局变量在另一个进程中都看不到&#xff0c;所以进程和进程之间不能相互访问&#xff0c;要交换数据必须通过内核&#xff0c;在内核中开辟一块缓冲…

并发编程三大特性之可见性

一、什么是可见性&#xff1f; 可见性问题是基于CPU位置出现的&#xff0c;cpu处里速度非常快&#xff0c;相对CPU来说去主内存 获取数据这个事情太慢了&#xff0c;CPU就提供了 L1&#xff0c;L2&#xff0c;L3的三季缓存&#xff0c;每次去主内存拿完 数据后&#xff0c;数据…