这是我的IIC的C文件:
#include <hidef.h> /* common defines and macros */
#include "Q.h"
#include "uart.h"
#include "derivative.h" /* derivative-specific definitions */
#include "IIC_L3G4200D.h"
#include "MC9S12XS128.h"
#define uint unsigned int
int IIC_Receive[6];
uchar IIC_ERROR; /*应答标志位*/
/***************************************************
IIC通信
注意 !总线频率为80MHZ,如需应用与不同频率,请
更改延时函数,增减至合适的NOP数量。器件地址为SDO接高的地址
SDO默认为高。
****************************************************/
void IIC_Init()
{
DDRA=0xff;
}
void Delay1us(int c)
{
int cnt;
for(cnt=0;cnt<c;cnt++)
{
_asm NOP;_asm NOP;_asm NOP;
_asm NOP;_asm NOP;_asm NOP;
_asm NOP;_asm NOP;_asm NOP;
_asm NOP;_asm NOP;_asm NOP;
_asm NOP;_asm NOP;
_asm NOP;_asm NOP;_asm NOP;
_asm NOP;_asm NOP;_asm NOP;
}
}
void IIC_START()
{
SDA=1; /*发送起始条件的数据信号*/
Delay1us(1);
SCL=1;
Delay1us(5); /*起始条件建立时间大于4.7us,延时*/
SDA=0; /*发送起始信号*/
Delay1us(5); /* 起始条件锁定时间大于4μs*/
SCL=0; /*钳住IIC总线,准备发送或接收数据 */
Delay1us(2);
}
void IIC_STOP()
{
SDA=0; /*发送结束条件的数据信号*/
Delay1us(1); /*发送结束条件的时钟信号*/
SCL=1; /*结束条件建立时间大于4us*/
Delay1us(5);
SDA=1; /*发送IIC总线结束信号*/
Delay1us(4);
}
void IIC_Send_ack(uchar A)
{
SDA=A;
Delay1us(1);
SCL=1;
Delay1us(5);
SCL=0;
Delay1us(2);
}
void IIC_Check_ack()
{
Delay1us(3);
SCL=0;
Delay1us(3);
DDRJ_DDRJ6=0;
SDA=1;
Delay1us(3);
SCL=1;
Delay1us(5);
if(SDA==1)
IIC_ERROR=1;
else
IIC_ERROR=0;
SCL=0;
Delay1us(3);
DDRJ_DDRJ6=1;
}
//**************通过IIC总线发送1字节数据***************//
void IIC_Send1byte(uchar data)
{
uint i=8;
uchar m=data;
uchar temp;
for(i=8;i>0;i--)
{
temp=m&0x80;
if(temp==0x80)
SDA=1;
else
SDA=0;
Delay1us(5);
SCL=1;
Delay1us(5);
SCL=0;
m=m<<1;
}
}
//***************通过IIC总线接受1字节数据******************//
uchar IIC_Receive1byte()
{
int i=8;
uchar j=0;
DDRJ_DDRJ6=0;
SDA=1;
for(i=8;i>0;i--)
{
SDA=1;
Delay1us(3);
SCL=1;
Delay1us(5);
if(SDA==1)
j=j|0x01;
else j=j;
SCL=0;
if(i!=1)
{
j=j<<1;
}
}
DDRJ_DDRJ6=1;
return j;
}
// *****通过IIC总线向某一寄存器写入一个字节数据********
void IIC_write(uchar add,uchar mem,uchar data) // 写数据(器件地址,寄存器地址,数据)
{
IIC_START();
IIC_Send1byte(add);
IIC_Check_ack();
IIC_Send1byte(mem);
IIC_Check_ack();
IIC_Send1byte(data);
IIC_Check_ack();
IIC_STOP();
}
//***************L3G4200D读取*******************//
void L3G4200D_Init()
{
IIC_write(READ,0X20, 0xce); // 0x8f=10001111 800hz普通模式 X Y Z 启用。
IIC_write(READ,0X21, 0x00); // 选择高通滤波模式和高通截止频率 此为普通模式
IIC_write(READ,0X22, 0x08); // 0x08=0000 1000 DRDY/INT2 数据准备(0: Disable; 1: Enable)默认0
IIC_write(READ,0X23, 0x36); // 选择量程 满量程选择(默认 00)(01:500dps)
IIC_write(READ,0X24, 0x00); // FIFO使能,高通滤波使能 默认全0 都不使能
}
int IIC_Read(uchar add,uchar mem) // 读数据(器件地址,寄存器地址)
{
int data;
IIC_START();
IIC_Send1byte(add);
IIC_Check_ack();
IIC_Send1byte(mem);
IIC_Check_ack();
IIC_START();
IIC_Send1byte(add+1);
IIC_Check_ack();
data=IIC_Receive1byte();
IIC_Send_ack(1);
IIC_STOP();
return data;
}
/************************************************
* 函数名称:Get_Gyro
* 功能说明:读取L3G4200D数据
* 参数说明:n为读几次,Axis为哪个轴,'X''Y''Z'
* 函数返回:角速度的值
* 修改时间:2014-1-14 已经测试
*************************************************/
int Get_Gyro(unsigned char n,unsigned char Axis) //n为读几次
{
unsigned char h,l;
int sum=0;
short int single=0;
unsigned char i;
unsigned char MSB,LSB;
if(Axis=='X') //侧身
{
MSB=OUT_X_H;
LSB=OUT_X_L;
}
else if(Axis=='Y') //cos
{
MSB=OUT_Y_H;
LSB=OUT_Y_L;
}
else if(Axis=='Z') //sin
{
MSB=OUT_Z_H;
LSB=OUT_Z_L;
}
for(i=0;i<n;i++)
{
h = IIC_Read(0xD2,MSB);
l = IIC_Read(0xD2,LSB);
single = (h<<8u) + l;
sum += single;
}
return(sum/n);
}
IIC的h文件如下:
#ifndef __IIC_L3G4200D_H__
#define __IIC_L3G4200D_H__
#define uchar unsigned char
#include <hidef.h> /* common defines and macros */
#include "uart.h"
#include "derivative.h" /* derivative-specific definitions */
#include "MC9S12XS128.h"
#define SDA PORTA_PA1
#define SCL PORTA_PA0
#define READ 0XD2
#define OUT_X_L 0x28
#define OUT_X_H 0x29
#define OUT_Y_L 0x2A
#define OUT_Y_H 0x2B
#define OUT_Z_L 0x2C
#define OUT_Z_H 0x2D
extern int dis_datay,dis_dataz;
void GET_AngleSpeed(void) ;
void IIC_Init(void); //IIC初始化
void Delay1us(int c); //精准延时,80MHZ下的,如需更改,按个数增减NOP即可。不同PLL也要更改
void IIC_START(void);
void IIC_STOP(void);
void IIC_Send_ack(uchar A) ; //发送应答信号
void IIC_Check_ack(void); //检查应答信号
void IIC_Send1byte(uchar data); //发送一个字节数据
uchar IIC_Receive1byte(void); //接收一个字节数据
void IIC_write(uchar add,uchar mem,uchar data); // 写数据(器件地址,寄存器地址,数据)
int IIC_Read(uchar add,uchar mem); // 读数据(器件地址,寄存器地址)
void L3G4200D_Init(void);
//void Display_Vs(void) ; //输出到虚拟示波器VisualScope上
#endif
主函数调用如下:
#include <hidef.h> /* common defines and macros */
#include "Q.h"
#include "uart.h"
#include "derivative.h" /* derivative-specific definitions */
#include "IIC_L3G4200D.h"
#include "MC9S12XS128.h"
#define uint unsigned int
#define uchar unsigned char
unsigned char ID1;
int dis_datay;
int dis_dataz;
//-----时钟初始化程序--------//
void PLL_Init(void) //PLLCLK=2*OSCCLK*(SYNR+1)/(REFDV+1) 40MHZ
{
CLKSEL=0X00; //disengage PLL to system
PLLCTL_PLLON=1; //turn on PLL
SYNR =0xc0 | 0x09;
REFDV=0x80 | 0x01;
POSTDIV=0x00; //pllclock=2*osc*(1+SYNR)/(1+REFDV)=160MHz; 这里的SYNR和REFDV的值指的是低六位的有效值。
_asm(nop); //BUS CLOCK=80M
_asm(nop);
while(!(CRG标志寄存器_LOCK==1)); //when pll is steady ,then use it;
CLKSEL_PLLSEL =1; //engage PLL to system;
}
///////------------ PIT定时2ms---------//////////
void PIT_Init(void) //2MS
{
PITCFLMT=0x00; //禁止PIT模块
PITCE_PCE0=1; //使能定时器通道0
PITMUX=0x00; //定时器通道0使能微定时基准0
PITMTLD0=0xFF; //设置8位微定时器的初值为0
PITLD0=0x0270;//设置16位装载寄存器的初值
PITINTE=0x01; //使能定时器通道0中断
PITCFLMT=0X80; //使能PIT模块 定时时间=(PITMTLD0+1)*(PITLD0+1)/fBUS
}
void main(void)
{
PLL_Init(); //时钟初始化放在最开始处
PIT_Init();
IIC_Init(); //IIC初始化
L3G4200D_Init(); //L3G4200D初始化
ID1=IIC_Read(READ,0X0F);
SCI_Init();
EnableInterrupts;
send(0x58);
send(0xaa);
send(0x01);
send(0x02);
for(;;) {
dis_datay=Get_Gyro(1,'X')-30; //用于转弯的角速度
dis_dataz=Get_Gyro(1,'Y')-20;
}
for(;;) {
_FEED_COP(); /* feeds the dog */
} /* loop forever */
/* please make sure that you never leave main */
}
大神们求救,感激! |