题目
这套题也是有点麻烦,之前一直做不到稳定满分(相同代码测评分数有差异),问题应该是定时问题,这套题有5秒熄灭,3秒led点亮,之前的写法不好,这几天看了几个新的写法修改了一下,也是稳定满分了。
CubeMX配置
引脚配置
ADC配置
这题使用的还是R37,和之前一样的配置PB15,这里就不多说了
定时器配置
这里我使用了TIM2,TIM4,TIM6,TIM8,和之前一样TIM2_CH2用于PA1的PWM脉冲输出,TIM4用于按键中断,TIM6和TIM8用于计时,代码中只用了TIM6来计时数据界面5秒息屏,LD3的3秒点亮这里我们使用滴答定时器比较简单。
串口配置
串口配置没什么难的地方,注意的是一定要根据题目要求修改波特率和开启NVIC
代码实现
中断回调函数
我们每次的中断回调函数都是差不多的,所以每次做题目可以优先写interrupt部分
//中断回调函数
#include "interrupt.h"
#include "usart.h"
struct keys key[4]={0,0,0,0};
int time1=0,time2=0,time1_flag=0;
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;
}
}
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++;
}
if(htim->Instance==TIM8){
time2++;
}
}
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 "adc.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "interrupt.h"
#include "string.h"
#include "stdio.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
extern struct keys key[4];
extern int time1,time2; //定时器6和定时器8
extern double ccr1;
extern int frq1;
extern char rxdata[30];
extern int rx_pointer;
extern uint8_t rxda;;
double temp=0; //温度
int view=0; //界面
char text[20];
char mode[5]="Auto"; //模式(初始为自动)
int gear=1; //挡位
int pa1_duty; //PA1的占空比
int rxled_time=0; //LD4计时
unsigned char led=0x00;
int rx_flag=0; //串口接收标志
extern __IO uint32_t uwTick;
/* 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){ //LED
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_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
double getADC(ADC_HandleTypeDef *pin){ //ADC
unsigned int adc;
HAL_ADC_Start(pin);
adc = HAL_ADC_GetValue(pin);
return adc *3.3/4096;
}
void tem_mea(void){ //温度测量
if(getADC(&hadc2)>3)
temp = 40;
if(getADC(&hadc2)<1)
temp = 0;
if(getADC(&hadc2)>=1&&getADC(&hadc2)<=3)
temp = getADC(&hadc2)*10+10;
if(strcmp(mode,"Auto")==0){ //在自动模式中,挡位随温度切换
if(temp<25)
gear=1;
if(temp>30)
gear=3;
if(temp>=25&&temp<=30)
gear=2;
}
}
void lcd_pro(void){
//数据界面
if(view==0){
LCD_DisplayStringLine(Line1, (unsigned char *)" DATA");
sprintf(text," TEMP:%.1f",temp);
LCD_DisplayStringLine(Line3, (unsigned char *)text);
sprintf(text," MODE:%.5s",mode);
LCD_DisplayStringLine(Line4, (unsigned char *)text);
sprintf(text," GEAR:%d",gear);
LCD_DisplayStringLine(Line5, (unsigned char *)text);
}
//睡眠界面
if(view==1){
LCD_DisplayStringLine(Line4, (unsigned char *)" SLEEPING");
sprintf(text," TEMP:%.1f",temp);
LCD_DisplayStringLine(Line5, (unsigned char *)text);
}
}
void key_pro(void){
if(view==0){//数据界面
//数据界面计时(无按键动作和串口接收5s后切换为睡眠界面)
HAL_TIM_Base_Start_IT(&htim6);
if(strcmp(mode,"Auto")==0)
{
if(key[0].single_flag==1){//切换手动模式
strcpy(mode, "Manu");
key[0].single_flag=0;
}
key[1].single_flag=0;
key[2].single_flag=0;
}
if(strcmp(mode,"Manu")==0)
{
if(key[0].single_flag==1){//切换自动模式
strcpy(mode, "Auto");
key[0].single_flag=0;
}
if(key[1].single_flag==1){//B2手动加档
gear+=1;
if(gear>3)
gear=3;
key[1].single_flag=0;
}
if(key[2].single_flag==1){//B3手动减档
gear-=1;
if(gear<1)
gear=1;
key[2].single_flag=0;
}
}
}
if(view==1)//睡眠界面
{
//任意按键唤醒
if(key[0].single_flag==1||key[1].single_flag==1||key[2].single_flag==1){
LCD_Clear(Black);
view=0;
key[0].single_flag=0;
key[1].single_flag=0;
key[2].single_flag=0;
}
}
//无按键动作和串口接收5s后切换为睡眠界面
if(time1>=500)
{
if(view==0&&key[0].key_sta==1&&key[1].key_sta==1&&key[2].key_sta==1&&rx_flag==0)
{
LCD_Clear(Black);
view=1;
time1=0;
HAL_TIM_Base_Stop_IT(&htim6);
}
}
//在5s内按键和串口有动作停止计时
if(time1<500)
{
if(key[0].key_sta==0||key[1].key_sta==0||key[2].key_sta==0||rx_flag==1)
{
time1=0;
HAL_TIM_Base_Stop_IT(&htim6);
}
}
}
void uart_rx(void){
if(rx_pointer>0)
{
rx_flag=1; //串口接收标志位
uwTick = rxled_time;
if(rx_pointer==2)
{
if(view==0)//数据界面
{
//接收B1
if(strcmp(rxdata,"B1")==0){
key[0].single_flag=1;
}
//B2
if(strcmp(rxdata,"B2")==0){
key[1].single_flag=1;
}
//B3
if(strcmp(rxdata,"B3")==0){
key[2].single_flag=1;
}
//如果不是B1、B2、B3 发送NULL
else if(strcmp(rxdata,"B1")!=0&&strcmp(rxdata,"B2")!=0&&strcmp(rxdata,"B3")!=0)
{
sprintf(text,"NULL");
HAL_UART_Transmit(&huart1,(uint8_t *)text,strlen(text),50);
}
}
if(view==1)//睡眠界面
{
//B1、B2、B3唤醒
if(strcmp(rxdata,"B1")==0||strcmp(rxdata,"B2")==0||strcmp(rxdata,"B3")==0)
{
LCD_Clear(Black);
view=0;
}
//如果不是B1、B2、B3 发送NULL
else
{
sprintf(text,"NULL");
HAL_UART_Transmit(&huart1,(uint8_t *)text,strlen(text),50);
}
}
}
//如果不是rx_pointer不等于2发送NULL
else
{
sprintf(text,"NULL");
HAL_UART_Transmit(&huart1,(uint8_t *)text,strlen(text),50);
}
}
rx_pointer=0;
memset(rxdata,0,30);
}
void pwm_pro(void){
if(gear==1){
pa1_duty = htim2.Init.Period;
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,pa1_duty*0.1);
}
if(gear==2){
pa1_duty = htim2.Init.Period;
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,pa1_duty*0.4);
}
if(gear==3){
pa1_duty = htim2.Init.Period;
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,pa1_duty*0.8);
}
}
void led_pro(void){
if(gear==1)
led |= 0x01;
else
led &= ~0x01;
if(gear==2)
led |= 0x02;
else
led &= ~0x02;
if(gear==3)
led |= 0x04;
else
led &= ~0x04;
if(strcmp(mode,"Auto")==0)
led |= 0x80;
else
led &= ~0x80;
if(uwTick-rxled_time<3000)
{
led |= 0x08;
rx_flag=0;
}
else
led &= ~0x08;
led_disp(led);
}
/* 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_USART1_UART_Init();
MX_TIM6_Init();
MX_TIM4_Init();
MX_TIM8_Init();
MX_TIM7_Init();
/* USER CODE BEGIN 2 */
LCD_Init();
led_disp(led);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
HAL_TIM_Base_Start_IT(&htim4);
HAL_UART_Receive_IT(&huart1,&rxda,1);
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,pa1_duty);
uwTick=3000;
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
uart_rx();
tem_mea();
key_pro();
lcd_pro();
led_pro();
pwm_pro();
}
/* USER CODE END 3 */
}