基于BBB-PRU 的流水呼吸灯
一、项目介绍
本项目是以BBB开发板中的PRU模块为核心的一个流水呼吸灯项目。本项目使用的开发板为BeagleBone Black,可以简称为BBB开发板,该开发板使用的微处理器为AM3358,该处理器为ARM Cortex-A8单核,主频高达1GHz。但本项目使用的是微处理器中的PRU-ICSS模块,PRU-ICSS与ARM内核分离,拥有可以独立运行的时钟,主频为200M。由于BBB板卡上运行的是linux这种非硬实时操作系统,使用PRU-ICSS模块实现流水灯这种高频IO操作会更简单、更灵活且实时性更好一些。
二、硬件介绍
本项目使用的开发板为BeagleBone Black,BeagleBone Black 是一款面向开发人员和业余爱好者的低成本、高扩展、社区支持的开发平台,板卡处理器选用的是 TI 公司 AM3358 芯片,处理器集成了高达 1GHz 的 ARM Cortex A8 内核,具有强大的处理能力并提供了丰富的外设接口。
本项目主要使用了BeagleBone Black板卡中的PRU模块,PRU-ICSS 与 ARM 内核分离,允许独立运行和时钟,从而提高了效率和灵活性。此外,PRU-ICSS 的可编程特性及其对引脚、事件和所有片上系统 (SoC) 资源的访问,为实现快速、实时响应、专用数据处理操作、定制外设接口以及卸载 SoC 其他处理器内核的任务提供了灵活性。
三、设计思路
2.1 搭建开发环境
首先需要在官网下载最新的系统镜像,然后使用烧写工具烧录到SD卡中。之后将烧录好的SD卡插到板卡上,先按住boot switch按键(S2)后再通电启动。此时系统会从SD卡启动,然后自动将系统烧录到EMMC中,最后会自动重启。从最新的系统启动后我们可以使用网线连接板卡与路由器,或者使用USB WiFi,这样我们就可以使用SSH登录板卡系统,默认用户名密码为debian:temppwd。登录系统后可以执行sudo systemctl start bb-code-server.service 命令启动网页VSCODE 服务,此时可以在网页导航栏上输入https://beaglebone.local然后选择bb-code-server,这样就可以在网页上使用VSCode了。当然直接使用vim进行开发也是没问题的,只是查看文档方便与否的问题。
同时登陆到系统后可以使用命令git clone https://git.beagleboard.org/beagleboard/pru-cookbook-code下载pru cookbook。下载好后进入路径下执行安装操作./install.sh,这个脚本会自动安装pru相关的头文件并给pru库打个软链。这样我们就可以直接使用cookbook中的Makefile了,开发环境到此就搭建完毕。
2.2 确定硬件使用引脚
本项目主要涉及到了LED输出和按键检测输入,输出引脚就使用开发板上已有的四个USER LED,输入引脚可以在板子上找一个未被使用的GPIO。最终我选择了P8排母上的12引脚,原理图上标识为GPIO1_12。我们可以在系统中确认一下这个IO是否可以正常使用。首先使用CD 命令切换到/sys/class/gpio/gpio44,gpio44由1_12确定,1*32+12=44。这个路径下的value与direction文件中的内容就标识GPIO的输入输出值和输入输出方向。使用cat命令打印一下value就可以确定IO状态
此时可以使用gpioinfo命令查看该GPIO的相关信息,从下图中我们可以看出该IO名称为P8_12。
2.3呼吸灯实现
呼吸灯简单来说就是使用PWM控制LED的开关,在一定时间内将占空比逐渐从0提高到100然后再逐渐从100减少到0,这样0到100再从100到0的过程就像一呼一吸一样,因此称为呼吸灯。而本项目没有直接使用PWM输出功能,而是采用GPIO输出高低电平加延时的方法实现的。流水灯则需要使用GPIO输入检测按键,每检测到按下一次就切换一个使用的LED灯并改变一次呼吸频率。软件整体流程图如下所示,呼吸灯的实现主要由延时t微秒和延时2000-t微秒实现,改变呼吸灯的呼吸频率主要靠改变n打大小来实现。
2.4编译并运行
代码编写好则可以进行编译,首此编译需要将目标设定为我们的代码源文件名
然后就可以直接执行make命令,编译正常通过后会自动将可执行文件复制到相应目录并运行程序,
四、主要功能代码与说明
本项目的功能实现比较简单,主要功能代码如下所示
void main(void)
{
uint32_t *gpio1 = (uint32_t *)GPIO1;
uint32_t P8_12 = 1<<12;
int time = 1;
int t=1;
int i=0;
int key_pressed = 0;
uint32_t breathe_led = USR0;
/* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */
CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;
while(1)
{
if((gpio1[GPIO_DATAOUT]&P8_12)==P8_12){
if(key_pressed==0)
{
delay_ms(10);
if((gpio1[GPIO_DATAOUT]&P8_12)==P8_12){
key_pressed = 1;
gpio1[GPIO_CLEARDATAOUT] = (15<<21);//clear all leds
if(breathe_led==USR3)breathe_led=USR0;
else breathe_led <<=1;
time = 0;
i++;
if(i==10)i=0;
t = freqs[i];
}
}
}
else key_pressed = 0;
gpio1[GPIO_SETDATAOUT] = breathe_led;
delay_us(time);
gpio1[GPIO_CLEARDATAOUT] = breathe_led;
delay_us(2000-time);
time += t;
if(time>1999){
time = 2000;
t = -freqs[i];
}
if(time<1){
time = 0;
t = freqs[i];
}
}
}
首先将cookbook头文件prugpio.h中的宏GPIO1强制转换为指针,这样我们就可以直接访问和操作GPIO相关的寄存器了。gpio1[GPIO_SETDATAOUT] = breathe_led为设置LED为亮,gpio1[GPIO_CLEARDATAOUT] = breathe_led为设置LED为灭,gpio1[GPIO_DATAOUT]则为读取GPIO端口的输入数值,判断(gpio1[GPIO_DATAOUT]&P8_12)==P8_12就是检测按键是否按下(GPIO按下输入1,释放输入0)。同时还需要对按键进行消抖,检测到按键按下后延时10ms再检测,按键释放后再继续检测,防止连按。按键每按下一次就切换一个使用的LED并修改呼吸频率。
五、功能展示
呼吸状态如下图所示