蓝桥杯嵌入式2015年第六届省赛主观题解析

1 题目

2 解析

cpp 复制代码
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "rtc.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "lcd.h"
#include "stdio.h"
#include "string.h"
#include "i2c_hal.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
RTC_TimeTypeDef sTime;//直接从rtc.c中复制
RTC_DateTypeDef sDate;
char buf[20],buf1[20],buf2[20];//给LCD打印的每行内容存到一个buf里
int hour,min,second;//从串口接收到的上报电压的时间
double k=0.1;
double val;//测得的电位器电压
struct keys{
	int step;
	int state;
}key[4];//按键
int cnt1,cnt2,cnt3,cnt4;记录每个按键按下的次数
int num=1;//LCD展示的页序号
/* 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 */
void LED_Close()//初始时把所有LED熄灭
{
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
uint8_t EEPROM_Read(uint8_t addr)//EEPROM读写函数(固定模板)
{
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(addr);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0xa1);
	I2CWaitAck();
	uint8_t val=I2CReceiveByte();
	I2CWaitAck();
	I2CStop();
	return val;
}
void EEPROM_Write(uint8_t addr,uint8_t info)
{
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(addr);
	I2CWaitAck();
	I2CSendByte(info);
	I2CWaitAck();
	I2CStop();
}
double getADC()//测量电位器电压
{
	HAL_ADC_Start(&hadc2);
	val=HAL_ADC_GetValue(&hadc2)*3.3/4096;
	return val;
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance==TIM8)//给RTC设定一个1s的回调函数,隔一秒打印一次(这里也可以用闹钟中断)
	{
		HAL_RTC_GetTime(&hrtc,&sTime,RTC_FORMAT_BIN);//先获取时间,再获取日期
		HAL_RTC_GetDate(&hrtc,&sDate,RTC_FORMAT_BIN);
		getADC();//测量电压需要时间,先测量出电压
		if(num==1)
		{
			LCD_ClearLine(Line2);
			LCD_ClearLine(Line6);
			LCD_DisplayStringLine(Line6,(uint8_t*)buf2);
			sprintf(buf,"   T:%02d-%02d-%02d",sTime.Hours,sTime.Minutes,sTime.Seconds);
			LCD_ClearLine(Line7);
			LCD_DisplayStringLine(Line7,(uint8_t*)buf);//打印RTC时间
			sprintf(buf,"   V1:%.2lfV",val);
			LCD_ClearLine(Line4);
			LCD_DisplayStringLine(Line4,(uint8_t*)buf);//打印电压值
			sprintf(buf,"   k:%.1lf",k);
			LCD_ClearLine(Line5);
			LCD_DisplayStringLine(Line5,(uint8_t*)buf);//打印k值
		}
		if(hour==sTime.Hours&&min==sTime.Minutes&&second==sTime.Seconds)//如果RTC时间和设定上报电压时间相同,则按照格式上报电压
		{
			sprintf(buf,"%.2lf+%.1lf+%02d%02d%02d\r\n",val,(double)EEPROM_Read(0x10)/10,hour,min,second);
			HAL_UART_Transmit_DMA(&huart1,(uint8_t*)buf,strlen(buf));//串口发送
		}
	}
	if(htim->Instance==TIM1)//间隔0.2s切换LED电平(电压满足条件+监测处于ON状态)
	{
		if(val>(double)EEPROM_Read(0x10)/10*3.3&&buf2[8]=='N')
		{
			HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
			HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_8);
			HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
		}
		else
		{
			HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_SET);
			HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
		}
	}
	if(htim->Instance==TIM3)//给按键设定一个10ms中断回调函数
	{
		key[0].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
		key[1].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
		key[2].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
		key[3].state=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
		for(int i=0;i<4;i++)
		{
			switch(key[i].step)
			{
				case 0:
				{
					if(key[i].state==GPIO_PIN_RESET)
					{
						key[i].step=1;
					}
				}
				break;
				case 1:
				{
					if(key[i].state==GPIO_PIN_RESET)
					{
						if(i==0)
						{
							if(++cnt1%2==0)//cnt1是偶数,监测ON(默认监测打开);cnt1是奇数,监测OFF
							{
								sprintf(buf2,"   LED:ON");
								if(num==1)//这是在页面1显示的内容
								{
									LCD_ClearLine(Line6);
									LCD_DisplayStringLine(Line6,(uint8_t*)buf2);
								}
							}
							else
							{
								/*HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
								HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_SET);
								HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);*/
								sprintf(buf2,"   LED:OFF");
								if(num==1)
								{
									LCD_ClearLine(Line6);
									LCD_DisplayStringLine(Line6,(uint8_t*)buf2);
								}
							}
						}
						if(i==1)
						{
							if(++cnt2%2==1)//设定上报时间的页面是页面2
							{
								num=2;
								LCD_Clear(White);
								LCD_DisplayStringLine(Line2,(uint8_t*)"      Setting      ");
								sprintf(buf,"    %02d-%02d-%02d    ",hour,min,second);
								LCD_DisplayStringLine(Line5,(uint8_t*)buf);
							}
							else
							{
								num=1;
							}
							cnt3=0;
						}
						if(i==2&&num==2)//只有在页面2时按键PB3才计入,抗干扰
						{
							cnt3++;
						}
						if(i==3&&num==2)//只有在页面2时按键PA0才计入,抗干扰
						{
							if(cnt3%3==0)//进入Setting页面默认调整时
							{
								hour++;
								if(hour==24) hour=0;
								LCD_ClearLine(Line5);
								sprintf(buf,"    %02d-%02d-%02d    ",hour,min,second);
								LCD_DisplayStringLine(Line5,(uint8_t*)buf);
							}
							if(cnt3%3==1)//按一次为分
							{
								min++;
								if(min==60) min=0;
								LCD_ClearLine(Line5);
								sprintf(buf,"    %02d-%02d-%02d    ",hour,min,second);
								LCD_DisplayStringLine(Line5,(uint8_t*)buf);
							}
							if(cnt3%3==2)//按两次为秒
							{
								second++;
								if(second==60) second=0;
								LCD_ClearLine(Line5);
								sprintf(buf,"    %02d-%02d-%02d    ",hour,min,second);
								LCD_DisplayStringLine(Line5,(uint8_t*)buf);
							}
						}
						key[i].step=2;
					}
					else
					{
						key[i].step=0;
					}
				}
				break;
				case 2:
				{
					if(key[i].state==GPIO_PIN_SET)
					{
						key[i].step=0;
					}
				}
				break;
			}
		}
	}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)//串口中断回调函数,接收到一次上报电压的数据就回复一次ok
	{
		sscanf(buf1,"k%lf\r\n",&k);
		EEPROM_Write(0x10,(uint8_t)(10*k));
		HAL_UART_Transmit_DMA(&huart1,(uint8_t*)"ok\r\n",4);
		HAL_UART_Receive_DMA(&huart1,(uint8_t*)buf1,6);
	}
}
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* 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_DMA_Init();
  MX_RTC_Init();
  MX_TIM1_Init();
  MX_TIM8_Init();
  MX_USART1_UART_Init();
  MX_ADC2_Init();
  MX_TIM3_Init();
  /* USER CODE BEGIN 2 */
	I2CInit();
	HAL_TIM_Base_Start_IT(&htim8);
	HAL_TIM_Base_Start_IT(&htim1);
	HAL_TIM_Base_Start_IT(&htim3);
	LCD_Init();
	LED_Close();
	LCD_Clear(White);
	LCD_SetBackColor(White);
	LCD_SetTextColor(Black);
	
	if(EEPROM_Read(0x99)!=2)//监测板子是不是第一次上电
	{
		EEPROM_Write(0x99,2);
		HAL_Delay(20);
		EEPROM_Write(0x10,1);
	}
	HAL_UART_Receive_DMA(&huart1,(uint8_t*)buf1,6);
	sprintf(buf2,"   LED:ON");
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		
		
  }
  /* USER CODE END 3 */
}
相关推荐
Wallace Zhang32 分钟前
STM32F103_Bootloader程序开发11 - 实现 App 安全跳转至 Bootloader
stm32·嵌入式硬件·安全
GodKK老神灭36 分钟前
STM32 CCR寄存器
stm32·单片机·嵌入式硬件
杰克逊的日记9 天前
MCU编程
单片机·嵌入式硬件
Python小老六9 天前
单片机测ntc热敏电阻的几种方法(软件)
数据库·单片机·嵌入式硬件
懒惰的bit9 天前
STM32F103C8T6 学习笔记摘要(四)
笔记·stm32·学习
HX科技9 天前
STM32给FPGA的外挂FLASH进行升级
stm32·嵌入式硬件·fpga开发·flash·fpga升级
Li Zi10 天前
STM32 ADC(DMA)双缓冲采集+串口USART(DMA)直接传输12位原始数据到上位机显示并保存WAV格式音频文件 收藏住绝对实用!!!
经验分享·stm32·单片机·嵌入式硬件
damo王10 天前
Zephyr 系统深入解析:SoC 支持包结构与中断调度器调优实践
单片机·嵌入式硬件·zephyr
逼子格10 天前
硬件工程师笔试面试高频考点汇总——(2025版)
单片机·嵌入式硬件·面试·硬件工程·硬件工程师·硬件工程师真题·硬件工程师面试
循环过三天10 天前
1.2、CAN总线帧格式
笔记·stm32·单片机·嵌入式硬件·学习