第十四届省赛我觉得是第三难的。
题目要求
题目分析
我的话其实一开始没啥思路,但是做着做着就有了,我做题都是有一套流程的。这一届的难点,我觉得是阅读理解和标志位很多,容易把人绕晕。
Cubemx配置
我是直接用官方给的模板配置的,sys设置成串行线,然后生成.c.h文件勾选上。
led配置
led原理图
原理图和74HC_HCT573手册可以看出,有一个PD2的锁存器,当PD2输出高电平,LE输入高电平即可使能锁存器,并且PC8-PC15输出低电平二极管导通。
所以led的配置
PC8-PC15,PD2,设为out_put
PC8-PC15 SPlO output level设置为High,其他的默认就好。
按键配置
按键原理图
按键配置就是PA0,PB0,PB1,PB2,配置为input和上拉
adc配置
R37对应的是PB15,所以开启PB15的ADC2的通道15,其他默认就可以了。
pwm配置
接下来是pa1的pwm的配置,题目说默认是低频模式,低频模式是4000hz,所以频率=80000000/80*250 = 4000hz,其他默认就可以。
输入捕获配置
这里是PA7进行捕获频率,并不用捕获占空比,所以一个通道直接捕获就可以了,我这里选择的是TIM17的CH1,记得勾上NVIC!!
然后直接生成代码就可以了
做题思路
做题的话要有自己固定的思路,我的话就是一开始把所有基本的模块实现然后就进下一步的逻辑分析。一般我会先创建好user.c和user.h,,然后把模块基本函数丢进去,在main.c写逻辑,做题可以先对lcd和key先入手这样做题会轻松些。
我直接丢代码先把,
user.c
#include "user.h"
void led_ctrl(u8 led){
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,led<<8, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2, GPIO_PIN_RESET);
}
u8 key_value,key_up,key_down,key_old = 0;
void key_ctrl(){
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0){
key_value = 1;
}else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==0){
key_value = 2;
}else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==0){
key_value = 3;
}else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==0){
key_value = 4;
}else {
key_value = 0;
}
key_down = key_value&(key_value^key_old);
key_up = ~key_value&(key_value^key_old);
key_old = key_value;
}
u16 adc_value = 0;
float Vr37 = 0;
u32 adc_tick = 0;
void adc_proc(){
if(uwTick - adc_tick<100)
return;
adc_tick = uwTick;
HAL_ADC_Start(&hadc2);
adc_value = HAL_ADC_GetValue(&hadc2);
Vr37 = 3.3*adc_value/4096.0;
}
//v = (f*2*pi*R)/100*K
u8 R = 1;
u8 K = 1;
float pi = 3.14;
float V = 0;
u8 N = 0;
u16 F_PA1 = 4000;
float D_PA1 = 50;
float MH = 0;
float ML = 0;
u32 pwm_tick = 0;
void pwm_proc(){
if(uwTick - pwm_tick<100)
return;
pwm_tick = uwTick;
__HAL_TIM_SetAutoreload(&htim2,1e6/F_PA1-1);
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,1e6/F_PA1*D_PA1/100);
}
float ic_value = 0;
u16 F_PA7 = 0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){
if(htim==&htim17){
if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1){
ic_value = HAL_TIM_ReadCapturedValue(&htim17, TIM_CHANNEL_1);
__HAL_TIM_SetCounter(htim,0);
F_PA7 = (1000000)/ic_value;
HAL_TIM_IC_Start_IT(&htim17, TIM_CHANNEL_1);
}
}
}
float MLL = 0;
float MHH = 0;
u8 ic_cnt = 0;
u32 ic_tick = 0;
void ic_proc(){
if(uwTick - ic_tick<100)
return;
ic_tick = uwTick;
V = (F_PA7*2*pi*R)/(100*K);
//100*20 = 2000
if(HL_Mode==0){
if(ic_cnt==0){
MLL = ML;
}
if(V>ML&&ic_cnt>=20&&MLL==ML){
ML = V;
ic_cnt = 0;
}
ic_cnt++;
}else {
if(ic_cnt==0){
MHH = MH;
}
if(V>MH&&ic_cnt>=20&&MHH==MH){
MH = V;
ic_cnt = 0;
}
ic_cnt++;
}
}
user.h
#ifndef _USER_H
#define _USER_H
#include "main.h"
#include "user.h"
void led_ctrl(u8 led);
extern u8 key_value,key_up,key_down,key_old;
void key_ctrl();
extern u16 adc_value;
extern float Vr37;
void adc_proc();
extern u8 R;
extern u8 K;
extern float pi;
extern float V;
extern u8 N;
extern u16 F_PA1;
extern float D_PA1;
extern float MH;
extern float ML;
void pwm_proc();
extern float ic_value;
extern u16 F_PA7;
void ic_proc();
#endif
main.c
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "tim.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
_Bool HL_Mode = 0;
_Bool lcd_line = 0;
_Bool lock = 0;
u8 Change_Mode = 0;
u8 ui = 0;
u8 led_num = 0;
u32 led_tick = 0;
void led_proc(){
if(uwTick - led_tick<100)
return;
led_tick = uwTick;
if(ui==0){
led_num |=1<<0;
}else {
led_num &=~(1<<0);
}
if(Change_Mode==1){
led_num ^=1<<1;
}else {
led_num &=~(1<<1);
}
if(lock==1){
led_num |=1<<2;
}else {
led_num &=~(1<<2);
}
led_ctrl(led_num);
}
u16 Mode_cnt = 0;
u32 key_tick = 0;
u32 key_long_tick = 0;
void key_proc(){
if(uwTick - key_tick<20)
return;
key_tick = uwTick;
key_ctrl();
if(ui==0){
if(key_down==1){
ui++;
if(ui>2)
ui = 0;
LCD_Clear(Black);
}else if(key_down==2&&Change_Mode==0){
HL_Mode=!HL_Mode;
Change_Mode= 1;
N++;
LCD_Clear(Black);
}else if(key_down==3){
}else if(key_up==4&&uwTick - key_long_tick<2000){
lock = 0;
}else if(key_down==4){
key_long_tick = uwTick;
}
if(key_value==4&&uwTick - key_long_tick>=2000){
lock = 1;
}
}else if(ui==1){
if(key_down==1){
ui++;
if(ui>2)
ui = 0;
LCD_Clear(Black);
}else if(key_down==2){
lcd_line=!lcd_line;
}else if(key_down==3){
if(lcd_line==0){
R++;
if(R>10){
R = 1;
}
}else{
K++;
if(K>10){
K = 1;
}
}
}else if(key_down==4){
if(lcd_line==0){
R--;
if(R<1){
R = 10;
}
}else{
K--;
if(K<1){
K = 10;
}
}
}
}else if(ui==2){
if(key_down==1){
ui++;
if(ui>2)
ui = 0;
LCD_Clear(Black);
}else if(key_down==2){
}else if(key_down==3){
}else if(key_down==4){
}
}
if(Change_Mode==1){
Mode_cnt++;
//20*250 = 5000
if(Mode_cnt>=250){
Change_Mode = 0;
Mode_cnt = 0;
}
}
}
u8 lcd_buf[30];
u32 lcd_tick = 0;
void lcd_proc(){
if(uwTick - lcd_tick<100)
return;
lcd_tick = uwTick;
if(ui==0){
sprintf((char *)lcd_buf," DATA ");
LCD_DisplayStringLine(Line1,lcd_buf);
if(HL_Mode==0)//L
sprintf((char *)lcd_buf," M = L ");
if(HL_Mode==1)//H
sprintf((char *)lcd_buf," M = H ");
LCD_DisplayStringLine(Line3,lcd_buf);
sprintf((char *)lcd_buf," P = %0.0f %% ",D_PA1);
LCD_DisplayStringLine(Line4,lcd_buf);
sprintf((char *)lcd_buf," V = %0.1f ",V);
LCD_DisplayStringLine(Line5,lcd_buf);
}else if(ui==1){
sprintf((char *)lcd_buf," PARA ");
LCD_DisplayStringLine(Line1,lcd_buf);
if(lcd_line == 0)
LCD_SetBackColor(Red);
sprintf((char *)lcd_buf," R = %d ",R);
LCD_DisplayStringLine(Line3,lcd_buf);
LCD_SetBackColor(Black);
if(lcd_line == 1)
LCD_SetBackColor(Red);
sprintf((char *)lcd_buf," K = %d ",K);
LCD_DisplayStringLine(Line4,lcd_buf);
LCD_SetBackColor(Black);
}else if(ui==2){
sprintf((char *)lcd_buf," RECD ");
LCD_DisplayStringLine(Line1,lcd_buf);
sprintf((char *)lcd_buf," N = %d ",N);
LCD_DisplayStringLine(Line3,lcd_buf);
sprintf((char *)lcd_buf," MH = %0.1f ",MH);
LCD_DisplayStringLine(Line4,lcd_buf);
sprintf((char *)lcd_buf," ML = %0.1f ",ML);
LCD_DisplayStringLine(Line5,lcd_buf);
}
}
u32 pwm_flag_tick = 0;
u8 pwm_flag_cnt = 0;
void pwm_mode(){
if(uwTick - pwm_flag_tick<100)
return;
pwm_flag_tick = uwTick;
//100*50 = 5000; 4000->8000 80*50 =4000
if(Change_Mode == 1){
if(HL_Mode==1){
F_PA1+=63;
pwm_flag_cnt++;
if(pwm_flag_cnt>=50)
pwm_flag_cnt = 0;
}else if(HL_Mode==0){
F_PA1 -=63;
pwm_flag_cnt++;
if(pwm_flag_cnt>=50)
pwm_flag_cnt = 0;
}
}else{
}
}
u32 pwm_status_tick = 0;
void pwm_status(){
if(uwTick - pwm_status_tick<100)
return;
pwm_status_tick = uwTick;
if(lock==0){
if(Vr37*100<=100){
D_PA1 = 10;
}else if(Vr37*100>=300){
D_PA1 = 85;
}else if(Vr37*100>100&&Vr37*100<300){
D_PA1 = 37.5*Vr37-27.5;
}
}else {
}
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
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_TIM2_Init();
MX_TIM17_Init();
/* USER CODE BEGIN 2 */
led_ctrl(0);
LCD_Init();
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
HAL_TIM_IC_Start_IT(&htim17, TIM_CHANNEL_1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
while (1)
{
pwm_proc();
ic_proc();
adc_proc();
pwm_status();
pwm_mode();
led_proc();
key_proc();
lcd_proc();
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
RCC_OscInitStruct.PLL.PLLN = 20;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
main.h
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.h
* @brief : Header for main.c file.
* This file contains the common defines of the application.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32g4xx_hal.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#define u8 uint8_t
#define u16 uint16_t
#define u32 uint32_t
extern _Bool HL_Mode;
#include "user.h"
#include "lcd.h"
#include "adc.h"
#include "tim.h"
#include "gpio.h"
#include "stdio.h"
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */
我这写的还是挺有问题的。