题目
这套模拟题和十四届模拟一很相似,主要是按键控制频率和占空比,串口切换界面,十四届模拟一是按键控制频率,串口控制占空比,都是差不多写法
CubeMX配置
首先,查看题目
这个图可以让我们知道大概有那些功能,有LCD、LED、KEY、PWM、USART,根据比赛给出的产品手册去配置相应的引脚和参数就行。
引脚配置
前面我的文章里也有CubeMX的配置,大家不知道怎么配置的可以去看一下,这里就不多说了,我们这里直接看一下代码实现
代码实现
我一般习惯将按键、输入捕获和串口放在一个interrupt.c中,led、pwm这些放在主函数中。
中断回调函数
//中断回调函数
#include "interrupt.h"
#include "usart.h"
extern int pa1_frq,pa7_frq;
struct keys key[4]={0,0,0,0};
int time1,time2;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM4)
{
key[0].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
key[1].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
key[2].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
key[3].key_sta=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
for(int i=0;i<4;i++)
{
switch(key[i].judge_sta)
{
case 0:
{
if(key[i].key_sta==0)
{
key[i].judge_sta=1;
key[i].key_time=0;
}
}
break;
case 1:
{
if(key[i].key_sta==0)
{
key[i].judge_sta=2;
key[i].single_flag=1;
}
else
key[i].judge_sta=0;
}
break;
case 2:
{
if(key[i].key_sta==1)
{
key[i].judge_sta=0;
}
}
break;
}
}
}
if(htim->Instance==TIM6) //time1用于ld1闪烁
{
if(pa1_frq>pa7_frq)
time1++;
else
time1=0;
}
if(htim->Instance==TIM8) //time2用于ld2闪烁
{
if(pa1_frq<pa7_frq)
time2++;
else
time2=0;
}
}
char rxdata[30];
int rx_pointer;
uint8_t rxda;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
rxdata[rx_pointer++] = rxda;
HAL_UART_Receive_IT(&huart1,&rxda,1);
}
主函数
/* 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 "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "interrupt.h"
#include "stdio.h"
#include "string.h"
#include "lcd.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
extern char rxdata[30];
extern int rx_pointer;
extern uint8_t rxda;
extern struct keys key[4];
extern int time1,time2;
int view=0; //界面
char text[20];
int pa1_duty=10,pa7_duty=10;
int pa1_frq=1000,pa7_frq=1000;
int num1=1,num2=1,num3=1,num4=1;
int control_flag=0;
unsigned char led=0x00;
/* 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 */
void led_disp(unsigned char dsled)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,dsled<<8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
void lcd_pro(void)
{
if(view==0)
{
LCD_DisplayStringLine(Line3,(u8 *)" PA1 ");
sprintf(text," F:%dHz ",pa1_frq);
LCD_DisplayStringLine(Line4,(u8 *)text);
sprintf(text," D:%d%% ",pa1_duty);
LCD_DisplayStringLine(Line5,(u8 *)text);
}
if(view==1)
{
LCD_DisplayStringLine(Line3,(u8 *)" PA7 ");
sprintf(text," F:%dHz ",pa7_frq);
LCD_DisplayStringLine(Line4,(u8 *)text);
sprintf(text," D:%d%% ",pa7_duty);
LCD_DisplayStringLine(Line5,(u8 *)text);
}
}
void key_pro(void)
{
//B1增加PA1频率
if(view==0)
{
if(key[0].single_flag==1)
{
num1+=1;
if(num1>10)
num1=1;
pa1_frq=1000*num1;
TIM2->ARR = 1000000/(1000*num1)-1;
__HAL_TIM_SetCounter(&htim2,0);
TIM2->CCR2 = (0.1*num3) * TIM2->ARR;
key[0].single_flag=0;
}
}
//B1增加PA7频率
if(view==1)
{
if(key[0].single_flag==1)
{
num2+=1;
if(num2>10)
num2=1;
pa7_frq=1000*num2;
TIM3->ARR = 1000000/(1000*num2)-1;
__HAL_TIM_SetCounter(&htim3,0);
TIM3->CCR2 = (0.1*num4) * TIM3->ARR;
key[0].single_flag=0;
}
}
//B2增加PA1占空比
if(view==0)
{
if(key[1].single_flag==1)
{
num3+=1;
if(num3>9)
num3=1;
pa1_duty=10*num3;
TIM2->CCR2 = (0.1*num3) * TIM2->ARR;
key[1].single_flag=0;
}
}
//B2增加PA7占空比
if(view==1)
{
if(key[1].single_flag==1)
{
num4+=1;
if(num4>9)
num4=1;
pa7_duty=10*num4;
TIM3->CCR2 = (0.1*num4) * TIM3->ARR;
key[1].single_flag=0;
}
}
//按键控制模式下按下B3可切换
if(key[2].single_flag==1&&control_flag==0)
{
view^=1;
LCD_Clear(Black);
key[2].single_flag=0;
}
//B4切换控制模式 0:按键 1:串口
if(key[3].single_flag==1)
{
control_flag^=1;
key[3].single_flag=0;
}
}
void rx_pro(void)
{
if(rx_pointer>0)
{
if(rx_pointer==1&&control_flag==1)
{
if(rxda=='@')
{
view=0;
}
if(rxda=='#')
{
view=1;
}
else
{
sprintf(text,"ERROR");
HAL_UART_Transmit(&huart1,(unsigned char *)text,strlen(text),10);
}
}
if(rx_pointer>=2&&control_flag==1)
{
sprintf(text,"ERROR");
HAL_UART_Transmit(&huart1,(unsigned char *)text,strlen(text),12);
}
if(control_flag==0)
{
sprintf(text,"KEY CONTROL");
HAL_UART_Transmit(&huart1,(unsigned char *)text,strlen(text),12);
}
}
rx_pointer=0;
memset(rxdata,0,strlen(rxdata));
}
void led_pro(void)
{
if(view==0&&pa1_frq<=pa7_frq)
led |= 0x01;
else
led &= ~0x01;
if(view==1&&pa1_frq>=pa7_frq)
led |= 0x02;
else
led &= ~0x02;
if(control_flag==0)
led |= 0x04;
else
led &= ~0x04;
if(time1%2==0&&pa1_frq>pa7_frq)
led |= 0x01;
if(time1%2==1&&pa1_frq>pa7_frq)
led &= ~0x01;
if(time2%2==0&&pa1_frq<pa7_frq)
led |= 0x02;
if(time2%2==1&&pa1_frq<pa7_frq)
led &= ~0x02;
led_disp(led);
}
void pwm_start(void)
{
TIM2->ARR = 1000000/1000-1;
TIM2->CCR2 = 0.1*TIM2->ARR;
TIM3->ARR = 1000000/1000-1;
TIM3->CCR2 = 0.1*TIM2->ARR;
}
/* 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_TIM2_Init();
MX_TIM3_Init();
MX_TIM4_Init();
MX_USART1_UART_Init();
MX_TIM6_Init();
MX_TIM8_Init();
/* USER CODE BEGIN 2 */
LCD_Init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
led_disp(led);
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
HAL_UART_Receive_IT(&huart1,&rxda,1);
pwm_start();
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);
HAL_TIM_Base_Start_IT(&htim4);
HAL_TIM_Base_Start_IT(&htim6);
HAL_TIM_Base_Start_IT(&htim8);
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
lcd_pro();
key_pro();
rx_pro();
led_pro();
}
/* USER CODE END 3 */
}
这套模拟题比较简单,看不懂的地方可以发在评论区,需要源码的可以私