蓝桥杯备赛 按键、LCD、定时器

一、按键原理图

蓝色框中是与对应按键相连接的引脚,红色框中是按键。

将PB0、PB1、PB2、PA0这四个引脚设置为上拉输入模式,即

按键没有按下时,输入得到高电平,(按键断开(未被按下),PB0只会接收来自VDD的高电平)。

按键按下时, 输入得到低电平,(按键闭合(被按下),PB0接收来自GND的低电平)。

二、按键扫描函数

三、LCD 显示

fun.c

cpp 复制代码
#include "headfile.h"

int count = 0;

void led_show(uint8_t led, uint8_t mode)
{
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
	if(mode)
	{	
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8 << (led-1),GPIO_PIN_RESET);
	}
	else
	{
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8 << (led-1),GPIO_PIN_SET);
	}
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}

uint8_t B1_state; //B1当前状态
uint8_t B1_last_state; //B1上次的状态
uint8_t B2_state;
uint8_t B2_last_state;

void key_scan()
{
	B1_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);
	B2_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);
	if(B1_state == 0 && B1_last_state == 1)//按键B1按下
	{
		count++;
	}
	if(B2_state == 0 && B2_last_state == 1)//按键B1按下
	{
		count--;
	}
	
	B1_last_state = B1_state;
	B2_last_state = B2_state;
}

char date[20]; //因为这块lcd屏幕最多只能展示20个字符
void lcd_show()
{
	sprintf(date, "        test        ");
	LCD_DisplayStringLine(Line0, (uint8_t *)date);
	sprintf(date, "     count: %d      ", count);
	LCD_DisplayStringLine(Line3, (uint8_t *)date);
}

四、解决led和lcd引脚冲突问题

解决方法

五、定时器

一般用通用定时器

1s中断一次

led闪烁

长按键和短按键

定时器的三个寄存器

长按的意思是:当按键按下时,CNT = 0,(在未松开按键的这段时间里面,CNT的值会一直增加) 过来一段时间后,判断CNT是否大于10000,自己定义如果大于,就意味着按键是长按。

lcd高亮显示(fun.c)

cpp 复制代码
#include "headfile.h"

int count = 0; //计数
uint8_t led_mode = 0; //mode为1,灯亮;mode为2,灯灭
uint8_t lcd_highshow = 0; //lcd_highshow行进行高亮显示

void led_show(uint8_t led, uint8_t mode)
{
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
	if(mode)
	{	
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8 << (led-1),GPIO_PIN_RESET);
	}
	else
	{
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8 << (led-1),GPIO_PIN_SET);
	}
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
	
}

uint8_t B1_state; //B1当前状态
uint8_t B1_last_state = 1; //B1上次的状态
uint8_t B2_state;
uint8_t B2_last_state = 1;
uint8_t B3_state;
uint8_t B3_last_state = 1;
uint8_t B4_state;
uint8_t B4_last_state = 1;

void key_scan()
{
	B1_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);
	B2_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);
	B3_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2);
	B4_state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
	
//按键B1
	if(B1_state == 0 && B1_last_state == 1)//按键B1按下
	{
		TIM3->CNT  = 0; //计数器清零
	}
	else if(B1_state == 0 && B1_last_state == 0)//按键B1一直按着
		{
			if(TIM3->CNT >= 10000)//按键B1长按1s
			{
				count++;
			}
		}
	else if(B1_state == 1 && B1_last_state == 0) //按键B1松开
		{
			if(TIM3->CNT < 10000) //按键B1短按
			{
				count += 2;
			}
		}
//按键B2
	if(B2_state == 0 && B2_last_state == 1)//按键B1按下
	{
		TIM3->CNT  = 0; //计数器清零
	}
	else if(B2_state == 0 && B2_last_state == 0)//按键B1一直按着
		{
			if(TIM3->CNT >= 10000)//按键B1长按1s
			{
				count--;
			}
		}
	else if(B2_state == 1 && B2_last_state == 0) //按键B1松开
		{
			if(TIM3->CNT < 10000) //按键B1短按
			{
				count -= 2;
			}
		}

//按键B3
	if(B3_state == 0 && B3_last_state == 1)//按键B1按下
	{
		led_show(2, 1);
	}
	
