蓝桥杯嵌入式LED模块不受控制的解决方法

Ivy ·
更新时间:2024-09-21
· 574 次阅读

文章目录方案一:引脚PD2锁存问题方案二:直接对LCD部分函数进行修改方案三:定时器方式下LED模块不受控制

关于蓝桥杯这个LED模块,如果想控制的效果如你所愿,其实并非常的简单。在这里我提供了三种方案,这三种全部使用之后,可以说99.99%可以解决问题。

方案一:引脚PD2锁存问题

由下图官方提供的使用手册,我们可以看出蓝桥杯使用的这款板子的LCD显示屏模块与LED模块公用引脚,所以有可能是你在使用LCD屏的时候导致了LED的变化。

解决方案如下:
Led.c

#include "Led.h" void Led_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD,ENABLE GPIO_InitStructure.GPIO_Pin = Led_All; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOC,&GPIO_InitStructure); //这里是对锁存器引脚进行初始化PD2 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOD, &GPIO_InitStructure); Led_Control(Led_All,0); //默认灯全灭 } void Led_Control(u16 LED,u8 mode){ if(mode==0){ GPIO_SetBits(GPIOC,LED); GPIO_SetBits(GPIOD,GPIO_Pin_2);//这里就是把引脚进行锁存 GPIO_ResetBits(GPIOD,GPIO_Pin_2); } else{ GPIO_ResetBits(GPIOC,LED); GPIO_SetBits(GPIOD,GPIO_Pin_2); GPIO_ResetBits(GPIOD,GPIO_Pin_2); } }

Led.h

#ifndef __LED_H #define __LED_H #include "stm32f10x.h" #define Led1 GPIO_Pin_8 #define Led2 GPIO_Pin_9 #define Led3 GPIO_Pin_10 #define Led4 GPIO_Pin_11 #define Led5 GPIO_Pin_12 #define Led6 GPIO_Pin_13 #define Led7 GPIO_Pin_14 #define Led8 GPIO_Pin_15 #define Led_All 0xff00 void Led_Init(void); void Led_Control(u16 LED,u8 mode); #endif

然后对Led进行控制的时候只需要调用Led_Contril(led,mode)函数,就可以避免公用引脚的问题。
如果说你已经操作了此方案,但是LED模块还是不受控制,那么请看方案二。

方案二:直接对LCD部分函数进行修改

我们先打开lcd.h,然后拉到最下面会发现有一堆的函数,如下图所示。在这里插入图片描述
那么我们需要修改的就是:

void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue); void LCD_WriteRAM_Prepare(void); void LCD_WriteRAM(u16 RGB_Code);

如果说你仔细想一想也大概知道什么意思了,因为LCD模块和LED模块会公用GPIOC的某些引脚,那么先我们在LCD写数据前,先把GPIOC的数据存起来,然后LCD写完数据之后,再把数据放出来就可以了。具体实现如下操作:

void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue) { //这就是我们自己需要加的,先把GPIOC的数据存起来 __IO uint32_t PCout = GPIOC->ODR; //然后对LCD进行操作 GPIOB->BRR = 0x0200; GPIOB->BRR = 0x0100; GPIOB->BSRR = 0x0020; GPIOC->ODR = LCD_Reg; GPIOB->BRR = 0x0020; GPIOB->BSRR = 0x0020; GPIOB->BSRR = 0x0100; GPIOC->ODR = LCD_RegValue; GPIOB->BRR = 0x0020; GPIOB->BSRR = 0x0020; GPIOB->BSRR = 0x0100; //操作结束之后,再把GPIOC的数据换回来 GPIOC->ODR = PCout; }

后面的两个函数,操作相同,我直接把代码放出来。

void LCD_WriteRAM_Prepare(void) { __IO uint32_t PCout = GPIOC->ODR; GPIOB->BRR = 0x0200; GPIOB->BRR = 0x0100; GPIOB->BSRR = 0x0020; GPIOC->ODR = R34; GPIOB->BRR = 0x0020; GPIOB->BSRR = 0x0020; GPIOB->BSRR = 0x0100; GPIOB->BSRR = 0x0200; GPIOC->ODR = PCout; } void LCD_WriteRAM(u16 RGB_Code) { __IO uint32_t PCout = GPIOC->ODR; GPIOB->BRR = 0x0200; GPIOB->BSRR = 0x0100; GPIOB->BSRR = 0x0020; GPIOC->ODR = RGB_Code; GPIOB->BRR = 0x0020; GPIOB->BSRR = 0x0020; GPIOB->BSRR = 0x0100; GPIOB->BSRR = 0x0200; GPIOC->ODR = PCout; }

这样操作之后,就又增加了一层保护,绝大多数情况下,基本上不会有任何的问题了。但是有时候还是会会导致LED模块不受控制,那就是在定时器模块下。

方案三:定时器方式下LED模块不受控制

由于蓝桥杯的题目经常会这样出,比如说如果达到某个标准的时候,让你控制LED1每秒闪烁一次,然后不满足标准的时候让其保持灭的状态。
这个理论上实现是非常的简单,就是利用一个定时器,然后在中断函数里控制一下灯的亮灭就可以了。但是有的时候实现的效果,永远并非你所想。
下面我给大家提供一种方法,绝对不会出现任何问题,废话不多说直接上代码:
Timer.c

#include "Timer.h" _Bool State_Flag=0,Led1_State=0; //这里我的Arr为999,Psc为71。相当于定时器1ms进一次 void Timer2_Init(u16 Arr,u16 psc){ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_TimeBaseStructure.TIM_Period = Arr; TIM_TimeBaseStructure.TIM_Prescaler = psc; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); TIM_Cmd(TIM2, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } u32 Timer2_LedCnt=0; //最好定义为32位的,因为很容易超出定义的长度 void TIM2_IRQHandler(void) { if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //下面这句话很重要的,可能有人说在下面的State_Flag!=1的条件中单独关闭LED1,其实也可以但。 //这就可能会导致一个现象,那就是LED1确实关闭了,但是导致其他的LED全都亮了。 Led_Control(Led_All,0); if(State_Flag==1){ Timer2_LedCnt++; if(Timer2_LedCnt>=1000){ Timer2_LedCnt=0; Led1_State!=Led1_State; Led_Control(Led1,Led1_State); } } else{ Timer2_LedCnt=0; } } }

这些操做之后,我可以确定你99.99%都不会出现LED不受控制的现象。
当然如果说还不亮,那多半的可能就是你没有对LED模块初始化,或者你的LED坏了。。。。


作者:琰婧



蓝桥杯 方法 嵌入 受控

需要 登录 后方可回复, 如果你还没有账号请 注册新账号