文章目录

  • 前言
  • 一、CubeMX配置(第十四届模拟题2完整版)
  • 二、代码相关定义、声明
    • 1.函数声明
    • 2.宏定义
    • 3.变量定义
  • 三、主要函数
    • 1.按键扫描
    • 2.各参数控制
    • 3.LCD显示
    • 4.输出信号改变
    • 5.串口接收
    • 6.Main函数
  • 四、实验结果
    • 1.数据页1
    • 2.数据页2
    • 3.输出频率
    • 4.串口数据
  • 五、查漏补缺!
  • 六、源码(转载请注明出处)
  • 总结

前言

相关说明:

开发板: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);   //LCD初始化显示
void LCD_Refresh(void);     //LCD更新显示 gpio.h
void KEY_Scan(void);//按键扫描
void LED_AllClose(uint8_t *LED_Close);//LED更新显示
void LED_Change(void);//LED状态改变adc.h
double ADC_GetValue(void);//获取R37电压值time.h
void PWM_Out(double R37_V,uint32_t FRQ,uint8_t  R);//PWM输出

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}; //LED状态数组uint16_t PA7_HZ = 1000;      //PA7输出信号频率
uint8_t PA7_D = 10;            //PA7输出信号占空比
uint16_t PA1_HZ = 1000;        //PA1输出信号频率
uint8_t PA1_D = 10;            //PA1输出信号占空比
uint8_t page = 1;          //page1:PA1数据页 page2:PA7数据页
uint8_t rec_byte;           //串口数据存储
uint8_t mode = 1;          //当前模式 1:按键控制 0:串口控制
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;            //PA7输出信号频率
uint8_t PA7_D = 10;                //PA7输出信号占空比
uint16_t PA1_HZ = 1000;            //PA1输出信号频率
uint8_t PA1_D = 10;                //PA1输出信号占空比
uint8_t page = 1;              //page1:PA1数据页 page2:PA7数据页
uint8_t mode = 1;              //当前模式 1:按键控制 0:串口控制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{PA1_HZ+=HZ_pace;if(PA1_HZ > HZ_max){PA1_HZ = HZ_min;}}else if(page == 2)//PA7{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{PA1_D+=D_pace;if(PA1_D > D_max){PA1_D = D_min;}}else if(page == 2)//PA7{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);//LED更新
}/*数据页改变*/
void Page_Change()
{if(page == 1)//PA1数据页->PA7数据页{page = 2;sprintf(buf,"    PA7    "); LED[1] = 1;LED[2] = 0;}else if(page == 2)//PA7数据页->PA1数据页{page = 1;sprintf(buf,"    PA1    "); LED[1] = 0;LED[2] = 1;}LED_Control(LED);//LED更新LCD_DisplayStringLine(Line2,(u8*)buf);//JLCD更新
}

3.LCD显示

共有两个函数:
1.LCD_InitShow(),在上电启动后对LCD进行初始化显示操作。
2.LCD_Refresh(),LCD更新显示,数据更新后需要实时进行更新显示。

/*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*)"                    ");
}/*LCD更新函数 page1:PA1 page2:PA7*/
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)//PA1{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);//关闭定时器7rec_flag = 1;//接收检测标志位置1}...
}/*串口接收回调函数*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{rec_num++;//接收字节数增加HAL_UART_Receive_IT(&huart1,&rec_byte,1);//再次打开串口接收中断TIM7->CNT = 0;//定时器7计数值清零 重新计时HAL_TIM_Base_Start_IT(&htim7);//开始计时
}

6.Main函数

注意调用PWM的start函数打开PWM、以中断方式打开定时器以及打开串口接收中断等

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_TIM6_Init();MX_USART1_UART_Init();MX_TIM2_Init();MX_TIM3_Init();MX_TIM7_Init();/* USER CODE BEGIN 2 */LCD_Init();//LCD初始化LCD_InitShow();//LCD初始化显示LED_Control(LED);//LED初始化HAL_UART_Receive_IT(&huart1,&rec_byte,1);//打开串口接收中断HAL_TIM_Base_Start_IT(&htim6);//开启定时器6HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);//PWM启动HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);//PWM启动printf("uart test...\n");/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){KEY_Process();//按键处理LCD_Refresh();//LCD更新if(rec_flag == 1)//串口数据接收标志位{rec_flag = 0;//标志位清零Check_UartRec();//串口数据处理}/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

四、实验结果

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.一文看懂如何玩转显示高亮

六、源码(转载请注明出处)


总结

以上就是全部内容,如有错误请批评指正。

