自学内容网 自学内容网

第十二届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)(第二套)

一.题目分析

(1).题目

 (2).题目分析

1.按键功能分析

a.B1界面切换

b.B2每次按下R加2

c.B3每次按下R减2

d.LED控制按键

2.信号输出功能分析

a.PA7信号输出-----信号的输出就需要使用到输入捕获和输出比较功能

b.输出信号的频率为输入信号频率的R分频

c.输出信号占空比和检测到的R37成正比

        (当前电压值/3.3V)*周期 = 占空比

 (3).逻辑导图

二.CubeMX配置

由于蓝桥杯使用的板子都是STM32G431RBT6,配置都是相同的,模板已经在第六届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)-CSDN博客配置完成,大家可以前往学习

三.相关代码实现

(1)MAIN

1.全局变量声明

#include "main.h"
#include "RCC\bsp_rcc.h"
#include "KEY_LED\bsp_key_led.h"
#include "LCD\bsp_lcd.h"
#include "ADC\bsp_adc.h"
#include "TIM\bsp_tim.h"

//***全局变量声明区
//*减速变量
__IO uint32_t uwTick_Key_Set_Point = 0;//控制Key_Proc的执行速度
__IO uint32_t uwTick_Led_Set_Point = 0;//控制Led_Proc的执行速度
__IO uint32_t uwTick_Lcd_Set_Point = 0;//控制Lcd_Proc的执行速度

//*按键扫描专用变量
uint8_t ucKey_Val, unKey_Down, ucKey_Up, ucKey_Old;

//*LED专用变量
uint8_t ucLed = 0x01;

//*LCD显示专用变量
uint8_t Lcd_Disp_String[21];//最多显示20个字符

//*pwm相关变量
uint16_t PWM_T_Count;
//*主逻辑使用变量
uint8_t Disp_Screen_Num;//0-数据,1-参数
uint8_t R_Freq = 4;//分频值,初试为4
uint16_t ADC_Voltage_X100;
uint16_t Frq;
uint8_t LED_Func = 1;//1-启用,0-禁用
uint32_t AUTORELOAD_Num;
uint32_t COMPARE_Num;


//***子函数声明区
void Key_Proc(void);
void Led_Proc(void);
void Lcd_Proc(void);

2.系统主函数

int main(void)
{

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

/*bsp资源的初始化*/
KEY_LED_Init();

LCD_Init();
LCD_Clear(Black);
  LCD_SetBackColor(Black);
  LCD_SetTextColor(White);
  ADC2_Init();
PWM_INPUT_TIM2_Init();
PWM_OUTPUT_TIM17_Init();

//*输入捕获PWM启动
HAL_TIM_Base_Start(&htim2);  /* 启动定时器 */
  HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_2);

//PA7黄色
__HAL_TIM_SET_COMPARE(&htim17, TIM_CHANNEL_1, 500);//没有波形输出
__HAL_TIM_SET_AUTORELOAD(&htim17, 4999);//200HZ
  HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);//PA7

  while (1)
  {
Key_Proc();
Led_Proc();
Lcd_Proc();
  }

}

3.按键扫描子函数

a. 逻辑框图

b. 程序源码

//***按键扫描子函数
void Key_Proc(void)
{
if((uwTick -  uwTick_Key_Set_Point)<50)return;//减速函数
uwTick_Key_Set_Point = uwTick;

ucKey_Val = Key_Scan();
unKey_Down = ucKey_Val & (ucKey_Old ^ ucKey_Val); 
ucKey_Up = ~ucKey_Val & (ucKey_Old ^ ucKey_Val);
ucKey_Old = ucKey_Val;

if(unKey_Down == 1)//完成界面的切换
{
Disp_Screen_Num ^= 0x01;
LCD_Clear(Black);
if(Disp_Screen_Num == 0x00)//数据界面LD1点亮
{
ucLed &= (~0x03);
ucLed |= 0x01;
}
else if(Disp_Screen_Num == 0x01)//参数界面LD2点亮
{
ucLed &= (~0x03);
ucLed |= 0x02;
}
}
if(Disp_Screen_Num == 0x01)//在参数设置界面的时候,才可以加减
{
    if(unKey_Down == 2)//+2功能
{
R_Freq += 2;
if(R_Freq > 10)
R_Freq = 10;
}

    if(unKey_Down == 3)//-2功能
{
R_Freq -= 2;
if(R_Freq < 2)
R_Freq = 2;
}
}

    if(unKey_Down == 4)//LED启用和停用功能
{
LED_Func ^= 0x01;
}

}

4.LED扫描子函数

a. 程序源码

void Led_Proc(void)
{
if((uwTick -  uwTick_Led_Set_Point)<200)return;//减速函数
uwTick_Led_Set_Point = uwTick;

if(LED_Func == 0x01)
LED_Disp(ucLed);
else if(LED_Func == 0x00)
LED_Disp(0x00);
}

5.LCD扫描子函数

a. 逻辑框图

b. 程序源码

void Lcd_Proc(void)
{
if((uwTick -  uwTick_Lcd_Set_Point)<100)return;//减速函数
uwTick_Lcd_Set_Point = uwTick;
ADC_Voltage_X100 = ((((float)getADC2())/4096)*330);
Frq = (1000000/PWM_T_Count);

//控制LED灯的变化
if((ADC_Voltage_X100<100)||(ADC_Voltage_X100>=300))
{
ucLed |= 0x04;
}
else 
ucLed &= (~0x04);

if((Frq<1000)||(Frq>=5000))
{
ucLed |= 0x08;
}
else 
ucLed &= (~0x08);


//控制输出PWM的变化
//AUTORELOAD_Num = 6289;
AUTORELOAD_Num = (1000000.0/(Frq/R_Freq));
COMPARE_Num = (((330-ADC_Voltage_X100)/330.0)*AUTORELOAD_Num);//求助各位大佬?究竟为什么?如果您告诉我,我以您的名义,补充录制一段,单独解释这个地方。


//完成频率的设置
__HAL_TIM_SET_AUTORELOAD(&htim17, AUTORELOAD_Num);

    //完成占空比的设置
__HAL_TIM_SET_COMPARE(&htim17, TIM_CHANNEL_1, COMPARE_Num);

if(Disp_Screen_Num == 0)//显示数据
{
sprintf((char *)Lcd_Disp_String, "       Data      ");
LCD_DisplayStringLine(Line1, Lcd_Disp_String);

sprintf((char *)Lcd_Disp_String, "   FRQ:%dHz        ",(unsigned int)Frq);
LCD_DisplayStringLine(Line3, Lcd_Disp_String);

sprintf((char *)Lcd_Disp_String, "   R37:%4.2fV      ",(ADC_Voltage_X100*0.01));
LCD_DisplayStringLine(Line5, Lcd_Disp_String);
}
else if(Disp_Screen_Num == 1)//显示参数
{
sprintf((char *)Lcd_Disp_String, "       Para      ");
LCD_DisplayStringLine(Line1, Lcd_Disp_String);

sprintf((char *)Lcd_Disp_String, "      R:%2d",(unsigned int)R_Freq);
LCD_DisplayStringLine(Line3, Lcd_Disp_String);
}
}

5.输入捕获PWM中断回调

a. 程序源码

//输入捕获PWM中断回调
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
  if(htim->Instance==TIM2)
  {
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
PWM_T_Count =  HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2)+1;
}
}
}

(2)BSP

第六届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)-CSDN博客里面有详细的讲解,大家可前往此链接学习


原文地址:https://blog.csdn.net/weixin_51089092/article/details/142703840

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!