搜索
bottom↓
回复: 32

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

[复制链接]

出0入0汤圆

发表于 2012-3-27 09:32:24 | 显示全部楼层 |阅读模式
本帖最后由 济南电子爱好者 于 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总线中的从地址,根据ALT  ADDRESS地址引脚不同修改
typedef unsigned char  BYTE;
typedef unsigned short WORD;
BYTE BUF[8];                         //接收数据缓存区             
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);
void  Single_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);
void  L3G4200D_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;             //读数据      SDA  00000000 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[0]= Single_ReadL3G4200D(OUT_X_L);
    BUF[1]= Single_ReadL3G4200D(OUT_X_H);//数值计算,请参考L3G4200D_AN3393  PDF 第12页
    dis_data=(BUF[1]<<8)+BUF[0];   //合成数据   
        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[2]= Single_ReadL3G4200D(OUT_Y_L);
        BUF[3]= Single_ReadL3G4200D(OUT_Y_H); //数值计算,请参考L3G4200D_AN3393  PDF 第12页
        dis_data=(BUF[3]<<8)+BUF[2];   //合成数据   
        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[4]= Single_ReadL3G4200D(OUT_Z_L);
        BUF[5]= Single_ReadL3G4200D(OUT_Z_H); //数值计算,请参考L3G4200D_AN3393  PDF 第12页
        dis_data=(BUF[5]<<8)+BUF[4];    //合成数据   
        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_()指令就够了。

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2012-3-27 09:38:48 | 显示全部楼层
正想了解一下陀螺仪程序

出0入0汤圆

发表于 2012-3-27 09:44:28 | 显示全部楼层
谢谢。以后会有用,留着。
顺便帮顶。

出0入0汤圆

发表于 2012-3-27 11:24:45 | 显示全部楼层
本帖最后由 Name_006 于 2012-3-27 11:24 编辑

顶顶啊  支持开源~~~~~~~~~~~~~~~~~~~      

出0入0汤圆

发表于 2012-4-13 21:51:56 | 显示全部楼层
支持!

出0入0汤圆

发表于 2012-4-15 13:35:37 | 显示全部楼层
谢谢分享啊!以后可能用得上

出0入0汤圆

发表于 2012-4-17 22:33:53 | 显示全部楼层
一直认为程序很高深 怎样能从做硬件的 转到做程序上呢?

出0入0汤圆

 楼主| 发表于 2012-4-19 18:20:04 | 显示全部楼层
w_ying_qun 发表于 2012-4-17 22:33
一直认为程序很高深 怎样能从做硬件的 转到做程序上呢?

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

出0入0汤圆

发表于 2012-4-26 18:11:01 | 显示全部楼层
我也刚开始用L3G4200D,真的谢谢楼主的分享呀

出0入0汤圆

发表于 2012-5-7 19:18:55 | 显示全部楼层
嗯 论坛上正缺这样的人

出0入0汤圆

发表于 2012-5-7 20:38:09 | 显示全部楼层
不过陀螺仪的初始化配置为什么是这样的?

出0入0汤圆

发表于 2012-5-7 23:51:38 | 显示全部楼层
驱动是好东西,ctrl+c,ctrl+v

出0入0汤圆

发表于 2012-5-8 09:54:47 | 显示全部楼层
帮顶!我的L3G4200D还在路上呢  要了试试

出0入0汤圆

发表于 2012-5-16 19:13:41 | 显示全部楼层
mark,谢谢.....

出0入0汤圆

发表于 2012-5-18 09:23:13 来自手机 | 显示全部楼层
谢谢。帮助理解。
来自:amoBBS 阿莫电子论坛 Android客户端

出0入0汤圆

发表于 2012-6-22 23:07:12 | 显示全部楼层
这个必须要支持

出0入0汤圆

发表于 2012-7-31 17:43:08 | 显示全部楼层
陀螺仪的驱动一直想玩玩,倒是没有找到资料,有时间再淘宝上淘几片玩玩。。谢谢LZ的程序

出0入0汤圆

发表于 2012-7-31 17:44:15 | 显示全部楼层
陀螺仪的驱动一直想玩玩,倒是没有找到资料,有时间再淘宝上淘几片玩玩。。谢谢LZ的程序

出0入0汤圆

发表于 2012-9-2 11:30:46 | 显示全部楼层
支持 ,好贴。

出0入0汤圆

发表于 2012-10-7 14:07:50 | 显示全部楼层
mark......

出0入0汤圆

发表于 2012-10-23 14:32:26 | 显示全部楼层
看看。。。。。。。。。。

出0入0汤圆

发表于 2012-10-28 15:50:19 | 显示全部楼层
顶楼主,还有,我想问下,陀螺仪读取出来的角速度有偏差,怎么矫正呢?

出0入0汤圆

发表于 2012-11-9 22:58:20 | 显示全部楼层
lz问下,你的四轴做的怎么样了,你这个是不是不用电调了,也不用飞控,直接就是51+1个陀螺仪+IIC模拟,我想用其他的单片机做下,但不知道需要哪些东西

出0入0汤圆

 楼主| 发表于 2012-11-13 21:58:16 | 显示全部楼层
id_dingjia 发表于 2012-10-28 15:50
顶楼主,还有,我想问下,陀螺仪读取出来的角速度有偏差,怎么矫正呢?

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

出0入0汤圆

 楼主| 发表于 2012-11-13 21:59:14 | 显示全部楼层
vincen 发表于 2012-11-9 22:58
lz问下,你的四轴做的怎么样了,你这个是不是不用电调了,也不用飞控,直接就是51+1个陀螺仪+IIC模拟,我想 ...

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

出0入0汤圆

 楼主| 发表于 2012-11-13 22:01:27 | 显示全部楼层
w_ying_qun 发表于 2012-4-17 22:33
一直认为程序很高深 怎样能从做硬件的 转到做程序上呢?

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

出0入0汤圆

发表于 2012-11-22 11:24:44 | 显示全部楼层
mark,留着有用

出0入0汤圆

发表于 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

出0入0汤圆

发表于 2012-11-24 13:47:57 | 显示全部楼层
本帖最后由 haolei432370 于 2012-11-24 13:50 编辑

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

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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2012-11-25 14:05:12 | 显示全部楼层
mark           

出0入0汤圆

发表于 2012-12-24 19:27:51 | 显示全部楼层
我看懂了,其实不难的!

出0入0汤圆

发表于 2012-12-24 19:28:31 | 显示全部楼层
是一个很好的学习例程!

出0入0汤圆

发表于 2013-5-3 16:26:08 | 显示全部楼层
学习了...
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-3 09:58

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表