关于蓝桥杯这个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.h,然后拉到最下面会发现有一堆的函数,如下图所示。
那么我们需要修改的就是:
如果说你仔细想一想也大概知道什么意思了,因为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坏了。。。。