济南电子爱好者 发表于 2012-3-27 09:32:24

51单片机 L3G4200D三轴陀螺仪 IIC测试程序

本帖最后由 济南电子爱好者 于 2012-3-27 09:41 编辑

    本人新手,最近也开始做起了四轴,我看论坛里贴代码很少,难道大家都是编程高手。下面是51单片机 L3G4200D三轴陀螺仪 IIC测试程序,只显示角速度没读取温度。
代码来自模块的资料,经过大量的修改。
这是1602的头文件
#define   DataPort P0    //LCD1602数据端口
sbit      LCD_RS=P2^4;   //LCD1602命令端口               
sbit      LCD_RW=P2^5;   //LCD1602命令端口               
sbit      LCD_EN=P2^6;   //LCD1602命令端口
#include <INTRINS.H>
#define   uchar unsigned char
void WaitForEnable(void)       
{                                       
        DataPort=0xff;               
        LCD_RS=0;
        LCD_RW=1;
        _nop_();
        LCD_EN=1;
        _nop_();
        _nop_();
        while(DataPort&0x80);       
        LCD_EN=0;                               
}       

void WriteCommandLCD(uchar CMD,uchar Attribc)
{                                       
        if(Attribc)
           WaitForEnable();       
        LCD_RS=0;
        LCD_RW=0;
        _nop_();
        DataPort=CMD;
        _nop_();       
        LCD_EN=1;
        _nop_();
        _nop_();
        LCD_EN=0;
}       
void WriteDataLCD(uchar dataW)
{                                       
        WaitForEnable();               
        LCD_RS=1;
        LCD_RW=0;
        _nop_();
        DataPort=dataW;
        _nop_();       
        LCD_EN=1;
        _nop_();
        _nop_();
        LCD_EN=0;
}       

void InitLcd()                               
{                       
        WriteCommandLCD(0x38,1);       
        WriteCommandLCD(0x08,1);       
        WriteCommandLCD(0x01,1);       
        WriteCommandLCD(0x06,1);       
        WriteCommandLCD(0x0c,1);
}
void DisplayOneChar(uchar X,uchar Y,uchar DData)
{                                               
        Y&=1;                                               
        X&=15;                                               
        if(Y)
          X|=0x40;                                       
        X|=0x80;                       
        WriteCommandLCM(X,0);               
        WriteDataLCD(DData);               
}
                       

下面是主程序:                                                                                                                                               


//***************************************
// L3G4200D三轴陀螺仪 IIC测试程序
// 使用单片机STC89C51
// 晶振:11.0592M
// 显示:LCD1602
// 编译环境 Keil uVision2
// 参考宏晶网站24c04通信程序
// 时间:2011年3月1日
// ****************************************
#include <reg52.h>
#include "1602.h"
#include <math.h>   
#include <stdio.h>          
#include <INTRINS.H>   
#define   uchar unsigned char
#define   uint unsigned int       
sbit          SCL=P1^0 ;   //IIC时钟引脚定义
sbit           SDA=P1^1;    //IIC数据引脚定义

//********************

#define WHO_AM_I 0x0F
#define CTRL_REG1 0x20   //
#define CTRL_REG2 0x21   
#define CTRL_REG3 0x22
#define CTRL_REG4 0x23
#define CTRL_REG5 0x24
#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

#define        SlaveAddress   0xD2          //定义器件在IIC总线中的从地址,根据ALTADDRESS地址引脚不同修改
typedef unsigned charBYTE;
typedef unsigned short WORD;
BYTE BUF;                         //接收数据缓存区             
uchar ge,shi,bai,qian,wan;         //显示变量
int dis_data;//变量
//int temp;
void delay(unsigned int k);
void InitL3G4200D(uchar );             //初始化L3G4200D
void conversion(uint temp_data);
voidSingle_WriteL3G4200D(uchar REG_Address,uchar REG_data);   //单个写入数据
uchar Single_ReadL3G4200D(uchar REG_Address);                   //单个读取内部寄存器数据
            
