文章目录
前言
相关说明:
开发板:CT117E-M4(STM32G431RB 蓝桥杯嵌入式比赛板)
开发环境: CubeMX+Keil5
涉及题目:第十三届蓝桥杯嵌入式模拟题1
题目难点:相对较易,主要需掌握调节PWM输出占空比及频率、ADC获取、以及定时器配置。
CubeMX配置、主要函数代码及说明:
一、CubeMX配置(第十三届模拟题完整版)
1.使能外部高速时钟:
2.配置时钟树:
3.GPIO:
4.ADC(检测R37电压值):
5.TIM3(PWM):
6.TIM6(0.1s中断):
7.NVIC:
二、代码相关定义、声明
1.函数声明
main.c
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);//定时器回调函数
void D_change(void); //D改变规则
void LCD_InitShow(void);//LCD初始化显示
void LCD_Refresh(void); //LCD显示更新
void LED_change(void); //LED2状态改变
gpio.h
void KEY_Scan(void);//按键扫描
void LED_AllClose(uint8_t *LED_Close);//LED更新显示
adc.h
double ADC_GetValue(void);//获取R37电压值
time.h
void PWN_OutPut(uint16_t Period,uint16_t Pulse);//配置PWM输出参数
2.宏定义
#define LED_GPIO_PORT GPIOC
#define LED1_GPIO_PIN GPIO_PIN_8
#define LED2_GPIO_PIN GPIO_PIN_9
#define LED3_GPIO_PIN GPIO_PIN_10
#define LED4_GPIO_PIN GPIO_PIN_11
#define LED5_GPIO_PIN GPIO_PIN_12
#define LED6_GPIO_PIN GPIO_PIN_13
#define LED7_GPIO_PIN GPIO_PIN_14
#define LED8_GPIO_PIN GPIO_PIN_15
#define ON GPIO_PIN_RESET
#define OFF GPIO_PIN_SET
#define LED1(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED1_GPIO_PIN,a)
#define LED2(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED2_GPIO_PIN,a)
#define LED3(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED3_GPIO_PIN,a)
#define LED4(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED4_GPIO_PIN,a)
#define LED5(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED5_GPIO_PIN,a)
#define LED6(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED6_GPIO_PIN,a)
#define LED7(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED7_GPIO_PIN,a)
#define LED8(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED8_GPIO_PIN,a)
#define KEY1_GPIO_PORT GPIOB
#define KEY1_GPIO_PIN GPIO_PIN_0
#define KEY2_GPIO_PORT GPIOB
#define KEY2_GPIO_PIN GPIO_PIN_1
#define KEY3_GPIO_PORT GPIOB
#define KEY3_GPIO_PIN GPIO_PIN_2
#define KEY4_GPIO_PORT GPIOA
#define KEY4_GPIO_PIN GPIO_PIN_0
3.变量定义
main.c
double v_value; //R37电压值
uint8_t D; //占空比
uint16_t F=1000; //PWM输出频率
uint16_t F_step=1000; //F每次改变值
uint16_t F_max=10000; //F上限
uint16_t F_min=1000; //F下限
char str[30]; //用于组合字符串
uint8_t LCD_RefreshFlag=0; //LCD更新标志位
uint8_t LED_Close[3]={
1,1,0}; //LED关闭字符串(保存LED状态,值为1,则下标对应LED关闭)
uint8_t LED2_flag=0; //LED2状态标志位 R37电压>1V时置1
uint32_t TIM_Clock=1000000; //定时器6工作频率
tim.c
TIM_OC_InitTypeDef sConfigOC = {
0};//配置该结构体为全局变量,MX配置后删除生成函数中的这句代码
三、主要函数
1.按键扫描
按键按下后的操作封装为函数,可降低函数耦合。
void KEY_Scan()
{
static uint8_t clock=0;
if(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET && !clock)//++
{
HAL_Delay(10);
if(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET)
{
while(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET);
Dat_change(add);
LCD_Refresh();
}
}
else if(HAL_GPIO_ReadPin(KEY2_GPIO_PORT,KEY2_GPIO_PIN)==GPIO_PIN_RESET && !clock)//--
{
HAL_Delay(10);
if(HAL_GPIO_ReadPin(KEY2_GPIO_PORT,KEY2_GPIO_PIN)==GPIO_PIN_RESET)
{
while(HAL_GPIO_ReadPin(KEY2_GPIO_PORT,KEY2_GPIO_PIN)==GPIO_PIN_RESET);
Dat_change(sub);
LCD_Refresh();
}
}
else if(HAL_GPIO_ReadPin(KEY3_GPIO_PORT,KEY3_GPIO_PIN)==GPIO_PIN_RESET)
{
HAL_Delay(10);
if(HAL_GPIO_ReadPin(KEY3_GPIO_PORT,KEY3_GPIO_PIN)==GPIO_PIN_RESET)
{
while(HAL_GPIO_ReadPin(KEY3_GPIO_PORT,KEY3_GPIO_PIN)==GPIO_PIN_RESET);
clock=!clock;
LED_Close[1]=!LED_Close[1];
LED_AllClose(LED_Close);
}
}
}
2.LED更新显示
将LED灯状态为灭还是亮,保存在LED_Close数组里,LCD就影响不了了,如果数组中值为1,则下标对应LED关闭,否则为开启,理解了逻辑很好写。具体可参考STM32LED–基于HAL库(第七届蓝桥杯嵌入式省赛)。
void LED_AllClose(uint8_t *LED_Close)//LED更新显示
{
uint8_t i;
LED1(ON);
LED2(ON);
for(i=1;i<3;i++)
{
if(LED_Close[i])
{
switch(i)
{
case 1:
LED1(OFF);
break;
case 2:
LED2(OFF);
break;
}
}
}
LED3(OFF);
LED4(OFF);
LED5(OFF);
LED6(OFF);
LED7(OFF);
LED8(OFF);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
3.PWM输出参数配置
PWM频率=定时器工作频率/重装载值
占空比=Pulse/重装载值*100%
void PWN_OutPut(uint16_t Period,uint16_t Pulse)//第一个参数为频率,第二个参数为占空比
{
htim3.Init.Period = Period;//频率配置 PWM频率=定时器工作频率/重装载值
sConfigOC.Pulse = Pulse;//占空比配置 占空比=Pulse/重装载值*100%
HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);//更改配置后需要重新Start才能生效
}
4.Main函数
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC2_Init();
MX_TIM3_Init();
MX_TIM6_Init();
/* USER CODE BEGIN 2 */
LCD_Init();//LCD初始化
v_value=ADC_GetValue();//获取R37电压值
D_change();//D值初始化
LCD_InitShow();//LCD初始化显示
LED_change();//LED状态改变
TIM6->SR=0;//关闭定时器6中断标志位
TIM6->CNT=0;//定时器6计数器清零
HAL_TIM_Base_Start_IT(&htim6);//以中断方式开启定时器6
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);//开启PWM
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
KEY_Scan();//按键扫描
if(LCD_RefreshFlag>4)//每0.5s更新一次LCD以及PWM(更新频率可调节)
{
LCD_RefreshFlag=0;//LCD更新标志位清零
v_value=ADC_GetValue();//重新获取R37电压值
D_change();//D值更新
LCD_Refresh();//LCD更新显示
LED_change();//LED状态更新
PWN_OutPut((TIM_Clock/F)-1,(D*1.0/100*TIM_Clock/F)-1);//PWM更新输出
}
LED_AllClose(LED_Close);//LED更新
}
/* USER CODE END 3 */
}
四、实验结果
1.初始状态
R37电压调节为1.5,对应D值为1.5/2*80=60;PWM初始频率1Khz
2.输出PWM
3.调节输出频率
4.输出PWM
五、源码(转载请注明出处)
总结
以上就是全部内容,如有错误请批评指正。