三轴加速度传感器MMA8452 IIC测试程序资料.docx
《三轴加速度传感器MMA8452 IIC测试程序资料.docx》由会员分享,可在线阅读,更多相关《三轴加速度传感器MMA8452 IIC测试程序资料.docx(15页珍藏版)》请在冰豆网上搜索。
三轴加速度传感器MMA8452IIC测试程序资料
//***************************************
//GY-45MMA8452IIC测试程序
//使用单片机PIC16F877A
//晶振:
4M
//显示:
Nokia5110
//编译环境MPLAB
//时间:
2012.9.11吴迪
//QQ:
362911737
//****************************************
#include
#include"SPI-CHAR.h"
__CONFIG(0x3b32);
#defineucharunsignedchar
#defineuintunsignedint
#defineSCLRD0//IIC时钟引脚定义
#defineSDARE1//IIC数据引脚定义
#defineSDA_DIRTRISE1//定义E口方向寄存器
#defineSDA_HIGH()SDA_DIR=1//设置数据口为输入
#defineSDA_LOW()SDA_DIR=0//设置数据口为输出
#define_nop_NOP()
#defineSlaveAddress0x38//定义器件在IIC总线中的从地址,根据SA0地址引脚不同修改
typedefunsignedcharBYTE;
typedefunsignedshortWORD;
ucharBUF_drift[8];
BYTEBUF[8];//接收数据缓存区
ucharge,shi,bai,qian,wan;//显示变量
intdis_data;//变量
intx,y,z;
ucharCY;
voiddelay(unsignedintk);
voidInit_MMA8452(void);//初始化MMA8452
voidconversion(uinttemp_data);
voidSingle_Write_MMA8452(ucharREG_Address,ucharREG_data);//单个写入数据
ucharSingle_Read_MMA8452(ucharREG_Address);//单个读取内部寄存器数据
voidMultiple_Read_MMA8452(void);//连续的读取内部寄存器数据
//------------------------------------
voidDelay5us();
voidDelay5ms();
voidMMA8452_Start();
voidMMA8452_Stop();
voidMMA8452_SendACK(ucharack);
bitMMA8452_RecvACK();
voidMMA8452_SendByte(BYTEdat);
BYTEMMA8452_RecvByte();
voidMMA8452_ReadPage();
voidMMA8452_WritePage();
//*********************************************************
voidconversion(uinttemp_data)
{
wan=temp_data/10000+16;
temp_data=temp_data%10000;//取余运算
qian=temp_data/1000+16;
temp_data=temp_data%1000;//取余运算
bai=temp_data/100+0x10;
temp_data=temp_data%100;//取余运算
shi=temp_data/10+0x10;
temp_data=temp_data%10;//取余运算
ge=temp_data+0x10;
}
/*******************************/
voiddelay(unsignedintk)
unsignedinti,j;
for(i=0;i{for(j=0;j<110;j++);}}/**************************************延时5微秒(STC90C52RC@12M)不同的工作环境,需要调整此函数,注意时钟过快时需要修改当改用1T的MCU时,请调整此延时函数**************************************/voidDelay5us(){NOP();NOP();NOP();NOP();NOP();//NOP();NOP();NOP();//NOP();NOP();NOP();NOP();}/**************************************延时5毫秒(STC90C52RC@12M)不同的工作环境,需要调整此函数当改用1T的MCU时,请调整此延时函数**************************************/voidDelay5ms(){WORDn=560;while(n--);}/**************************************起始信号**************************************/voidMMA8452_Start(){SDA_LOW();SDA=1;//拉高数据线SCL=1;//拉高时钟线Delay5us();//延时SDA=0;//产生下降沿Delay5us();//延时SCL=0;//拉低时钟线}/**************************************停止信号**************************************/voidMMA8452_Stop(){SDA_LOW();SDA=0;//拉低数据线SCL=1;//拉高时钟线Delay5us();//延时SDA=1;//产生上升沿Delay5us();//延时}/**************************************发送应答信号入口参数:ack(0:ACK1:NAK)**************************************/voidMMA8452_SendACK(ucharack){SDA_LOW();SDA=ack;//写应答信号SCL=1;//拉高时钟线Delay5us();//延时SCL=0;//拉低时钟线Delay5us();//延时}/**************************************接收应答信号**************************************/bitMMA8452_RecvACK(){SDA_HIGH();SCL=1;//拉高时钟线Delay5us();//延时if(SDA==1)CY=1;elseCY=0;//读应答信号SCL=0;//拉低时钟线Delay5us();//延时SDA_LOW();returnCY;}/**************************************向IIC总线发送一个字节数据**************************************/voidMMA8452_SendByte(BYTEdat){BYTEi;SDA_LOW();for(i=0;i<8;i++)//8位计数器{if(dat&0x80)CY=1;elseCY=0;SDA=CY;//送数据口SCL=1;//拉高时钟线Delay5us();//延时SCL=0;//拉低时钟线Delay5us();//延时dat<<=1;//移出数据的最高位}MMA8452_RecvACK();}/**************************************从IIC总线接收一个字节数据**************************************/BYTEMMA8452_RecvByte(){BYTEi;BYTEdat=0;SDA_LOW();SDA=1;//使能内部上拉,准备读取数据,SDA_HIGH();for(i=0;i<8;i++)//8位计数器{dat<<=1;SCL=1;//拉高时钟线Delay5us();//延时if(SDA==1)dat|=1;//读数据elsedat|=0;SCL=0;//拉低时钟线Delay5us();//延时}SDA_LOW();returndat;}//******单字节写入*******************************************voidSingle_Write_MMA8452(ucharREG_Address,ucharREG_data){MMA8452_Start();//起始信号MMA8452_SendByte(SlaveAddress);//发送设备地址+写信号MMA8452_SendByte(REG_Address);//内部寄存器地址MMA8452_SendByte(REG_data);//内部寄存器数据MMA8452_Stop();//发送停止信号}//********单字节读取*****************************************ucharSingle_Read_MMA8452(ucharREG_Address){ucharREG_data;MMA8452_Start();//起始信号MMA8452_SendByte(SlaveAddress);//发送设备地址+写信号MMA8452_SendByte(REG_Address);//发送存储单元地址,从0开始MMA8452_Start();//起始信号MMA8452_SendByte(SlaveAddress+1);//发送设备地址+读信号REG_data=MMA8452_RecvByte();//读出寄存器数据MMA8452_SendACK(1);MMA8452_Stop();//停止信号returnREG_data;}//*********************************************************////连续读出MMA8452内部加速度数据,地址范围0x01~0x06////*********************************************************voidMultiple_Read_MMA8452(void){uchari;MMA8452_Start();//起始信号MMA8452_SendByte(SlaveAddress);//发送设备地址+写信号MMA8452_SendByte(0x01);//发送存储单元地址,从0x01开始MMA8452_Start();//起始信号MMA8452_SendByte(SlaveAddress+1);//发送设备地址+读信号for(i=0;i<6;i++)//连续读取6个地址数据,存储中BUF{BUF[i]=MMA8452_RecvByte();//BUF[0]存储0x32地址中的数据if(i==5){MMA8452_SendACK(1);//最后一个数据需要回NOACK}else{MMA8452_SendACK(0);//回应ACK}}MMA8452_Stop();//停止信号Delay5ms();}voidWrite_drift_MMA8452(inti,intj,intz){MMA8452_Start();MMA8452_SendByte(SlaveAddress);MMA8452_SendByte(0x2F);MMA8452_SendByte(i);MMA8452_Start();MMA8452_SendByte(SlaveAddress);MMA8452_SendByte(0x30);MMA8452_SendByte(j);MMA8452_Start();MMA8452_SendByte(SlaveAddress);MMA8452_SendByte(0x31);MMA8452_SendByte(z);}//*********************************************************/*voidRead_drift_MMA8452(void){uchari;MMA8452_Start();//起始信号MMA8452_SendByte(SlaveAddress);//发送设备地址+写信号MMA8452_SendByte(0x10);//发送存储单元地址,从0x32开始MMA8452_Start();//起始信号MMA8452_SendByte(SlaveAddress+1);//发送设备地址+读信号for(i=0;i<7;i++)//连续读取6个地址数据,存储中BUF{BUF_drift[i]=MMA7455_RecvByte();//BUF[0]存储0x32地址中的数据if(i==6){MMA7455_SendACK(1);//最后一个数据需要回NOACK}else{MMA7455_SendACK(0);//回应ACK}}MMA7455_Stop();//停止信号Delay5ms();}*/voidcheck()//自检{inti=0,j=0,k=0,flag1=1,flag2=1,flag3=1;floattemp1,temp2,temp3;Single_Write_MMA8452(0x2A,0x01);//Single_Write_MMA8452(0x2B,0x02);//delay(10);while(flag1||flag2||flag3){Multiple_Read_MMA8452();dis_data=BUF[0];if(dis_data>0x7f)dis_data=(((dis_data-1)^0xff)&0x7f);//取反并屏掉符号位temp1=(float)dis_data/63;temp1*=100;dis_data=BUF[1];if(dis_data>0x7f)dis_data=(((dis_data-1)^0xff)&0x7f);//取反并屏掉符号位temp2=(float)dis_data/63;temp2*=100;dis_data=BUF[2];if(dis_data>0x7f)dis_data=(((dis_data-1)^0xff)&0x7f);//取反并屏掉符号位temp3=(float)dis_data/63;temp3*=100;Write_drift_MMA8452(i,j,k);if((temp2!=0)&&flag2)j++;elseflag2=0;if((temp3<98)&&flag3)k++;elseflag3=0;if((temp1!=0)&&flag1)i++;elseflag1=0;delay(1);}}//******************初始化IO口voidinit_IO(){ADCON1=0x06;//设置A口为普通I/O口TRISB=0X00;TRISA=0X00;//设置A口为输出//TRISE=0xf0;//PORTE=0;}//初始化MMA8452,根据需要请参考pdf进行修改************************voidInit_MMA8452(){Single_Write_MMA8452(0x2A,0x01);//Single_Write_MMA8452(0x2B,0x02);//LCD_clear();//清屏LCD_write_char(2,2,'C');LCD_write_char(3,2,'H');LCD_write_char(4,2,'E');LCD_write_char(5,2,'C');LCD_write_char(6,2,'K');LCD_write_char(7,2,14);LCD_write_char(8,2,14);LCD_write_char(9,2,14);LCD_write_char(10,2,14);LCD_write_char(11,2,14);LCD_write_char(12,2,14);LCD_write_char(0,3,'P');LCD_write_char(1,3,'L');LCD_write_char(2,3,'E');LCD_write_char(3,3,'A');LCD_write_char(4,3,'S');LCD_write_char(5,3,'E');LCD_write_char(6,3,0);LCD_write_char(7,3,'W');LCD_write_char(8,3,'A');LCD_write_char(9,3,'I');LCD_write_char(10,3,'T');delay(500);check();}//*********************************************************//******主程序********//*********************************************************voidmain(){intsign_bit;unsignedinti;floattemp;delay(2);//上电延时init();SPIINT();delay(500);LCD_init();//初始化LCD模块init_IO();Init_MMA8452();//初始化MMA8452LCD_clear();//清屏幕while(1)//循环{Multiple_Read_MMA8452();//连续读出数据,存储在BUF中//---------显示X轴dis_data=BUF[0];if(dis_data>0x7f){dis_data=0xff-dis_data;sign_bit=1;}elsesign_bit=0;//确定正负符号位temp=(float)dis_data/63;temp*=100;conversion(temp);//计算数据和显示LCD_write_char(0,0,56);//XLCD_write_char(1,0,26);//':'if(sign_bit==1)LCD_write_char(2,0,13);//-elseLCD_write_char(2,0,0);//显示正负符号位LCD_write_char(3,0,bai);LCD_write_char(4,0,14);//.LCD_write_char(5,0,shi);LCD_write_char(6,0,ge);LCD_write_char(7,0,'G');//---------显示Y轴dis_data=BUF[2];if(dis_data>0x7f){dis_data=0xff-dis_data;sign_bit=1;}elsesign_bit=0;//确定正负符号位temp=(float)dis_data/63;temp*=100;conversion(temp);//计算数据和显示LCD_write_char(0,1,57);//YLCD_write_char(1,1,26);//:if(sign_bit==1)LCD_write_char(2,1,13);//-elseLCD_write_char(2,1,0);//显示正负符号位LCD_write_char(3,1,bai);LCD_write_char(4,1,14);//.LCD_write_char(5,1,shi);LCD_write_char(6,1,ge);LCD_write_char(7,1,'G');//-------显示Z轴dis_data=BUF[4];if(dis_data>0x7f){dis_data=0xff-dis_data;sign_bit=1;}elsesign_bit=0;//确定正负符号位temp=(float)dis_data/63;temp*=100;conversion(temp);//计算数据和显示LCD_write_char(0,2,58);//Z
for(j=0;j<110;j++);
/**************************************
延时5微秒(STC90C52RC@12M)
不同的工作环境,需要调整此函数,注意时钟过快时需要修改
当改用1T的MCU时,请调整此延时函数
**************************************/
voidDelay5us()
NOP();NOP();NOP();NOP();
NOP();//NOP();NOP();NOP();
//NOP();NOP();NOP();NOP();
延时5毫秒(STC90C52RC@12M)
不同的工作环境,需要调整此函数
voidDelay5ms()
WORDn=560;
while(n--);
起始信号
voidMMA8452_Start()
SDA_LOW();
SDA=1;//拉高数据线
SCL=1;//拉高时钟线
Delay5us();//延时
SDA=0;//产生下降沿
SCL=0;//拉低时钟线
停止信号
voidMMA8452_Stop()
SDA=0;//拉低数据线
SDA=1;//产生上升沿
发送应答信号
入口参数:
ack(0:
ACK1:
NAK)
voidMMA8452_SendACK(ucharack)
SDA=ack;//写应答信号
接收应答信号
bitMMA8452_RecvACK()
SDA_HIGH();
if(SDA==1)
CY=1;
else
CY=0;//读应答信号
returnCY;
向IIC总线发送一个字节数据
voidMMA8452_SendByte(BYTEdat)
BYTEi;
for(i=0;i<8;i++)//8位计数器
if(dat&0x80)
elseCY=0;
SDA=CY;//送数据口
dat<<=1;//移出数据的最高位
MMA8452_RecvACK();
从IIC总线接收一个字节数据
BYTEMMA8452_RecvByte()
BYTEdat=0;
SDA=1;//使能内部上拉,准备读取数据,
dat<<=1;
dat|=1;//读数据
dat|=0;
returndat;
//******单字节写入*******************************************
voidSingle_Write_MMA8452(ucharREG_Address,ucharREG_data)
MMA8452_Start();//起始信号
MMA8452_SendByte(SlaveAddress);//发送设备地址+写信号
MMA8452_SendByte(REG_Address);//内部寄存器地址
MMA8452_SendByte(REG_data);//内部寄存器数据
MMA8452_Stop();//发送停止信号
//********单字节读取*****************************************
ucharSingle_Read_MMA8452(ucharREG_Address)
{ucharREG_data;
MMA8452_SendByte(REG_Address);//发送存储单元地址,从0开始
MMA8452_SendByte(SlaveAddress+1);//发送设备地址+读信号
REG_data=MMA8452_RecvByte();//读出寄存器数据
MMA8452_SendACK
(1);
MMA8452_Stop();//停止信号
returnREG_data;
//
//连续读出MMA8452内部加速度数据,地址范围0x01~0x06
voidMultiple_Read_MMA8452(void)
{uchari;
MMA8452_SendByte(0x01);//发送存储单元地址,从0x01开始
for(i=0;i<6;i++)//连续读取6个地址数据,存储中BUF
BUF[i]=MMA8452_RecvByte();//BUF[0]存储0x32地址中的数据
if(i==5)
(1);//最后一个数据需要回NOACK
MMA8452_SendACK(0);//回应ACK
Delay5ms();
voidWrite_drift_MMA8452(inti,intj,intz)
MMA8452_Start();
MMA8452_SendByte(SlaveAddress);
MMA8452_SendByte(0x2F);
MMA8452_SendByte(i);
MMA8452_SendByte(0x30);
MMA8452_SendByte(j);
MMA8452_SendByte(0x31);
MMA8452_SendByte(z);
/*voidRead_drift_MMA8452(void)
uchari;
MMA8452_SendByte(0x10);//发送存储单元地址,从0x32开始
for(i=0;i<7;i++)//连续读取6个地址数据,存储中BUF
BUF_drift[i]=MMA7455_RecvByte();//BUF[0]存储0x32地址中的数据
if(i==6)
MMA7455_SendACK
MMA7455_SendACK(0);//回应ACK
MMA7455_Stop();//停止信号
}*/
voidcheck()//自检
inti=0,j=0,k=0,flag1=1,flag2=1,flag3=1;
floattemp1,temp2,temp3;
Single_Write_MMA8452(0x2A,0x01);//
Single_Write_MMA8452(0x2B,0x02);//
delay(10);
while(flag1||flag2||flag3)
Multiple_Read_MMA8452();
dis_data=BUF[0];
if(dis_data>0x7f)
dis_data=(((dis_data-1)^0xff)&0x7f);//取反并屏掉符号位
temp1=(float)dis_data/63;
temp1*=100;
dis_data=BUF[1];
temp2=(float)dis_data/63;
temp2*=100;
dis_data=BUF[2];
temp3=(float)dis_data/63;
temp3*=100;
Write_drift_MMA8452(i,j,k);
if((temp2!
=0)&&flag2)
j++;
flag2=0;
if((temp3<98)&&flag3)
k++;
flag3=0;
if((temp1!
=0)&&flag1)
i++;
flag1=0;
delay
//******************初始化IO口
voidinit_IO()
ADCON1=0x06;//设置A口为普通I/O口
TRISB=0X00;
TRISA=0X00;//设置A口为输出
//TRISE=0xf0;
//PORTE=0;
//初始化MMA8452,根据需要请参考pdf进行修改************************
voidInit_MMA8452()
LCD_clear();//清屏
LCD_write_char(2,2,'C');LCD_write_char(3,2,'H');LCD_write_char(4,2,'E');
LCD_write_char(5,2,'C');LCD_write_char(6,2,'K');
LCD_write_char(7,2,14);LCD_write_char(8,2,14);
LCD_write_char(9,2,14);LCD_write_char(10,2,14);
LCD_write_char(11,2,14);LCD_write_char(12,2,14);
LCD_write_char(0,3,'P');LCD_write_char(1,3,'L');LCD_write_char(2,3,'E');LCD_write_char(3,3,'A');LCD_write_char(4,3,'S');
LCD_write_char(5,3,'E');LCD_write_char(6,3,0);LCD_write_char(7,3,'W');LCD_write_char(8,3,'A');LCD_write_char(9,3,'I');
LCD_write_char(10,3,'T');
delay(500);
check();
//******主程序********
voidmain()
intsign_bit;
unsignedinti;
floattemp;
(2);//上电延时
init();
SPIINT();
LCD_init();//初始化LCD模块
init_IO();
Init_MMA8452();//初始化MMA8452
LCD_clear();//清屏幕
while
(1)//循环
Multiple_Read_MMA8452();//连续读出数据,存储在BUF中
//---------显示X轴
dis_data=0xff-dis_data;
sign_bit=1;
sign_bit=0;//确定正负符号位
temp=(float)dis_data/63;
temp*=100;
conversion(temp);//计算数据和显示
LCD_write_char(0,0,56);//X
LCD_write_char(1,0,26);//':
'
if(sign_bit==1)LCD_write_char(2,0,13);//-
elseLCD_write_char(2,0,0);//显示正负符号位
LCD_write_char(3,0,bai);
LCD_write_char(4,0,14);//.
LCD_write_char(5,0,shi);
LCD_write_char(6,0,ge);
LCD_write_char(7,0,'G');
//---------显示Y轴
if(dis_data>0x7f){
LCD_write_char(0,1,57);//Y
LCD_write_char(1,1,26);//:
if(sign_bit==1)LCD_write_char(2,1,13);//-
elseLCD_write_char(2,1,0);//显示正负符号位
LCD_write_char(3,1,bai);
LCD_write_char(4,1,14);//.
LCD_write_char(5,1,shi);
LCD_write_char(6,1,ge);
LCD_write_char(7,1,'G');
//-------显示Z轴
dis_data=BUF[4];
LCD_write_char(0,2,58);//Z
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1