//------------------------------------
void Delay5us();
void L3G4200D_Start();
void L3G4200D_Stop();
void L3G4200D_SendACK(bit ack);
voidL3G4200D_RecvACK();
void L3G4200D_SendByte(BYTE dat);
BYTE L3G4200D_RecvByte();

void display_x();
void display_y();
void display_z();

//-----------------------------------

//*********************************************************
void conversion(uint temp_data)
{
    temp_data*=0.875;
    wan=temp_data/10000+0x30 ;
    temp_data=temp_data%10000;   //取余运算
        qian=temp_data/1000+0x30 ;
    temp_data=temp_data%1000;    //取余运算
    bai=temp_data/100+0x30   ;
    temp_data=temp_data%100;   //取余运算
    shi=temp_data/10+0x30    ;
    temp_data=temp_data%10;      //取余运算
    ge=temp_data+0x30;        
}

/*******************************/
void delay(unsigned int k)       
{                                               
        unsigned int i,j;                               
        for(i=0;i<k;i++)
        {                       
          for(j=0;j<121;j++)                       
          {;}
        }                                               
}
/*****************************

************************************
延时5微秒(STC90C52RC@12M)
不同的工作环境,需要调整此函数,注意时钟过快时需要修改
当改用1T的MCU时,请调整此延时函数
**************************************/
void Delay5us()
{
    _nop_();_nop_();_nop_();_nop_();
    _nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();
    _nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();
}


/**************************************
起始信号
**************************************/
void L3G4200D_Start()
{
    SDA = 1;                  //拉高数据线
    SCL = 1;                  //拉高时钟线
    Delay5us();               //延时
    SDA = 0;                  //产生下降沿
    Delay5us();               //延时
    SCL = 0;                  //拉低时钟线
}

/**************************************
停止信号
**************************************/
void L3G4200D_Stop()
{
    SDA = 0;                  //拉低数据线
    SCL = 1;                  //拉高时钟线
    Delay5us();               //延时
    SDA = 1;                  //产生上升沿
    Delay5us();               //延时
}

/**************************************
发送应答信号
入口参数:ack (0:ACK 1:NAK)
**************************************/
void L3G4200D_SendACK(bit ack)
{
    SDA = ack;                  //写应答信号
    SCL = 1;                  //拉高时钟线
    Delay5us();               //延时
    SCL = 0;                  //拉低时钟线
    Delay5us();               //延时
}

/**************************************
接收应答信号
**************************************/
void L3G4200D_RecvACK()
{
    SCL = 1;                  //拉高时钟线
    Delay5us();               //延时
    while(SDA==1);
    SCL = 0;                  //拉低时钟线
    Delay5us();               //延时

}



/**************************************
向IIC总线发送一个字节数据
**************************************/
void L3G4200D_SendByte(BYTE dat)
{
    BYTE i;
    for (i=0; i<8; i++)         //8位计数器
    {
      SDA = dat&0x80;               //送数据口
      dat=dat<<1;
      SCL = 1;                //拉高时钟线
      Delay5us();             //延时
      SCL = 0;                //拉低时钟线
      Delay5us();             //延时
    }
    L3G4200D_RecvACK();
}

/**************************************
   从IIC总线接收一个字节数据
**************************************/
BYTE L3G4200D_RecvByte()
{
    BYTE i;
    BYTE dat = 0;
    SDA = 1;                  //使能内部上拉,准备读取数据,
    for (i=0; i<8; i++)         //8位计数器
    {
      dat <<= 1;                              //这里的1是 00000001
      SCL = 1;                //拉高时钟线
      Delay5us();             //延时
      dat |= SDA;             //读数据      SDA00000000 or 00000001         
      SCL = 0;                //拉低时钟线
      Delay5us();             //延时
    }
    return dat;
}

