蓝桥杯嵌入式——基础模块的使用(初始化+调度器+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");
}
相关推荐
XCOSnTh3 小时前
XCOSnTh单片机的串口
c语言·单片机·嵌入式硬件·算法·xcosnth
XINVRY-FPGA4 小时前
XA7A75T-1FGG484Q 赛灵思 Xilinx AMD Artix-7 XA 系列 FPGA
嵌入式硬件·fpga开发·车载系统·云计算·硬件架构·硬件工程·fpga
沉在嵌入式的鱼4 小时前
STM32--大功率mos管驱动模块
stm32·单片机·mos管
驱动起爆大师x_x5 小时前
CAN总线的数据采样和同步问题
stm32·嵌入式硬件·学习·can
XINVRY-FPGA6 小时前
XC7A100T-2CSG324I 赛灵思 Xilinx AMD Artix-7 FPGA
arm开发·嵌入式硬件·fpga开发·硬件工程·信号处理·dsp开发·fpga
2301_1472583697 小时前
STM32 单片机开发 - FreeRTOS 实时操作系统
stm32·单片机·嵌入式硬件
jianqiang.xue8 小时前
ESP32-S3入门第七天:UART串口通信与设备交互
c语言·单片机·嵌入式硬件·mcu·物联网·51单片机
【云轩】8 小时前
嵌入式开发常见问题解决:Keil头文件路径与MCUXpresso外设配置错误
经验分享·单片机
三佛科技-134163842129 小时前
电动修眉刀MCU方案开发,基于国产单片机方案设计
单片机·嵌入式硬件·智能家居·pcb工艺