蓝桥杯嵌入式第十一届省赛真题
首先要知道P37对应的CubeMx上面的引脚是PB15,给PB15设置成ADC采集。使用到的PA6和PA7的端口要进行定时器配置ADC采集只需要选择好adc1、adc2 再选择好它的通道就可以了,不需要配置其它的100Hz和200Hz只需要配置好PSC和ARR,不需要配置中断和占空比题目还对按键有要求,所以我们需要CubeMX里面配置好按键,再GPIO的配置里面把按键配置为上拉输入模式。
(一)题目
首先要知道P37对应的CubeMx上面的引脚是PB15,给PB15设置成ADC采集。使用到的PA6和PA7的端口要进行定时器配置
100Hz=80 000 000/800 *1000 200Hz=80 000 000/400 *1000
ADC采集只需要选择好adc1、adc2 再选择好它的通道就可以了,不需要配置其它的
100Hz和200Hz只需要配置好PSC和ARR,不需要配置中断和占空比
题目还对按键有要求,所以我们需要CubeMX里面配置好按键,再GPIO的配置里面把按键配置为上拉输入模式
题目中提到了LCD模块,所以不要忘记添加LCD资源包到文件中去,已经在keil5写代码的时候不要忘记掉lcd的头文件包含。详细介绍看后文
题目中还有对LED的要求,所以我们要配置好LED的CubeMx
因为这套题比较简单,所以我们只需要配置定时器,ADC,按键,LED就可以了
接下来是最基础的配置
还有一个按键扫描的函数,需要放在定时器里面去,所以要开一个TIM4,别忘了开中断
关键参数 24 和 80
(2)底层代码
注意:新建文件里面没有信息提示可能是新建文件还没有添加进BSP里面,还有一种可能就是没有添加“F103G431”的头文件,还有各个.h之间文件的包含,以及在新建文件里面也要写#include“tim.h”之类使用到的模块的头文件,不然就算.h的文件包含正确了,也是使用不到tim等对应的文件的。所以添加文件、新建文件的时候不要着急,一步一步来,别漏了
先把新建的sys.h、fun.c、fun.h都保存到BSP里面,然后再在BSP里面添加文件,然后再写sys.h里面的文件。这个里面就要写G431的头文件,还有tim,adc的头文件,还有打印的头文件“string”“stdio.h”还有布尔类型的头文件”stdbool.h“。最后就是lcd,fun的.h文件
只需要在main函数里面添加一下sys.h的头文件就可以了
#ifndef __SYS_H
#define __SYS_H
#include "stm32g4xx.h" // Device header
#include "main.h"
#include "adc.h"
#include "tim.h"
#include "stdio.h"
#include "string.h"
#include "stdbool.h"
#include "fun.h"
#include "lcd.h"
#endif
按键的底层
这个是放在fun.h里面的,而且里面还要记得添加一下sys.h的头文件。fun.h里面还要写上fun.c里面使用到的函数的函数名
struct keys
{
bool short_flag;
bool long_flag;
bool key_sta;
uint8_t key_time;
unsigned char jungle_sta;
};
struct keys key[4]={0,0,0};//别忘了写结构体
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//5933
{
if(htim->Instance==TIM4)//这个很重要!!!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].jungle_sta)
{
case 0:
{
if(key[i].key_sta==0)
{
key[i].jungle_sta=1;
key[i].key_time=0;
}
}
break;
case 1:
{
if(key[i].key_sta==0)
{
key[i].jungle_sta=2;
}
else
{
key[i].jungle_sta=0;
}
}
break;
case 2:
{
if(key[i].key_sta==1)
{
key[i].jungle_sta=0;
//最开始下进去代码出现问题就是这里没有把标志位清零
if(key[i].key_time<70)
{
key[i].short_flag=1;
}
}
else
{
key[i].key_time++;
if(key[i].key_time>70)
{
key[i].long_flag=1;
}
}
}
break;
}
}
}
}
ADC的底层
//这里要是double,不然没有返回的adc的值
double getADC(ADC_HandleTypeDef*pin)
{
unsigned int adc;
HAL_ADC_Start(pin);
adc=HAL_ADC_GetValue(pin);
HAL_ADC_Stop(pin);
return adc;
}
//有些字母的大小写没记清楚,还有些字母忘写了
(3)逻辑板块!!!
首先很重要的就是按键的逻辑,因为它的逻辑决定着其他模块的逻辑LCD、LED、PWM
这里需要对mode,view,pa6_duty,pa7_duty 进行定义
unsigned int view_chart;
unsigned int menu_mode;
unsigned int pa6_duty=10;
unsigned int pa7_duty=10;
void key_pro()
{
if(key[0].short_flag==1)
{
view_chart=!view_chart;
LCD_Clear(Black);//切换屏幕的时候一定要记得清屏
key[0].short_flag=0;
}
if(view_chart==1)
{
if(key[1].short_flag==1)
{
pa6_duty=pa6_duty+10;
//这里最开始无法实现按键加是因为pa6_duty=+10这种写法是错的
if(pa6_duty>90)
{
pa6_duty=10;
}
key[1].short_flag=0;//一定要记得标志位清零
}
if(key[2].short_flag==1)
{
pa7_duty=pa7_duty+10;//A=A+10;
if(pa7_duty>90)//大于九十就要归回10,但要到90这个数字
{
pa7_duty=10;
}
key[2].short_flag=0;
}
}
if(key[3].short_flag==1)
{
menu_mode=!menu_mode;
LCD_Clear(Black);//切换屏幕的时候一定要记得清屏
key[3].short_flag=0;
}
}
然后进行LCD的逻辑表述
float volt;//这个是全局变量
void lcd_pro()
{
volt=getADC(&hadc2)*5/4096;
if(view_chart==0)
{
sprintf (temp," Data ");
LCD_DisplayStringLine(Line1,(uint8_t*)temp);
sprintf(temp," V=%.2f ",volt);
LCD_DisplayStringLine(Line3,(uint8_t*)temp);
if(menu_mode==0)
{
sprintf(temp," Mode:ATUO ");
LCD_DisplayStringLine(Line5,(uint8_t*)temp);
}
else
{
sprintf(temp," Mode:MANU ");
LCD_DisplayStringLine(Line5,(uint8_t*)temp);
}
}
else
{
sprintf (temp," Para ");
LCD_DisplayStringLine(Line1,(uint8_t*)temp);
sprintf(temp," PA6=%d%% ",pa6_duty);
LCD_DisplayStringLine(Line3,(uint8_t*)temp);
sprintf(temp," PA7=%d%% ",pa7_duty);
LCD_DisplayStringLine(Line5,(uint8_t*)temp);
}
}
更多推荐
所有评论(0)