本帖主要实现以下功能:
编程实现LED灯的闪烁((尽量实现呼吸灯)
编程实现按键控制LED灯的亮灭(按下一次LED亮,再按一次LED灭)。
可以看到要求中包含LED的亮灭控制和呼吸灯,以及按键采集部分,所以我们先初步划分一下,LED的状态至少有三种亮、灭、闪烁、呼吸灯,正好可以对应4个按键,同时显示模块上还有一个RGB,也可以通过按键控制加入。实际上加上开发板上的资源,我们可以使用的是1个LED、一个RGB、5个用户按键。
首先看一下LED:
LED的亮灭直接受控于GPIO状态,高电平激活LED发光,低电平则熄灭LED。基于PICO开发板设计,绿色LED与GPIO25引脚相连,采用高电平触发点亮机制。
开发板按键:
该板载按键原本设计为BOOT功能,但在系统运行时也能作为普通按键使用,其按下时通过电阻R11的作用,使得QSPI_SS端(即PICO的56号引脚)呈现低电平状态,进而被系统检测识别,对按键输入电平检测,则需要将端口引脚设置为输入模式。
扩展模组上的RGB灯和按键实际上也是同理的,我们大致看一下原理图就可以了:
灯点亮的控制是低电平点亮,按键采集方式是一样的。
我们回到程序上,本次使用的是课程提供的工程进行设计,这样可以避免很多不必要的麻烦。
我们首先实现LED的闪烁:
#define PICO_LED_PIN 25 //GPIO初始化函数 void LED_init(){ gpio_init(PICO_LED_PIN); gpio_set_dir(PICO_LED_PIN, GPIO_OUT); } //板载灯点亮函数 void LED_ON(){ gpio_put(PICO_LED_PIN, 1); } //板载灯熄灭函数 void LED_OFF(){ gpio_put(PICO_LED_PIN, 0); }
闪烁的实现还是比较简单的,通过演示实现闪烁:
LED_init(); while (true){ DEV_Delay_ms(500); LED_ON(); DEV_Delay_ms(500); LED_OFF(); }
效果如下:
接下来实现呼吸灯的操作:
void LED_PWM_init(){ // PWM Config gpio_set_function(PICO_LED_PIN, GPIO_FUNC_PWM); my_slice_num = pwm_gpio_to_slice_num(PICO_LED_PIN); pwm_set_wrap(my_slice_num, 100); pwm_set_chan_level(my_slice_num, PWM_CHAN_B, 1); pwm_set_clkdiv(my_slice_num,50); pwm_set_enabled(my_slice_num, true); } void LED_SET_PWM(uint8_t Value) { if(Value<0 || Value >100){ //printf("DEV_SET_PWM Error \r\n"); }else { pwm_set_chan_level(my_slice_num, PWM_CHAN_B, Value); } }
通过循环修改PWM的值实现呼吸灯效果:
LED_PWM_init(); while (true){ DEV_Delay_ms(10); if(pwm_cnt == 0){ pwm_dir = 0; } if(pwm_cnt >= 100){ pwm_dir = 1; } if(pwm_dir == 0){ pwm_cnt++; } else{ pwm_cnt--; } LED_SET_PWM(pwm_cnt); }
效果如下:
按键的采集实际上是输入检测的实现,这里我们也扩展一下,使用三个按键实现RGB的三个灯的亮灭控制,按一下状态翻转一下。按键都是0表示按下,这里我们集合到一起:
void key_init(){ gpio_init (PIN_DIRECTION_KEY_A); gpio_set_dir(PIN_DIRECTION_KEY_A, GPIO_IN); gpio_set_pulls(PIN_DIRECTION_KEY_A,1, 0); gpio_init (PIN_DIRECTION_KEY_B); gpio_set_dir(PIN_DIRECTION_KEY_B, GPIO_IN); gpio_set_pulls(PIN_DIRECTION_KEY_B,1, 0); gpio_init (PIN_DIRECTION_KEY_X); gpio_set_dir(PIN_DIRECTION_KEY_X, GPIO_IN); gpio_set_pulls(PIN_DIRECTION_KEY_X,1, 0); gpio_init (PIN_DIRECTION_KEY_Y); gpio_set_dir(PIN_DIRECTION_KEY_Y, GPIO_IN); gpio_set_pulls(PIN_DIRECTION_KEY_Y,1, 0); } uint8_t get_button(uint8_t key_pin){ if(gpio_get(key_pin) == 0){ DEV_Delay_ms(10); if(gpio_get(key_pin) == 0){ while(gpio_get(key_pin) == 0); return 1; } else return 0; }else{ return 0; } }
LED的翻转也集合一下:
void LED_Toggle(uint8_t LED_GPIO){ uint8_t led_on = 0; led_on = gpio_get(LED_GPIO); led_on=!led_on; gpio_put(LED_GPIO, led_on); }
然后将按键与灯进行关联:
while (true){ if(get_button(PIN_DIRECTION_KEY_A) == 1) LED_Toggle(PICO_Pack_R_PIN); if(get_button(PIN_DIRECTION_KEY_B) == 1) LED_Toggle(PICO_Pack_G_PIN); if(get_button(PIN_DIRECTION_KEY_X) == 1) LED_Toggle(PICO_Pack_B_PIN); }
效果如下: