作者:卢老师,华清远见嵌入式学院讲师。
在cc2530中没有IIC总线控制器,只能使用模拟的方式采集,在下面原理图中,重力加速度传感器是飞思卡尔的MMA7455L。
IIC的时钟接cc2530 的P0_5 ;数据线接 P0-7,在使用模拟方式时,数据线要随输入输出改变自己的IO方向。
原理图:
#define I2C_SCL P0_5// I2C Serial Clock
#define I2C_SDA P0_7 // I2C Serial Data
#define ADDR_MMA7455L_WR (0x1D << 1)
#define ADDR_MMA7455L_RD (0x1D << 1)
首先对IO初始化,P0DIR=0XA0;//P0_5 out;p0_7 out
IIC启动:
void I2C_start(void)
{
P0DIR|=0X80;//data out ;
I2C_SDA=1;
I2C_SCL=1;
delay_us(6);
I2C_SDA=0;
delay_us(6);
I2C_SCL=0;
delay_us(6);
}
IIc停止
void I2C_stop(void)
{
P0DIR|=0X80;//data out ;
I2C_SCL=0;
I2C_SDA=0;
delay_us(6);
I2C_SCL=1;
delay_us(6);
I2C_SDA=1;
delay_us(6);
EA = 1 ;
}
IIC等待应答
unsigned char WaitAck(void)
{
unsigned interrtime =60000; //最大值不就65536
P0DIR |=0X80;//data out ;
I2C_SDA=1;
P0DIR |=(~0X80);// data int ;
delay_us(60);
I2C_SCL=1;delay_us(6);
while(I2C_SDA)
{
errtime--;
if(!errtime)
{
I2C_stop();
return(1);
}
}
delay_us(6);
I2C_SCL = 0;
return(1);
}
IIC发送应答
void I2C_sendAck(void) // ACK
{
P0DIR |=0X80;//data out ;
I2C_SDA=0;delay_us(6);
I2C_SCL=1;delay_us(6);
I2C_SCL=0;delay_us(6);
I2C_SDA=1;
}
IIC发送一个字节
void I2C_sendByte(unsigned char sdata) //发送数据字节格式
{
unsigned char i = 8;
P0DIR |=0X80;//data out ;
while(i--)
{
I2C_SCL=0;
delay_us(60);
if((sdata& 0x80)==1)
{I2C_SDA =1;}
else
{I2C_SDA =0;}
sdata=sdata<<1;
delay_us(6);
I2C_SCL=1;
delay_us(6);
}
I2C_SCL=0;
}
IIC接受一个字节
unsigned char I2C_receiveByte(void) //接受数据
{
unsigned char i = 8;
unsigned char rdata = 0;
P0DIR |=(~0X80);// data int ;
while(i--)
{
rdata=rdata<<1;
I2C_SCL=0; delay_us(6);
I2C_SCL=1; delay_us(6);
rdata |= I2C_SDA;
delay_us(6);
}
I2C_SCL=0;
delay_us(6);
return(rdata);
}
IIC发送数据包
voidwrite_block(unsigned char address,unsigned char wdata)
{
I2C_start();
I2C_sendByte(ADDR_MMA7455L_WR);
while(!WaitAck());
I2C_sendByte(address);
while(!WaitAck());
I2C_stop();
}
//读外部数据//
signed char read_block(unsigned char address)
{
signed char j;
I2C_start();
I2C_sendByte(ADDR_MMA7455L_WR);
while(!WaitAck());
I2C_sendByte(address);
while(!WaitAck());
I2C_start();
I2C_sendByte(ADDR_MMA7455L_RD|0x01);
while(!WaitAck());
j= I2C_receiveByte();
delay_us(5);
I2C_stop();
return j;
}
读取MMA7455L x轴,y轴,z轴的值;
voidacc_read (int8_t *x, int8_t *y, int8_t *z)
{
charbuf[1];
while ((getStatus() & ACC_STATUS_DRDY) == 0);
buf[0] = read_block(ACC_ADDR_XOUT8);
*x = (char)buf[0];
buf[0] = read_block(ACC_ADDR_YOUT8);
*y = (char)buf[0];
buf[0] = read_block(ACC_ADDR_ZOUT8);
*z = (char)buf[0];
}
MMA7455L测试程序;
void Axis3_Test(void)
{
I2CInit();
acc_init();
// Assume base board in zero-g position when reading first value.
acc_read(&x, &y, &z);
xoff = 0-x;
yoff = 0-y;
zoff = 0-z;
{
acc_read(&x, &y, &z);
x = x+xoff;
y = y+yoff;
z = z+zoff;
}
}
主程序将采集的值通过串口打印出来
void main(void) {
CLKCONCMD &= ~0x40; //设置系统时钟源为32MHZ晶振
while(CLKCONSTA & 0x40); //等待晶振稳定为32M
CLKCONCMD &= ~0x47; //设置系统主时钟频率为32MHZ
IO_Init();
InitUART();
I2CInit();
write_block(0x16,0x05);
while(1)
{
Axis3_Test();
Txdata[0]=x;
Txdata[1]=0;
Txdata[2]=y;
Txdata[3]=0;
Txdata[4]=z;
Txdata[5]=0;
UartSend_String(Txdata,7); //串口发送数
Delay_ms(500); //延时
LED1=!LED1; //标志发送状态
}
}
旋转重力加速模块,,打印结果如下图: