/*编译环境**************************************
功能 :加速度传感MXC6202接口时序代码
适用 :
CPU :STC12LE5616
IDE :Keil uVision2
电路板 :
加速度传感器MXC6202
P0.0: MXCSDA
P0.1: MXCSCL
本程序说明
本程序已经调试通过并已开始使用,确保时序无误。
如果不能调试通过,请确保硬件电路正确,且延时足够。
本程序包含三个文件:MXC6202.c,MXC6202.h,const.h。
这只是一个项目中的部分文件,不能单独编译。
如果有疑问,欢迎交流:leruite@126.com
广告^_^:
北京乐锐特电子有限公司
老中发3037柜
主营电阻、电容、集成电路,并为客户提供配单服务;单片机系统开发,指导学生毕业设计
电话:010-62610288,15611692294
传真:010-62610288
邮箱:leruite@126.com
QQ:21418740
MSN:leruite@live.cn
欢迎光临、欢迎垂询,本柜台竭诚为您服务。
************************************************/
/*I2C时序说明***********************************
总线空闲
SCLK和SDA都保持高电平
开始信号
SCLK为高,SDA下降沿视为开始信号;从该信号以后总线被认为忙.
数据传送
SCLK为高时,SDA的数据需保持稳定;只有当SCLK为低电平时,才允许SDA上的数据改变.
应答信号
接收数据的IC在每收到1字节(8bit)数据,向发送数据的IC发出低电平脉冲信号,视为已收到信号
结束信号
SCLK为高时,SDA上升沿视为结束信号
************************************************/
#define MXC6202_CFILE
#include "const.H"
#include "MXC6202.h"
#include "utils.h"
/*延时子程序************************************/
static void Delay_Time(u8 time)
{
for(;time>0;time--)
{}
}
/*I2C start***********************************
正常返回0,错误返回-1****************************/
s8 I2c_Start(void) //在SCLK为高时,SDA由高变低,开始
{
u8 temp;
High_Sda(); //SDA置高
Delay_Time(I2C_DELAY);
High_Sclk(); //SCLK置高
Delay_Time(I2C_DELAY); //延时
Set_Sda_In();
temp=I2CSDA;
if(temp)
{
Low_Sda(); //如果SDA为高,正常,把SDA和SCLK置低
Delay_Time(I2C_DELAY);
Low_Sclk();
Delay_Time(I2C_DELAY);
return(0); //返回0表示正常
}
else
{
putstr("Start Error"); //向串口输出提示
return(-1); //否则不正常
}
}
/*I2C stop************************************/
void I2c_Stop(void) //在SCLK为高时,SDA由低变高,结束
{
Low_Sclk();
Low_Sda();
Delay_Time(I2C_DELAY);
High_Sclk();
Delay_Time(I2C_DELAY);
High_Sda();
Delay_Time(I2C_DELAY); //延时
}
/*发送一个ACk***********************************/
void I2c_Send_Ack(void)
{
Low_Sda(); //置低SDA
Delay_Time(I2C_DELAY);
High_Sclk(); //发送一个正脉冲,该位被送出
Delay_Time(I2C_DELAY);
Low_Sclk();
Delay_Time(I2C_DELAY);
}
/*发送一个NOACk*********************************/
void I2c_Send_No_Ack(void)
{
High_Sda(); //置低SDA
Delay_Time(I2C_DELAY);
High_Sclk(); //发送一个正脉冲,该位被送出
Delay_Time(I2C_DELAY);
Low_Sclk();
Delay_Time(I2C_DELAY);
}
/*接收一个ACk***********************************/
u8 I2c_Read_Ack(void)
{
u8 temp;
High_Sda(); //置高SDA
Delay_Time(I2C_DELAY);
High_Sclk(); //发送一个正脉冲,读SDA
Delay_Time(I2C_DELAY);
Set_Sda_In();
temp=I2CSDA;
Low_Sclk(); //把SDA和SCLK置低
Delay_Time(I2C_DELAY);
return(temp);
}
/*发送一个Byte**********************************
由高位到低位发送********************************/
void I2c_Send_Byte(u8 abyte)
{
s8 i;
for(i=7;i>=0;i--) //循环发送每一位
{
if(abyte&(0x01<<i))
{
High_Sda(); //如果被发送的位为高,置高SDA
}
else
{
Low_Sda(); //否则置低SDA
}
Delay_Time(I2C_DELAY);
High_Sclk(); //发送一个正脉冲,该位被送出
Delay_Time(I2C_DELAY);
Low_Sclk();
Delay_Time(I2C_DELAY);
}
}
/*读一个Byte************************************
由高位到低位接收********************************/
u8 I2c_Read_Byte(void)
{
u8 temp=0;
s8 i;
High_Sda();
Set_Sda_In();
for(i=8;i>0;i--) //循环接收每一位
{
temp<<=1; //把数据左移准备读下一次bit
Delay_Time(I2C_DELAY);
High_Sclk(); //拉高SCK
Delay_Time(I2C_DELAY);
if(I2CSDA) //读取一个bit
{
temp|=0x01;
}
Low_Sclk(); //拉低SCK
}
return temp;
}
s8 Init_Mxc6202(void)
{
P0M1&=~0x03; //P0口 7 6 5 4 3 2 1 0
// P0M1|=0x08; // O D
P0M0&=~0x01; //P0M1 0 0
P0M0|=0x02; //P0M0 1 0
Acc_Status=0;
while(I2c_Start()); //第1个周期,启动I2C
I2c_Send_Byte(MXC6202_WR_ADDR); //发送MXC6202写地址
if(I2c_Read_Ack()) //读ACK,错误则停止I2C,返回-1
{
I2c_Stop();
return(-1);
}
I2c_Send_Byte(0); //第2个周期,发送0,做为写入数据的地址
if(I2c_Read_Ack()) //读ACK,错误则停止I2C,返回-1
{
I2c_Stop();
return(-1);
}
I2c_Send_Byte(0); //写入XXXXXXX0B,使其从低功耗模式返回到正常模式
if(I2c_Read_Ack()) //读ACK,错误则停止I2C,返回-1
{
I2c_Stop();
return(-1);
}
I2c_Stop(); //停止I2C总线
Mxc6202_Delay_Cnt=100; //延时1s
while(Mxc6202_Delay_Cnt);
return 0;
}
s8 Get_Mxc6202_Data(s8 * mxc_data)
{
s8 idata i;
while(I2c_Start()); //第4个周期,启动I2C
I2c_Send_Byte(MXC6202_WR_ADDR); //发送MXC6202写地址
if(I2c_Read_Ack()) //读ACK,错误则停止I2C,返回-1
{
I2c_Stop();
return(-1);
}
I2c_Send_Byte(0); //第5个周期,写0,即从地址0开始读取数据
if(I2c_Read_Ack()) //读ACK,错误则停止I2C,返回-1
{
I2c_Stop();
return(-1);
}
I2c_Stop();
while(I2c_Start()); //第6个周期,启动I2C
I2c_Send_Byte(MXC6202_RD_ADDR); //发送MXC6202读地址
if(I2c_Read_Ack()) //读ACK,错误则停止I2C,返回-1
{
I2c_Stop();
return(-1);
}
for(i=4;i>0;i--) //第7~10周期,读出四个数据,并发送ACK
{
mxc_data[i]=I2c_Read_Byte();
I2c_Send_Ack();
}
mxc_data[0]=I2c_Read_Byte(); //第11个周期,读出第五个数据,并发送NO_ACK
I2c_Send_No_Ack();
I2c_Stop(); //停止I2C
return 0;
}
void Get_Static_ACC(void)
{
s8 Mxc_Data[5],i;
Get_Mxc6202_Data(Mxc_Data);
Get_Mxc6202_Data(Mxc_Data);
Get_Mxc6202_Data(Mxc_Data);
X_Static_Acc=0;
Y_Static_Acc=0;
for(i=8;i--;i>0)
{
Get_Mxc6202_Data(Mxc_Data);
X_Static_Acc+=(Mxc_Data[3]<<8)+Mxc_Data[2];
Y_Static_Acc+=(Mxc_Data[1]<<8)+Mxc_Data[0];
}
X_Static_Acc>>=3;
Y_Static_Acc>>=3;
}
void Get_Current_ACC(void)
{
s8 Mxc_Data[5];
s16 xtmp,ytmp;
Get_Mxc6202_Data(Mxc_Data);
X_Acc=(Mxc_Data[3]<<8)+Mxc_Data[2];
Y_Acc=(Mxc_Data[1]<<8)+Mxc_Data[0];
xtmp=X_Acc-X_Static_Acc;
ytmp=Y_Acc-Y_Static_Acc;
if(xtmp<0)
xtmp=~xtmp+1;
if(ytmp<0)
ytmp=~ytmp+1;
if((xtmp>UP_ACC)||(ytmp>UP_ACC))
{
Acc_Status=2;
}
else if((xtmp>MIDDLE_ACC)||(ytmp>MIDDLE_ACC))
{
Acc_Status=1;
}
else
{
Acc_Status=0;
}
}
void Delay_Mxc6202_10ms(void)
{
if(Mxc6202_Delay_Cnt>0)
Mxc6202_Delay_Cnt--;
}