STM32G431-基于HAL库(第十四届蓝桥杯嵌入式模拟题2)相关推荐

  1. 第十四届蓝桥杯校内模拟赛第二期-Java个人题解(仅供参考)

    刚刚结束第十四届蓝桥杯校内模拟赛第二期,在这记录下自己的代码 不保证正确! 不保证正确! 不保证正确! 有问题一起改正!! 题解 2048 代码: package _14届模拟2;public cla ...

  2. 第十四届蓝桥杯三月真题刷题训练——第 23 天

    目录 第 1 题:长草 题目描述 输入描述 输出描述 输入输出样例 运行限制 代码: 思路: 第 2 题:蓝肽子序列_LCS_最长公共子序列dp问题 题目描述 输入描述 输出描述 输入输出样例 运行限 ...

  3. 第十四届蓝桥杯三月真题刷题训练——第 13 天

    目录 第 1 题:特殊日期 问题描述 答案提交 运行限制 代码: 思路: 第 2 题:重合次数 问题描述 答案提交 运行限制 代码: 第 3 题:左移右移 问题描述 输入格式 输出格式 样例输入 样例 ...

  4. 第十四届蓝桥杯三月真题刷题训练——第 9 天

    第 1 题:找素数 题目描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可. 素数就是不能再进行等分的整数.比如:7,11.而 9 不是素数,因为它可以平分为 3 等份.一般 ...

  5. 第十四届蓝桥杯三月真题刷题训练——第 22 天

    目录 第 1 题:受伤的皇后_dfs 题目描述 输入描述 输出描述 输入输出样例 运行限制 代码: 思路: 第 2 题:完全平方数 问题描述 输入格式 输出格式 样例输入 1 样例输出 1 样例输入 ...

  6. 第十四届蓝桥杯三月真题刷题训练——第 14 天

    目录 第 1 题:组队 题目描述 运行限制 代码: 第 2 题:不同子串 题目描述 运行限制 代码: 思路: 第 3 题:等差数列 题目描述 输入描述 输出描述 输入输出样例 运行限制 代码: 思路: ...

  7. 第十四届蓝桥杯三月真题刷题训练——第 20 天

    目录 第 1 题:纸张尺寸 问题描述 输入格式 输出格式 样例输入1 样例输出1 样例输入 2 样例输出 2 运行限制 代码: 解析: 第 2 题:最大数字 第 3 题:全排列的价值_递推公式 问题描 ...

  8. 第十四届蓝桥杯三月真题刷题训练——第 15 天

    目录 第 1 题:斐波那契与7 问题描述 答案提交 运行限制 代码: 第 2 题:小蓝做实验 问题描述 答案提交 运行限制 代码: 第 1 题:斐波那契与7 问题描述 斐波那契数列的递推公式为: Fn ...

  9. 第十四届蓝桥杯三月真题刷题训练——第 21 天

    目录 第 1 题:灭鼠先锋 问题描述 运行限制 代码: 思路: 第 2 题:小蓝与钥匙 问题描述 答案提交 运行限制 代码: 思路 : 第 3 题:李白打酒加强版 第 4 题:机房 第 1 题:灭鼠先 ...

最新文章

  1. matlab repmate,MATLAB中“repmat”与“cat”函数的用法
  2. vue中手机号,邮箱正则验证以及60s发送验证码
  3. SAP 电商云 Spartacus UI 的 style library 介绍
  4. python程序开发总结_python开发总结
  5. 实现文件中名词的统计计数_通过勤哲EXCEL和Excel中的rank函数实现排名统计
  6. Stm32之通用定时器复习
  7. [WP8] Binding时,依照DataType来选择DataTemplate
  8. python win32api sendmessage_Python win32api.SendMessage方法代码示例
  9. 食堂刷卡消费系统服务器,食堂一卡通消费系统如何使用
  10. 加密狗只是开始,区块链+文娱才是大趋势
  11. wifi认证源码html,openwrt 实现本地wifidog简单认证,认证端纯html
  12. 误删代码,回收站又被清空还没有备份教你如何解决
  13. 什么是百度竞价包年?竞价包年骗局揭露
  14. 侯捷c++课程学习一
  15. onenote文本每一行出现绿色背景和旁边出现作者信息的完美解决方法
  16. 常见的开发模式和不常见的开发模式
  17. c语言pm2.5检测系统,基于Arduino的PM2.5实时检测系统
  18. Linux网络常用命令
  19. 用verilog HDL实现数字基带信号的2FSK调制
  20. Unexpected token u in JSON at position 0 控制台报错

热门文章

  1. SAP中如何从应用角度理解虚拟装配phantom assembly
  2. uni-app下载图片(新手上路)
  3. fancybox 的使用
  4. mac可以上QQ,打不开网页,上不了网
  5. 【科技百咖】法大大:“法律+电子签名”版的中国合伙人
  6. 戴尔U盘重装系统Win10步骤和详细教程
  7. 【好图】美国定义的无人机自主控制等级及规划图 | 无人装备
  8. “河道”收窄的水滴公司,要奔往哪片“汪洋”
  9. 盲校计算机教学策略,浅谈盲校计算机教学策略.doc
  10. 使用MERGE语句合并数据