蓝桥杯嵌入式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 */
}
相关推荐
[J] 一坚6 小时前
嵌入式高手C
c语言·开发语言·stm32·单片机·mcu·51单片机·iot
FreakStudio6 小时前
和做工厂系统的印尼老哥,复刻了一套属于 MicroPython 的包管理系统
python·单片机·嵌入式·大学生·面向对象·并行计算·电子diy·电子计算机
HIZYUAN7 小时前
AG32 MCU Reference Manual(202401008修订版)使用手册
单片机·嵌入式硬件
guygg888 小时前
STM32 汉字显示程序(标准外设库版本)
stm32·单片机·嵌入式硬件
7yewh13 小时前
电阻应变片的深度探究
嵌入式
国科安芯14 小时前
商业航天与航空安全场景下抗辐射 MCU 选型、应用实践及发展趋势
单片机·嵌入式硬件·无人机·cocos2d·risc-v
CinzWS15 小时前
A53低功耗验证:状态机验证与唤醒时序检查——芯片的“睡眠科学“
嵌入式·芯片验证·原型验证·a53
Jun62616 小时前
【STM32】HMC5883驱动(带航向角计算)
stm32·单片机·嵌入式硬件
wearegogog12317 小时前
基于STM32的酒精检测仪设计
stm32·单片机·嵌入式硬件
Deitymoon17 小时前
STM32——led灯点亮
stm32·单片机·嵌入式硬件