一、任务目标
点亮RGB,实现红色、绿色、蓝色的循环显示!
二、功能分析
点亮RGB,对于单色LED的显示基本上是通过IO口的直接实现的,分别点亮三个LED,这个需要通过开发板的原理图具体分析了;
循环点亮功能可能会需要定时器,按键等功能的加入。
我们在这里对功能进行一下扩展,循环点亮通过定时器实现,并且可以通过按键进行循环点亮频率的切换。
三、硬件原理分析
根据功能分析的介绍,本课程涉及的硬件包括RGB灯和按键。
针对板卡的LED使用情况进行LED的控制,板载LED资源如下图:
我们本次使用的是LED2进行功能展示,引脚涉及到红灯(PA26)、绿灯(PA13)、蓝灯(PA27);
板载按键资源如下:
本次我们使用S2按键(PA14)进行测试模式的开关,使用S1作为循环转换速度的变化控制,注意这两个按键在按下时的状态不一样。
四、关键软件代码
本次课程1效果的实现总共涉及到了4个IO的输出,2个IO的外部中断,以及一个定时器,这些外设的初始化的实现都可以直接通过配置文件去实现,例如本次实现的部分配置如下图:
这次为了实现我们添加以下代码,其中宏定义:
#define LED1_SET DL_GPIO_clearPins(GPIOA, DL_GPIO_PIN_0) #define LED1_RESET DL_GPIO_setPins(GPIOA, DL_GPIO_PIN_0) #define LED2_Green_RESET DL_GPIO_clearPins(GPIOA, DL_GPIO_PIN_13) #define LED2_Green_SET DL_GPIO_setPins(GPIOA, DL_GPIO_PIN_13) #define LED2_Green_toggle DL_GPIO_togglePins(GPIOA, DL_GPIO_PIN_13) #define LED2_Red_RESET DL_GPIO_clearPins(GPIOA, DL_GPIO_PIN_26) #define LED2_Red_SET DL_GPIO_setPins(GPIOA, DL_GPIO_PIN_26) #define LED2_Red_toggle DL_GPIO_togglePins(GPIOA, DL_GPIO_PIN_26) #define LED2_Blue_RESET DL_GPIO_clearPins(GPIOA, DL_GPIO_PIN_27) #define LED2_Blue_SET DL_GPIO_setPins(GPIOA, DL_GPIO_PIN_27) #define LED2_Blue_toggle DL_GPIO_togglePins(GPIOA, DL_GPIO_PIN_27)
创建了一个LED有关的结构体:
typedef struct { uint8_t Mode_On_Off; //LED显示开关 uint8_t Mode_speed; //LED速度模式 uint8_t Mode_Dis; //LED显示模式 uint8_t Mode_OidDis; //LED上一次显示模式 uint8_t PWMcnt; //LED控制模式 uint8_t state; //LED过程 uint8_t UpFlag; //更新标志 uint8_t Upcnt; //更新计时计数 }LED_states; LED_states LED;
while中主要实现的是LED各种变量状态的判断与执行:
void LED_Alter(void) { if(LED.UpFlag == 1) { if(!(LED.Mode_Dis == LED.Mode_OidDis)) { LED2_Green_RESET; LED2_Red_RESET; LED2_Blue_RESET; switch(LED.Mode_Dis) { case 0: LED2_Red_SET; break; case 1: LED2_Green_SET; break; case 2: LED2_Blue_SET; break; default: break; } LED.Mode_OidDis = LED.Mode_Dis; LED.UpFlag = 0; } } }
非阻塞式的实现就是通过定时器完成的,为此需要添加定时器中断服务程序:
void TIMER_Basic_INST_IRQHandler(void) { switch (DL_TimerG_getPendingInterrupt(TIMG0)) { case DL_TIMER_IIDX_ZERO: if(LED.Mode_On_Off == 1) { LED.Upcnt++; if(LED.Upcnt%(50*(LED.Mode_speed+1)) == 0) { LED.Mode_Dis++; LED.Mode_Dis %= 3; LED.UpFlag = 1; LED.Upcnt = 0; } } break; default: break; } }
当然了还有外部中断中按键的响应:
void GROUP1_IRQHandler(void) { switch (DL_GPIO_getPendingInterrupt(GPIO_key_PORT)) { case GPIO_key_S1_IIDX: if(LED.Mode_On_Off == 1) { LED.Mode_speed++; LED.Mode_speed %= 3; } break; case GPIO_key_S2_IIDX: if(LED.Mode_On_Off == 0) { LED.Mode_On_Off = 1; LED1_SET; } else { LED.Mode_On_Off = 0; LED1_RESET; } break; default: break; } }
到这里就完成了实现上述功能的代码,虽然功能比较简单,不过基本上涉及到了很多我们常用的外设。
五、实验结果