//单字节写入*******************************************

void Single_WriteL3G4200D(uchar REG_Address,uchar REG_data)
{
    L3G4200D_Start();                  //起始信号
    L3G4200D_SendByte(SlaveAddress);   //发送设备地址+写信号
    L3G4200D_SendByte(REG_Address);    //内部寄存器地址,请参考中文pdf22页
    L3G4200D_SendByte(REG_data);       //内部寄存器数据,请参考中文pdf22页
    L3G4200D_Stop();                   //发送停止信号
}

//单字节读取*****************************************
uchar Single_ReadL3G4200D(uchar REG_Address)
{uchar REG_data;
    L3G4200D_Start();                        //起始信号
    L3G4200D_SendByte(SlaveAddress);         //发送设备地址+写信号
    L3G4200D_SendByte(REG_Address);            //发送存储单元地址,从0开始       
    L3G4200D_Start();                        //起始信号
    L3G4200D_SendByte(SlaveAddress+1);         //发送设备地址+读信号
    REG_data=L3G4200D_RecvByte();            //读出寄存器数据
        L3G4200D_SendACK(1);   
        L3G4200D_Stop();                           //停止信号
    return REG_data;
}
//*************************************************



//*****************************************************************

//初始化L3G4200D,根据需要请参考pdf,第27页,进行修改************************
void InitL3G4200D()
{
   Single_WriteL3G4200D(CTRL_REG1, 0x0f);   //0x0f=00001111普通模式   X Y Z 启用。
   Single_WriteL3G4200D(CTRL_REG2, 0x00);   //选择高通滤波模式和高通截止频率此为普通模式
   Single_WriteL3G4200D(CTRL_REG3, 0x08);   //0x08=0000 1000    DRDY/INT2 数据准备(0: Disable; 1: Enable)默认0
   Single_WriteL3G4200D(CTRL_REG4, 0x00 );//选择量程    满量程选择(默认 00)(00:250dps)
   Single_WriteL3G4200D(CTRL_REG5, 0x00);   //   篎FIFO使能,高通滤波使能    默认全0
}
//***********************************************************************
//显示x轴
void display_x()
{

    BUF= Single_ReadL3G4200D(OUT_X_L);
    BUF= Single_ReadL3G4200D(OUT_X_H);//数值计算,请参考L3G4200D_AN3393PDF 第12页
    dis_data=(BUF<<8)+BUF;   //合成数据   
        if(dis_data<0)
        {
                dis_data=-dis_data;            //芯片内储存的就是数值,所以无需转化。
          DisplayOneChar(1,0,'-');       //显示正负符号位
        }
        else
          DisplayOneChar(1,0,' ');//显示空格
//        temp=dis_data*0.875;   //    dis_data/0.00875*100
    conversion(dis_data);          //转换出显示需要的数据
        DisplayOneChar(0,0,'X');       //第0行,第0列 显示X
    DisplayOneChar(2,0,wan);
    DisplayOneChar(3,0,qian);
        DisplayOneChar(4,0,bai);
    DisplayOneChar(5,0,'.');       //8.75mdps/digit就是8.75毫度步进,就是0x0000和0x0001相差8.75毫度。
    DisplayOneChar(6,0,shi);
        DisplayOneChar(7,0,ge);
}

//***********************************************************************
//显示y轴
void display_y()
{   
        BUF= Single_ReadL3G4200D(OUT_Y_L);
        BUF= Single_ReadL3G4200D(OUT_Y_H); //数值计算,请参考L3G4200D_AN3393PDF 第12页
        dis_data=(BUF<<8)+BUF;   //合成数据   
        if(dis_data<0)
        {
                dis_data=-dis_data;
          DisplayOneChar(1,1,'-');       //显示正负符号位
        }
        else
           DisplayOneChar(1,1,' ');//显示空格

    conversion(dis_data);          //转换出显示需要的数据
        DisplayOneChar(0,1,'Y');       //第1行,第0列 显示y
    DisplayOneChar(2,1,wan);
    DisplayOneChar(3,1,qian);
        DisplayOneChar(4,1,bai);
    DisplayOneChar(5,1,'.');
    DisplayOneChar(6,1,shi);
        DisplayOneChar(7,1,ge);
}

//***********************************************************************
//显示z轴
void display_z()
{      
        BUF= Single_ReadL3G4200D(OUT_Z_L);
        BUF= Single_ReadL3G4200D(OUT_Z_H); //数值计算,请参考L3G4200D_AN3393PDF 第12页
        dis_data=(BUF<<8)+BUF;    //合成数据   
        if(dis_data<0)
        {
                dis_data=-dis_data;
          DisplayOneChar(9,1,'-');       //显示负符号位
        }
        else
    {
          DisplayOneChar(9,1,' ');//显示空格
        }
    conversion(dis_data);          //转换出显示需要的数据
        DisplayOneChar(9,0,'Z');      //第0行,第10列 显示Z
    DisplayOneChar(10,0,':');
    DisplayOneChar(11,0,'a');
        DisplayOneChar(12,0,'n');
        DisplayOneChar(13,0,'g');
        DisplayOneChar(14,0,'l');
    DisplayOneChar(15,0,'e');
    DisplayOneChar(10,1,wan);
    DisplayOneChar(11,1,qian);
        DisplayOneChar(12,1,bai);
    DisplayOneChar(13,1,'.');
    DisplayOneChar(14,1,shi);
        DisplayOneChar(15,1,ge);
}


//*********************************************************
//                         主程序
//*********************************************************
void main()
{
delay(500);                         //上电延时               
InitLcd();                     //液晶初始化
InitL3G4200D();                  //初始化L3G4200D
while(1)                         //循环
{   
    display_x();                   //---------显示X轴
    display_y();                   //---------显示Y轴
    display_z();                   //---------显示Z轴
    delay(350);                  //延时            
}
}

补充内容 (2012-3-27 16:40):
我又仔细看了一下在延时5us的函数有点问题,但能够使用。 11.0592Mhz的晶振 只需要延时 4个_nop_()指令就够了。

jiege0119 发表于 2012-3-27 09:38:48

正想了解一下陀螺仪程序

zzz1367 发表于 2012-3-27 09:44:28

谢谢。以后会有用,留着。
顺便帮顶。

Name_006 发表于 2012-3-27 11:24:45

本帖最后由 Name_006 于 2012-3-27 11:24 编辑

顶顶啊支持开源~~~~~~~~~~~~~~~~~~~       {:2_27:}

HYZ1989 发表于 2012-4-13 21:51:56

支持!{:lol:}

xqn2012 发表于 2012-4-15 13:35:37

谢谢分享啊!以后可能用得上

w_ying_qun 发表于 2012-4-17 22:33:53

一直认为程序很高深 怎样能从做硬件的 转到做程序上呢?

济南电子爱好者 发表于 2012-4-19 18:20:04

w_ying_qun 发表于 2012-4-17 22:33 static/image/common/back.gif
一直认为程序很高深 怎样能从做硬件的 转到做程序上呢?

其实不难的,我就是自学的。可以看学习一下汇编,再学习C语言,C语言还是比较通用的。

xue_xi_zhong 发表于 2012-4-26 18:11:01

我也刚开始用L3G4200D,真的谢谢楼主的分享呀

changqing 发表于 2012-5-7 19:18:55

嗯 论坛上正缺这样的人

changqing 发表于 2012-5-7 20:38:09

不过陀螺仪的初始化配置为什么是这样的?

wwwymq 发表于 2012-5-7 23:51:38

驱动是好东西,ctrl+c,ctrl+v

蓝海de梦 发表于 2012-5-8 09:54:47

帮顶!我的L3G4200D还在路上呢要了试试

supan1001 发表于 2012-5-16 19:13:41

mark,谢谢.....

litaov2010 发表于 2012-5-18 09:23:13

谢谢。帮助理解。
来自:amoBBS 阿莫电子论坛 Android客户端

liyue52133 发表于 2012-6-22 23:07:12

这个必须要支持

234918154 发表于 2012-7-31 17:43:08

陀螺仪的驱动一直想玩玩,倒是没有找到资料,有时间再淘宝上淘几片玩玩。。谢谢LZ的程序

234918154 发表于 2012-7-31 17:44:15

陀螺仪的驱动一直想玩玩,倒是没有找到资料,有时间再淘宝上淘几片玩玩。。谢谢LZ的程序

heimantou 发表于 2012-9-2 11:30:46

支持 ,好贴。

long578553882 发表于 2012-10-7 14:07:50

mark......

aa280723148 发表于 2012-10-23 14:32:26

看看。。。。。。。。。。

id_dingjia 发表于 2012-10-28 15:50:19

顶楼主,还有,我想问下,陀螺仪读取出来的角速度有偏差,怎么矫正呢?

vincen 发表于 2012-11-9 22:58:20

lz问下,你的四轴做的怎么样了,你这个是不是不用电调了,也不用飞控,直接就是51+1个陀螺仪+IIC模拟,我想用其他的单片机做下,但不知道需要哪些东西

济南电子爱好者 发表于 2012-11-13 21:58:16

id_dingjia 发表于 2012-10-28 15:50 static/image/common/back.gif
顶楼主,还有,我想问下,陀螺仪读取出来的角速度有偏差,怎么矫正呢?

直接输出的时候给加上或减去一个偏移量就可以 了

济南电子爱好者 发表于 2012-11-13 21:59:14

vincen 发表于 2012-11-9 22:58 static/image/common/back.gif
lz问下,你的四轴做的怎么样了,你这个是不是不用电调了,也不用飞控,直接就是51+1个陀螺仪+IIC模拟,我想 ...

这个只是一个测试的程序 ,设计用ARM9做飞控,开发周期比较的长,目前正在完善中

济南电子爱好者 发表于 2012-11-13 22:01:27

w_ying_qun 发表于 2012-4-17 22:33 static/image/common/back.gif
一直认为程序很高深 怎样能从做硬件的 转到做程序上呢?

可以先从C 51编程入手,会了C语言,其它编程都会很好入手。

culk2008 发表于 2012-11-22 11:24:44

mark,留着有用

haolei432370 发表于 2012-11-24 11:41:53

本帖最后由 haolei432370 于 2012-11-24 12:01 编辑

我也是新手。来讨论问题的。
void Delay5us()
{
    _nop_();_nop_();_nop_();_nop_();
    _nop_();_nop_();_nop_();_nop_();
      _nop_();_nop_();_nop_();_nop_();
      _nop_();_nop_();_nop_();_nop_();
    _nop_();_nop_();_nop_();_nop_();
      _nop_();_nop_();_nop_();_nop_();
}
这个延时是24+2+2=28us(在机械周期1us情况下)
最近也在玩L3G4200D

haolei432370 发表于 2012-11-24 13:47:57

本帖最后由 haolei432370 于 2012-11-24 13:50 编辑

我也来开源下。有问题大家讨论【新手】

有用SPI写的嘛?听说用SPI要在模块上拆两电阻。不知是真是假

redwolf310 发表于 2012-11-25 14:05:12

mark         

CDWJ 发表于 2012-12-24 19:27:51

我看懂了,其实不难的!

CDWJ 发表于 2012-12-24 19:28:31

是一个很好的学习例程!

Zoiphy 发表于 2013-5-3 16:26:08

学习了...
页: [1]
查看完整版本: 51单片机 L3G4200D三轴陀螺仪 IIC测试程序