硬件准备
ADSP-EDU-BF533:BF533开发板
AD-HP530ICE:ADI DSP仿真器
软件准备
Visual DSP++软件
硬件链接
MEMS三轴加速度传感器
我做了一个三轴加速度传感器的子卡,插在这个板子上,然后写了一些有意思的应用程序。
硬件实现原理
MEMS 子卡板连接在 ADSP-EDU-BF53x 开发板的扩展端口 PORT3 和 PORT4 上,板卡插入时,应将扩展子卡板上标注的“圆圈”符号与板卡上的“圆圈”对准插入,避免子卡板反向接入板卡。
MEMS 传感器芯片有两个外部中断管脚,该中断管脚连接在扩展接口的外部中断管脚上,由于 MEMS 传感器默认的中断触发为高电平触发,上电后,中断管脚会将板卡上的中断触发管脚拉到 0,导致板卡中断异常。这时若
不使用扩展板外部中断资源,可执行 CPLD 配置函数ExtIO_Interrupt_Disable (),将外部中断接入关掉。或者通过配置 MEMS 传感器的 DATA_FORMAT 寄存器中的 INT_INVERT 位,将其设置为低电平触发中断。
MEMS 子卡板采用了 ADI 公司的数字加速度传感器 ADXL345。采用 SPI 接口方式接入。通过配置 CPLD 将 SPI的片选切换至外部的子卡板 ExtSPI0 管脚。
DEVICE_OE 寄存器(读/写):
DEVICE_OE 寄存器地址:0x20320000
DEVICE_OE 寄存器设置硬件设备上一些控制管脚的电平状态。
DEVICE_OE 寄存器位功能:
SPI_SEL1~0:SPI 片选选择位
00:SPI_SEL 选通触摸屏模块
01:SPI_SEL 选通 SD 卡模块
10:SPI_SEL 选通外部 SPI0 模块
11:SPI_SEL 选通外部 SPI1 模块
选通 MEMS 子卡板上 SPI 接口,需将 SPI_SEL0 位设置为 0,SPI_SEL1 位设置为 1。
MEMS 芯片坐标判定:
硬件连接示意图
代码实现功能
代码实现了通过 SPI 接口读取 MEMS 芯片 ADXL345 的三轴坐标数据,并将坐标打印出。
测试步骤
1. 将仿真器(ICE)与 ADSP-EDU-BF53x 开发板和计算机连接好,将 MEMS 子卡板插入扩展板接口 PORT3 和PORT4。
2. 先给 ADSP-EDU-BF53x 开发板上电,再为仿真器(ICE)上电。
3. 运行 VisualDSP++ 5.0 软件,选择合适的 BF53x 的 session 将仿真器与软件连接。
4. 加载 VisualDSP++ 5.0 工程文件 BF53x_MEMS.dpj 文件,编译并全速运行。
测试结果
在 VDSP 软件输出窗口连续打印出读到的当前 MEMS 的坐标数据,当将板卡倾斜后,打印的坐标数据会随倾斜改变。
程序源码
adxl345.c
#include <cdefBF533.h>
#include"adxl345.h"
#define DELAY_DATA 500
void SPIinit(void)
{
*pSPI_BAUD = 50;
*pSPI_FLG |=FLS2;
*pSPI_CTL = 0x1001|CPHA| CPOL|EMISO ;
*pSPI_CTL = (*pSPI_CTL | SPE);
}
unsigned char spi_byte_rw(unsigned char value)
{
unsigned char incoming=0;
while(!(*pSPI_STAT & SPIF));
*pSPI_TDBR = value;
while(*pSPI_STAT & RXS)
incoming = *pSPI_RDBR;
return(incoming);
}
adxl345_write(unsigned char data,unsigned char address)
{
*pSPI_FLG &= ~FLG2;
delay(DELAY_DATA);
spi_byte_rw(address|0x40);
spi_byte_rw(data);
delay(DELAY_DATA);
*pSPI_FLG |= FLG2;
delay(DELAY_DATA);
}
unsigned char adxl345_read(unsigned char address)
{
unsigned char read_data;
*pSPI_FLG &= ~FLG2;
delay(DELAY_DATA);
spi_byte_rw(address|0xc0);
delay(DELAY_DATA);
read_data = spi_byte_rw(0xff);
delay(DELAY_DATA);
read_data = spi_byte_rw(0xff);
delay(DELAY_DATA);
*pSPI_FLG |= FLG2;
delay(DELAY_DATA);
return read_data;
}
unsigned char adxl345_read_id(void)
{
unsigned char id = 0;
id = adxl345_read(DEVID);
return id;
}
void adxl345_init(void) //ADXL345初始化设置
{
adxl345_write(0xfe,OFSX); //X\Y\Z轴校正偏移
adxl345_write(0xff,OFSY);
adxl345_write(0x05,OFSZ);
adxl345_write(0x77,ACT_INACT_CTL); //X\Y\Z轴使能
adxl345_write(0x01,BW_RATE); //功率选择及输出数据速率
adxl345_write(0x38,POWER_CTL); //测量、待机及测量模式控制
adxl345_write(0x0b,DATA_FORMAT); //数据及通信形式控制
adxl345_write(0x03,THRESH_ACT);
adxl345_write(0x03,THRESH_INACT);
adxl345_write(0x0f,TIME_INACT); //加速度时间阈值
adxl345_write(0x77,ACT_INACT_CTL); //使能控制
adxl345_write(0xa0,THRESH_FF); //自由落体加速度阈值
adxl345_write(0xff,TIME_FF); //自由落体时间阈值
adxl345_write(0x00,TAP_AXES);
adxl345_write(0x77,ACT_TAP_STATUS);
adxl345_write(0x0a,BW_RATE);
adxl345_write(0x38,POWER_CTL);
}
unsigned short adxl345_read_xyzdat(short *buffer)
{
short tem_x = 0,tem_y = 0,tem_z = 0;
int i;
signed short dlXDiff0,dlXDiff1,dlXDiff2;
signed short dlYDiff0,dlYDiff1,dlYDiff2;
signed short dlZDiff0,dlZDiff1,dlZDiff2;
short ptx[9];
short pty[9];
short ptz[9];
short pax[3];
short pay[3];
short paz[3];
for(i=0;i<9;i++)
{
ptx[i] =adxl345_read(DATAX1)<<8|adxl345_read(DATAX0);
pty[i] =adxl345_read(DATAY1)<<8|adxl345_read(DATAY0);
ptz[i] =adxl345_read(DATAZ1)<<8|adxl345_read(DATAZ0);
}
///
pax[0]=(ptx[0]+ptx[1]+ptx[2])/3;
pax[1]=(ptx[3]+ptx[4]+ptx[5])/3;
pax[2]=(ptx[6]+ptx[7]+ptx[8])/3;
dlXDiff0 = pax[ 0 ] - pax[ 1 ];
dlXDiff1 = pax[ 1 ] - pax[ 2 ];
dlXDiff2 = pax[ 2 ] - pax[ 0 ];
dlXDiff0 = dlXDiff0 > 0 ? dlXDiff0 : -dlXDiff0;
dlXDiff1 = dlXDiff1 > 0 ? dlXDiff1 : -dlXDiff1;
dlXDiff2 = dlXDiff2 > 0 ? dlXDiff2 : -dlXDiff2;
if ( dlXDiff0 < dlXDiff1 )
{
if ( dlXDiff2 < dlXDiff0 )
{
tem_x = ( ( pax[ 0 ] + pax[ 2 ] ) >> 1 ) ;
}
else
{
tem_x = ( ( pax[ 0 ] + pax[ 1 ] ) >> 1 );
}
}
else if ( dlXDiff2 < dlXDiff1 )
{
tem_x = ( ( pax[ 0 ] + pax[ 2 ] ) >> 1 ) ;
}
else
{
tem_x= ( ( pax[ 1 ] + pax[ 2 ] ) >> 1 ) ;
}
///
pay[0]=(pty[0]+pty[1]+pty[2])/3;
pay[1]=(pty[3]+pty[4]+pty[5])/3;
pay[2]=(pty[6]+pty[7]+pty[8])/3;
dlYDiff0 = pay[ 0 ] - pay[ 1 ];
dlYDiff1 = pay[ 1 ] - pay[ 2 ];
dlYDiff2 = pay[ 2 ] - pay[ 0 ];
dlYDiff0 = dlYDiff0 > 0 ? dlYDiff0 : -dlYDiff0;
dlYDiff1 = dlYDiff1 > 0 ? dlYDiff1 : -dlYDiff1;
dlYDiff2 = dlYDiff2 > 0 ? dlYDiff2 : -dlYDiff2;
if ( dlYDiff0 < dlYDiff1 )
{
if ( dlYDiff2 < dlYDiff0 )
{
tem_y = ( ( pay[ 0 ] + pay[ 2 ] ) >> 1 ) ;
}
else
{
tem_y = ( ( pay[ 0 ] + pay[ 1 ] ) >> 1 );
}
}
else if ( dlYDiff2 < dlYDiff1 )
{
tem_y = ( ( pay[ 0 ] + pay[ 2 ] ) >> 1 ) ;
}
else
{
tem_y= ( ( pay[ 1 ] + pay[ 2 ] ) >> 1 ) ;
}
//
paz[0]=(ptz[0]+ptz[1]+ptz[2])/3;
paz[1]=(ptz[3]+ptz[4]+ptz[5])/3;
paz[2]=(ptz[6]+ptz[7]+ptz[8])/3;
dlZDiff0 = paz[ 0 ] - paz[ 1 ];
dlZDiff1 = paz[ 1 ] - paz[ 2 ];
dlZDiff2 = paz[ 2 ] - paz[ 0 ];
dlZDiff0 = dlZDiff0 > 0 ? dlZDiff0 : -dlZDiff0;
dlZDiff1 = dlZDiff1 > 0 ? dlZDiff1 : -dlZDiff1;
dlZDiff2 = dlZDiff2 > 0 ? dlZDiff2 : -dlZDiff2;
if ( dlZDiff0 < dlZDiff1 )
{
if ( dlZDiff2 < dlZDiff0 )
{
tem_z = ( ( paz[ 0 ] + paz[ 2 ] ) >> 1 ) ;
}
else
{
tem_z = ( ( paz[ 0 ] + paz[ 1 ] ) >> 1 );
}
}
else if ( dlZDiff2 < dlZDiff1 )
{
tem_z = ( ( paz[ 0 ] + paz[ 2 ] ) >> 1 ) ;
}
else
{
tem_z= ( ( paz[ 1 ] + paz[ 2 ] ) >> 1 ) ;
}
*buffer++ = tem_x;
*buffer++ = tem_y;
*buffer = tem_z;
}
cpu.c
#include <cdefBF533.h>
#include <sys/exception.h>
#include “ccblkfn.h”
#include “sysreg.h”
/****************************************************************************
- 名称 : Init_PLL
- 功能 : 配置处理器的内核与系统时钟
- 入口参数 :无
- 返回值 :无
****************************************************************************/
void Set_PLL(int pmsel,int pssel)
{
int new_PLL_CTL;
*pPLL_DIV = pssel;
asm(“ssync;”);
new_PLL_CTL = (pmsel & 0x3f) << 9;
*pSIC_IWR |= 0xffffffff;
if (new_PLL_CTL != *pPLL_CTL)
{
*pPLL_CTL = new_PLL_CTL;
asm(“ssync;”);
asm(“idle;”);
}
}
void Init_Flags(void)
{
*pFIO_INEN = 0x0001;
*pFIO_DIR = 0x0000;
*pFIO_EDGE = 0x0001;
*pFIO_POLAR = 0x0001;
*pFIO_MASKA_D = 0x0001;
}
void Init_SDRAM(void)
{
*pEBIU_SDRRC = 0x00000817;
*pEBIU_SDBCTL = 0x00000013;
*pEBIU_SDGCTL = 0x0091998d;
ssync();
}
void Init_EBIU(void)
{
*pEBIU_AMBCTL0 = 0x7bb07bb0;
*pEBIU_AMBCTL1 = 0xffc07bb0;
*pEBIU_AMGCTL = 0x000f;
}
void delay(volatile int tem)
{
volatile int i;
while(tem–)
for(i=6; i>0; i–);
}
main.c
#include <stdio.h>
#include <cdefBF533.h>
void main(void)
{
unsigned char adxl345_id;
unsigned char buf[3];
short buf_data[3];
float XDat,YDat,ZDat;
Set_PLL(16,4);
Init_EBIU();
ExtSPI0_Enable();
SPIinit();
adxl345_init();
adxl345_id = adxl345_read_id();
printf("adxl345 id is :%x\r\n",adxl345_id);
while(1)
{
adxl345_read_xyzdat(buf_data);
if(buf_data[0]&0xe000) //判断正负
{
buf_data[0] = ~buf_data[0]+1;
buf[0] = '-';
XDat = (float)buf_data[0]*0.0039;
}
else
{
buf_data[0] = buf_data[0];
XDat =(float) buf_data[0]*0.0039;
buf[0] = '+';
}
if(buf_data[1]&0xe000) //判断正负
{
buf_data[1] = ~buf_data[1]+1;
buf[1] = '-';
YDat = (float)buf_data[1]*0.0039;
}
else
{
buf_data[1] = buf_data[1];
YDat =(float) buf_data[1]*0.0039;
buf[1] = '+';
}
if(buf_data[2]&0xe000) //判断正负
{
buf_data[2] = ~buf_data[2]+1;
buf[2] = '-';
ZDat =(float) buf_data[2]*0.0039;
}
else
{
buf_data[2] = buf_data[2];
buf[2] = '+';
ZDat =(float) buf_data[2]*0.0039;
}
printf("mems x y z is %c%1.1fg,%c%1.1fg,%c%1.1fg\r\n",buf[0],XDat,buf[1],YDat,buf[2],ZDat);
}
}