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(); 
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章