蓝桥杯嵌入式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 */
}
相关推荐
v先v关v住v获v取5 分钟前
模块机器人逆向设计cad5张+三维图+设计说明书
科技·单片机·51单片机
SystickInt5 分钟前
上电复位、掉电复位MOS管
单片机·嵌入式硬件
Arciab7 分钟前
51单片机__LED相关
单片机·嵌入式硬件·51单片机
码咔吧咔13 分钟前
STM32 系列 MCU 常见接口类型
stm32·嵌入式硬件
点灯小铭13 分钟前
基于单片机的智慧校园自动打铃系统设计
数据库·单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
点灯小铭8 小时前
基于单片机的多路热电偶温度监测与报警器
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
tianyue10013 小时前
STM32G431 ADC 多个channel 采集
stm32·单片机·嵌入式硬件
切糕师学AI14 小时前
NuttX RTOS是什么?
嵌入式·rtos
清风66666614 小时前
基于单片机的水泵效率温差法测量与报警系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
z203483152016 小时前
定时器练习报告
单片机·嵌入式硬件