14届蓝桥杯嵌入式国赛

目录

前言:

1.使用CUbeMX进行基础初始化配置

(1)选则芯片与基本初始化

(2)LED配置

(3)按键配置

(4)定时器和PWM以及频率

(5)ADC电压检测

2.各外设使用代码。

(1)LED灯

 (2)按键代码(长短按都包含)

(3)定时器

1.定时器中断溢出函数

2.用于定时器中断溢出函数的定时器启用函数(没错,在CubeMX设定了之后还要在函数里初始化)

 3.输入捕获回调函数

 3.用于输入捕获回调函数的定时器启用函数

4. 负责PWM波的定时器的开启

 5.负责PWM波的定时器的赋值使用(分HAL库操作及汇编操作)

 (4)ADC转移(可测电压)直接使用型代码。

(5)LCD显示屏

 3.题目逻辑代码实现

 4.总实现照片

总结

实现代码


前言:

此版是本人使用CUbeMx的创建库函数的练手之作,仅仅涉及到了adc,pwm,频率,LED,LCD,回访记录,按键等操作。

题目:14届蓝桥杯嵌入式国赛

硬件框图:

总体框架较为简单,这个题目考到了DS18B20、单路PWM捕获、ADC采集、PWM生成等模块。细节上东西比较多,处理记录波形和产生波形的时序、温度的温定读取、双按键长按、时间准确控制等,很多都可以在哔站的网站看速成——B站推荐速成总结。
14届国赛省赛都在PWM生成上作文章,控制好变化时间还是可以很丝滑的,这题目就是记录电压与PWM波,频率的时候有点怪,其他都非常简单!

由于一些设备原因,本人没有做DS18B20的温度读取(写了一个壳子),其他均符合题目要求。

1.使用CUbeMX进行基础初始化配置

(1)选则芯片与基本初始化

这个操作不多赘述,想了解的可以看看这个博主的博客。嵌入式开发--CubeMX使用入门教程-CSDN博客,值得注意的是我们所要用到芯片主频是80,这个帧率配置过程B站的视频教程里面有。

(2)LED配置

在STM32G431RBTx的芯片图上,LED1~LED8对应的是PC8~15

所以在CUbeMX中,我们要对PC8~15进行配置,

(3)按键配置

同样的,在STM32G431RBTx的芯片图上,B1~B4对应的是PB0~2和PA0。

所以要将所用的引脚配置成输入(GPIO_Input)模式,并设置成上拉输入。

(4)定时器和PWM以及频率

题目要求用PA1进行频率采集,同PA7进行频率输出,我看了一下使用PA1采集PWM就要使用TIM2这个定时器的CH2通道,而PA7用定时器17就可以了。所以定时器的开启也是要注意看题目要求,不要占用定时器。

这个是我配置定时器的设定,通道一采集上升沿,通道二采集下降沿

我们配置的时候修改PSC与Counter,他们遵循公式

工作频率=外部总线频率/(PSC+1)

定时频率=定时器工作频率/(counter+1)=外部总线频率/(PSC+1)*(counter+1)

 由于我设置的外部总线频率为80MHZ(80*10^6HZ),所以可以计算得我设置的TIM2频率为100HZ,0.01秒触发一次中断,注意要设置中段哦!一定要勾选Enabled!

接着是PA7的PWM输出定时器TIM17,这个定时器像我这么设置就可以了,注意输出PWM波的话就不要设置中断,会出问题的!

接下来是其他TIM定时器,这是我代码中所用到的所有定时器。

(5)ADC电压检测

ADC的话直接在Analog里面去选择ADC1,然后再IN11里像我一样配置就好了,其他直接默认就行了。

2.各外设使用代码。

(1)LED灯

#include "led.h"

void LED_Disp(uchar dsLED)
{
    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
      HAL_GPIO_WritePin(GPIOC, dsLED<<8, GPIO_PIN_RESET);//
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}

这个是本次使用的点亮LED灯的代码,但因为不知道什么原因,只能亮灭0~2的LED灯,所以我是把它当LED初始化全灭代码。

 (2)按键代码(长短按都包含)

