文章目录
一、开发板资源介绍
如原理图所示,开发板上有8个可供编程的LED。但8个LED与LCD引脚复用。若同时使用LED和LCD会出现冲突。
所以开发板上使用了74HC573锁存器,只有在PD2引脚由高到低时,LED的状态才会刷新。由此解决LED和LCD冲突的问题。
8个LED为低电平时点亮。
二、配置工程
1、配置引脚
在引脚图上单击某个引脚,选择想要配置的模式,即可配置成功。如下图为配置PD2引脚为输出模式。
由于开发板上8个LED与LCD引脚冲突,所以需要将PD2设置为输出模式,我习惯性将该引脚重命名为LE,也可不命名。LED的状态将在PD2的由高到低时刷新。
8个LED对应引脚为PC8-PC15,同样设置为输出模式。
如下图即为配置完成。
2、设置变量
在main.c中用户添加变量区内设置变量
uint8_t ucLed;
3、通用函数
在main.c中用户添加代码区添加以下代码
此函数在为通用函数,只要涉及有LED的题目,都需要编写此函数。
void LED_Disp(uint8_t led)
{
GPIOC->ODR = ~led<<8;
//LED的状态将在PD2的由高到低时刷新。CubeMx中已将PD2重命名为LE。
HAL_GPIO_WritePin(LE_GPIO_Port,LE_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LE_GPIO_Port,LE_Pin,GPIO_PIN_RESET);
}
函数使用方法:
- 若想让LED1点亮,只需调用函数LED_Disp(0x01);
因为0x01=0000 0001,取反,~0x01=1111 1110,再<<8,即为PC引脚高8位为1111 1110。也就是PC8为低电平,由原理图可知LED低电平时被点亮。 - 若想要LED1和LED5被点亮,只需调用函数LED_Disp(0x11);
因为0x11=0001 0001,取反,~0x11=1110 1110,再<<8,即为PC引脚高8位为1110 1110。也就是PC8和PC12为低电平。
以下代码是基于2设置变量,3通用函数的基础上编写的功能函数。 |
4、应用函数
由于题目中对于LED的要求一般是,在xxx情况下点亮,在xxx情况下熄灭。在xxx情况下以0.5s频率闪烁,因此我们需要根据题意编写应用函数。
4.1 LED1在lck≠0时点亮,否则熄灭;LED2在VR37>1时闪烁,否则熄灭。
1.在main.c中用户添加代码区添加以下代码
//通过ucLed按位或、与、异或的方式可改变某个LED状态而不影响其他LED,记得调用 LED_Disp(ucLed);
void LED_Proc(void)
{
if(lck != 0)
ucLed |= 1;//按位或,LD1亮 例如: 1111 1110|0000 0001=1111 1111
else
ucLed &= ~1;//按位与,LD1灭 例如1010 1111&1111 1110=1010 1110
if(VR37 > 1)
ucLed ^= 2;//按位异或 1^1=0 0^1=1,LD2状态翻转
else
ucLed &= ~2;//按位与1&0=0 0&0=0,LD2灭
LED_Disp(ucLed);
}
2.最后在while中调用LED_Proc();
4.2 LED1以0.5s频率闪烁
1.在stm32g4xx_it.c中声明变量
uint32_t ulTime;
2.在stm32g4xx_it.c中void SysTick_Handler(void)下添加以下代码
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
ulTime++;
if(ulTime % 500 == 0)
ucLedState ^= 1;
/* USER CODE END SysTick_IRQn 1 */
}
每过1ms,ulTime加一;每到ulTime是500的倍数(每隔0.5s)时,ucLedState翻转,在LED_Proc(void)中,ucLedState=1点亮,ucLedState=0熄灭,即每隔0.5sLED1状态翻转1次,LED1以0.5s频率闪烁。
3.在main.c中用户添加代码区添加以下代码
void LED_Proc(void)
{
if(ucLedState)//以0.5s频率闪烁
ucLed |= 1;
else
ucLed &= ~1;
LED_Disp(ucLed);
}
4.最后在while中调用LED_Proc();
三、真题小练习
1、 按键按下后LD1亮3秒之后灭
1.在main.c中设置变量
uint16_t usLed;
2.main.c中添加代码
void KEY_Proc(void)
{
if(ucKEY==1)//如果按键1被按下,按键检测函数可查阅学习笔记四
usLed = 3000;
}
void LED_Proc(void)
{
if(usLed>0)
ucLed |= 1;
else
ucLed &= ~1;
LED_Disp(ucLed);
}
3.在stm32g4xx_it.c中声明外部变量
extern uint16_t usLed;
4.在stm32g4xx_it.c中void SysTick_Handler(void)下添加代码
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
if(usLed>0)
usLed--;
/* USER CODE END SysTick_IRQn 1 */
}
5.最后在while中调用LED_Proc();
2、 LED状态和LED序号均改变
LED状态根据电压值改变
R37 输出电压值超过电压上限值时(VR37>V 上限),上限提醒指示灯以 0.2 秒为间隔闪烁,下限指示灯熄灭。
R37 输出电压值低于电压下限值时(VR37<V 下限),下限提醒指示灯以 0.2 秒为间隔闪烁,上限指示灯熄灭。
R37 输出电压值介于上限和下限电压之间时(V 下限≤VR37≤V 上限),上限、下限提醒指示灯熄灭。
竞赛板上除当前用做超出上限、低于下限提醒功能的指示灯外,其它指示灯应处于熄灭状态。
LED序号根据按键值改变
B3:定义为“加”按键,LED 指示灯序号加 1。
B4:定义为“减”按键,LED 指示灯序号减 1。
1.在main.c中设置变量
uint8_t ucLed,ucLedState;
uint16_t Led_All[8]={GPIO_PIN_8,GPIO_PIN_9,GPIO_PIN_10,GPIO_PIN_11,
GPIO_PIN_12,GPIO_PIN_13,GPIO_PIN_14,GPIO_PIN_15};
2.main.c中添加代码
void LED_Disp(uint8_t led)
{
GPIOC->ODR = ~led<<8;
//LED的状态将在PD2的由高到低时刷新。CubeMx中已将PD2重命名为LE。
HAL_GPIO_WritePin(LE_GPIO_Port,LE_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LE_GPIO_Port,LE_Pin,GPIO_PIN_RESET);
}
void LED_Proc(void)
{
//如果用原来改变ucled的方法,在切换led时会出现,几个led同时亮的情况,所以用下面的方法
//设置数组的目的是按键可改变上下限指示灯,Led_Upper和Led_Lower的值在按键函数中改变
LED_Disp(ucLed);//此时ucLed=0,所以灯全熄灭。
if(VR37 > MaxVolt)
HAL_GPIO_WritePin(GPIOC,Led_All[Led_Upper-1],ucLedState);
else
HAL_GPIO_WritePin(GPIOC,Led_All[Led_Upper-1],GPIO_PIN_SET);
if(VR37 < MinVolt)
HAL_GPIO_WritePin(GPIOC,Led_All[Led_Lower-1],ucLedState);
else
HAL_GPIO_WritePin(GPIOC,Led_All[Led_Lower-1],GPIO_PIN_SET);
HAL_GPIO_WritePin(LE_GPIO_Port,LE_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LE_GPIO_Port,LE_Pin,GPIO_PIN_RESET);
}
3.在stm32g4xx_it.c中声明变量
uint32_t ucLedTime;
extern uint8_t ucLedState ;
4.在stm32g4xx_it.c中void SysTick_Handler(void)下添加代码
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
ucLedTime++;
if(ucLedTime%200 == 0)
ucLedState ^=1;
/* USER CODE END SysTick_IRQn 1 */
}
5.最后在while中调用LED_Proc();
LED的题目要求往往要和其他条件相连,所以可以再学习其他模块后做真题过程中强化LED。
在这里有一些学习资料建议,欢迎批评指正【蓝桥杯嵌入式组】HAL库STM32CubeMx学习笔记汇总:学习建议及资料