一.项目介绍
BeagleBone® Black是一款功能强大的开源硬件平台,广泛应用于DIY项目、教育、科研等领域。其内置的可编程实时单元(PRU)使其能够处理实时控制任务,而不占用主CPU资源。本项目利用BeagleBone Black的PRU模块,设计了一个可以通过按钮调节呼吸灯闪烁频率的电路。
项目任务:
1、采集按钮的按下
2、实现呼吸灯的输出
3、实现对呼吸灯频率的调节
BeagleBone Black(BBB)的PRU模块是其强大的核心功能之一,以下是对该模块的详细介绍:
1、基本概念
PRU,全称Programmable Real-time Unit,即可编程实时单元。它是集成在BBB的AM335x系列处理器中的一个独立子系统,专门用于处理对实时性要求极高的任务。
2、主要特点
独立性:PRU独立于ARM CPU运行,不会受到操作系统调度的影响,因此能够提供非常稳定的实时性能。
高速性:PRU的运行频率为200MHz,即每条汇编指令的执行时间为5ns,这使得它能够快速响应并处理外部事件。
可编程性:PRU支持使用专门的汇编语言进行编程,开发者可以根据需求编写自定义的实时控制程序。
3、应用场景
高速ADC数据采集:PRU能够直接访问I/O端口,因此可以高效地处理高速ADC的数据采集任务。
摄像机接口和显示屏接口:PRU的低延迟特性使其成为处理摄像机数据和驱动显示屏的理想选择。
音频处理:PRU可以实时处理音频数据,实现音频信号的编码、解码和混音等功能。
二 硬件准备
- BeagleBone Black开发板
- LED灯(支持PWM控制)
- 按钮开关
- 电阻(用于按钮的限流保护)
三、软件准备
- BeagleBone Black的操作系统镜像(推荐使用Debian)
- 必要的驱动和工具(如Cloud9 IDE)
四、项目步骤
- 硬件连接
- 将LED灯的正极连接到BeagleBone Black的PWM引脚(例如P9_14)。
- 将LED灯的负极通过电阻连接到GND。
- 将按钮的一端连接到GND,另一端连接到一个GPIO引脚(例如P9_30),并通过电阻进行限流保护。
- 软件设置
- 在BeagleBone Black上安装并配置最新的操作系统(Debian)。
- 使用USB数据线将BeagleBone Black连接到PC,并通过SSH连接到开发板。
- 在Cloud9 IDE中编写和调试代码。
- 流程图
PRU编程
- 编写PRU代码,用于实现PWM信号的生成和控制。PRU代码需要能够响应GPIO引脚的输入(按钮按下),并动态调整PWM信号的频率。
- 使用BeagleBone Black的PRU库和工具进行编译和加载PRU程序。
#include <stdint.h>
#include <pru_cfg.h>
#include "resource_table_empty.h"
#include "prugpio.h"
volatile register unsigned int __R30;
volatile register unsigned int __R31;
void user_delay(uint32_t delay_time)
{
while(delay_time>0)
{
__delay_cycles(1);
delay_time--;
}
}
uint32_t cycleTimeArray[4]={50000,100000,150000,200000};
void main(void) {
// Points to the GPIO port that is used
uint32_t *gpio1 = (uint32_t *)GPIO1;
uint32_t array = 0;
uint32_t cycleTime = cycleTimeArray[array]; // 一个周期的时间
int dutyCycle = 0; //现在的占空比
uint32_t forwardCycle=1; //正循环为占空比由暗变亮;
/* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */
CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;
while(1) {
if(__R31 & P9_30) {
;
} else
{
array++;
if(array>=4)
{
array=0;
}
cycleTime = cycleTimeArray[array];
while(!(__R31 & P9_30));
}
gpio1[GPIO_SETDATAOUT] = P9_14; // Turn the USR1 LED on
//user_delay(100);
int temp=cycleTime*(100-dutyCycle)/100;
while(temp>0)
{
__delay_cycles(1);
temp--;
}
gpio1[GPIO_CLEARDATAOUT] = P9_14; // Off
temp=cycleTime*(dutyCycle)/100;
while(temp>0)
{
__delay_cycles(1);
temp--;
}
//user_delay(cycleTime*(dutyCycle)/100);
if(forwardCycle)
{
dutyCycle+=1;
}else
{
dutyCycle-=1;
}
if(dutyCycle>=100)
{
dutyCycle=100;
forwardCycle=0;//正循环最大变为 循环变为由亮慢慢变暗
}else if(dutyCycle<=0)
{
dutyCycle=0;
forwardCycle=1; //反循环结束 循环变为由暗变亮
}
}
__halt();
}
// Set direction of P9_14 (which is port 1 pin 18)
#pragma DATA_SECTION(init_pins, ".init_pins")
#pragma RETAIN(init_pins)
const char init_pins[] =
"/sys/class/gpio/gpio50/direction\0out\0" \
"/sys/devices/platform/ocp/ocp:P9_14_pinmux/state\0gpio\0" \
"/sys/class/leds/beaglebone:green:usr0/trigger\0none\0" \
"/sys/devices/platform/ocp/ocp:P9_30_pinmux/state\0pruin\0" \
"\0\0";
遇到的问题及总结:
发现在增加了几行代码和方法后完全没有按照想象的方式进行运行后面发现只在主循环中进行就可以解决;
活动总结
完成BeagleBone Black的PRU实验后,我深感理论与实践结合的重要性。硬件连接、PRU编程、软件设置等步骤让我熟悉了开发板布局,掌握了PRU指令集和寄存器操作,学会了与主CPU通信的方法。调试与优化过程中,我解决了呼吸灯效果不理想的问题,提高了系统的稳定性和性能。最终,通过按下按钮成功改变呼吸灯频率,我感受到了成就感和自豪感。这次实验不仅锻炼了我的动手能力和解决问题的能力,还为我未来的学习和工作积累了宝贵经验。