蓝桥杯嵌入式2021第十二届省赛真题解答

1 题目分析

使用到的外设:LED、LCD、按键、串口、TIM(PWM)。

 

 

2 Cubemx配置

外设具体方法参考我写的其他文章

配置完成如下:

时钟树配置如下: 

 

 3 文件移植

 

其中灯和按键程序自己添加 

添加到项目中

 先编译,左边会显示出添加的文件

 

 添加头文后再编译一下,确保头文件和.c文件都被正确引用

4 代码

所有的外设配置Cubemx都配置好了,无需自己配置(巨省工作量)

下面介绍自己添加的部分

4.1 led和Key部分

头文件 ledAndKey.h

#include "main.h"
void Led_Disp(unsigned char c);
unsigned char Key_Scan(void);

.c文件

#include "ledAndKey.h"
 
//灯
void Led_Disp(unsigned char c)
{
	//全部熄灭
	  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
                          |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_SET);
	  HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
	  HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
	//点亮对应位
	  HAL_GPIO_WritePin(GPIOC, c<<8, GPIO_PIN_RESET);
	  HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
	  HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}
 
//按键扫描
unsigned char Key_Scan(void)
{
	unsigned char c;
	if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==GPIO_PIN_RESET)
	{
		c = 1;
	}
	else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==GPIO_PIN_RESET)
	{
		c = 2;
	}
	else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==GPIO_PIN_RESET)
	{
		c = 3;
	}
	else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET)
	{
		c = 4;
	}
	
	return c;
}

4.4 主函数部分

#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include "ledAndKey.h"
#include <stdio.h>
#include "lcd.h"


void SystemClock_Config(void);
void keyPro(void);
void lcdPro(void);
void ledPro(void);

//dida
__IO uint32_t uwtick_Key,uwtick_Lcd,uwtick_Led,uwtick_rx_it;

//key
unsigned char Key_Value,Key_Old,Key_Up,Key_Dowm;

//led
unsigned char LED_Value;

//uart
unsigned char str[20];
unsigned char uart_rx_it[1];
unsigned char uart_rx[25];
unsigned char uart_tx[25];
unsigned char uart_index = 0;

unsigned char car[8][1+22];//8辆车的信息  空闲标志
unsigned char car_flag = 0;  //查询车牌索引

//user
unsigned char CNBR = 0;
unsigned char VNBR = 0;
unsigned char IDLE = 8;
double free_CNBR = 3.5;
double free_VNBR = 2;
unsigned char page = 1;
unsigned char pwm_flag = 0;

unsigned char time;
double free;
unsigned char error_flag;


int main(void)
{

  HAL_Init();
  SystemClock_Config();
	LCD_Init();

  MX_GPIO_Init();
  MX_TIM17_Init();
  MX_USART1_UART_Init();

	HAL_UART_Receive_IT(&huart1,uart_rx_it,1);
	HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);
	__HAL_TIM_SET_COMPARE(&htim17,TIM_CHANNEL_1,0);
	
	LCD_Clear(Black);
	LCD_SetBackColor(Black);
	LCD_SetTextColor(White);
	Led_Disp(0);
	
  while (1)
  {
		 keyPro();
		 lcdPro();
		 ledPro();
  }
}
void lcdPro(void)
{
	if(uwTick - uwtick_Lcd<50) return;
	uwtick_Lcd = uwTick;
	if(page == 1)
	{
		sprintf((char *)str,"       DATA ");			
		LCD_DisplayStringLine(Line1,str);	
		
		sprintf((char *)str,"   CNBR:%d ",CNBR);			
		LCD_DisplayStringLine(Line3,str);	
	
		sprintf((char *)str,"   VNBR:%d ",VNBR);			
		LCD_DisplayStringLine(Line5,str);	
		
		sprintf((char *)str,"   IDLE:%d ",IDLE);			
		LCD_DisplayStringLine(Line7,str);	
	}
	else
	{
		sprintf((char *)str,"       PARA ");			
		LCD_DisplayStringLine(Line1,str);		

		sprintf((char *)str,"   CNBR:%4.2f ",free_CNBR);			
		LCD_DisplayStringLine(Line3,str);	
	
		sprintf((char *)str,"   VNBR:%4.2f ",free_VNBR);			
		LCD_DisplayStringLine(Line5,str);					
	}
	
	
	
	sprintf((char *)str,"%d ",uart_index);			
	LCD_DisplayStringLine(Line8,str);	
	sprintf((char *)str,"TEST ");			
	LCD_DisplayStringLine(Line9,str);
		
}

