蓝桥杯嵌入式第六届省赛题目

前言

本次进行蓝桥杯第六届程序编写,本人水平有限,若能提出一些建议可以留言或者私信

一.阅读题目

本届题运用到了串口,eeprom,led闪烁,按键检测,adc转换,RTC实时时钟

led闪烁以及按键检测采用定时器检测,题目如下

看完题有了大体思路,这套题整体来说不是非常的麻烦,比较常规的一道题,题目尚未要求选择时分秒时是否要突出显示,则博主为更好的显示,添加选择时有闪烁突出显示

二.用cubomx进行底层配置

使用TIM2,TIM3定时器进行按键检测,定时时间都为10ms,串口使用pa9和pa10,使用其他引脚需要单独引出转usb与电脑通信

具体cubomx的配置如图所示

三.进行程序编写

本次编写出现了几个细节问题本人的处理方案如下:

本次因为at24c02代码写的时候返回值为int则,存储的时候存入的时k的十倍,读取时除十就好。

问题1:由于题目说初始值为0.1,初始状态at24c02中没有数,则博主在这里用at24c02中第一位作为存储标志,当第一次存储进去的时候,c02的1位也会存储一个数,后面程序进行判断如果1位是相应的数则再进行k值的读取,如果没有的话,那k值就为0.1。

问题2:本题目要求当到达上报时间时就要通过串口进行传输相应文案,但上报时间与RTC时间相等的时间为一秒,串口会发送很多次,所以博主定义一个标志位当发送一次后标志位置1。

注意1:lcd进行界面切换时需要clear一下,由于他是局部刷新则会有上一界面的遗留。

注意2:按键进行操作的时候,每次判断需要手动标志位清零。

注意3:题目尚未要求b4按键具体怎么加减,则博主直接定义为加,加到最大归零。

#include "main.h"
#include "adc.h"
#include "rtc.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "i2c_hal.h"
#include "lcd.h"
#include "M24C02.h"
#include "my_ad.h"
#include "my_lcdshow.h"
#include "interrupt.h"
#include "string.h"
#include "stdbool.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

#define VDD 3.3 //题目VDD宏定义

extern struct key Key_structure[4];
extern char uart_rx[20];
extern unsigned char dat;
extern unsigned char index_rx;

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
RTC_TimeTypeDef my_clocktime;//RTC时钟接收时间结构体
RTC_DateTypeDef my_clockdata;//RTC时钟接收日期结构体
/*LCD显示结构体*/
struct lcd_show{
	char lcd_line1[20];
	char lcd_line2[20];
	char lcd_line3[20];
	char lcd_line4[20];
}lcd_showstructure = {0,0,0,0};

/*设置上报时间结构体*/
struct time_setting{
	unsigned char hour;
	unsigned char min;
	unsigned char sec;
}time_settingstruct = {0,0,0};

double adc_value = 0;//接收adc转换变量
unsigned char led_state = 0;//控制led是否满足闪烁条件变量
bool led_key_state = 0;//开关led闪烁功能变量
float k = 0.1;//题目k值
unsigned char tx_state = 0;//防止串口一次多发变量
unsigned char lcd_state = 0;//控制lcd显示界面变量
unsigned char choose_value = 1;//设置界面选择时分秒变量

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

void lcd_showvalue();//lcd界面显示参数函数
void value_handle();//题目数值处理函数
void uart_autosend();//串口自动发送函数
void lcd_showsetting();//lcd界面显示设置函数
void rx_handle();//串口发送处理函数
/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
/******************************
*功能:串口发送处理函数
*参数:无
******************************/
void rx_handle()
{
	char send_ok[5] = {0};
	sprintf((char*)send_ok,"OK\r\n");
	if (index_rx)
	{
		if (index_rx == 4){		
			sscanf(uart_rx,"k%f",&k);
			if (k < 0.9 && k > 0.1){
				M24C02_write(0,k * 10);
				M24C02_write(1,55);
				HAL_UART_Transmit(&huart1,(unsigned char *)send_ok,strlen(send_ok),50);
			}
			index_rx = 0;
		}
	}
}

