蓝桥杯嵌入式——基础模块的使用(初始化+调度器+LED+按键+LCD)

准备工作,创建工程

一、系统初始化

1.1 CubeMX配置

1.2 Keil配置

新建APP文件夹

1.3 Keil底层代码

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

void System_Init(void)
{
    GPIOC->ODR &= 0x00ff;//清空PC8-PC15位  LED低电平亮此时全亮
    GPIOC->ODR |= 0xff00;//熄灭LED
    GPIOD->BSRR = 0x01 << 2;//PD2置1
    GPIOD->BRR = 0x01 << 2;//PD2置0
}

二、系统调度器(scheduler.c)

2.1 CubeMX配置

调度器无需配置CubeMX。

2.2 Keil底层代码

cpp 复制代码
typedef struct{
   void (*func)(void);
    uint32_t interval;//运行时间间隔
    uint32_t next_run;//下次运行时间
}task_t;
/*任务注册*/
task_t tasks[] = {
    {key_proc,10,0}
    ,
    {led_proc,10,0}
    ,
    {lcd_proc,100,0}
    ,
    {adc_proc,10,0}
    ,
    {uart_proc,10,0}
};
uint8_t task_count =  sizeof(tasks)/sizeof(task_t);//任务数量

void scheduler_run(void)
{//调度器运行
    
    for(uint8_t i = 0;i<task_count;i++)
    {
        uint32_t current_time = HAL_GetTick();
        if(current_time >= tasks[i].next_run)
        {
            tasks[i].next_run = current_time+tasks[i].interval;
            tasks[i].func();
        }
    }
}

三 、LED配置(led_app.c)

3.1 CubeMX配置

在第一节中已经配置了LED灯的PC8--PC15口以及 PD2的使能口,在此无需额外配置。

3.2 底层代码

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

uint8_t ucled[8] = {0,1,0,1,1,0,0,0};
void led_show(uint8_t *ucled)
{
    uint8_t temp = 0x00;
    static uint8_t temp_old = 0xff;
    
    for(uint8_t i = 0;i<8;i++)
        temp |= (ucled[i] << i);
        //temp |= (ucled[i] << (7-i));//temp = 0101 1000
    //这里应该把7-去了,因为板子上是反的
    if(temp != temp_old)
    {
        GPIOC->ODR &= 0x00ff;
        GPIOC->ODR |= ~(temp << 8);//~0101 1000  0000 0000 == 1010 0111
        GPIOD->BSRR |= (0x01 << 2);//PD2 0x04
        GPIOD->BRR |= (0x01 << 2);//0x04
        temp_old = temp;//
    }
}
void led_proc(void)
{
    led_show(ucled);
}

四、按键配置(key_app.c)

4.1 CubeMX配置

4.2 底层代码

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

uint8_t key_value;
uint8_t key_old;
uint8_t key_down;
uint8_t key_up;

uint8_t key_read(void)
{
    uint8_t temp = 0;
    
    if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0) == GPIO_PIN_RESET)
        temp = 1;
    if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == GPIO_PIN_RESET)
        temp = 2;
    if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2) == GPIO_PIN_RESET)
        temp = 3;
    if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET)
        temp = 4;
    return temp;
}
void key_proc(void)
{
    key_value = key_read();
    key_down = key_value & (key_old ^ key_value);
    key_up = ~key_value & (key_old ^ key_value);
    key_old = key_value;
    
    
}

4.3 按键长按&按键双击