void keyPro(void)
{
	if(uwTick - uwtick_Key<50) return;
	uwtick_Key = uwTick;
	
	Key_Value = Key_Scan();
	Key_Dowm = Key_Value&(Key_Value^Key_Old);
	Key_Up = ~Key_Value&(Key_Value^Key_Old);
	Key_Old = Key_Value;
	
	if(Key_Dowm == 1)
	{
		LCD_Clear(Black);
		if(page == 1)
		{
			page = 2;
		}
		else
		{
			page = 1;
		}
	}
	else if(Key_Dowm == 2)
	{
		if(page == 2)
		{
			free_CNBR += 0.5;
			free_VNBR += 0.5;	
		}
	}
	else if(Key_Dowm == 3)
	{
		if(page == 2)
		{
			if(free_CNBR>=0.5)
			{
				free_CNBR -= 0.5;
			}
			else
			{
				free_CNBR = 0;
			}
			if(free_VNBR>=0.5)
			{
				free_VNBR -= 0.5;
			}
			else
			{
				free_VNBR = 0;
			}
		}
	}
	else if(Key_Dowm == 4)
	{
		if(pwm_flag == 0)
		{		
			pwm_flag = 1;
		}
		else
		{
			pwm_flag = 0;
		}
	}
	
}
void ledPro(void)
{
	if(uwTick - uwtick_Led<100) return;
	uwtick_Led = uwTick;
	
	LED_Value = 0;
	if(pwm_flag == 0)
	{
		__HAL_TIM_SET_COMPARE(&htim17,TIM_CHANNEL_1,0);
		LED_Value&=0xfd;
	}
	else
	{
		__HAL_TIM_SET_COMPARE(&htim17,TIM_CHANNEL_1,100);
		LED_Value|=0x2;
	}
	//Led_Disp(LED_Value);
	
	//接受超时
	if(uwTick - uwtick_rx_it > 200)
	{
		if((error_flag == 1||uart_index<22)&&uart_index!=0)
		{
					sprintf((char *)uart_tx,"Error\r\n");
					HAL_UART_Transmit(&huart1,uart_tx,strlen((char *)uart_tx),50);			
		}
		uart_index = 0;
	}
}

//接受中断  
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{

	if((uart_rx_it[0] == 'V'||uart_rx_it[0] == 'C')&&uart_index == 0)
	{
		uart_index = 1; //数据头有效 ,开始接受后面的数据
		uart_rx[0] = uart_rx_it[0];
		uwtick_rx_it = uwTick;//开始计时
	}
	else if(uart_index != 0)
	{
		uart_rx[uart_index] = uart_rx_it[0];
		uart_index++;
		if(uart_index >= 22) //到达数据尾,解析数据
		{				

			if(uart_rx[9] == ':'&&uart_rx[4]==':') //有效数据
			{
				car_flag = 0;
				//对比车牌信息
				for(int i = 0;i<8;i++)
				{
					if(car[i][0]!=0)//此i坑有车
					{
						if(uart_rx[0]==car[i][1]&&uart_rx[5]==car[i][6]&&uart_rx[6]==car[i][7]&&uart_rx[7]==car[i][8]&&uart_rx[8]==car[i][9]) //车牌一样
						{
							car_flag = i;  //坑位值赋给car_flag
						}
					}
				}
				//判断执行
				if(car_flag == 0&&IDLE != 0) //说明没车匹配,且有空位,进场
				{
					for(int j = 0;j<8;j++)
					{
						if(car[j][0]==0&&car_flag == 0)//找到第一个空位
						{
							car_flag = j;  //第j个
						}
					}
					//存数据
					car[car_flag][0] = 1; //标志位
					for(int k = 0;k<22;k++)
					{
						car[car_flag][k+1] = uart_rx[k];  //存入时间
					}			
						if(car[car_flag][1] == 'C')
							CNBR ++;
						else
							VNBR++;
						IDLE--;					
				}
				else  //出场(数组第car_flag个)
				{
					car[car_flag][0] = 0;//清除标志位
					//计算费用
					time = uart_rx[16]*10+uart_rx[17]-car[car_flag][17]*10-car[car_flag][18];//小时
					if(uart_rx[18]*10+uart_rx[19] - car[car_flag][19]*10-car[car_flag][20]>0) //判断分
					{
						time+=1;
					}
					else
					{
						if(uart_rx[20]*10+uart_rx[21] - car[car_flag][21]*10-car[car_flag][22]>0)
						{
							time+=1;
						}									
					}
					if(car[car_flag][1] == 'C')
						free = time*free_CNBR;
					else
						free = time*free_VNBR;
					sprintf((char *)uart_tx,"%cNBR:%c%c%c%c:%02d:%5.2f\r\n",car[car_flag][1],car[car_flag][6],car[car_flag][7],car[car_flag][8],car[car_flag][9],time,free);
					HAL_UART_Transmit(&huart1,uart_tx,strlen((char *)uart_tx),50);
					if(car[car_flag][1] == 'C')
						CNBR --;
					else
						VNBR--;
					IDLE++;				
				}	
			}
			else  //数据有误
			{
				uart_index = 0;
				error_flag = 1;
			}
		}
	}
	HAL_UART_Receive_IT(&huart1,uart_rx_it,1);	
}

void SystemClock_Config(void)
{
 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {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();
  }
  /** Initializes the peripherals clocks
  */
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_USART1;
  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV32;

  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}



  • 16
    点赞
  • 94
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值