/******************************
*功能:lcd界面显示设置函数
*参数:无
******************************/
void lcd_showsetting()
{
	sprintf((char *)lcd_showstructure.lcd_line1,"       Setting    ");
	LCD_DisplayStringLine(Line2,(unsigned char*)lcd_showstructure.lcd_line1);
	/*进行闪烁*/
	switch (choose_value){
		case 1:{
			sprintf((char *)lcd_showstructure.lcd_line2,"    %02d - %02d - %02d",time_settingstruct.hour,
				time_settingstruct.min,time_settingstruct.sec);
			LCD_DisplayStringLine(Line5,(unsigned char*)lcd_showstructure.lcd_line2);
			HAL_Delay(200);
			sprintf((char *)lcd_showstructure.lcd_line2,"       - %02d - %02d",time_settingstruct.min,time_settingstruct.sec);
			LCD_DisplayStringLine(Line5,(unsigned char*)lcd_showstructure.lcd_line2);
			HAL_Delay(200);
			break;
		}
		case 2:{
			sprintf((char *)lcd_showstructure.lcd_line2,"    %02d - %02d - %02d",time_settingstruct.hour,
				time_settingstruct.min,time_settingstruct.sec);
			LCD_DisplayStringLine(Line5,(unsigned char*)lcd_showstructure.lcd_line2);
			HAL_Delay(200);
			sprintf((char *)lcd_showstructure.lcd_line2,"    %02d -    - %02d",time_settingstruct.hour,time_settingstruct.sec);
			LCD_DisplayStringLine(Line5,(unsigned char*)lcd_showstructure.lcd_line2);
			HAL_Delay(200);
			break;
		}
		case 3:{
			sprintf((char *)lcd_showstructure.lcd_line2,"    %02d - %02d - %02d",time_settingstruct.hour,
				time_settingstruct.min,time_settingstruct.sec);
			LCD_DisplayStringLine(Line5,(unsigned char*)lcd_showstructure.lcd_line2);
			HAL_Delay(200);
			sprintf((char *)lcd_showstructure.lcd_line2,"    %02d - %02d -   ",time_settingstruct.hour,time_settingstruct.min);
			LCD_DisplayStringLine(Line5,(unsigned char*)lcd_showstructure.lcd_line2);
			HAL_Delay(200);
			break;
		}
	}
	/*end*/
}
/******************************
*功能:串口自动发送函数
*参数:无
******************************/
void uart_autosend()
{
	char tx_send[20] = {0};
	sprintf(tx_send,"%.2f+%.1f+%02d%02d%02d\r\n",adc_value,k,my_clocktime.Hours,
	my_clocktime.Minutes,my_clocktime.Seconds);
	HAL_UART_Transmit(&huart1,(unsigned char *)tx_send,strlen(tx_send),50);
	tx_state = 1;
}

/******************************
*功能:题目数值处理函数
*参数:无
******************************/
void value_handle()
{
	unsigned char state = 0;
	state = M24C02_read(1);
	if (state != 55)
		k = 0.1;
	else
		k = (float)M24C02_read(0) / 10;
	HAL_RTC_GetTime(&hrtc,&my_clocktime,RTC_FORMAT_BIN);
	HAL_RTC_GetDate(&hrtc,&my_clockdata,RTC_FORMAT_BIN);
	adc_value = adc_get(&hadc2);
	if (adc_value > (VDD * k))
		led_state = 1;
	else led_state = 0;
	if (my_clocktime.Hours == time_settingstruct.hour && 
	my_clocktime.Minutes == time_settingstruct.min &&
	my_clocktime.Seconds == time_settingstruct.sec){
		if (!tx_state)//防止一次多发
			uart_autosend();
	}
	else tx_state = 0;
}

/******************************
*功能:lcd界面显示设置函数
*参数:无
******************************/
void lcd_showvalue()
{
	value_handle();
	sprintf((char *)lcd_showstructure.lcd_line1,"  V1:%.2f",adc_value);
	sprintf((char *)lcd_showstructure.lcd_line2,"  k:%.1f", k);
	if (!led_key_state)
		sprintf((char *)lcd_showstructure.lcd_line3,"  LED:OFF");
	else
		sprintf((char *)lcd_showstructure.lcd_line3,"  LED:ON ");
	sprintf((char *)lcd_showstructure.lcd_line4,"  T:%02d-%02d-%02d",my_clocktime.Hours,
		my_clocktime.Minutes,my_clocktime.Seconds);
	LCD_DisplayStringLine(Line1, (unsigned char *)lcd_showstructure.lcd_line1);
	LCD_DisplayStringLine(Line3, (unsigned char *)lcd_showstructure.lcd_line2);
	LCD_DisplayStringLine(Line5, (unsigned char *)lcd_showstructure.lcd_line3);
	LCD_DisplayStringLine(Line7, (unsigned char *)lcd_showstructure.lcd_line4);
}
/* 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 */

