第十届 蓝桥杯 嵌入式设计与开发项目 省赛(大学组)

硬件框图

在这里插入图片描述

CubeMX配置

1、SYS 中的 Debug 设置为 Serial Wire
在这里插入图片描述

2、RCC 中的 HSE 设置为 Crystal/Ceramic Resonator
在这里插入图片描述

3、时钟树
在这里插入图片描述
4、配置LED灯的引脚(PB8 — PB15)为推挽输出,初始化为高电平
在这里插入图片描述

5、配置PD2为输出,保证led的功能正常运行
6、LCD的引脚可以不用在CubeMX中配置,资料包里的 lcd.c 中有对相应引脚的配置
7、配置按键的引脚(PB0、PB1、PB2、PA0 —— B1、B2、B3、B4)为输入并设置为上拉
在这里插入图片描述
8、配置定时器TIM4去扫描按键
在这里插入图片描述
在这里插入图片描述

9、电压采集1 的引脚为 PB15 对应ADC2_IN15
在这里插入图片描述

keil里的一些设置

在这里插入图片描述
在这里插入图片描述

代码编写

1、创建一个文件夹bsp用于存放各模块的 .c 和 .h 文件
在这里插入图片描述
2、将创建的文件夹路径加载进 “include path” 中
在这里插入图片描述
3、新建分组,并将用到的文件引入
在这里插入图片描述

LED

#include "led.h"
uint16_t LED_Val;

//描述:关闭所有LED
void Off_LEDs(void)
{
	LED_Val |= (0xff<<8);
	GPIOC->ODR = (uint32_t)LED_Val;
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}

//描述:开启所有LED
void On_LEDs(void)
{
	LED_Val &= ~(0xff<<8);
	GPIOC->ODR = (uint32_t)LED_Val;
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}

//描述:开启指定的LED,输入的参数为(1~8)
void TurnOn_LED(uint8_t led)
{
	LED_Val &= ~(0x01<<(7+led));
	GPIOC->ODR = (uint32_t)LED_Val;
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}

//描述:关闭指定的LED,输入的参数为(1~8)
void TurnOff_LED(uint8_t led)
{
	LED_Val |= (0x01<<(7+led));
	GPIOC->ODR = (uint32_t)LED_Val;
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}

注:初始化时,要将LED灯全部关闭

Off_LEDs();

KEY

创建 interrupt.c 和 interrupt.h
interrupt.c

#include "interrupt.h"

struct key keys[4]={0,0,0,0};     //定义4个按键

// 80M/80/10000=100Hz,即10ms进入一次中断
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM4)
	{
		//分别读取4个按键的状态
		keys[0].key_sta = KB1;    
		keys[1].key_sta = KB2;
		keys[2].key_sta = KB3;
		keys[3].key_sta = KB4;
		
		for(int i=0; i<4; i++)
		{
			switch(keys[i].judge_sta)
			{
				//第一阶段:进入按键,先进行消抖
				case 0:
					if(keys[i].key_sta == 0)
					{
						keys[i].judge_sta = 1;
					}
					break;
				//第二阶段:经过消抖后,确定已经处于稳定状态	
				case 1:
					if(keys[i].key_sta == 0)
					{
						keys[i].judge_sta = 2;
					}
					else
					{
						keys[i].judge_sta = 0;
					}
					break;
				//第三阶段:等待按键被抬起,设置按键标志位	
				case 2:
					if(keys[i].key_sta == 1)
					{
						keys[i].judge_sta = 0;
						keys[i].single_flag = 1;
					}
					break;
			}
		}
	}
}

interrupt.h

#ifndef __INTERRUPT_H
#define __INTERRUPT_H

#include "main.h"
#include "stdbool.h"

//简化读取按键代码
#define KB1 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0)
#define KB2 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1)
#define KB3 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)
#define KB4 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)

struct key
{
	unsigned char judge_sta;   //判断按键处于那个阶段(消抖、稳定、抬起)
	bool key_sta;              //按键输入引脚此时的状态
	bool single_flag;          //单击按键的标志位
};

#endif

注:初始化时,要开启定时器TIM4中断

HAL_TIM_Base_Start_IT(&htim4);  //开启TIM4的时钟中断——扫描按键

LCD

将资料包里LCD例程中的 lcd.c、lcd.h、fonts.h 移植到自己项目中的 bsp
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注:初始化时,将LCD屏的初始状态设置为黑屏,黑底白字

LCD_Init();				  //初始化LCD
LCD_Clear(Black);         //将LCD清空为黑屏
LCD_SetBackColor(Black);  //背景色——黑色
LCD_SetTextColor(White);  //文字色——白色

ADC

创建bsp_adc.c 和 bsp_adc.h

#include "bsp_adc.h"

//描述:获取ADC数据
uint16_t getADC(ADC_HandleTypeDef *hadc)
{
	uint16_t adc;
	HAL_ADC_Start(hadc);
	adc = HAL_ADC_GetValue(hadc);
	return adc;
}

注:初始化时,校准ADC2

HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED);

main.c

1、定义变量

int view = 0;
int options = 0;
float max_volt = 2.4, min_volt = 1.2;
int upper_val = 1, lower_val = 2;
float adc = 0;
extern struct key keys[4];

2、在main函数的while中主要执行对 LED 灯、LCD显示屏、按键的控制,所以分别编写相应的函数

LCD显示屏控制

