有没有谁做过类似的设计?LPC2378与ADXL345进行SPI通信,然后转换为角度传出,我这里有一段代码,但是到后面就不太明白了,求大神帮忙解答。
/*****************************************************************************
* spi.c: SPI C file for NXP LPC23xx/24xx Family Microprocessors
*
* Copyright(C) 2006, NXP Semiconductor
* All rights reserved.
*
* History
* 2012.05.19 ver 1.00 Prelimnary version, first Release
*
*****************************************************************************/
#include "LPC23xx.h" /* LPC23xx/24xx Peripheral Registers */
#include "AllIncludes.h"
INT32U SspBaseAddr[SSP_NUMMAX]={SSP0_BASE_ADDR,SSP1_BASE_ADDR};
/*****************************************************************************
函数说明:把SSP初始化为SPI工作方式
*****************************************************************************/
INT32U SspInitial(INT16U sspn){
INT32U SspAddrStart;
if(sspn==0){
PCONP |=DEF_BIT_21;//DEF_BIT_21 SSP0供电.
SspAddrStart=SSP0_BASE_ADDR;
WriteDWord(SspAddrStart+SSP_CR0,0XF|(0<<7)|(1<<6));//SPI16位模式,平时时钟保持高电平.CPOL=1.CPHA=0.
WriteDWord(SspAddrStart+SSP_CR1,0x00);//主模式,SSP禁止.
WriteDWord(SspAddrStart+SSP_CPSR,4);//设置为最小值,为PCLK/2=24M时钟/CPSR.
WriteDWord(SspAddrStart+SSP_IMSC,0x00);//中断屏蔽清除寄存器.不采用中断模式.
WriteDWord(SspAddrStart+SSP_DMACR,0x00);//收发DMA被禁止.
}
else{
PCONP |= DEF_BIT_10;// DEF_BIT_10 SSP1供电
SspAddrStart=SSP1_BASE_ADDR;
WriteDWord(SspAddrStart+SSP_CR0,0XF|(1<<7)|(1<<6));//SPI16位模式,平时时钟保持高电平.CPOL=1.CPHA=0.
WriteDWord(SspAddrStart+SSP_CR1,0x00);//主模式,SSP禁止.
WriteDWord(SspAddrStart+SSP_CPSR,6);//设置为最小值,为PCLK/2=24M时钟/CPSR.
WriteDWord(SspAddrStart+SSP_IMSC,0x00);//中断屏蔽清除寄存器.不采用中断模式.
WriteDWord(SspAddrStart+SSP_DMACR,0x00);//收发DMA被禁止.
}
//设置管脚功能.
if(sspn==0){
GpioPinFuncSel(GPIO_SPIM_SCK,PIN_SEL_FUN2,PIN_MODE_PULLUP_EN);// Port 0.15 SSP SCK0
GpioPinFuncSel(GPIO_SPIM_MISO,PIN_SEL_FUN2,PIN_MODE_PULLUP_EN);//port0.17 MISO0
GpioPinFuncSel(GPIO_SPIM_MOSI,PIN_SEL_FUN2,PIN_MODE_PULLUP_EN);//port0.18 MOSI0.
GpioPinFuncSel(GPIO_CS_G_X,PIN_SEL_GPIO,PIN_MODE_PULLUP_EN);//port0.16 uses GPIO SPI_SEL
GpioPinFuncSel(GPIO_CS_G_Y,PIN_SEL_GPIO,PIN_MODE_PULLUP_EN);//port1.21 uses GPIO SPI_SEL
GpioPinFuncSel(GPIO_CS_G_Z,PIN_SEL_GPIO,PIN_MODE_PULLUP_EN);//port0.06 uses GPIO SPI_SEL
//设置管脚方向
GpioDirSet(GPIO_CS_G_X,GPIO_DIR_OUTPUT);//设置为输出管脚.
GpioDirSet(GPIO_CS_G_Y,GPIO_DIR_OUTPUT);//设置为输出管脚.
GpioDirSet(GPIO_CS_G_Z,GPIO_DIR_OUTPUT);//设置为输出管脚.
//设置管脚的初始状态,高
GpioPinSet(GPIO_CS_G_X,HIGH);//设置为输出管脚为高.
GpioPinSet(GPIO_CS_G_Y,HIGH);//设置为输出管脚为高.
GpioPinSet(GPIO_CS_G_Z,HIGH);//设置为输出管脚为高.
WriteDWord(SspAddrStart+SSP_CR1,(1<<1));//主模式,SSP使能.
}
else{
GpioPinFuncSel(GPIO_SPIS_MISO,PIN_SEL_FUN2,PIN_MODE_PULLUP_EN); //P0.12 MISO
// GpioPinFuncSel(GPIO_SPIS_MOSI,PIN_SEL_FUN2,PIN_MODE_PULLUP_EN); //P0.13 MOSI
GpioPinFuncSel(GPIO_CS_ACC,PIN_SEL_GPIO,PIN_MODE_PULLUP_EN); //P0.14 CS
GpioPinFuncSel(GPIO_SCK_ACC,PIN_SEL_FUN2,PIN_MODE_PULLUP_EN); //p1.31 SCK
GpioDirSet(GPIO_CS_ACC,GPIO_DIR_OUTPUT);//设置为输出管脚.
GpioPinSet(GPIO_CS_ACC,HIGH);//设置为输出管脚为高.
WriteDWord(SspAddrStart+SSP_CR1,(1<<1));//主模式,SSP使能.
}
return( TRUE );
}
/*****************************************************************************
函数说明:从SSP中读取一个字数据
*****************************************************************************/
INT16U SspReadWord(INT16U sspn){
INT16U flag,count,dat=0;
INT32U SspAddrStart=SspBaseAddr[sspn];
for(count=0;count<SSP_FIFOSIZE;count++){
flag=ReadDWord(SspAddrStart+SSP_SR);
if(flag&SSP_SR_RNE){//接收FIFO不为空.
dat=ReadDWord(SspAddrStart+SSP_DR);//获取的数据为FIFO里的最新数据.
}
else{//数据读空了,跳出循环.
break;
}
}
return dat;
}
/*****************************************************************************
函数说明:向SSP中写一个字数据数据.
*****************************************************************************/
INT16U SspWriteWord(INT16U sspn,INT16U dat){
INT16U flag,count;
INT32U SspAddrStart=SspBaseAddr[sspn];
for(count=0;count<100;count++){
flag=ReadDWord(SspAddrStart+SSP_SR);
if(flag&SSP_SR_TFE){//发送缓冲区空,可以发送数据.
WriteHWord(SspAddrStart+SSP_DR,dat);
for(count=0;count<100;count++){
flag=ReadDWord(SspAddrStart+SSP_SR);
if(!(flag&SSP_SR_BSY)){//发送接收完毕
break;
}
}
return TRUE;
}
}
return FALSE;
}
/*****************************************************************************
函数说明:获取SSP的状态.
*****************************************************************************/
INT16U SspGetRisReady(INT16U sspn){
INT16U flag,count;
INT32U SspAddrStart=SspBaseAddr[sspn];
for(count=0;count<100;count++){
flag=ReadDWord(SspAddrStart+SSP_RIS);
if(flag&(1<<1)){//RTRIS接收缓冲区不空.
return TRUE;
}
}
return FALSE;
}
/*****************************************************************************
函数说明:读取陀螺仪内数据.
*****************************************************************************/
INT16U GyroscopeReadReg(INT16U gyrn){
INT32U GyroCsGpio;
INT16U count,value=0;
switch(gyrn){
case GYROSCOPE_X:
GyroCsGpio=GPIO_CS_G_X;
break;
case GYROSCOPE_Y:
GyroCsGpio=GPIO_CS_G_Y;
break;
case GYROSCOPE_Z:
GyroCsGpio=GPIO_CS_G_Z;
break;
default:
break;
}
GpioPinSet(GyroCsGpio,LOW);//片选为低
value |=(0x3<<8)|(0<<4);//读操作.采用补码模式.陀螺仪输出.
SspWriteWord(0,value);//向SSP写数据.
if(SspGetRisReady(0)){//接收数据准备好.
value=SspReadWord(0);//读取结果.
}
if(value&(1<<11)){//为负数,采用补码表示.
value |=0xF000;
}
GpioPinSet(GyroCsGpio,HIGH);//片选为高.
return value;
}
/*****************************************************************************
函数说明:设置陀螺仪输入的数据源.
*****************************************************************************/
INT16U GyroscopeWriteReg(INT16U gyrn,INT16U reg){
INT32U GyroCsGpio;
INT16U count,value=0;
switch(gyrn){
case GYROSCOPE_X:
GyroCsGpio=GPIO_CS_G_X;
break;
case GYROSCOPE_Y:
GyroCsGpio=GPIO_CS_G_Y;
break;
default:
GyroCsGpio=GPIO_CS_G_Z;
break;
}
GpioPinSet(GyroCsGpio,LOW);//片选为低
reg <<=10;//00 陀螺仪 01 温度 10 模拟1输出 11模拟2 输出
value |=(0x3<<8)|(0<<4)|reg|(1<<15);//读操作.采用补码模式.陀螺仪输出.
SspWriteWord(0,value);//向SSP写数据.
if(SspGetRisReady(0)){//接收数据准备好.
value=SspReadWord(0);//读取结果.
}
if(value&(1<<11)){//为负数,采用补码表示.
value |=0xF000;
}
GpioPinSet(GyroCsGpio,HIGH);//片选为高.
return value;
}
/*****************************************************************************
函数说明:设置加速度计输入的数据源.
*****************************************************************************/
INT16U Adxl345WriteReg(INT16U index,INT16U dat){
INT32U GyroCsGpio;
INT16U value;
value=index<<8;
value |=dat;;
GyroCsGpio=GPIO_CS_ACC;
GpioPinSet(GyroCsGpio,LOW);//片选为低
SspWriteWord(1,value);//向SSP写数据.
if(SspGetRisReady(1)){//接收数据准备好.
value=SspReadWord(1);//读取结果.
}
GpioPinSet(GyroCsGpio,HIGH);//片选为高.
return NULL;
}
/*****************************************************************************
函数说明:读取加速度计内数据.Accelerometer
*****************************************************************************/
INT16U Adxl345ReadReg(INT16U regindex){
INT32U AccCsGpio;
INT16U ret;
AccCsGpio=GPIO_CS_ACC;
GpioPinSet(AccCsGpio,LOW);//片选为低
regindex |=0X80;regindex <<=8;//R/W=1 read.
SspWriteWord(1,regindex);//向SSP写数据.
if(SspGetRisReady(1)){//接收数据准备好.
ret=SspReadWord(1);//读取结果.
}
GpioPinSet(AccCsGpio,HIGH);//片选为高.
return ret&0xFF;
}
void InitialAdx345(void){
SspInitial(1);//初始化SSP.
Adxl345WriteReg(ACC_REG_BW_RATE,0x0A);
Adxl345WriteReg(ACC_REG_POWER_CTL,0x08);
}
/*****************************************************************************
函数说明:读取加速度计数据.
*****************************************************************************/
INT16U AccGetXyz(INT16U xyz){
INT16U value;
switch(xyz){
case 0://获取X方向加速
value=Adxl345ReadReg(ACC_REG_DATAX1);
value <<=8;
value |=Adxl345ReadReg( ACC_REG_DATAX0);
break;
case 1://获取Y方向加速
value=Adxl345ReadReg(ACC_REG_DATAY1);
value <<=8;
value |=Adxl345ReadReg(ACC_REG_DATAY0);
break;
case 2://获取Z方向加速
value=Adxl345ReadReg(ACC_REG_DATAZ1);
value <<=8;
value |=Adxl345ReadReg(ACC_REG_DATAZ0);
break;
default:
break;
}
xval=GPIO_CS_G_X;
yval=GPIO_CS_G_Y;
zval=GPIO_CS_G_Z;
if(GPIO_CS_G_Y==0&GPIO_CS_G_Z){
AngleB=90;
AngleA=0;
}
else if(GPIO_CS_G_X==0&GPIO_CS_G_Z==0){
AngleA=90;
AngleB=0;
}
else{
AngleB=yval/zval;
AngleB=atan(AngleB)*180/3.1415;
AngleA=xval/zval;
AngleA=atan(AngleA)*180/3.1415;
}
return value;
}
/******************************************************************************
** End Of File
******************************************************************************/
还没有写完。。。 |
|