找回密码
 注册
关于网站域名变更的通知
查看: 151|回复: 2
打印 上一主题 下一主题

ADXL345倾角传感器的51单片机源程序

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2022-6-29 09:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

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

x
这是自己做的一个小程序,用到了STC12C5160S2这块单片机芯片做控制,实现ADXL345倾角传感器模块测量角度  @0 H4 e4 ~/ x, ?

4 n3 e! [9 w- k: y5 ?, B3 t单片机源程序如下:
  `2 P/ t/ ~0 ?! @
  • /********************************************************************
  • * 文件名  :GY-29 ADXL345 测角度,角度值显示
  • * 创建人  :飞翔的猫
  • * 描述    : 该文件实现了用GY-29 ADXL345角度的采集,并在数码管上显示出来。
  •                          使用单片机STC89C51
  • *晶振          :11.0592M
  • *显示     :LCD1602
  • *编译环境 :Keil uVision4
  • ****************************************/
  • #include  <REG51.H>
  • #include  <math.h>    //Keil library
  • #include  <stdio.h>   //Keil library
  • #include  <INTRINS.H>
  • #define   uchar unsigned char
  • #define   uint unsigned int
  • //这个一定要根据自己接的引脚来改,否则不出数据
  • sbit          SCL=P2^0;      //IIC时钟引脚定义
  • sbit           SDA=P2^1;      //IIC数据引脚定义
  • #define   DataPort P0    //LCD1602数据端口
  • sbit      LCM_RS=P2^4;   //LCD1602命令端口
  • sbit      LCM_RW=P2^5;   //LCD1602命令端口
  • sbit      LCM_EN=P2^7;   //LCD1602命令端口
  • #define        SlaveAddress   0xA6          //定义器件在IIC总线中的从地址,根据ALT  ADDRESS地址引脚不同修改
  •                               //ALT  ADDRESS引脚接地时地址为0xA6,接电源时地址为0x3A
  • typedef unsigned char  BYTE;
  • typedef unsigned short WORD;
  • BYTE BUF[8];                         //接收数据缓存区
  • uchar ge,shi,bai,qian,wan;           //显示变量
  • int  dis_data;                       //变量
  • int  data_xyz[3];
  • void delay(unsigned int k);
  • void InitLcd();                      //初始化lcd1602
  • void Init_ADXL345(void);             //初始化ADXL345
  • void WriteDataLCM(uchar dataW);
  • void WriteCommandLCM(uchar CMD,uchar Attribc);
  • void DisplayOneChar(uchar X,uchar Y,uchar DData);
  • void conversion(uint temp_data);
  • void  Single_Write_ADXL345(uchar REG_Address,uchar REG_data);   //单个写入数据
  • uchar Single_Read_ADXL345(uchar REG_Address);                   //单个读取内部寄存器数据
  • void Mutiple_Read_ADXL345(void);
  • void clear(void);                               //连续的读取内部寄存器数据
  • //------------------------------------
  • void Delay5us();
  • void Delay5ms();
  • void ADXL345_Start();
  • void ADXL345_Stop();
  • void ADXL345_SendACK(bit ack);
  • bit  ADXL345_RecvACK();
  • void ADXL345_SendByte(BYTE dat);
  • BYTE ADXL345_RecvByte();
  • void ADXL345_ReadPage();
  • void ADXL345_WritePage();
  • //-----------------------------------
  • //*********************************************************
  • void conversion(uint temp_data)
  • {
  •     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++)
  • {;}}
  • }
  • /*******************************/
  • void WaitForEnable(void)
  • {
  • DataPort=0xff;
  • LCM_RS=0;LCM_RW=1;_nop_();
  • LCM_EN=1;_nop_();_nop_();
  • while(DataPort&0x80);
  • LCM_EN=0;
  • }
  • /*******************************/
  • void WriteCommandLCM(uchar CMD,uchar Attribc)
  • {
  • if(Attribc)WaitForEnable();
  • LCM_RS=0;LCM_RW=0;_nop_();
  • DataPort=CMD;_nop_();
  • LCM_EN=1;_nop_();_nop_();LCM_EN=0;
  • }
  • /*******************************/
  • void WriteDataLCM(uchar dataW)
  • {
  • WaitForEnable();
  • LCM_RS=1;LCM_RW=0;_nop_();
  • DataPort=dataW;_nop_();
  • LCM_EN=1;_nop_();_nop_();LCM_EN=0;
  • }
  • /***********************************/
  • void InitLcd()                        //液晶显示器的设置
  • {
  • WriteCommandLCM(0x38,1);
  • WriteCommandLCM(0x08,1);
  • WriteCommandLCM(0x01,1);
  • WriteCommandLCM(0x06,1);
  • WriteCommandLCM(0x0c,1);
  • }
  • /***********************************/
  • void DisplayOneChar(uchar X,uchar Y,uchar DData)
  • {
  • Y&=1;
  • X&=15;
  • if(Y)X|=0x40;
  • X|=0x80;
  • WriteCommandLCM(X,0);
  • WriteDataLCM(DData);
  • }
  • /**************************************
  • 延时5微秒(STC90C52RC@12M)
  • 不同的工作环境,需要调整此函数,注意时钟过快时需要修改
  • 当改用1T的mcu时,请调整此延时函数
  • **************************************/
  • void Delay5us()
  • {
  •     _nop_();_nop_();_nop_();_nop_();
  •     _nop_();_nop_();_nop_();_nop_();
  •         _nop_();_nop_();_nop_();_nop_();
  • }
  • /**************************************
  • 延时5毫秒(STC90C52RC@12M)
  • 不同的工作环境,需要调整此函数
  • 当改用1T的MCU时,请调整此延时函数
  • **************************************/
  • 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();                 //延时
  • }
  • /**************************************
  • 发送应答信号
  • 入口参数:ack (0:ACK 1:NAK)
  • **************************************/
  • 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);    //内部寄存器地址,请参考中文pdf22页
  •     ADXL345_SendByte(REG_data);       //内部寄存器数据,请参考中文pdf22页
  •     ADXL345_Stop();                   //发送停止信号
  • }
  • //********单字节读取*****************************************
  • uchar Single_Read_ADXL345(uchar REG_Address)
  • {  uchar REG_data;
  •     ADXL345_Start();                          //起始信号
  •     ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号
  •     ADXL345_SendByte(REG_Address);                   //发送存储单元地址,从0开始
  •     ADXL345_Start();                          //起始信号
  •     ADXL345_SendByte(SlaveAddress+1);         //发送设备地址+读信号
  •     REG_data=ADXL345_RecvByte();              //读出寄存器数据
  •         ADXL345_SendACK(1);
  •         ADXL345_Stop();                           //停止信号
  •     return REG_data;
  • }
  • //*********************************************************
  • //
  • //连续读出ADXL345内部加速度数据,地址范围0x32~0x37
  • //
  • //*********************************************************
  • void Mutiple_Read_ADXL345()
  • {   uchar i;
  •     ADXL345_Start();
  •                                 //起始信号
  •     ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号
  •     ADXL345_SendByte(0x32);                   //发送存储单元地址,从0x32开始
  •     ADXL345_Start();                          //起始信号
  •     ADXL345_SendByte(SlaveAddress+1);         //发送设备地址+读信号
  •         for (i=0; i<6; i++)                      //连续读取6个地址数据,存储中BUF
  •     {
  •         BUF = ADXL345_RecvByte();          //BUF[0]存储0x32地址中的数据
  •                 //BUF=i;
  •         if (i == 5)
  •         {
  •            ADXL345_SendACK(1);                //最后一个数据需要回NOACK
  •         }
  •         else
  •         {
  •            ADXL345_SendACK(0);                //回应ACK
  •        }
  •    }
  •     ADXL345_Stop();                          //停止信号
  •     Delay5ms();
  • }
  • //*****************************************************************
  • void clear(void)
  • {   uchar i;
  •     ADXL345_Start();
  •                                 //起始信号
  •     ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号
  •     ADXL345_SendByte(0x32);                   //发送存储单元地址,从0x32开始
  •     ADXL345_Start();                          //起始信号
  •     ADXL345_SendByte(SlaveAddress+1);         //发送设备地址+读信号
  •          for (i=0; i<6; i++)                      //连续读取6个地址数据,存储中BUF
  •     {
  •         //BUF = ADXL345_RecvByte();          //BUF[0]存储0x32地址中的数据
  •                 BUF=i;
  •         if (i == 5)
  •         {
  •            ADXL345_SendACK(1);                //最后一个数据需要回NOACK
  •         }
  •         else
  •         {
  •            ADXL345_SendACK(0);                //回应ACK
  •        }
  •    }
  •     ADXL345_Stop();                          //停止信号
  •     Delay5ms();
  • }
  • //*****************************************************************
  • //初始化ADXL345,根据需要请参考pdf进行修改************************
  • void Init_ADXL345()
  • {
  •    Single_Write_ADXL345(0x31,0x0B);   //测量范围,正负16g,13位模式
  •    Single_Write_ADXL345(0x2C,0x08);   //速率设定为12.5 参考pdf13页
  •    Single_Write_ADXL345(0x2D,0x08);   //选择电源模式   参考pdf24页
  •    Single_Write_ADXL345(0x2E,0x80);   //使能 DATA_READY 中断
  •    Single_Write_ADXL345(0x1E,0x00);   //X 偏移量 根据测试传感器的状态写入pdf29页
  •    Single_Write_ADXL345(0x1F,0x00);   //Y 偏移量 根据测试传感器的状态写入pdf29页
  •    Single_Write_ADXL345(0x20,0x05);   //Z 偏移量 根据测试传感器的状态写入pdf29页
  • }
  • //***********************************************************************
  • //显示x轴
  • void display_x()
  • {   float temp;
  •     dis_data=(BUF[1]<<8)+BUF[0];  //合成数据
  •         if(dis_data<0){
  •         dis_data=-dis_data;
  •     DisplayOneChar(2,0,'-');      //显示正负符号位
  •         }
  •         else DisplayOneChar(2,0,' '); //显示空格
  •     temp=(float)dis_data*3.9;  //计算数据和显示,查考ADXL345快速入门第4页
  •     conversion(temp);          //转换出显示需要的数据
  •         DisplayOneChar(0,0,'X');   //第0行,第0列 显示X
  •     DisplayOneChar(1,0,':');
  •     DisplayOneChar(3,0,qian);
  •         DisplayOneChar(4,0,'.');
  •     DisplayOneChar(5,0,bai);
  •     DisplayOneChar(6,0,shi);
  •         DisplayOneChar(7,0,'g');
  • }
  • //***********************************************************************
  • //显示y轴
  • void display_y()
  • {     float temp;
  •     dis_data=(BUF[3]<<8)+BUF[2];  //合成数据
  •         if(dis_data<0){
  •         dis_data=-dis_data;
  •     DisplayOneChar(2,1,'-');      //显示正负符号位
  •         }
  •         else DisplayOneChar(2,1,' '); //显示空格
  •     temp=(float)dis_data*3.9;  //计算数据和显示,查考ADXL345快速入门第4页
  •     conversion(temp);          //转换出显示需要的数据
  •         DisplayOneChar(0,1,'Y');   //第1行,第0列 显示y
  •     DisplayOneChar(1,1,':');
  •     DisplayOneChar(3,1,qian);
  •         DisplayOneChar(4,1,'.');
  •     DisplayOneChar(5,1,bai);
  •     DisplayOneChar(6,1,shi);
  •         DisplayOneChar(7,1,'g');
  • }
  • //***********************************************************************
  • //显示z轴
  • void display_z()
  • {      float temp;
  •     dis_data=(BUF[5]<<8)+BUF[4];    //合成数据
  •         if(dis_data<0){
  •         dis_data=-dis_data;
  •     DisplayOneChar(10,1,'-');       //显示负符号位
  •         }
  •         else DisplayOneChar(10,1,' ');  //显示空格
  •     temp=(float)dis_data*3.9;  //计算数据和显示,查考ADXL345快速入门第4页
  •     conversion(temp);          //转换出显示需要的数据
  •         DisplayOneChar(10,0,'Z');  //第0行,第10列 显示Z
  •     DisplayOneChar(11,0,':');
  •     DisplayOneChar(11,1,qian);
  •         DisplayOneChar(12,1,'.');
  •     DisplayOneChar(13,1,bai);
  •     DisplayOneChar(14,1,shi);
  •         DisplayOneChar(15,1,'g');
  • }
  • //串口通讯函数  自己加的程序段,将ADXL的角度值写到串口中
  • void uart_initial_with_interrupt(void);
  • void uart_adxl(void);
  • int uart_i;
  • void uart_initial_with_interrupt(void)
  • {
  •         //TOMD 定时器工作模式寄存器
  •         //TCON 中断控制寄存器:定时器中断和外部中断
  •         //IE   中断允许控制寄存器
  •         TMOD=0x20;           //设置定时器工作模式,定时器1工作在模式2,8位自动重装
  •         TH1=0xfd;           //定时器1设置,产生9600波特率,开启定时器1
  •         TL1=0xfd;
  •         TR1=1;
  •         SM0=0;
  •         SM1=1;
  •         REN=1;
  •         EA=1;  //允许总中断
  •         ES=1;  //允许串口中断
  • }
  • void  uart_adxl(void) interrupt 4
  • {
  •         uchar ch;
  •         if(RI)
  •         {
  •                 ch='a';
  •         }
  • }
  • int Roll_int,Pitch_int;
  • uchar Roll_int_high,Roll_int_low;
  • uchar Pitch_int_high,Pitch_int_low;
  • //*********************************************************
  • //******主程序********
  • //*********************************************************
  • void main()
  • {         int d;
  •           uchar devid;
  •         float Roll,Pitch,Q,T,K;
  •         //打开串口中断
  •         uart_initial_with_interrupt();
  •         Init_ADXL345();                 //初始化ADXL345
  •         devid=Single_Read_ADXL345(0X00);//读出的数据为0XE5,表示正确
  •     while(1)                         //循环
  •     {
  •                 //测试串口工作情况
  •                 for(uart_i=0;uart_i<2;uart_i++)
  •                 {
  •                          SBUF=0;
  •                         while(!TI);
  •                         TI=0;
  •                         delay(500);
  •                 }
  •                 Init_ADXL345();                     //初始化ADXL345
  •        //连续读出数据,存储在BUF
  •                 Mutiple_Read_ADXL345();
  •                 data_xyz[0]=(BUF[1]<<8)|BUF[0];  //合成数据    【改动】将+ 改成了 |
  •                 data_xyz[1]=(BUF[3]<<8)|BUF[2];  //合成数据
  •                 data_xyz[2]=(BUF[5]<<8)|BUF[4];  //合成数据
  •                 //测试是否有数据改变
  •                 for(d=0;d<3;d++){
  •                 SBUF=data_xyz[d];
  •                 while(!TI);
  • ……………………
      x5 @$ Z. X& K! h

/ Z* H6 g3 j9 \" m7 D) }

该用户从未签到

2#
发表于 2022-6-29 10:19 | 只看该作者
能修改一下控制LED闪烁吗 不要显示!

该用户从未签到

3#
发表于 2022-6-29 16:39 | 只看该作者
看一看,学一下。||ヽ(* ̄▽ ̄*)ノミ|Ю
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-6-23 00:48 , Processed in 0.078125 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

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