51单片机课程设计:基于ADXL345的三轴偏移值显示(可用于加速度测量)
51单片机课程设计:基于ADXL345的三轴偏移值显示(可用于加速度测量)
本程序通过IIC的通讯方式读取三轴加速度模块ADXL345的数值,并且利用数码管显示出来,通过三个按键可以实现不同轴偏移值的显示,数码管显示电路和需要用到的相关器件,还有工程文件以及相关资料,可以在附件下载,程序适用于吉林农业大学单片机开发板,其他型号开发板修改部分代码既可以完成移植。
关于粘贴复制乱码的问题:如果程序复制到Keil编译器上出现注释乱码,可以先建一个.c文件,也就是说不在keil里面编辑,然后用记事本打开.c文件,将源码复制进去,再在keil中添加文件即可。
/*********************************************************************************** ADXL345加速度传感器实验 本程序是基于三轴加速度模块ADXL345的,能够读取到ADXL345三轴偏移数值,没有实现加速度 显示,如需达到此要求,可以自己找资料然后编写对应的函数。 程序利用三个按键实现不同轴的偏移数值显示, P3.0:显示x轴偏移值 P3.1:显示y轴偏移值 P3.2:显示z轴偏移值 模块的通讯方式为IIC SCL接P1.0 SDA接P1.1 CS接P1.2 (适用于吉农51开发板,如需移植,只需要更改显示电路即可) 2016-12-30---------------------------------SWorld ***********************************************************************************/ #include <REG51.H> #include <math.h> //库函数 #include <stdio.h> //库函数 #include <INTRINS.H> #define uchar unsigned char #define uint unsigned int /*********************************八段数码管引脚定义*********************************/ #define GPIO_DIG P0//位选以及段选数据输出端口定义 sbit WEC=P2^3; sbit DUC=P2^2; unsigned char code DIG_CODE[10]={ 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f}; //显示段码 unsigned char DisplayData[8]; //用来存放要显示的8位数的值 sbit SCL=P1^0; //IIC时钟引脚定义 sbit SDA=P1^1; //IIC数据引脚定义 sbit CS=P1^2; sbit isx=P3^0; //显示x sbit isy=P3^1;//显示y sbit isz=P3^2;//显示Z unsigned int show; //定义器件在IIC总线的从地址 根据ADDRESS引脚不同修改 接地时则地址为0xA6 接电源时0x3A #defineSlaveAddress 0xA6 typedef unsigned char BYTE; typedef unsigned short WORD; BYTE BUF[8]; //接收数据缓冲区 uchar ge,shi,bai,qian,wan; //显示变量 个十百千万 int dis_data; //变量 void delay(unsigned int k);//延时 void Init_ADXL345(void); //初始化ADXL void conversion(uint temp_data);//用来分离各位 void Single_Write_ADXL345(uchar REG_Address,uchar REG_data); //单个写入数据 uchar Single_Read_ADXL345(uchar REG_Address); //单个读取内部寄存器数据 void Multiple_Read_ADXL345(); //连续读取内部寄存器数据 //------------------------------------ void Delay5us(); //延时5us void Delay5ms();//延时5ms void ADXL345_Start();//其实信号 void ADXL345_Stop();//停止信号 void ADXL345_SendACK(bit ack); //发送一位数据 bit ADXL345_RecvACK();//接收一位数据 void ADXL345_SendByte(BYTE dat);//发送一字节数据 BYTE ADXL345_RecvByte();//接收一字节数据 //----------------------------------- /******************************************************************************* * 函 数 名 : DigDisplay * 函数功能 : 使用数码管显示 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void DigDisplay() { unsigned char i; unsigned int j; for(i=0;i<8;i++) { WEC=1;DUC=0; switch(i) //位选,选择点亮的数码管, { case(0): GPIO_DIG=0x7F; break;//显示第0位 case(1): GPIO_DIG=0xBF; break;//显示第1位 case(2): GPIO_DIG=0xDF; break;//显示第2位 case(3): GPIO_DIG=0xEF; break;//显示第3位 case(4): GPIO_DIG=0xF7; break;//显示第4位 case(5): GPIO_DIG=0xFB; break;//显示第5位 case(6): GPIO_DIG=0xFD; break;//显示第6位 case(7): GPIO_DIG=0xFE; break;//显示第7位 } WEC=0;DUC=1; GPIO_DIG=DisplayData[i];//发送段码 j=15; //扫描间隔时间设定 while(j--); GPIO_DIG=0x00;//消隐 } } //延时10ms void Delay10ms(unsigned int c) //误差 0us { unsigned char a, b; //--c已经在传递过来的时候已经赋值了,所以在for语句第一句就不用赋值了--// for (;c>0;c--) { for (b=38;b>0;b--) { for (a=130;a>0;a--); } } } /*--------------------------------------三个按键检测 -----------------------------------------------*/ unsigned char Key_Scan() { unsigned char keyValue = 0 , i; //保存键值 //--检测按键1--// if (isx != 1)//检测按键K1是否按下 { Delay10ms(1);//消除抖动 if (isx != 1)//再次检测按键是否按下 { keyValue = 1; i = 0; while ((i<50) && (isx != 1)) //检测按键是否松开 { Delay10ms(1); i++; } } } //--检测按键1--// if (isy != 1)//检测按键K1是否按下 { Delay10ms(1);//消除抖动 if (isy!= 1)//再次检测按键是否按下 { keyValue = 2; i = 0; while ((i<50) && (isy != 1)) //检测按键是否松开 { Delay10ms(1); i++; } } } //--检测按键1--// if (isz!= 1)//检测按键K1是否按下 { Delay10ms(1);//消除抖动 if (isz!= 1)//再次检测按键是否按下 { keyValue = 3; i = 0; while ((i<50) && (isz != 1)) //检测按键是否松开 { Delay10ms(1); i++; } } } return keyValue; //将读取到键值的值返回 } //*************存入各位数据******************************************** void conversion(uint temp_data) { wan=temp_data/10000 ; temp_data=temp_data%10000; qian=temp_data/1000 ; temp_data=temp_data%1000; bai=temp_data/100 ; temp_data=temp_data%100; shi=temp_data/10 ; temp_data=temp_data%10; ge=temp_data; } /*******************************/ void delay(unsigned int k) { unsigned int i,j; for(i=0;i<k;i++) { for(j=0;j<121;j++) {;} } } /************************************** 延时5us **************************************/ void Delay5us() { _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); } /************************************** 延时5ms **************************************/ void Delay5ms() { WORD n = 560; while (n--); } /************************************** 起始信号 **************************************/ void ADXL345_Start() { SDA = 1; //拉高数据线 SCL = 1; //拉高时钟线 Delay5us(); //延时 SDA = 0; //拉低数据线 Delay5us(); //延时 SCL = 0; //拉低时钟线 } /************************************** 结束信号 **************************************/ void ADXL345_Stop() { SDA = 0; //拉低数据线 SCL = 1; //拉高时钟线 Delay5us(); //延时 SDA = 1; //产生上升沿 Delay5us(); //延时 } /************************************** 发送应答信号 **************************************/ void ADXL345_SendACK(bit ack) { SDA = ack; //写应答信号 SCL = 1; //拉高时钟线 Delay5us(); //延时 SCL = 0; //拉低时钟线 Delay5us(); //延时 } /************************************** 接收应答信号 **************************************/ bit ADXL345_RecvACK() { SCL = 1; //拉高时钟线 Delay5us(); //延时 CY = SDA; //读取应答信号 SCL = 0; //拉低时钟线 Delay5us(); //延时 return CY; //返回应答数据 } /************************************** 向IIC总线发送一字节数据 **************************************/ void ADXL345_SendByte(BYTE dat) { BYTE i; for (i=0; i<8; i++) //8位计数器 { dat <<= 1; //移除数据最高位 SDA = CY; //送数据口 SCL = 1; //拉高时钟线 Delay5us(); //延时 SCL = 0; //拉低时钟线 Delay5us(); //延时 } ADXL345_RecvACK(); } /************************************** 向IIC总线取一字节数据 **************************************/ BYTE ADXL345_RecvByte() { BYTE i; BYTE dat = 0; SDA = 1; //拉高数据线 for (i=0; i<8; i++) //8为计数器 { dat <<= 1; SCL = 1; //左移一位 Delay5us(); //延时 dat |= SDA; //读数据 SCL = 0; //拉低时钟线 Delay5us(); //延时 } return dat; //返回一字节数据 } //******单字节写入******************************************* void Single_Write_ADXL345(uchar REG_Address,uchar REG_data) { ADXL345_Start(); //起始信号 ADXL345_SendByte(SlaveAddress); //发送设备地址 ADXL345_SendByte(REG_Address); //内部寄存器地址 ADXL345_SendByte(REG_data); //内部数据地址 ADXL345_Stop(); //结束信号 } //********单字节读取***************************************** uchar Single_Read_ADXL345(uchar REG_Address) { uchar REG_data; ADXL345_Start(); //起始信号 ADXL345_SendByte(SlaveAddress); //发送设备地址 ADXL345_SendByte(REG_Address); //发送寄存器地址 ADXL345_Start(); //起始信号 ADXL345_SendByte(SlaveAddress+1); //发送设备地址 REG_data=ADXL345_RecvByte(); //接收一字节数据 ADXL345_SendACK(1); ADXL345_Stop(); //结束信号 return REG_data; } //********************************************************* // //连续读取器内部加速度数据 范围0x32-0x37 // //********************************************************* void Multiple_read_ADXL345(void) { uchar i; ADXL345_Start(); //起始 ADXL345_SendByte(SlaveAddress); //设备地址 ADXL345_SendByte(0x32); //存储单元地址 ADXL345_Start(); //起始信号 ADXL345_SendByte(SlaveAddress+1); //设备地址加读信号 for (i=0; i<6; i++) //连续接收六个地址数据 存入BUF { BUF[i] = ADXL345_RecvByte(); // if (i == 5) { ADXL345_SendACK(1); //最后一个数据 } else { ADXL345_SendACK(0); //回应ACK } } ADXL345_Stop(); //结束 Delay5ms(); } //***************************************************************** //初始化ADXL345*********************** void Init_ADXL345() { Single_Write_ADXL345(0x31,0x0B); //测量范围 正负16g 13位模式 Single_Write_ADXL345(0x2C,0x08); //速率12.5 Single_Write_ADXL345(0x2D,0x08); //电源模式 Single_Write_ADXL345(0x2E,0x80); //使能DATA_READY中断 Single_Write_ADXL345(0x1E,0x00); //X 偏移量 Single_Write_ADXL345(0x1F,0x00); //Y Single_Write_ADXL345(0x20,0x05); //Z } //*********************************************************************** //显示x void display_x() { float temp; dis_data=(BUF[1]<<8)+BUF[0]; //合成数据 if(dis_data<0){ dis_data=-dis_data; DisplayData[6]=0x40; } else { DisplayData[6]=0x00; } temp=(float)dis_data*3.9; //计算数据 conversion(temp); //分解数据 } //*********************************************************************** //y void display_y() { float temp; dis_data=(BUF[3]<<8)+BUF[2]; if(dis_data<0){ dis_data=-dis_data; DisplayData[6]=0x40; } else { DisplayData[6]=0x00; } temp=(float)dis_data*3.9; conversion(temp); } //*********************************************************************** //z void display_z() { float temp; dis_data=(BUF[5]<<8)+BUF[4]; if(dis_data<0){ dis_data=-dis_data; DisplayData[6]=0x40; } else { DisplayData[6]=0x00; } temp=(float)dis_data*3.9; conversion(temp); } //********************************************************* //************************主函数*************************** //********************************************************* void main() { uchar devid; delay(500); //延时 Init_ADXL345(); //初始化ADXL345 CS=1; devid=Single_Read_ADXL345(0X00);//读取数据为0xE5表示正确 show=1; DisplayData[7]=DIG_CODE[1]; while(1) //循环 { switch(Key_Scan()) { case 1: show=1; DisplayData[7]=DIG_CODE[1]; break; case 2: show=2; DisplayData[7]=DIG_CODE[2]; break; case 3: show=3; DisplayData[7]=DIG_CODE[3]; break; } switch(show) { case 1: Multiple_Read_ADXL345(); //读取数据存入BUF display_x(); //显示x break; case 2: Multiple_Read_ADXL345(); //读取数据存入BUF display_y(); //显示x break; case 3: Multiple_Read_ADXL345(); //读取数据存入BUF display_z(); //显示x break; } DisplayData[5]=DIG_CODE[wan]; DisplayData[4]=DIG_CODE[qian]; DisplayData[3]=DIG_CODE[bai]; DisplayData[2]=DIG_CODE[shi]; DisplayData[1]=DIG_CODE[ge]; DigDisplay(); } }
附件:http://down.51cto.com/data/2366393