文章目录
- 前言
- 一、CubeMX配置(第十四届模拟题2完整版)
- 二、代码相关定义、声明
-
- 三、主要函数
- 1.按键扫描
- 2.各参数控制
- 3.LCD显示
- 4.输出信号改变
- 5.串口接收
- 6.Main函数
- 四、实验结果
-
- 五、查漏补缺!
- 六、源码(转载请注明出处)
- 总结
前言
相关说明:
开发板:CT117E-M4(STM32G431RB 蓝桥杯嵌入式比赛板)
开发环境: CubeMX+Keil5
涉及题目:第十四届蓝桥杯嵌入式模拟题2
题目难点:难度相对较低
题目来源:4T
CubeMX配置、主要函数代码及说明:
一、CubeMX配置(第十四届模拟题2完整版)
1.使能外部高速时钟:
2.配置时钟树:
3.GPIO:
4.TIM2(PA1输出):
5.TIM3(同上,PA7输出):
6.TIM6(控制LED闪烁):
7.TIM7(判断串口接收,同上,5ms中断):
8.NVIC(输入捕获中断配置):
二、代码相关定义、声明
1.函数声明
main.c
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim);
void LCD_Init_Show(void);
void LCD_Refresh(void);
gpio.h
void KEY_Scan(void);
void LED_AllClose(uint8_t *LED_Close);
void LED_Change(void);
adc.h
double ADC_GetValue(void);
time.h
void PWM_Out(double R37_V,uint32_t FRQ,uint8_t R);
2.宏定义
在CubeMX中可以配置User Label选项即可生成对应宏定义
生成宏定义:
main.h
#define LED6_Pin GPIO_PIN_13
#define LED6_GPIO_Port GPIOC
#define LED7_Pin GPIO_PIN_14
#define LED7_GPIO_Port GPIOC
#define LED8_Pin GPIO_PIN_15
#define LED8_GPIO_Port GPIOC
#define KEY4_Pin GPIO_PIN_0
#define KEY4_GPIO_Port GPIOA
#define KEY1_Pin GPIO_PIN_0
#define KEY1_GPIO_Port GPIOB
......此处省略
自定义宏定义(灯的控制,PD2引脚控制):
main.h
#define OFF GPIO_PIN_SET
#define ON GPIO_PIN_RESET
#define LED1(a) HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,a)
#define LED2(a) HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,a)
#define LED3(a) HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,a)
#define LED4(a) HAL_GPIO_WritePin(LED4_GPIO_Port,LED4_Pin,a)
#define LED5(a) HAL_GPIO_WritePin(LED5_GPIO_Port,LED5_Pin,a)
#define LED6(a) HAL_GPIO_WritePin(LED6_GPIO_Port,LED6_Pin,a)
#define LED7(a) HAL_GPIO_WritePin(LED7_GPIO_Port,LED7_Pin,a)
#define LED8(a) HAL_GPIO_WritePin(LED8_GPIO_Port,LED8_Pin,a)
#define LED_All(a) HAL_GPIO_WritePin(LED8_GPIO_Port,GPIO_PIN_All,a)
#define LOCK_HIGH() HAL_GPIO_WritePin(LOCK_GPIO_Port,LOCK_Pin,GPIO_PIN_SET)
#define LOCK_LOW() HAL_GPIO_WritePin(LOCK_GPIO_Port,LOCK_Pin,GPIO_PIN_RESET)
3.变量定义
char buf[20];
uint8_t LED[4] = {1,0,1,0};
uint16_t PA7_HZ = 1000;
uint8_t PA7_D = 10;
uint16_t PA1_HZ = 1000;
uint8_t PA1_D = 10;
uint8_t page = 1;
uint8_t rec_byte;
uint8_t mode = 1;
uint8_t rec_flag = 0;
uint16_t rec_num = 0;
三、主要函数
1.按键扫描
此处将按键按下后的操作都封装成独立的函数调用:
KEY1 – 改变频率
KEY2 – 改变占空比
KEY3 – 数据页改变
KEY4 – 操作模式改变
void KEY_Process()
{
if((HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == GPIO_PIN_RESET))
{
HAL_Delay(10);
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == GPIO_PIN_RESET)
{
HZ_Change();
while(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == GPIO_PIN_RESET);
}
}
else if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin) == GPIO_PIN_RESET)
{
HAL_Delay(10);
if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin) == GPIO_PIN_RESET)
{
D_Change();
while(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin) == GPIO_PIN_RESET);
}
}
else if(HAL_GPIO_ReadPin(KEY3_GPIO_Port,KEY3_Pin) == GPIO_PIN_RESET && (mode == 1))
{
HAL_Delay(10);
if(HAL_GPIO_ReadPin(KEY3_GPIO_Port,KEY3_Pin) == GPIO_PIN_RESET)
{
Page_Change();
while(HAL_GPIO_ReadPin(KEY3_GPIO_Port,KEY3_Pin) == GPIO_PIN_RESET);
}
}
else if(HAL_GPIO_ReadPin(KEY4_GPIO_Port,KEY4_Pin) == GPIO_PIN_RESET)
{
HAL_Delay(10);
if(HAL_GPIO_ReadPin(KEY4_GPIO_Port,KEY4_Pin) == GPIO_PIN_RESET)
{
Mode_Change();
while(HAL_GPIO_ReadPin(KEY4_GPIO_Port,KEY4_Pin) == GPIO_PIN_RESET);
}
}
}
2.各参数控制
输出信号频率、占空比、数据页以及操作模式改变
uint16_t PA7_HZ = 1000;
uint8_t PA7_D = 10;
uint16_t PA1_HZ = 1000;
uint8_t PA1_D = 10;
uint8_t page = 1;
uint8_t mode = 1;
const uint16_t HZ_pace = 1000;
const uint16_t HZ_max = 10000;
const uint16_t HZ_min = 1000;
const uint8_t D_pace = 10;
const uint8_t D_max = 90;
const uint8_t D_min = 10;
void HZ_Change()
{
if(page == 1)
{
PA1_HZ+=HZ_pace;
if(PA1_HZ > HZ_max)
{
PA1_HZ = HZ_min;
}
}
else if(page == 2)
{
PA7_HZ+=HZ_pace;
if(PA7_HZ > HZ_max)
{
PA7_HZ = HZ_min;
}
}
PWM_change();
HAL_TIM_Base_Start(&htim6);
}
void D_Change()
{
if(page == 1)
{
PA1_D+=D_pace;
if(PA1_D > D_max)
{
PA1_D = D_min;
}
}
else if(page == 2)
{
PA7_D+=D_pace;
if(PA7_D > D_max)
{
PA7_D = D_min;
}
}
PWM_change();
}
void Mode_Change()
{
mode = !mode;
if(mode == 1)
{
LED[3] = 0;
}
else
{
LED[3] = 1;
}
LED_Control(LED);
}
void Page_Change()
{
if(page == 1)
{
page = 2;
sprintf(buf," PA7 ");
LED[1] = 1;
LED[2] = 0;
}
else if(page == 2)
{
page = 1;
sprintf(buf," PA1 ");
LED[1] = 0;
LED[2] = 1;
}
LED_Control(LED);
LCD_DisplayStringLine(Line2,(u8*)buf);
}
3.LCD显示
共有两个函数:
1.LCD_InitShow(),在上电启动后对LCD进行初始化显示操作。
2.LCD_Refresh(),LCD更新显示,数据更新后需要实时进行更新显示。
void LCD_InitShow()
{
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
LCD_DisplayStringLine(Line0,(u8*)" ");
LCD_DisplayStringLine(Line1,(u8*)" ");
LCD_DisplayStringLine(Line2,(u8*)" PA1 ");
LCD_DisplayStringLine(Line3,(u8*)" ");
sprintf(buf," F:%d ",PA1_HZ);
LCD_DisplayStringLine(Line4,(u8*)buf);
LCD_DisplayStringLine(Line5,(u8*)" ");
sprintf(buf," D:%d ",PA1_D);
LCD_DisplayStringLine(Line6,(u8*)buf);
LCD_DisplayStringLine(Line7,(u8*)" ");
LCD_DisplayStringLine(Line8,(u8*)" ");
LCD_DisplayStringLine(Line9,(u8*)" ");
}
void LCD_Refresh()
{
if(page == 1)
{
sprintf(buf," F:%d ",PA1_HZ);
LCD_DisplayStringLine(Line4,(u8*)buf);
sprintf(buf," D:%d ",PA1_D);
LCD_DisplayStringLine(Line6,(u8*)buf);
}
else if(page == 2)
{
sprintf(buf," F:%d ",PA7_HZ);
LCD_DisplayStringLine(Line4,(u8*)buf);
sprintf(buf," D:%d ",PA7_D);
LCD_DisplayStringLine(Line6,(u8*)buf);
}
}
4.输出信号改变
直接对TIM2和TIM3的寄存器操作即可
ARR – 寄存器存储的是重装载值
CCRx – 定时器x通道的比较值
要使定时器输出对应频率的信号,重装载值=定时器工作频率/目标频率。
控制该信号的占空比,比较值=重装载值*占空比。
void PWM_change()
{
if(page == 1)
{
TIM2->ARR = 1000000/PA1_HZ;
TIM2->CCR2 = TIM2->ARR*PA1_D/100;
TIM2->CNT = 0;
}
else if(page == 2)
{
TIM3->ARR = 1000000/PA7_HZ;
TIM3->CCR2 = TIM3->ARR*PA7_D/100;
TIM3->CNT = 0;
}
}
5.串口接收
每次串口接收到数据都重新开启定时器,这样能使最后一字节数据接收完5ms后才开始对接收数据进行处理,而不是每接收一个字节数据都去处理一次
uint8_t rec_flag = 0;
uint16_t rec_num = 0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
...
if(htim == &htim7)
{
HAL_TIM_Base_Stop_IT(&htim7);
rec_flag = 1;
}
...
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
rec_num++;
HAL_UART_Receive_IT(&huart1,&rec_byte,1);
TIM7->CNT = 0;
HAL_TIM_Base_Start_IT(&htim7);
}
6.Main函数
注意调用PWM的start函数打开PWM、以中断方式打开定时器以及打开串口接收中断等
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM6_Init();
MX_USART1_UART_Init();
MX_TIM2_Init();
MX_TIM3_Init();
MX_TIM7_Init();
LCD_Init();
LCD_InitShow();
LED_Control(LED);
HAL_UART_Receive_IT(&huart1,&rec_byte,1);
HAL_TIM_Base_Start_IT(&htim6);
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);
printf("uart test...\n");
while (1)
{
KEY_Process();
LCD_Refresh();
if(rec_flag == 1)
{
rec_flag = 0;
Check_UartRec();
}
}
}
四、实验结果
1.数据页1
上电默认值F为1000 D为10
2.数据页2
上电默认值F为1000 D为10
3.输出频率
默认D值为10,占空比为10%,F为1000,输出频率为1KHz
4.串口数据
1.按键控制模式:
2.串口控制模式,数据长度不符:
3.切换到PA7数据页,操作成功:
五、查漏补缺!
1.蓝桥杯嵌入式赛前梳理
2.一文看懂如何使用RTC秒中断
3.一文看懂如何解决LED与LCD冲突
4.一文看懂如何玩转显示高亮
六、源码(转载请注明出处)
总结
以上就是全部内容,如有错误请批评指正。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)