非常感谢老师提供的学习资料包,资料包里资料非常细致,是学习RP2040非常好的学习资源。参考着这个学习资料,开始逐一实现任务。
1、编程实现按键控制LED灯的亮灭(按下一次LED亮,再按一次LED灭)
打开资料包中的工程文件,可以找到my_led.c文件。首先来看LED_init()方法
void LED_init()
{
gpio_init(PICO_LED_PIN);
gpio_set_dir(PICO_LED_PIN, GPIO_OUT);
}
void LED_ON()
{
gpio_put(PICO_LED_PIN, 0);
}
void LED_OFF()
{
gpio_put(PICO_LED_PIN, 1);
}这里将LED管脚设置为输出状态。RP2040板子上带着一颗LED,对应管脚是25脚。在my_led.h中将25脚宏定义为PICO_LED_PIN了。GPIO可以设置为输入和输出,驱动LED灯,就设置为输出,后边按键输入的管脚,就需要设置为输入了。后边两个方法,就是给驱动对应管脚高、低电平。对应的就是驱动LED灯的亮灭。
再来看my_key.c文件,这里设置了按键的输入。先看电路图,这里有三个按键,分别接到了12、13、14管脚上。

这里,使用A键来控制LED灯的亮灭。所以在按键初始化时,将A键对应的12管脚设置为输入口,留意初始化中调用了gpio_set_pulls,这里将12管脚设置为它设置为上拉(true)并禁用下拉(false),即在没有任何信号输入时,12管脚处于高电平,当按键按下后,即12管脚与地短路,12管脚就处于低电平了。
void key1_init()
{
gpio_init(PICO_KEYA_PIN);
gpio_set_dir(PICO_KEYA_PIN, GPIO_IN);
gpio_set_pulls(PICO_KEYA_PIN, 1, 0);
// gpio_init(PICO_KEYB_PIN);
// gpio_set_dir(PICO_KEYB_PIN, GPIO_IN);
// gpio_set_pulls(PICO_KEYB_PIN, 1, 0);
// gpio_init(PICO_KEYC_PIN);
// gpio_set_dir(PICO_KEYC_PIN, GPIO_IN);
// gpio_set_pulls(PICO_KEYC_PIN, 1, 0);
}
char get_key()
{
if (gpio_get(PICO_KEYA_PIN) == 0)
{
sleep_ms(20);
if (gpio_get(PICO_KEYA_PIN) == 0) return 1;
}
else
{
return 0;
}
}在get_key方法中,当读取12脚为低电平时(即按键A按下了),就延时20毫秒,再次去读取12脚,如果依然读取到的是低电平,就判断为A键按下了,通过延时消除了按键抖动。
最后在main方法中调用这些函数,即可完成按键控制LED灯状态。
int main(void)
{
int val = 0;
system_init();
LED_init();
key1_init();
while (true)
{
if(get_key()==1) val=!val;
val==1?LED_OFF():LED_ON();
}
return 0;
}
2、编程实现LED灯的呼吸灯和墨水屏的显示
led呼吸灯,使用PWM输出实现。即在LED的管脚以很高频率输出高低电平,通过调整高低电平的时长来调节LED灯的亮度。
void my_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, 1000);
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 my_SET_PWM(uint16_t Value)
{
if (Value < 0 || Value > 1000)
{
// printf("DEV_SET_PWM Error rn");
}
else
{
pwm_set_chan_level(my_slice_num, PWM_CHAN_B, Value);
}
}这里我们将LED灯的25管脚设置为PWM输出,通过my_SET_PWM就可以设置输出的亮度了,亮度值可以从0~1000变化。
我们再来看看学习资料中的驱动墨水屏的部分,墨水屏使用了spi方式驱动。并给出了可以运行的例子,例子中是在屏幕上绘制了一个点。
void epd_init()
{
OLED_GPIOInit();
EPD_2IN9D_Init();
EPD_2IN9D_Clear();
fb_init();
DEV_Delay_ms(500);
}
void updata_to_epd(char flag)
{
fb_to_epddata();
if (flag == DISPLAY_PART)
{
EPD_2IN9D_DisplayPart(Image_BW2);
DEV_Delay_ms(500); // Analog clock 1s
}
else
{
// DEV_Delay_ms(500);//Analog clock 1s
EPD_2IN9D_Init();
EPD_2IN9D_Display(Image_BW2);
DEV_Delay_ms(2000);
}
}仔细看墨水屏绘制部分代码,发现和以前接触过“中景园”OLED驱动代码非常相似,于是就用OLED的绘制字符的方式写了墨水屏的绘制字符串的方法。
// 在指定位置显示一个字符,包括部分字符
// x:0~127
// y:0~63
// size1:选择字体 6x8/6x12/8x16/12x24
// mode:0,反色显示;1,正常显示
void EPD_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t size1, uint8_t mode)
{
u8 i, m, temp, size2, chr1;
u8 x0 = x, y0 = y;
if (size1 == 8)
size2 = 6;
else
size2 = (size1 / 8 + ((size1 % 8) ? 1 : 0)) * (size1 / 2); // 得到字体一个字符对应点阵集所占的字节数
chr1 = chr - ' '; // 计算偏移后的值
for (i = 0; i < size2; i++)
{
if (size1 == 8)
{
temp = asc2_0806[chr1][i];
} // 调用0806字体
else if (size1 == 12)
{
temp = asc2_1206[chr1][i];
} // 调用1206字体
else if (size1 == 16)
{
temp = asc2_1608[chr1][i];
} // 调用1608字体
else if (size1 == 24)
{
temp = asc2_2412[chr1][i];
} // 调用2412字体
else
return;
for (m = 0; m < 8; m++)
{
if (temp & 0x01)
mode == 1 ? draw_fb_point(x, y) : clear_fb_point(x, y);
else
mode == 1 ? clear_fb_point(x, y) : draw_fb_point(x, y);
temp >>= 1;
y++;
}
x++;
if ((size1 != 8) && ((x - x0) == size1 / 2))
{
x = x0;
y0 = y0 + 8;
}
y = y0;
}
}
// 显示字符串
// x,y:起点坐标
// size1:字体大小 8 12 16 24
//*chr:字符串起始地址
// mode:0,反色显示;1,正常显示
void EPD_ShowString(uint8_t x, uint8_t y, char *chr, uint8_t size1, uint8_t mode)
{
while ((*chr >= ' ') && (*chr <= '~')) // 判断是不是非法字符!
{
EPD_ShowChar(x, y, *chr, size1, mode);
if (size1 == 8)
x += 6;
else
x += size1 / 2;
chr++;
}
}最后在main方法中调用这些方法,就能在墨水屏上成功显示字符串啦!LED灯也渐亮渐暗地变化起来。
int main(void)
{
int val = 0, step = 10;
system_init();
epd_init();
EPD_ShowString(0, 0, "Hello EEPW & DigiKey ! ", 8, 1);
EPD_ShowString(0, 20, "Hello EEPW & DigiKey ! ", 12, 0);
EPD_ShowString(0, 40, "Hello EEPW & DigiKey ! ", 16, 1);
EPD_ShowString(0, 60, "Hello EEPW & DigiKey ! ", 24, 0);
EPD_ShowString(0, 100, "Hello EEPW & DigiKey ! ", 16, 1);
updata_to_epd(DISPLAY_ALL);
my_pwm_init();
while (true)
{
pwm_set_chan_level(my_slice_num, PWM_CHAN_B, val);
MY_DEV_Delay_ms(12);
val = val + step;
if (val >= 1000)
{
val = 1000;
step = -10;
}
if (val <= 0)
{
val = 0;
step = 10;
}
}
return 0;
}

视频地址:https://www.bilibili.com/video/BV1d2Y5eCEut/
我要赚赏金
