打印
[ARM7]

LPC2378与ADXL345进行SPI通信的问题

[复制链接]
765|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yl1231|  楼主 | 2015-3-12 16:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
有没有谁做过类似的设计?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
******************************************************************************/

还没有写完。。。

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

2

帖子

0

粉丝