Funpack3-5 - BeagleBone® Black 任务一 - 通过PRU实现按键切换呼吸灯呼吸频率
该项目使用了BeagleBone Black,实现了PRU控制呼吸灯的设计,它的主要功能为:通过按键控制呼吸灯闪烁频率。
标签
FunPack3-5
BeagleBone® Black
oxlm
更新2025-01-13
10

项目介绍

朋友突然丢了一个链接过来,发现搞的活动中有一个叫PRU编程的东东,之前玩TI的芯片从来没玩过这个,因此就直接下单参加这个活动了。

下单后,直接在网上查阅PRU相关的资料,发现网上共享出来的资料写的都比较简单,直接汇编代码编程,而汇编这种东西,对芯片平台指令集熟悉程度要求特别高,其实并不适合刚接触PRU的小白使用。因此在查阅了资料后,考虑使用arm核写主要业务逻辑,pru实现固定频率的亮灭(占空比可调)的思路实现。

而在后面群友的沟通中,有群友截了张图,直接用C编写PRU代码,因此便再一次搜索相关资料,终于在狗板官方资料中找到了PRU的参考实现例程。虽然没板卡验证,但是基本上可以确认,纯PRU编程难度已经降低了。完全可以按照裸机C编程的方法实现PRU的呼吸灯效果。

硬件设计思路

由于狗板没有用户操作的按键,因此考虑飞线跳接一个按键出来,这里选用了RT1021_MB板卡的旋钮按键实现(有现成的就不用再去找面包板甚至烙铁去折腾了,杜邦线搞定)。

而查看PRU例程,发现狗板上的四颗LED灯都可以通过PRU直接控制,因此之前考虑的灯也飞到RT1021_MB上的思路可以使用狗板的LED灯替代(纯粹的因为想少接几根线,连接不稳定的问题少一些)。

因此最终的硬件接口为:

BeagleBone Black

RT1021_MB

Function

P9_1

J1_1

GND

P9_3

J1_3

3_3V

P9_27

J1_15

Key(3.3V When not pressed)

USR0 LED


Key press state

UDR1 LED


Breath LED

USR2 LED


Breath LED

USR3 LED


Breath LED

软件设计思路

按照功能需求,软件需要实现这么个功能,按键按一下,呼吸灯呼吸速度变化一次。因此考虑按键释放通知上层变更呼吸灯速率。具体设计如下:

至于流程图,按照上面的思路,几乎可以不用画了,就如下框图:

具体实现

具体是现代码见:PROJECT_LOCATION\docs\09_led_pwm\led_pwm.pru0.c

按键功能

int isKeyPressed(void) {
unsigned int sw = 0x1 << 5; // P9_27
unsigned int keyState = 0;
unsigned int *gpio1 = (unsigned int *)GPIO1;
static int flag = 0;

if(!(__R31 & sw)) {
flag = 1;
gpio1[GPIO_SETDATAOUT] |= USR0;
} else if(flag) {
keyState = 1;
flag = 0;
} else {
gpio1[GPIO_CLEARDATAOUT] |= USR0;
}
return keyState;
}

上层业务逻辑

#define BREATH_FAST   20
#define BREATH_SLOW 60

void main(void) {
unsigned int keyState = 0;
unsigned int speed = BREATH_FAST;

unsigned int *gpio1 = (unsigned int *)GPIO1;

/* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */
CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;

while (1) {
if(isKeyPressed()) {
keyState = !keyState;
}

breath(speed);

if(keyState) {
speed = BREATH_SLOW;
} else {
speed = BREATH_FAST;
}
}
}

呼吸灯执行模块

void delay(int time) {
while(time--)
__delay_cycles(1000);
}

void setBrightness(int brightness) {
unsigned int *gpio1 = (unsigned int *)GPIO1;

gpio1[GPIO_SETDATAOUT] |= USR1;
gpio1[GPIO_SETDATAOUT] |= USR2;
gpio1[GPIO_SETDATAOUT] |= USR3;
delay(brightness);

gpio1[GPIO_CLEARDATAOUT] |= USR1;
gpio1[GPIO_CLEARDATAOUT] |= USR2;
gpio1[GPIO_CLEARDATAOUT] |= USR3;
delay(100 - brightness);
}


void breath(int speed) {
static int dutyCount = 0;
static int currentLevel = 0;
static int dir = 0;
int needChange = 0;

dutyCount++;
if(dutyCount >= speed) {
needChange = 1;
dutyCount = 0;
}

if(needChange) {
if(dir) {
currentLevel--;

if(currentLevel == 0) {
dir = 0;
}
} else {
currentLevel++;

if(currentLevel == 100) {
dir = 1;
}
}
}

setBrightness(currentLevel);
return;
}

辅助实现

由于实现是直接基于例程实现的,因此需要按照例程架构实现两个文件,一个是setup.sh,可以理解为PRU对应的外围硬件配置。另一个是Makefile,可以认为是编译并运行PRU程序的执行配置。

setup.sh

#!/bin/bash
#
export TARGET=led_pwm.pru0
echo TARGET=$TARGET

# Configure the PRU pins based on which Beagle is running
machine=$(awk '{print $NF}' /proc/device-tree/model)
echo -n $machine
if [ $machine = "Black" ]; then
   echo " Found"
    config-pin P9_27 pruin
    config-pin -q P9_27
fi

Makefile

include /var/lib/cloud9/common/Makefile

效果验证

在工程目录中输入以下命令并执行

source setup.sh
make

总结

经过此次活动,我大致掌握了如何快速入门PRU的方法,后续项目中若遇到有使用PRU的需求,可以快速上手并给出产出。另外,感觉狗板的设计思路感觉和arduino有些相像,偏向于将某些对于门外汉而言比较复杂的内容简单化,以达到加快项目落地的效果。

附件下载
beaglebone-black-pru.7z
项目源码
团队介绍
个人
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号