加速度计与陀螺仪的驱动和数据处理

由于SCA3000和ADIS16255的SPI时序有些差异,因此只能采取模拟SPI的方式进行通讯。本驱动,下载后可以根据MCU具体的引脚定义进行修改。16255需要进行设置以后,偏差小了很多。SCA3000基本上不需要进行参数设置。

附图1,陀螺数据处理后对比图片:
上部分(绿色)曲线为以陀螺仪数据变化量为纵向刻度,离中线最近的开始,依次为1次平均值滤波,2次平均值滤波,3次平均值滤波,4次平均值滤波。
中间部分为陀螺仪原值曲线,底部部分(红色)为多次平均值滤波后的陀螺仪数据值。
左转弯后再右转弯回到原来方向,不超过5度



附图2,陀螺数据处理图片:
多次转弯图,不超过5度




/********************************************************************
SPI.H
********************************************************************/
#ifndef __SPI0_H__
#define __SPI0_H__

#include
#include

#define SPI0_CLK (1<<1) //定义SPI时钟脚
#define SPI0_MISO (1<<2) //定义SPI从件输出脚
#define SPI0_MOSI (1<<3) //定义SPI从件输入脚

/// SPI Control Register (S0SPCR - 0xE0020000)
#define CPHA 3
#define CPOL 4
#define MSTR 5
#define LSBF 6
#define SPIE 7


/// SPI Status Register (S0SPSR - 0xE0020004)
#define ABRT 3
#define MODF 4
#define ROVR 5
#define VCOL 6
#define SPIF 7 // SPI transfer complete flag.

#define SPISetCLK() (IOSET0 |= SPI0_CLK)
#define SPIClearCLK() (IOCLR0 |= SPI0_CLK)
#define SPIWriteBit(Data) {if(Data) IOSET0 |= SPI0_MOSI; else IOCLR0 |= SPI0_MOSI;}
#define SPIReadBit() (0 < (int)(((unsigned long)SPI0_MISO) & IOPIN0))

void SetIdleSPI(void);
void WaitIdleSPI(void);

void SPIInit(void);

#endif

/********************************************************************
SPI.C
********************************************************************/


#include "SPI.h"

int IsBusySPI = 0;

void WaitIdleSPI(void)
{
while(IsBusySPI)//等待空闲
os_dly_wait(1);//OS不同,可以修改此句
IsBusySPI = 1;//获得设置忙标志
}

void SetIdleSPI(void)
{
IsBusySPI = 0;
}


/*void SPIDelayNS(int Time)
{
//一个时钟周期约为18ns(主频:11.0592 * 5),一条指令按一个时钟周期算
//本循环大约有8个指令,一指令占一个时钟周期来算
Time = (Time / 18) - 4;//进入循环前,使用了4条指令
while(Time > 0)//判断到退出使用2条指令,因此超过 18 × 6 纳秒的时间本函数方可有效,
Time -= 4; // 每个循环使用4条指令
}*/

void SPIInit(void)
{
//设置SPI总线引脚输入输出模式
PINSEL0 &= 0xFF;
//设置引脚输入输出方向
IODIR0 &= ~((unsigned long)SPI0_MISO); //从件输出脚
IODIR0 |= (SPI0_CLK | SPI0_MOSI); //从件输入脚
SPISetCLK();
}


/*******

*************************************************************
GRRO.C
GYRO.h引用SPI.h
********************************************************************/
#include "GYRO.h"

//定义陀螺仪片选引脚
#define GYRO_PIN (1 << 1)

#define GYRO_CS() IOCLR1 = GYRO_PIN
#define GYRO_UNCS() IOSET1 = GYRO_PIN

#define DelayTCLKH() {NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();}