struct keys key[4]={0,0,0};

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance ==TIM4){
            key[0].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
            key[1].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
            key[2].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
            key[3].key_sta=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
            
            
          for(int i=0;i<4;i++){
               switch(key[i].judge_sta){
                     case 0:
                     {
                         if(key[i].key_sta==0) key[i].judge_sta=1;
                           key[i].key_time= 0;
                     }
                     break;
                     case 1:
                     {
                         if(key[i].key_sta==0)
                             {
                                key[i].judge_sta=2;
                             }else {
                                 key[i].judge_sta=0;
                    //           key[i].key_time =0;
                             }
                     }
                     break;
                     case 2:
                     {
                        if(key[i].key_sta==1)
                            {
                                key[i].judge_sta=0;
                                if(key[i].key_time<70){
                                       key[i].single_flag=1;
                                    }                                
                            }else 
                                {
                                    key[i].key_time++;
                                  if(key[i].key_time>70){
                                       key[i].long_flag=1;
                                    }
                                  
                                }
                     }
                     break;
                 }
            }
        }

}

struct keys
{
  uchar judge_sta;
    bool key_sta;
    bool single_flag;
    bool long_flag;
    uint key_time; 
};

按键用swicth进行了消抖操作,并把按键函数设里在了定时器溢出函数里面,只要TIM定时器溢出中断触发,就会检测查看有没有按键被按下,由于函数溢出时间非常快,处理中断时间非常短,可以看成按键一直在检测,且由于是中断,所以不耽误主进程。

(3)定时器

定时器有基本,通用,高级定时器,我们主要了解如何去用这TIM,CUbeMX去配置初始化就不用多说,前文有描述,这里主要是如何在代码中使用TIM。

1.定时器中断溢出函数

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

      if(htim->Instance ==TIM4){//通过这个代码,可以判断是否是想要的TIM定时器溢出中断                   

      }

}

2.用于定时器中断溢出函数的定时器启用函数(没错,在CubeMX设定了之后还要在函数里初始化)

HAL_TIM_Base_Start_IT(&htim4);

 3.输入捕获回调函数

HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)

{

   if(htim->Instance ==TIM2){

     if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_2)

//这里是查看所用的通道有没有信号,毕竟捕获是数据输入,如果没有数据输入就不触发。
         {

         }

   }

}

 3.用于输入捕获回调函数的定时器启用函数

HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_2);

4. 负责PWM波的定时器的开启

HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);//负责PWM波的定时器开启代码

__HAL_TIM_SetCompare(&htim17,TIM_CHANNEL_1,pa7_duty);

 5.负责PWM波的定时器的赋值使用(分HAL库操作及汇编操作)

HAL库版

set_pwm_param(TIM_HandleTypeDef htim, uint32_t Channel, uint32_t freq, uint16_t duty);

该函数可直接调整占空比和频率

汇编语言版

 TIM17->ARR=1e6/freq_r[cnt_index]*FP-1;//直接调TIM17的ARR
 TIM17->CCR1=duty_r[cnt_index]*(1e6/freq_r[cnt_index]*FP)/100.0f;//直接调TIM17的RCC

 (4)ADC转移(可测电压)直接使用型代码。

#include "dadc.h"

double getADC(ADC_HandleTypeDef *pin)
{
  uint adc;
    HAL_ADC_Start(pin);
  adc =HAL_ADC_GetValue(pin);
    return adc*3.3/4096;
}

这里的4096是2^12的值,通过这一串带码,实现adc的读取

使用方式:getADC(&hadc1);//这里的&hadc1通过CubeMX开启

(5)LCD显示屏

LCD显示屏蓝桥杯官方已经公布了.c与.h文件,也可以去我的bsp文件里面找,可以直接拿来用。

我这里主要是讲LCD的代码初始化,以及如何使用。

LCD_Init();//LCD初始化
    LCD_Clear(Black);//黑色清屏
    LCD_SetBackColor(Black);//黑色背景颜色
    LCD_SetTextColor(White);//白色字体

 char text[30];//需要数组转存
 sprintf(text,"     change:FH      ");
 LCD_DisplayStringLine(Line8, (uint8_t *)text);操作显示在多少行。

 3.题目逻辑代码实现

关于逻辑代码这一块,非常感谢GHHHHHH!-CSDN博客大佬,我看了他的处理可谓是茅塞顿开,用一个数加加去进行定时处理,非常给力,在处理下图板块的时候,通过一个int数加加,进行判断,存储,再输出的时候,继续进行数的加加,非常巧妙。