//LCD显示屏控制函数
void disp_proc(void)
{
	char text[30];	
	switch(view)
	{
		//Main界面
		case 0:
			memset(text,0x00,30);		
			sprintf(text,"        Main     ");
			LCD_DisplayStringLine(Line1,(uint8_t *)text);
			adc = (float)getADC(&hadc2)*3.3/4095;
			sprintf(text,"   Volt: %.2fV",adc);
			LCD_DisplayStringLine(Line3,(uint8_t *)text);
			if(adc>max_volt)
				LCD_DisplayStringLine(Line5,(unsigned char *)"  Status:Upper      ");
			else if(adc<min_volt)
				LCD_DisplayStringLine(Line5,(unsigned char *)"  Status:Lower      ");
			else
				LCD_DisplayStringLine(Line5,(unsigned char *)"  Status:Normal     ");
		break;
			
		//Setting界面
		case 1:
			memset(text,0x00,30);
			sprintf(text,"       Setting     ");
			LCD_DisplayStringLine(Line1,(uint8_t *)text);
			//对选中部分进行高亮判断
			sprintf(text,"   Max Volt: %.1fV   ",max_volt);
			if(options == 1) LCD_SetBackColor(Green);		
			LCD_DisplayStringLine(Line3,(uint8_t *)text);	
			LCD_SetBackColor(Black);
			
			sprintf(text,"   Min Volt: %.1fV   ",min_volt);
			if(options == 2) LCD_SetBackColor(Green);		
			LCD_DisplayStringLine(Line4,(uint8_t *)text);	
			LCD_SetBackColor(Black);
			
			sprintf(text,"   Upper: LD%d        ",upper_val);
			if(options == 3) LCD_SetBackColor(Green);		
			LCD_DisplayStringLine(Line5,(uint8_t *)text);	
			LCD_SetBackColor(Black);
			
			sprintf(text,"   Lower: LD%d        ",lower_val);
			if(options == 4) LCD_SetBackColor(Green);		
			LCD_DisplayStringLine(Line6,(uint8_t *)text);	
			LCD_SetBackColor(Black);
		break;
	}
}

按键控制

//按键控制函数
void key_proc(void)
{
	if(keys[0].single_flag == 1)
	{
		view++;
		if(view == 2)
			view = 0;
		keys[0].single_flag = 0;
		LCD_Clear(Black);
		options = 0;
	}
	if(view == 1)
	{		
		if(keys[1].single_flag == 1)
		{			
			options++;
			if(options == 5)
				options = 1;
			keys[1].single_flag = 0;
		}
		switch (options)
		{
			case 1:
				if(keys[2].single_flag == 1)
				{
					max_volt += 0.3;
					if(max_volt>3.3)
						max_volt = 3.3;
					keys[2].single_flag = 0;
				}
				if(keys[3].single_flag == 1)
				{
					max_volt -= 0.3;
					if(max_volt < min_volt)
						max_volt += 0.3;
					keys[3].single_flag = 0;
				}
			break;
				
			case 2:
				if(keys[2].single_flag == 1)
				{
					min_volt += 0.3;
					if(min_volt > max_volt)
					{                
						min_volt -= 0.3;
					}					
					keys[2].single_flag = 0;
				}
				if(keys[3].single_flag == 1)
				{
					min_volt -= 0.3;
					if(min_volt < 0)
						min_volt = 0;
					keys[3].single_flag = 0;
				}
			break;
				
			case 3:
				if(keys[2].single_flag == 1)
				{
					upper_val++;
					if(upper_val>8)
						upper_val = 1;					
					if(upper_val==lower_val)
					{
						if(upper_val == 8)
							upper_val = 1;
						else
							upper_val++;
					}
					keys[2].single_flag = 0;
				}
				
				if(keys[3].single_flag == 1)
				{
					upper_val--;
					if(upper_val<1)
						upper_val = 8;					
					if(upper_val==lower_val)
					{
						if(upper_val == 1)
							upper_val = 8;
						else
							upper_val--;
					}									
					keys[3].single_flag = 0;
				}
			break;
				
			case 4:
				if(keys[2].single_flag == 1)
				{
					lower_val++;
					if(lower_val>8)
						lower_val = 1;
					if(upper_val==lower_val)
					{
						if(lower_val == 8)
							lower_val = 1;
						else
							lower_val++;
					}
					keys[2].single_flag = 0;
				}
				
				if(keys[3].single_flag == 1)
				{
					lower_val--;
					if(lower_val<1)
						lower_val = 8;
					if(upper_val==lower_val)
					{
						if(lower_val == 1)
							lower_val = 8;
						else
							lower_val--;
					}									
					keys[3].single_flag = 0;
				}
			break;				
		}
	}
}

LED控制

//LED控制函数
void led_proc(void)
{
	adc = (float)getADC(&hadc2)*3.3/4095;
	if(adc>max_volt)
	{
		TurnOn_LED(upper_val);
		HAL_Delay(200);
		TurnOff_LED(upper_val);
		HAL_Delay(200);
	}
	else if(adc<min_volt)
	{
		TurnOn_LED(lower_val);
		HAL_Delay(200);
		TurnOff_LED(lower_val);
		HAL_Delay(200);
	}
}

主函数中

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_TIM4_Init();
  MX_ADC2_Init();
  /* USER CODE BEGIN 2 */
  LCD_Init();								//初始化LCD
  Off_LEDs();               //关闭全部LED
  LCD_Clear(Black);         //将LCD清空为黑屏
  LCD_SetBackColor(Black);  //背景色——黑色
  LCD_SetTextColor(White);  //文字色——白色

  HAL_TIM_Base_Start_IT(&htim4);  //开启TIM4的时钟中断——扫描按键
  HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED);   //ADC2初始化校准
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	disp_proc();
	led_proc();
	key_proc();
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

效果图

在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值