unsigned short GYROReadWrite16Bit(unsigned short Data)
{
int i;

WaitIdleSPI();

//IntLock(); 关闭中断源

PINSEL0 &= ~0x0000ff00; // config P0.7~P0.4 as GPIO
IODIR1 |= GYRO_PIN;
IODIR0 &= ~((unsigned long)SPI0_MISO);
IODIR0 |= (SPI0_CLK|SPI0_MOSI);
SPISetCLK();
GYRO_CS();
DelayTCLKH();

for( i = 0; i < 16; i++)
{
SPIClearCLK();
//DelayTCLKL();
DelayTCLKH();
SPIWriteBit(Data & 0x8000);
Data <<= 1;
Data |= SPIReadBit();
SPISetCLK();
//DelayTCLKH();
DelayTCLKH();
}

SPISetCLK();
GYRO_UNCS();

IntUnlock(); //打开中断源

SetIdleSPI();

return(Data);
}

unsigned short GYRORead(int Addr)
{
GYROReadWrite16Bit(Addr << 8);
return(GYROReadWrite16Bit(0));
}

void GYROWrite(int Addr, int Data)
{
unsigned short AddrData;
///////////////////////////////////
Addr &= 0x3f;
Addr |= 0x80; //写标志
///////////////////////////////////
AddrData = Addr;
AddrData <<= 8;
AddrData |= Data;
GYROReadWrite16Bit(AddrData);
}

void GYROInit(void)
{
PINSEL1 &= ~GYRO_PIN;//设置引脚模式
IODIR1 |= GYRO_PIN;//设置引脚方向
GYRO_UNCS();
}

/******************************************************************** Accel.C Accel.h引用SPI.h********************************************************************/

include "Accel.h"

//定义加速度计片选引脚
#define ACCEL_PIN (1 << 1)

#define ACCEL_CS() IOCLR1 = ACCEL_PIN
#define ACCEL_UNCS() IOSET1 = ACCEL_PIN

void DoAccelWrite8Bit(unsigned long Data)
{
int i;

for( i = 0; i < 8; i++)
{
SPIWriteBit(Data & 0x80);
Data <<= 1;
SPISetCLK();
SPIClearCLK();
}
}

void DoAccelWrite16Bit(unsigned long Data)
{
int i;

for( i = 0; i < 16; i++)
{
SPIWriteBit(Data & 0x8000);
Data <<= 1;
SPISetCLK();
SPIClearCLK();
}
}

unsigned long DoAccelRead8Bit(void)
{
int i;
unsigned long Data = 0;

for( i = 0; i < 8; i++)
{
Data <<= 1;
SPISetCLK();
Data |= SPIReadBit();
SPIClearCLK();
}
return Data;
}

unsigned long DoAccelRead16Bit(void)
{
int i;
unsigned long Data = 0;

for( i = 0; i < 16; i++)
{
Data <<= 1;
SPISetCLK();
Data |= SPIReadBit();
SPIClearCLK();
}
return Data;
}

unsigned long AccelRead8Bit(unsigned long Addr)
{
unsigned long Data = 0;

WaitIdleSPI();

SPIClearCLK();
ACCEL_CS();

DoAccelWrite8Bit(Addr << 2);
Data = DoAccelRead8Bit();

ACCEL_UNCS();

SetIdleSPI();

return(Data);
}



unsigned long AccelRead16Bit(unsigned long Addr)
{
unsigned long Data = 0;

WaitIdleSPI();

SPIClearCLK();
ACCEL_CS();

DoAccelWrite8Bit(Addr << 2);
Data = DoAccelRead16Bit();

ACCEL_UNCS();

SetIdleSPI();

return(Data);
}

void AccelWrite8Bit(unsigned long Addr, unsigned long Data)
{
Addr <<= 10;
Addr |= 0x0200;
Addr |= Data;

WaitIdleSPI();

SPIClearCLK();
ACCEL_CS();

DoAccelWrite16Bit(Addr);

ACCEL_UNCS();

SetIdleSPI();
}

void AccelInit(void)
{
PINSEL1 &= ~ACCEL_PIN; //设置引脚模式
IODIR1 |= ACCEL_PIN; //设置引脚方向
ACCEL_UNCS();
}











相关文档
最新文档