關於藍橋杯這個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壞了。。。。