找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6439|回复: 14
收起左侧

ADXL345测倾斜角(程序)

  [复制链接]
grh 发表于 2017-7-26 20:09 | 显示全部楼层 |阅读模式
ADXL345测倾斜角

单片机源程序如下:

  1. #include  <REG51.H>       
  2. #include  <math.h>    //Keil library  
  3. #include  <stdio.h>   //Keil library       
  4. #include  <INTRINS.H>

  5. #define   uchar unsigned char
  6. #define   uint unsigned int       
  7. #define   DataPort P0    //LCD1602数据端口

  8. sfr TUXR=0x8E;
  9. sfr CMOD=0xD9;
  10. sfr CCON=0xD8;
  11. sfr CL=0xE9;
  12. sfr CH=0xF9;
  13. sfr CCAPM0=0xDA;
  14. sfr CCAPM1=0xDB;
  15. sfr CCAP0L=0xEA;
  16. sfr CCAP0H=0xFA;
  17. sfr CCAP1L=0xEB;
  18. sfr CCAP1H=0xFB;
  19. sbit CR=CCON^6;


  20. sbit          SCL=P2^0;      //IIC时钟引脚定义
  21. sbit           SDA=P2^1;      //IIC数据引脚定义
  22. sbit  p22=P2^2;
  23. sbit  p31=P3^1;
  24. sbit  p33=P3^3;
  25. sbit      LCM_RS=P2^6;   //LCD1602命令端口               
  26. sbit      LCM_RW=P2^5;   //LCD1602命令端口               
  27. sbit      LCM_EN=P2^7;   //LCD1602命令端口

  28. #define        SlaveAddress   0xA6        //定义器件在IIC总线中的从地址,根据ALT  ADDRESS地址引脚不同修改
  29.                             //ALT  ADDRESS引脚接地时地址为0xA6,接电源时地址为0x3A
  30. typedef unsigned char  BYTE;
  31. typedef unsigned short WORD;

  32. BYTE BUF[8];                         //接收数据缓存区             
  33. uchar ge,shi,bai,qian,wan;           //显示变量  个十百千万
  34. int  dis_data;                       //变量
  35. float jd;
  36. uint PWMH;
  37. void InitLcd();                      //初始化lcd1602
  38. void Init_ADXL345(void);             //初始化ADXL345

  39. void WriteDataLCM(uchar dataW);                // LCD1602相关函数
  40. void WriteCommandLCM(uchar CMD,uchar Attribc); //
  41. void DisplayOneChar(uchar X,uchar Y,uchar DData); //
  42. void conversion(uint temp_data);        //数据处理

  43. void  Single_Write_ADXL345(uchar REG_Address,uchar REG_data);   //单个写入数据
  44. uchar Single_Read_ADXL345(uchar REG_Address);                   //单个读取内部寄存器数据
  45. void  Multiple_Read_ADXL345();                                  //连续的读取内部寄存器数据
  46. //------------------------------------
  47. void Delay5us();
  48. void Delay5ms();
  49. void ADXL345_Start();       //与iic有关函数
  50. void ADXL345_Stop();
  51. void ADXL345_SendACK(bit ack); //传送应答
  52. bit  ADXL345_RecvACK();                   //接收应答
  53. void ADXL345_SendByte(BYTE dat);
  54. BYTE ADXL345_RecvByte();
  55. void ADXL345_ReadPage();
  56. void ADXL345_WritePage();

  57. /*******************************/
  58. void WaitForEnable(void)          
  59. {                                       
  60.         DataPort=0xff;               
  61.         LCM_RS=0;
  62.         LCM_RW=1;
  63.         _nop_(); _nop_();
  64.         LCM_EN=1;
  65.         _nop_();_nop_(); _nop_();_nop_();
  66.         while(DataPort&0x80);       
  67.         LCM_EN=0;                               
  68. }                                       
  69. /*******************************/
  70. void WriteCommandLCM(uchar CMD,uchar Attribc)
  71. {                                       
  72.         if(Attribc)
  73.         WaitForEnable();       
  74.         LCM_RS=0;
  75.         LCM_RW=0;
  76.         _nop_();_nop_();
  77.         DataPort=CMD;
  78.         _nop_();_nop_();       
  79.         LCM_EN=1;
  80.         nop_();_nop_();nop_();_nop_();
  81.         LCM_EN=0;
  82. }                                       
  83. /*******************************/
  84. void WriteDataLCM(uchar dataW)
  85. {                                       
  86.         WaitForEnable();               
  87.         LCM_RS=1;LCM_RW=0;
  88.         _nop_();_nop_();
  89.         DataPort=dataW;_nop_();       
  90.         LCM_EN=1;
  91.         _nop_();_nop_();_nop_();_nop_();
  92.          LCM_EN=0;
  93. }               
  94. /***********************************/
  95. void InitLcd()                               
  96. {                       
  97.         WriteCommandLCM(0x38,1);       
  98.         WriteCommandLCM(0x08,1);       
  99.         WriteCommandLCM(0x01,1);       
  100.         WriteCommandLCM(0x06,1);
  101.         WriteCommandLCM(0x0c,1);
  102. }                       
  103. /***********************************/
  104. void DisplayOneChar(uchar X,uchar Y,uchar DData) //X,Y为字符坐标
  105. {                                               
  106.         Y&=0x01;                                               
  107.         X&=0x0f;                                               
  108.         if(Y)
  109.         X|=0x40;   //8+4=c
  110.                                                
  111.         X|=0x80;                       
  112.         WriteCommandLCM(X,1);               
  113.         WriteDataLCM(DData);               
  114. }                                               


  115. void Delay5us()                //@12.000MHz
  116. {
  117.         unsigned char i;

  118.         i = 12;
  119.         while (--i);
  120. }


  121. void Delay5ms()                //@12.000MHz
  122. {
  123.         unsigned char i, j;

  124.         _nop_();
  125.         _nop_();
  126.         i = 59;
  127.         j = 89;
  128.         do
  129.         {
  130.                 while (--j);
  131.         } while (--i);
  132. }


  133. /**************************************
  134. 起始信号
  135. **************************************/
  136. void ADXL345_Start()
  137. {
  138.     SDA = 1;                    //拉高数据线
  139.     SCL = 1;                    //拉高时钟线
  140.     Delay5us();                 //延时
  141.     SDA = 0;                    //产生下降沿
  142.     Delay5us();                 //延时
  143.     SCL = 0;                    //拉低时钟线
  144. }

  145. /**************************************
  146. 停止信号
  147. **************************************/
  148. void ADXL345_Stop()
  149. {
  150.     SDA = 0;                    //拉低数据线
  151.     SCL = 1;                    //拉高时钟线
  152.     Delay5us();                 //延时
  153.     SDA = 1;                    //产生上升沿
  154.     Delay5us();                 //延时
  155. }

  156. /**************************************
  157. 发送应答信号
  158. 入口参数:ack (0:ACK 1:NAK)
  159. **************************************/
  160. void ADXL345_SendACK(bit ack)
  161. {
  162.     SDA = ack;                  //写应答信号
  163.     SCL = 1;                    //拉高时钟线
  164.     Delay5us();                 //延时
  165.     SCL = 0;                    //拉低时钟线
  166.     Delay5us();                 //延时
  167. }

  168. /**************************************
  169. 接收应答信号
  170. **************************************/
  171. bit ADXL345_RecvACK()
  172. {
  173.     SCL = 1;                    //拉高时钟线
  174.     Delay5us();                 //延时
  175.     CY = SDA;                   //读应答信号
  176.     SCL = 0;                    //拉低时钟线
  177.     Delay5us();                 //延时

  178.     return CY;
  179. }

  180. /**************************************
  181. 向IIC总线发送一个字节数据
  182. **************************************/
  183. void ADXL345_SendByte(BYTE dat)
  184. {
  185.     BYTE i;

  186.     for (i=0; i<8; i++)         //8位计数器
  187.     {
  188.         dat <<= 1;              //移出数据的最高位
  189.         SDA = CY;               //送数据口
  190.         SCL = 1;                //拉高时钟线
  191.         Delay5us();             //延时
  192.         SCL = 0;                //拉低时钟线
  193.         Delay5us();             //延时
  194.     }
  195.     ADXL345_RecvACK();
  196. }

  197. /**************************************
  198. 从IIC总线接收一个字节数据
  199. **************************************/
  200. BYTE ADXL345_RecvByte()
  201. {
  202.     BYTE i;
  203.     BYTE dat = 0;
  204.     SDA = 1;                    //使能内部上拉,准备读取数据,
  205.     for (i=0; i<8; i++)         //8位计数器
  206.     {
  207.         dat <<= 1;
  208.         SCL = 1;                //拉高时钟线
  209.         Delay5us();             //延时
  210.         dat |= SDA;             //读数据               
  211.         SCL = 0;                //拉低时钟线
  212.         Delay5us();             //延时
  213.     }
  214.     return dat;
  215. }

  216. //******单字节写入*******************************************
  217. //用于ADXL345初始化
  218. void Single_Write_ADXL345(uchar REG_Address,uchar REG_data)
  219. {
  220.     ADXL345_Start();                  //起始信号
  221.     ADXL345_SendByte(SlaveAddress);   //发送设备地址+写信号
  222.     ADXL345_SendByte(REG_Address);  //内部寄存器地址,请参考中文pdf22页
  223.     ADXL345_SendByte(REG_data);    //内部寄存器数据,请参考中文pdf22页
  224.                                        //相当于 向相应的地址写入命令字
  225.     ADXL345_Stop();                 //发送停止信号
  226. }

  227. //********单字节读取*****************************************
  228. uchar Single_Read_ADXL345(uchar REG_Address)
  229. {   
  230.     uchar REG_data;
  231.     ADXL345_Start();                          //起始信号
  232.     ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号,//0xA6写入
  233.     ADXL345_SendByte(REG_Address);            //发送存储单元地址,从0开始       
  234.     ADXL345_Start();                          //起始信号
  235.     ADXL345_SendByte(SlaveAddress+1);         //发送设备地址+读信号,//0xA7读取
  236.     REG_data=ADXL345_RecvByte();              //读出寄存器数据
  237.         ADXL345_SendACK(1);   
  238.         ADXL345_Stop();                           //停止信号
  239.     return REG_data;
  240. }
  241. //*********************************************************
  242. //
  243. //连续读出ADXL345内部加速度数据,地址范围0x32~0x37
  244. //
  245. //*********************************************************
  246. void Multiple_read_ADXL345(void)
  247. {   
  248.     uchar i;
  249.     ADXL345_Start();                          //起始信号
  250.     ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号
  251.     ADXL345_SendByte(0x32);                   //发送存储单元地址,从0x32开始       
  252.     ADXL345_Start();                          //起始信号
  253.     ADXL345_SendByte(SlaveAddress+1);         //发送设备地址+读信号
  254.          for (i=0; i<6; i++)                      //连续读取6个地址数据,存储中BUF
  255.     {
  256.         BUF[i] = ADXL345_RecvByte();          //BUF[0]存储0x32地址中的数据
  257.         if (i == 5)
  258.         {
  259.            ADXL345_SendACK(1);                //最后一个数据需要回NOACK
  260.         }
  261.         else
  262.         {
  263.           ADXL345_SendACK(0);                //回应ACK
  264.        }
  265.    }
  266.     ADXL345_Stop();                          //停止信号
  267.     Delay5ms();
  268. }

  269. //*****************************************************************

  270. //初始化ADXL345,根据需要请参考pdf进行修改************************
  271. void Init_ADXL345()
  272. {
  273.    Single_Write_ADXL345(0x31,0x0B);   //测量范围,正负16g,13位模式
  274.    Single_Write_ADXL345(0x2C,0x08);   //速率设定为12.5 参考pdf13页
  275.    Single_Write_ADXL345(0x2D,0x08);   //选择电源模式   参考pdf24页
  276.    Single_Write_ADXL345(0x2E,0x80);   //使能 DATA_READY 中断
  277.    Single_Write_ADXL345(0x1E,0x00);   //X 偏移量 根据测试传感器的状态写入,pdf29页//自己调试,得出偏移量
  278.    Single_Write_ADXL345(0x1F,0x00);   //Y 偏移量 根据测试传感器的状态写入,pdf29页
  279.    Single_Write_ADXL345(0x20,0x05);   //Z 偏移量 根据测试传感器的状态写入,pdf29页
  280. }

  281. //*********************************************************
  282. void conversion(uint temp_data)  
  283. {  
  284.     wan=temp_data/10000+0x30 ;              //0x30='0'
  285.     temp_data=temp_data%10000;   //取余运算
  286.         qian=temp_data/1000+0x30 ;
  287.     temp_data=temp_data%1000;    //取余运算
  288.     bai=temp_data/100+0x30   ;
  289.     temp_data=temp_data%100;     //取余运算
  290.     shi=temp_data/10+0x30    ;
  291.     temp_data=temp_data%10;      //取余运算
  292.     ge=temp_data+0x30;       
  293. }

  294. //显示x轴倾斜角,即x轴与垂线所成角度
  295. void display_jd_x()
  296. {   
  297.     bit bj=0;//标记
  298.     int  dis_data_x,dis_data_z;  //x,y轴加速度的原始数据,用补码形式表示
  299.     float mg_x,mg_z;           //角度,加速度
  300.     dis_data_x=(BUF[1]<<8)+BUF[0];  //合成数据   
  301.         dis_data_z=(BUF[5]<<8)+BUF[4];  //合成数据

  302.         if((dis_data_x<=0)&&(dis_data_z>0))          //第二象限
  303.         {
  304.             dis_data_x=-dis_data_x;
  305.                 DisplayOneChar(8,0,' ');
  306.         bj=1;
  307.         }
  308.         else if((dis_data_z<0)&&(dis_data_x>=0))         //第四象限
  309.         {
  310.             dis_data_z=-dis_data_z;
  311.         DisplayOneChar(8,0,'-');  //显示正负符号位
  312.         }
  313.         else if((dis_data_z<=0)&&(dis_data_x<0))           //第三象限
  314.         {
  315.             bj=1;
  316.             dis_data_z=-dis_data_z;
  317.                 dis_data_x=-dis_data_x;
  318.         DisplayOneChar(8,0,'-');  //显示正负符号位
  319.         }
  320.         else if((dis_data_z>=0)&&(dis_data_x>0))
  321.          DisplayOneChar(8,0,' ');                //第一象限

  322.     mg_x=(float)dis_data_x*3.9;  //计算数据和显示,查看ADXL345快速入门第4页,1LSB=3.9mg(毫g)
  323.         mg_z=(float)dis_data_z*3.9;         //强制类型转换,dis_data_z的类型和值不会发生改变

  324.         jd=atan2(mg_z,mg_x)*(180/3.14159);
  325.         if(bj==1)jd=180-jd;       
  326.           //jd=jd*10;  消除小数点,便于转换数据和显示
  327.     conversion(jd*10);      //转换出显示需要的数据                                        //
  328.         DisplayOneChar(6,0,'X');
  329.         DisplayOneChar(7,0,':');   
  330.         DisplayOneChar(9,0,qian);
  331.     DisplayOneChar(10,0,bai);        
  332.     DisplayOneChar(11,0,shi);
  333.     DisplayOneChar(12,0,'.');
  334.         DisplayOneChar(13,0,ge);
  335.         DisplayOneChar(14,0,0xdf);            //显示 °
  336.         DisplayOneChar(15,0,' ');
  337. }

  338. void PCAinit()        //PCA模块初始化
  339. {
  340.      CCON=0;
  341.          CL=0;
  342.          CH=0;
  343.          CMOD=0x00;        //sysclk/12
  344.          CCAPM0=0x42;//8位PWM,无中断
  345.          CR=1;
  346.          CCAP0H=CCAP0L=256-240;
  347. }
  348. void init_t0()         //定时器0初始化
  349. {
  350.     TUXR&=0x7f;         //12T
  351.         TMOD=0x01;
  352.         TH0=(65536-50000)/256;
  353.         TL0=(65536-50000)%256;
  354.         TR0=1;
  355.         EA=1;
  356.         ET0=1;
  357. }

  358. //*********************************************************
  359. //******主程序********
  360. //*********************************************************
  361. void main()
  362. {        
  363.         char H;       
  364.         InitLcd();               //液晶初始化ADXL345
  365.         Delay5ms();
  366.         Init_ADXL345();                 //初始化ADXL345
  367.         PCAinit();
  368.         init_t0();
  369.         H=CCAP0H;

  370.         while(1)
  371.         {                                                                         
  372.                 if(p33==0)
  373.                 {         
  374.                      Delay5ms();
  375.                      if(p33==0)
  376.                      {
  377.                           H=H+5;
  378.                               if(H>255)H=255;
  379.                               CCAP0H=H;
  380.                               CCAP0L=H;
  381.                               while(p33==0);
  382.                       }
  383.             }
  384.                 if(p31==0)
  385.                 {         
  386.                      Delay5ms();
  387.                      if(p31==0)
  388.                          {
  389.                             H=H-5;
  390.                                 if(H<0)H=0;
  391. ……………………

  392. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
ADXL345测倾斜角.zip (69.11 KB, 下载次数: 262)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

我们失恋在夏季 发表于 2017-8-1 20:10 | 显示全部楼层
谢谢 大神解答
回复

使用道具 举报

djk0125 发表于 2017-12-21 15:47 来自手机 | 显示全部楼层
感谢分享!!!
回复

使用道具 举报

lgp214 发表于 2018-4-23 21:05 来自手机 | 显示全部楼层
非常感谢大神的程序,Y轴的怎么写麻烦大神指导下?
回复

使用道具 举报

eassion_1 发表于 2018-8-17 11:33 | 显示全部楼层
感谢楼主感谢感谢
回复

使用道具 举报

chengweiquan 发表于 2018-8-22 15:31 | 显示全部楼层

感谢楼主分享
回复

使用道具 举报

376262974 发表于 2018-11-21 11:00 | 显示全部楼层
学习一下
回复

使用道具 举报

376262974 发表于 2018-11-21 11:03 | 显示全部楼层
代码写得好乱,不好分析。
回复

使用道具 举报

jerryyaozl 发表于 2019-2-28 16:34 | 显示全部楼层
感谢大神分享。
回复

使用道具 举报

qingxie 发表于 2019-3-30 23:17 | 显示全部楼层
感谢!!
回复

使用道具 举报

zhangchaoliang 发表于 2019-4-26 22:32 | 显示全部楼层
好的,后面的程序。
回复

使用道具 举报

lyt87336 发表于 2019-7-6 12:00 | 显示全部楼层
sbit  p22=P2^2;
sbit  p31=P3^1;
sbit  p33=P3^3;这连接的是什么
回复

使用道具 举报

GJ2020 发表于 2020-7-28 14:48 | 显示全部楼层
不错,有用的数据
回复

使用道具 举报

ganganoo 发表于 2020-11-16 21:49 | 显示全部楼层
有接法吗
回复

使用道具 举报

qewnja 发表于 2020-11-22 20:23 | 显示全部楼层
感谢分享,最近正在研究这个
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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