cpp 复制代码
uint8_t long_flag;
uint16_t key_1s;
uint8_t mul_flag;
uint16_t mul_500ms;
void key_proc(void)
{
    key_value = key_read();
    key_down = key_value & (key_old ^ key_value);
    key_up = ~key_value & (key_old ^ key_value);
    key_old = key_value;
    
    if(key_down == 1)
    	long_flag = 1;
    if(key_up == 1)
    {
    	if(long_flag == 1)
    	{//短按
    		long_flag = 0;//按下标志清零
    		key_1s = 0;//计数清零
    	}
    	if(long_flag == 2)
    	{//长按
    		long_flag = 0;
    		ucled[7] ^= 1;//切换led状态
    	}
    }
    if(key_down == 2)
    {
		switch(mul_flag)
        {
            case 0://单击
                ucled[6] ^= 1;
                mul_flag = 1;
            break;
            case 1://双击
                ucled[5] ^= 1;
                mul_flag = 2;
            break;
            case 2://三击
                ucled[4] ^= 1;
                mul_flag = 3;
            break;
        }
    }
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)  //中断回调1ms进一次
{//定时器回调函数  800*100/80 000 000=0.001s
	if(htim -> Instance == TIM6)
	{
        if(long_flag == 1)
        {
            if(++key_1s >= 1000)
            {
                long_flag = 2;
                key_1s = 0;
            }
        }
        if(mul_flag != 0)
        {//非零计时 超过500清零
            if(++mul_500ms >= 500)
            {
                mul_500ms = 0;
                mul_flag = 0;//超过500状态回归
            }
        }
	}		
}

五、LCD配置(lcd_app.c)

5.1 CubeMX配置

使用LCD需要将PC0------PC15都配置为GPIO_Output,此外还有PB5,8,9,PA8也需要配置。(但不配置似乎没啥影响)

5.2 底层代码

5.2.1 初始化语句

需要先将lcd的文件移入自己的项目文件夹

使用LCD需要初始化

将下面代码添加到while循环之前

cpp 复制代码
    LCD_Init();
    LCD_Clear(Black);//清除整个LCD屏幕
    LCD_SetTextColor(White);//文本色为 白色
    LCD_SetBackColor(Black);//背景色为 黑色
5.2.2 官方LCD函数

sprintf合成函数在stdio.h这个库文件中

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

char lcd_buffer[128];
void lcd_proc(void)
{
    sprintf(lcd_buffer,"    LCD_APP Test");
    LCD_DisplayStringLine(Line0,(u8*)lcd_buffer);
    LCD_DrawCircle(100,50,30);
}
5.2.3 升级版
cpp 复制代码
#include "lcd_app.h"

void LcdSprintf(uint8_t Line,char *format,...)
{
    char String[21];//缓冲区用于存放格式化的字符串
    va_list arg;//参数列表用于存储可变参数
    va_start(arg,format);//初始化可变参数列表
    vsprintf(String,format,arg);//格式化字符串并存储在缓冲区中
    va_end(arg);//清理参数列表
    LCD_DisplayStringLine(Line,(u8*)String);
}
void lcd_proc(void)
{
    LcdSprintf(Line2,"    LCD APP TEST");
}
相关推荐
btzhy4 小时前
STM32单片机:基本定时器应用:单脉冲模式(STM32L4xx)
stm32·单片机·嵌入式硬件·基本定时器应用:单脉冲模式
文sir.6 小时前
温湿度采集系统(stm32+mqtt+Onenet云平台+esp8266)
stm32·单片机·嵌入式硬件·mqtt·onenet·云平台·esp8266
DIY机器人工房6 小时前
嵌入式面试题:你有没有用过直接基于TCP协议,不借助HTTP、MQTT这类上层协议的项目经历?
stm32·单片机·嵌入式硬件·面试题·diy机器人工房
zhmc8 小时前
Cortex M0单片机指令执行周期
单片机·嵌入式硬件
编程小白菜1238 小时前
STM32L051单片机485Ymode升级后程序不能正常运行问题
stm32·嵌入式硬件
NEU-UUN10 小时前
5.1.STM32-EXTI外部中断——全程手敲板书
stm32·单片机·嵌入式硬件
TangDuoduo000511 小时前
【常见传感器原理及应用】
单片机·嵌入式硬件
q***064721 小时前
SocketTool、串口调试助手、MQTT中间件基础
单片机·嵌入式硬件·中间件
洋九八1 天前
电路基础和 PCB 制作
单片机·嵌入式硬件·pcb工艺
qq_401700411 天前
RS485基本原理,电路、防雷、layout及设计要点
stm32·单片机