下面是我看了大佬的博客之后的函数逻辑处理

  if(flag_Record==1){//记录标志位
           if(++cnt_Record>10*TT)
                 {
                     cnt_Record=0;
                     flag_Record=0;//控制LED灯的信号
                       cnt_index=0;
                       flag_jilu=1;//释放频率与占空比的通过信号
                     return ;
                 }
                 if(cnt_Record%10==0)//0.1s
            {
                freq_r[cnt_index]=frq1;//记录频率
                duty_r[cnt_index]=duty1;//记录占空比
                if(getADC(&hadc1)>=VP)//记录频率电压
                    duty_Adc[cnt_index]=90.0f/(3.3f-VP)*(getADC(&hadc1)-3.3f)+100.0f;
                 else
                      duty_Adc[cnt_index]=10;
                 cnt_index++;
                    }
                if(++led_cnt==10){
                    led_cnt=0;
                  LED_Disp(0x01);
                }else LED_Disp(0x00);
                }

 4.总实现照片

界面一和界面二

界面三和界面四

 

总结

作为一个从标准库转HAL库的程序猿,确实是觉得HAL库比标准库方便很多,主要是有CubeMx这个工具的存在,同时,现在一些芯片只能识别HAL库函数,而不能识别标准库,这更体现了HAl库的优势。但这并不意味着标准库就不行,且不说网上资料还是标准库的多,而且标准库可以更好的帮我们了解单片机的原理,打好基础。

希望我的这篇文章能帮助到大家!

实现代码

通过百度网盘分享的文件:14jie4.zip
链接:https://pan.baidu.com/s/1tzceKMszDdTQTxK8tLkfUA 
提取码:fwwz

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

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

相关文章

计算机网络 --- 初识协议

序言 上一篇文章中 &#xff08;&#x1f449;点击查看&#xff09;&#xff0c;我们简单的了解了怎么寻找目标计算机&#xff0c;需要通过交换机&#xff0c;路由器等设备跨越多个网络来不断的转发我们需要传输的数据&#xff0c;直至到达目标计算机。  那我们设备之间数据是…

JMeter 中使用 Gson 操作请求中的Boby参数

背景 使用org.json.JSONObject 转换&#xff0c;与原Body参数顺序发生变化&#xff0c;原因&#xff1a;JSONObject内部是用Hashmap来存储的&#xff0c;本质上是一个无序的键值对集合&#xff0c;不应依赖字段的添加顺序。 为解决org.json.JSONObject 输出顺序问题&#xff…

鸿蒙读书笔记2:《鸿蒙操作系统设计原理与架构》

2. OS基础平台部件化 &#xff08;1&#xff09;内核层 内核层包括内核部件和HDF驱动框架部件。当前已提供LiteOS-M、 LiteOS-A、Linux和UniProton这4种内核部件&#xff0c;未来还可增加更多类 型的内核部件。LiteOS、Linux内核部件可以按需部署在不同设备之 上&#xff0c;内…

echarts X轴文本太长 formatter自定义文本的显示方式

如果ECharts中X轴的文本太长&#xff0c;可以通过设置axisLabel的rotate属性来旋转标签&#xff0c;或者使用formatter函数来自定义文本的显示方式。另外&#xff0c;可以开启axisLabel的interval属性来控制显示的标签的间隔。 option {tooltip: {},xAxis: {type: category,d…

p14 使用阿里云服务器的docker部署NGINX

拉取NGINX的镜像 这里因为之前已经配置过从阿里云的镜像仓库里面拿镜像所以这里直接就执行docker pull nginx拉取NGINX镜像就OK了 运行NGINX镜像 这里执行docker run -d --name nginx01 -p 3344:80 nginx这里3344是服务器访问的端口80是容器内部的端口&#xff0c;可以看到…

【C++ Primer Plus习题】16.5

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: #include <iostream> #include <list> using namespace…

硬件工程师笔试面试——集成电路

目录 17、集成电路 17.1 基础 集成电路实物图 17.1.1 概念 17.1.2 集成电路的发展历程 17.1.3 集成电路的分类 17.1.4 集成电路的制造工艺 17.1.5 集成电路的应用 17.2 相关问题 17.2.1 集成电路的制造工艺中,光刻技术是如何实现的? 17.2.2 在集成电路设计中,如何…

微信电脑版聊天图片DAT格式文件转为普通JPG图片

