|
本帖最后由 济南电子爱好者 于 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周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|