蓝桥杯嵌入式第十五届模拟二

题目

这套题也是有点麻烦,之前一直做不到稳定满分(相同代码测评分数有差异),问题应该是定时问题,这套题有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>&copy; 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 */
}

  • 26
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 33
    评论
评论 33
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值