STM32PWM--基于HAL库(第十一届蓝桥杯嵌入式省赛)
文章目录
- 前言
- 一、CubeMX配置(第十三届模拟题完整版)
- 二、代码相关定义、声明
-
- 1.函数声明
- 2.宏定义
- 3.变量定义
- 三、主要函数
-
- 1.按键相关
- 2.数据更改
- 3.LCD更新显示
- 4.模式更改
- 5.LED状态更新
- 6.PWM输出
- 7.Main函数
- 四、实验结果
- 五、源码(转载请注明出处)
- 总结
前言
相关说明:
开发板:CT117E-M4(STM32G431RB 蓝桥杯嵌入式比赛板)
开发环境: CubeMX+Keil5
涉及题目:第十一届蓝桥杯嵌入式省赛
题目难点:相对容易,较少难点
(本次项目编写运用了模块化编程,更有利于代码阅读与理解。)
CubeMX配置、主要函数代码及说明:
一、CubeMX配置(第十三届模拟题完整版)
1.使能外部高速时钟:
2.配置时钟树:
3.GPIO:
4.TIM3、TIM17(PWM):
5.TIM6(0.5s中断):
6.ADC(获取R37电压值):
7.NVIC(使能TIM6中断):
二、代码相关定义、声明
1.函数声明
main.cvoid HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef * htim);//定时器中断函数void LCD_Init_Show(void);//LCD初始化界面void LCD_Refresh(uint8_t page);//LCD更新函数void Data_change(uint8_t dat);//数据改变函数void LED_Refresh(void);//LED更新函数void Mode_Change(void);//模式改变函数tim.hvoid PWM_OutPut(uint16_t PA6_pulse,uint16_t PA7_pulse);//PWM输出配置gpio.hvoid KEY_Scan(void);//按键扫描void LED_AllClose(uint8_t *LED_close);//LED关闭adc.hdouble ADC_GetValue(void);//获取R37电压值
2.宏定义
gpio.h#define LED_GPIO_PORT GPIOC#define LED1_GPIO_PINGPIO_PIN_8#define LED2_GPIO_PINGPIO_PIN_9#define LED3_GPIO_PINGPIO_PIN_10#define LED4_GPIO_PINGPIO_PIN_11#define LED5_GPIO_PINGPIO_PIN_12#define LED6_GPIO_PINGPIO_PIN_13#define LED7_GPIO_PINGPIO_PIN_14#define LED8_GPIO_PINGPIO_PIN_15#define ON GPIO_PIN_RESET#define OFFGPIO_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#defineKEY1_GPIO_PIN GPIO_PIN_0#define KEY2_GPIO_PORT GPIOB#defineKEY2_GPIO_PIN GPIO_PIN_1#define KEY3_GPIO_PORT GPIOB#defineKEY3_GPIO_PIN GPIO_PIN_2#define KEY4_GPIO_PORT GPIOA#defineKEY4_GPIO_PI GPIO_PIN_0main.h#define PA6 1#define PA7 2
3.变量定义
main.cdouble v_value;//R37的电压值char *pwm_mode="AUTO";//PWM占空比控制模式uint8_t PA6_air=10;//PA6输出PWM的占空比 (10即10%)uint8_t PA7_air=10;//PA7输出PWM的占空比uint8_t air_step=10;//占空比每次改变值uint8_t air_max=90;//最大占空比uint8_t air_min=10;//最小占空比uint8_t page_now=1;//LCD显示页(1为数据页/2为配置页)uint8_t PWM_refresh_flag=0;//PWM更新标志位(每0.5s更新一次)uint8_t LED_close[3]={0,0,0};//LED关闭数组(为1则下标对应LED关闭)char str[30];//组合字符串tim.cTIM_OC_InitTypeDef sConfigOC = {0};//重新配置后需要删除下面函数中的这个语句
三、主要函数
1.按键相关
key.c/* KEY */void Setting_Mode()//配置模式{while(1){if(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET){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);LCD_Refresh(1);//LCD更新显示break;//退出循环}}else if(HAL_GPIO_ReadPin(KEY2_GPIO_PORT,KEY2_GPIO_PIN)==GPIO_PIN_RESET)//PA6++{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);Data_change(PA6);//PA6数据改变LCD_Refresh(2);//LCD更新显示}}else if(HAL_GPIO_ReadPin(KEY3_GPIO_PORT,KEY3_GPIO_PIN)==GPIO_PIN_RESET)//PA7++{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);Data_change(PA7);//PA7数据改变LCD_Refresh(2);//LCD更新显示}}LED_Refresh();}}void KEY_Scan()//按键扫描{if(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET){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);LCD_Refresh(2);Setting_Mode();}}else if(HAL_GPIO_ReadPin(KEY4_GPIO_PORT,KEY4_GPIO_PIN)==GPIO_PIN_RESET){HAL_Delay(10);if(HAL_GPIO_ReadPin(KEY4_GPIO_PORT,KEY4_GPIO_PIN)==GPIO_PIN_RESET){while(HAL_GPIO_ReadPin(KEY4_GPIO_PORT,KEY4_GPIO_PIN)==GPIO_PIN_RESET); Mode_Change();}}}
2.数据更改
main.cvoid Data_change(uint8_t dat)//数据更改{switch(dat){case PA6:PA6_air+=air_step;if(PA6_air>air_max)PA6_air=air_min;break;case PA7:PA7_air+=air_step;if(PA7_air>air_max)PA7_air=air_min;break;}}
3.LCD更新显示
main.cvoid LCD_Refresh(uint8_t page)//LCD更新显示{if(page==1)//数据界面{page_now=1;LED_close[2]=0;LCD_DisplayStringLine(Line0,(unsigned char*)" Data ");sprintf(str," V:%.2fV ",v_value);LCD_DisplayStringLine(Line2,(unsigned char*)str);sprintf(str," Mode:%s ",pwm_mode);LCD_DisplayStringLine(Line4,(unsigned char*)str);}else if(page==2)//参数界面{page_now=2;LED_close[2]=1;LCD_DisplayStringLine(Line0,(unsigned char*)" Para ");sprintf(str," PA6:%d%% ",PA6_air);LCD_DisplayStringLine(Line2,(unsigned char*)str);sprintf(str," PA7:%d%% ",PA7_air);LCD_DisplayStringLine(Line4,(unsigned char*)str);}}
4.模式更改
main.cvoid Mode_Change()//模式更改{if(strcmp(pwm_mode,"AUTO")==0){pwm_mode="MANU";LED_close[1]=1;}else {pwm_mode="AUTO";LED_close[1]=0;}}
5.LED状态更新
main.c/* LED */void LED_Refresh()//LCD状态更新{LED_AllClose(LED_close); if(strcmp(pwm_mode,"AUTO")==0){LED1(ON);}if(page_now==1){LED2(ON);}}
6.PWM输出
TIM_OC_InitTypeDef sConfigOC = {0};这个结构体在这定义为全局变量,MX重新配置后需要删除tim.c生成函数中的这个语句。
tim.cvoid PWM_OutPut(uint16_tPA6_pulse,uint16_tPA7_pulse)//PWM输出函数{sConfigOC.Pulse=PA6_pulse;HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) ;HAL_TIM_PWM_Init(&htim3);HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);sConfigOC.Pulse=PA7_pulse;HAL_TIM_PWM_ConfigChannel(&htim17, &sConfigOC, TIM_CHANNEL_1) ;HAL_TIM_PWM_Init(&htim17);HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);}
7.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_TIM17_Init(); MX_TIM6_Init(); /* USER CODE BEGIN 2 */LCD_Init();//LCD初始化TIM6->SR=0;//定时器更新标志位清零TIM6->CNT=0;//定时器计数值清零HAL_TIM_Base_Start_IT(&htim6);//定时器开始计时v_value=ADC_GetValue();//获取ADC的值PWM_OutPut(v_value/3.3*(9999+1),v_value/3.3*(4999+1));//初始为AUTO模式LCD_Init_Show();//LCD初始化显示 /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */KEY_Scan();//按键扫描v_value=ADC_GetValue();//获取ADC的值LCD_Refresh(1);//LCD更新显示LED_Refresh();//LED更新显示if(PWM_refresh_flag==1)//每0.5S更新一次PWM{PWM_refresh_flag=0;if(strcmp(pwm_mode,"AUTO")==0)//如果为AUTO模式{PWM_OutPut(v_value/3.3*(9999+1),v_value/3.3*(4999+1));}else //如果为Menu模式{PWM_OutPut(PA6_air*1.0/100*(9999+1),PA7_air*1.0/100*(4999+1));}}HAL_Delay(50);//LCD更新延时,减少冲突 } /* USER CODE END 3 */}
四、实验结果
五、源码(转载请注明出处)
总结
以上就是全部内容,如有错误请批评指正。