1-7 本文章主要教你如何恢复微信聊天中的聊天图片&#xff0c;主要应用场景是&#xff0c;当你的微信被封号了&#xff0c;或者无法登录了&#xff0c;会导致微信聊天中的聊天图片没办法再打开&#xff0c;如果是重要的图片&#xff0c;那就有损失了&#xff0c;所以有了本文的…

【无人机设计与控制】四旋翼无人机轨迹跟踪及避障Matlab代码

摘要 本文主要研究了四旋翼无人机在复杂环境中的轨迹跟踪与避障控制策略。通过Matlab/Simulink对四旋翼无人机进行了建模与仿真。系统集成了避障算法&#xff0c;使得无人机在执行任务时能够有效避开障碍物&#xff0c;保证飞行的安全性与稳定性。 理论 无人机飞行控制通常涉…

leetcode-枚举算法

1.两数之和 题目一&#xff1a;两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案&#xff0c;并且你不能使用两次相同的元素…

Java项目实战II基于Spring Boot的宠物商城网站设计与实现

目录 一、前言 二、技术介绍 三、系统实现 四、论文参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 随着互联网…

6--SpringBootWeb案例(详解)

目录 环境搭建 部门管理 查询部门 接口文档 代码 删除部门 接口文档 代码 新增部门 接口文档 代码 已有前端&#xff0c;根据接口文档完成后端功能的开发 成品如下&#xff1a; 环境搭建 1. 准备数据库表 (dept 、 emp) -- 部门管理 create table dept( id int un…

快速入门Vue

Vue是什么 Vue.js&#xff08;通常简称为Vue&#xff09;是一个开源的JavaScript框架&#xff0c;用于构建用户界面和单页应用程序&#xff08;SPA&#xff09;。它由尤雨溪&#xff08;Evan You&#xff09;在2014年开发并发布。Vue的核心库只关注视图层&#xff0c;易于上手…

python实现多个pdf文件合并

打印发票时&#xff0c;需要将pdf合并成一个&#xff0c;单页两张打印。网上一些pdf合并逐渐收费&#xff0c;这玩意儿都能收费&#xff1f;自己写一个脚本使用。 实现代码&#xff1a; 输入pdf文件夹路径data_dir&#xff0c;统计目录下的“合并后的PDF”文件夹下&#xff0c;…

从边缘设备到云端平台,合宙DTURTU打造无缝物联网解决方案

如今&#xff0c;物联网&#xff08;IoT&#xff09;技术飞速发展&#xff0c;万物互联的时代已然到来&#xff0c;那么&#xff0c;高效、稳定地连接边缘设备与云端平台&#xff0c;实现数据的实时采集、传输与处理&#xff0c;就成为了推动物联网应用落地的关键。 DTU&#…

# wps必须要登录激活才能使用吗?

WPS 必须登录激活才能使用吗&#xff1f; 如下图&#xff0c;当我们使用WPS时&#xff0c;不登录会显示工具栏灰色不可用状态。 答&#xff1a;WPS 不一定要登录激活才能使用。 一、免费使用的情况 1、基础功能 在不登录的情况下&#xff0c;用户可以使用 WPS 的一些基础功…

【delphi】正则判断windows完整合法文件名,包括路径

在 Delphi 中&#xff0c;可以使用正则表达式来检查 Windows 文件名称或路径是否合法。合法的文件名和路径要求符合以下几点&#xff1a; 禁止的字符&#xff1a;文件名和路径不能包含以下字符&#xff1a;<, >, :, ", /, \, |, ?, *。文件名不能以空格或点结束。…

Java 入门指南:JVM(Java虚拟机)垃圾回收机制 —— 垃圾收集器

文章目录 垃圾回收机制Stop-the-World垃圾收集器垃圾收集器分类Serial 收集器Serial Old 收集器ParNew 收集器Parallel Scavenge 收集器Parallel Old 收集器CMS 收集器CMS 收集器缺点 G1 收集器G1 收集器特点G1 收集器的分代理念G1 收集器运作过程 垃圾回收机制 垃圾回收&…

【架构设计】多级缓存:应用案例与问题解决策略

【架构设计】多级缓存&#xff1a;应用案例与问题解决策略 多级缓存系统的工作原理及其在提升应用性能方面的关键作用。通过对比本地缓存与分布式缓存的特点 | 原创作者/编辑&#xff1a;凯哥Java | 分类&#xff1a;架构设计系列教程 多级缓存…