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();
}
}免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。