/* 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_RTC_Init();
  MX_TIM1_Init();
  MX_TIM2_Init();
  MX_USART1_UART_Init();
  MX_TIM3_Init();
  /* USER CODE BEGIN 2 */
	HAL_UART_Receive_IT(&huart1,&dat,1);
	HAL_TIM_Base_Start_IT(&htim3);
	HAL_TIM_Base_Start_IT(&htim2);
	I2CInit();
	LCD_Init();
	LCD_Clear(Blue2);
	LCD_SetTextColor(Black);
	LCD_SetBackColor(Blue2);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,1);
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,1);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,0);
  /* USER CODE END 2 */

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

    /* USER CODE BEGIN 3 */
		if (!lcd_state)
			lcd_showvalue();
		rx_handle();
		if (Key_structure[0].keynum){
			HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,1);
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,1);
			HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,0);
			led_key_state = !led_key_state;
			Key_structure[0].keynum = 0;
		}
		if (Key_structure[1].keynum){
			LCD_Clear(Blue2);//防止参数界面和设置界面切换时冲突
			lcd_state = !lcd_state;
			Key_structure[1].keynum = 0;
		}
		if (lcd_state){
			lcd_showsetting();
			if (Key_structure[2].keynum){
				choose_value++;
				if (choose_value > 3)
					choose_value = 1;
				Key_structure[2].keynum = 0;
			}
			switch (choose_value){
				case 1:{
					if (Key_structure[3].keynum){
						time_settingstruct.hour++;
						if (time_settingstruct.hour >= 24)
							time_settingstruct.hour = 0;
						Key_structure[3].keynum = 0;
					}
					break;
				}
				case 2:{
					if (Key_structure[3].keynum){
						time_settingstruct.min++;
						if (time_settingstruct.min >= 60)
							time_settingstruct.min = 0;
						Key_structure[3].keynum = 0;
					}
					break;
				}
				case 3:{
					if (Key_structure[3].keynum){
						time_settingstruct.sec++;
						if (time_settingstruct.sec >= 60)
							time_settingstruct.sec = 0;
						Key_structure[3].keynum = 0;
					}
					break;
				}
			}
		}
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV3;
  RCC_OscInitStruct.PLL.PLLN = 20;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

中断函数部分

中断服务函数部分每十毫秒进行一遍按键检测,此处为了修复当在界面一的情况下触碰b3b4按键切换界面时会被误判按下了一次,则博主进行判断只有当在设置界面的时候才进行按键b3b4b的扫描,TIM3时进行led的闪烁,因为lcd的影响,如果只控制LD1的,其他的灯也会乱量,所以博主在每次进行闪烁时把PC口全部置1,然后再进行计次对LD1进行单独操作。串口接收,因为每次只能接收到一位所以,要一位一位的接收。

#include "interrupt.h"
#include "usart.h"
#include "stdio.h"
#include "string.h"

/*按键宏定义*/
#define BUTTON_B1 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);
#define BUTTON_B2 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);
#define BUTTON_B3 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2);
#define BUTTON_B4 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
/*END*/

/*LED宏定义*/
#define LD1(x) HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8,x);
#define LD_ALL(x) HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All,x);
#define LD_START(x) HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2,x);
/*END*/
/*按键结构体*/
struct key{
	uint8_t state;//按键的状态
	uint8_t keynum;//判断是否成功按下变量
	uint8_t count;//消抖变量
};
extern unsigned char lcd_state;
extern unsigned char led_state;
extern unsigned char led_key_state;
struct key Key_structure[4] = {0,0,0};//按键结构体
char uart_rx[20] = {0};//接收串口信息数组
unsigned char index_rx = 0;//串口信息数组指针
unsigned char dat = 0;//串口信息接收变量
float rx_value = 0;//串口提取有效信息返回值
unsigned int led_count = 0;//定时器计时变量
unsigned char led_count_value = 0;//led闪烁奇偶变量
/**********************************************
*功能:TIM2为按键检测,TIM3为LED闪烁计时
*参数:无
***********************************************/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if (htim->Instance == TIM2){
		Key_structure[0].state = BUTTON_B1;
		Key_structure[1].state = BUTTON_B2;
		Key_structure[2].state = BUTTON_B3;
		Key_structure[3].state = BUTTON_B4;
		if (lcd_state){
			for (uint8_t i = 0; i < 4; ++i){
				switch(Key_structure[i].count){
					case 0:{
						if (!Key_structure[i].state)
							Key_structure[i].count = 1;
						break;
					}
					case 1:{
						if (!Key_structure[i].state){
							Key_structure[i].keynum = 1;
							Key_structure[i].count = 2;
						}
						break;
					}
					case 2:{
						if (Key_structure[i].state)
							Key_structure[i].count = 0;
						break;
					}
				}
			}
		}
		else{
		for (uint8_t i = 0; i < 2; ++i){
				switch(Key_structure[i].count){
					case 0:{
						if (!Key_structure[i].state)
							Key_structure[i].count = 1;
						break;
					}
					case 1:{
						if (!Key_structure[i].state){
							Key_structure[i].keynum = 1;
							Key_structure[i].count = 2;
						}
						break;
					}
					case 2:{
						if (Key_structure[i].state)
							Key_structure[i].count = 0;
						break;
					}
				}
			}
		}
	}
	else if (htim->Instance == TIM3){
		if (led_key_state && led_state){
			led_count++;
			if (led_count >= 20){
				led_count_value++;
				LD_START(1);
				LD_ALL(1);
				if (led_count_value%2){
					LD1(1);
				}
				else
					LD1(0);
				LD_START(0);
				led_count = 0;
			}
		}
		else{
			LD_START(1);
			LD_ALL(1);
			LD_START(0);
		}
	}
}
/*串口接收*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if (huart->Instance == USART1){
		uart_rx[index_rx++] = dat;
		HAL_UART_Receive_IT(&huart1,&dat,1);
	}
}

四.总结

本次代码只展示了最重要的两个部分,adc,at24c02等等的配置尚未展出,有需要完整工程的小伙伴可以私信我。

  • 18
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值