//按键B4
	if(B4_state == 0 && B4_last_state == 1)//按键B1按下
	{
		lcd_highshow++;
		lcd_highshow %= 3; //lcd_highshow的取值范围为0、1、2
		
		led_show(2, 0);
	}
	B1_last_state = B1_state;
	B2_last_state = B2_state;
	B3_last_state = B3_state;
	B4_last_state = B4_state;
}

char date[20]; //因为这块lcd屏幕最多只能展示20个字符
void lcd_show()
{
	sprintf(date, "        test        ");
	LCD_DisplayStringLine(Line0, (uint8_t *)date);
	if(lcd_highshow == 0)
	{
			LCD_SetBackColor(Yellow);//设置文字背景色
	  sprintf(date, "     count: %d      ", count);
	  LCD_DisplayStringLine(Line3, (uint8_t *)date);
		  LCD_SetBackColor(Black);
	  sprintf(date, "       para4        ");
	  LCD_DisplayStringLine(Line4, (uint8_t *)date);
		sprintf(date, "       para5        ");
	  LCD_DisplayStringLine(Line5, (uint8_t *)date);
		sprintf(date, "       para8        ");
	  LCD_DisplayStringLine(Line8, (uint8_t *)date);
	}
	else if(lcd_highshow == 1)
	{
		
	  sprintf(date, "     count: %d      ", count);
	  LCD_DisplayStringLine(Line3, (uint8_t *)date);
		  LCD_SetBackColor(Yellow);
	  sprintf(date, "       para4        ");
	  LCD_DisplayStringLine(Line4, (uint8_t *)date);
		  LCD_SetBackColor(Black);
		sprintf(date, "       para5        ");
	  LCD_DisplayStringLine(Line5, (uint8_t *)date);
		sprintf(date, "       para9        ");
	  LCD_DisplayStringLine(Line9, (uint8_t *)date);
	}
		else if(lcd_highshow == 2)
	{
	  sprintf(date, "     count: %d      ", count);
	  LCD_DisplayStringLine(Line3, (uint8_t *)date);
	  sprintf(date, "       para4        ");
	  LCD_DisplayStringLine(Line4, (uint8_t *)date);
			LCD_SetBackColor(Yellow);
		sprintf(date, "       para5        ");
	  LCD_DisplayStringLine(Line5, (uint8_t *)date);
		  LCD_SetBackColor(Black);
		sprintf(date, "12345678901234567890");
	  LCD_DisplayStringLine(Line9, (uint8_t *)date);

	}
	led_show(1, led_mode);//放在次处,是为了避免lcd和led引脚冲突
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) //中断回调函数(时间到了,就会触发该函数)
{
	if(htim->Instance == TIM2) //判断定时器中断来源是定时器2吗
	{
		led_mode++;
		led_mode = led_mode % 2;
	}
}
相关推荐
测试涛叔3 小时前
金三银四软件测试面试题(800道)
软件测试·面试·职场和发展
Angelina_Jolie4 小时前
一文搞懂 SCI、SSCI、CSSCI、C 刊、核心期刊:定义、作用、层级对比及投稿选择
考研·职场和发展·创业创新
User_芊芊君子6 小时前
【LeetCode经典题解】搞定二叉树最近公共祖先:递归法+栈存路径法,附代码实现
算法·leetcode·职场和发展
熬夜造bug6 小时前
LeetCode Hot100 刷题路线(Python版)
算法·leetcode·职场和发展
测试者家园11 小时前
测试用例智能生成:是效率革命,还是“垃圾进,垃圾出”的新挑战?
人工智能·职场和发展·测试用例·测试策略·质量效能·智能化测试·用例设计
win x13 小时前
JavaSE(基础)高频面试点及 知识点
java·面试·职场和发展
橘颂TA16 小时前
【剑斩OFFER】算法的暴力美学——力扣 207 题:课程表
数据结构·c++·算法·leetcode·职场和发展
谁刺我心16 小时前
【蓝桥杯刷题环境】VScode插件算法刷题Competitive Companion
职场和发展·蓝桥杯
有一个好名字16 小时前
力扣-迷宫中离入口最近的出口
算法·leetcode·职场和发展
努力学算法的蒟蒻17 小时前
day72(1.31)——leetcode面试经典150
面试·职场和发展