adxl345.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. #include "adxl345.h"
  2. #include "sys.h"
  3. #include "delay.h"
  4. #include "math.h"
  5. //////////////////////////////////////////////////////////////////////////////////
  6. //本程序只供学习使用,未经作者许可,不得用于其它任何用途
  7. //ALIENTEK战舰STM32开发板
  8. //ADXL345 驱动代码
  9. //正点原子@ALIENTEK
  10. //技术论坛:www.openedv.com
  11. //修改日期:2012/9/12
  12. //版本:V1.0
  13. //版权所有,盗版必究。
  14. //Copyright(C) 广州市星翼电子科技有限公司 2009-2019
  15. //All rights reserved
  16. //////////////////////////////////////////////////////////////////////////////////
  17. //初始化ADXL345.
  18. //返回值:0,初始化成功;1,初始化失败.
  19. u8 ADXL345_Init(void)
  20. {
  21. IIC_Init(); //初始化IIC总线
  22. if(ADXL345_RD_Reg(DEVICE_ID)==0XE5) //读取器件ID
  23. {
  24. ADXL345_WR_Reg(DATA_FORMAT,0X2B); //低电平中断输出,13位全分辨率,输出数据右对齐,16g量程
  25. ADXL345_WR_Reg(BW_RATE,0x0A); //数据输出速度为100Hz
  26. ADXL345_WR_Reg(POWER_CTL,0x28); //链接使能,测量模式
  27. ADXL345_WR_Reg(INT_ENABLE,0x00); //不使用中断
  28. ADXL345_WR_Reg(OFSX,0x00);
  29. ADXL345_WR_Reg(OFSY,0x00);
  30. ADXL345_WR_Reg(OFSZ,0x00);
  31. return 0;
  32. }
  33. return 1;
  34. }
  35. //写ADXL345寄存器
  36. //addr:寄存器地址
  37. //val:要写入的值
  38. //返回值:无
  39. void ADXL345_WR_Reg(u8 addr,u8 val)
  40. {
  41. IIC_Start();
  42. IIC_Send_Byte(ADXL_WRITE); //发送写器件指令
  43. IIC_Wait_Ack();
  44. IIC_Send_Byte(addr); //发送寄存器地址
  45. IIC_Wait_Ack();
  46. IIC_Send_Byte(val); //发送值
  47. IIC_Wait_Ack();
  48. IIC_Stop(); //产生一个停止条件
  49. }
  50. //读ADXL345寄存器
  51. //addr:寄存器地址
  52. //返回值:读到的值
  53. u8 ADXL345_RD_Reg(u8 addr)
  54. {
  55. u8 temp=0;
  56. IIC_Start();
  57. IIC_Send_Byte(ADXL_WRITE); //发送写器件指令
  58. temp=IIC_Wait_Ack();
  59. IIC_Send_Byte(addr); //发送寄存器地址
  60. temp=IIC_Wait_Ack();
  61. IIC_Start(); //重新启动
  62. IIC_Send_Byte(ADXL_READ); //发送读器件指令
  63. temp=IIC_Wait_Ack();
  64. temp=IIC_Read_Byte(0); //读取一个字节,不继续再读,发送NAK
  65. IIC_Stop(); //产生一个停止条件
  66. return temp; //返回读到的值
  67. }
  68. //读取ADXL的平均值
  69. //x,y,z:读取10次后取平均值
  70. void ADXL345_RD_Avval(short *x,short *y,short *z)
  71. {
  72. short tx=0,ty=0,tz=0;
  73. u8 i;
  74. for(i=0;i<10;i++)
  75. {
  76. ADXL345_RD_XYZ(x,y,z);
  77. delay_ms(10);
  78. tx+=(short)*x;
  79. ty+=(short)*y;
  80. tz+=(short)*z;
  81. }
  82. *x=tx/10;
  83. *y=ty/10;
  84. *z=tz/10;
  85. }
  86. //自动校准
  87. //xval,yval,zval:x,y,z轴的校准值
  88. void ADXL345_AUTO_Adjust(char *xval,char *yval,char *zval)
  89. {
  90. short tx,ty,tz;
  91. u8 i;
  92. short offx=0,offy=0,offz=0;
  93. ADXL345_WR_Reg(POWER_CTL,0x00); //先进入休眠模式.
  94. delay_ms(100);
  95. ADXL345_WR_Reg(DATA_FORMAT,0X2B); //低电平中断输出,13位全分辨率,输出数据右对齐,16g量程
  96. ADXL345_WR_Reg(BW_RATE,0x0A); //数据输出速度为100Hz
  97. ADXL345_WR_Reg(POWER_CTL,0x28); //链接使能,测量模式
  98. ADXL345_WR_Reg(INT_ENABLE,0x00); //不使用中断
  99. ADXL345_WR_Reg(OFSX,0x00);
  100. ADXL345_WR_Reg(OFSY,0x00);
  101. ADXL345_WR_Reg(OFSZ,0x00);
  102. delay_ms(12);
  103. for(i=0;i<10;i++)
  104. {
  105. ADXL345_RD_Avval(&tx,&ty,&tz);
  106. offx+=tx;
  107. offy+=ty;
  108. offz+=tz;
  109. }
  110. offx/=10;
  111. offy/=10;
  112. offz/=10;
  113. *xval=-offx/4;
  114. *yval=-offy/4;
  115. *zval=-(offz-256)/4;
  116. ADXL345_WR_Reg(OFSX,*xval);
  117. ADXL345_WR_Reg(OFSY,*yval);
  118. ADXL345_WR_Reg(OFSZ,*zval);
  119. }
  120. //读取3个轴的数据
  121. //x,y,z:读取到的数据
  122. void ADXL345_RD_XYZ(short *x,short *y,short *z)
  123. {
  124. u8 buf[6];
  125. u8 i;
  126. IIC_Start();
  127. IIC_Send_Byte(ADXL_WRITE); //发送写器件指令
  128. IIC_Wait_Ack();
  129. IIC_Send_Byte(0x32); //发送寄存器地址(数据缓存的起始地址为0X32)
  130. IIC_Wait_Ack();
  131. IIC_Start(); //重新启动
  132. IIC_Send_Byte(ADXL_READ); //发送读器件指令
  133. IIC_Wait_Ack();
  134. for(i=0;i<6;i++)
  135. {
  136. if(i==5)buf[i]=IIC_Read_Byte(0);//读取一个字节,不继续再读,发送NACK
  137. else buf[i]=IIC_Read_Byte(1); //读取一个字节,继续读,发送ACK
  138. }
  139. IIC_Stop(); //产生一个停止条件
  140. *x=(short)(((u16)buf[1]<<8)+buf[0]);
  141. *y=(short)(((u16)buf[3]<<8)+buf[2]);
  142. *z=(short)(((u16)buf[5]<<8)+buf[4]);
  143. }
  144. //读取ADXL345的数据times次,再取平均
  145. //x,y,z:读到的数据
  146. //times:读取多少次
  147. void ADXL345_Read_Average(short *x,short *y,short *z,u8 times)
  148. {
  149. u8 i;
  150. short tx,ty,tz;
  151. *x=0;
  152. *y=0;
  153. *z=0;
  154. if(times)//读取次数不为0
  155. {
  156. for(i=0;i<times;i++)//连续读取times次
  157. {
  158. ADXL345_RD_XYZ(&tx,&ty,&tz);
  159. *x+=tx;
  160. *y+=ty;
  161. *z+=tz;
  162. delay_ms(5);
  163. }
  164. *x/=times;
  165. *y/=times;
  166. *z/=times;
  167. }
  168. }
  169. //得到角度
  170. //x,y,z:x,y,z方向的重力加速度分量(不需要单位,直接数值即可)
  171. //dir:要获得的角度.0,与Z轴的角度;1,与X轴的角度;2,与Y轴的角度.
  172. //返回值:角度值.单位0.1°.
  173. short ADXL345_Get_Angle(float x,float y,float z,u8 dir)
  174. {
  175. float temp;
  176. float res=0;
  177. switch(dir)
  178. {
  179. case 0://与自然Z轴的角度
  180. temp=sqrt((x*x+y*y))/z;
  181. res=atan(temp);
  182. break;
  183. case 1://与自然X轴的角度
  184. temp=x/sqrt((y*y+z*z));
  185. res=atan(temp);
  186. break;
  187. case 2://与自然Y轴的角度
  188. temp=y/sqrt((x*x+z*z));
  189. res=atan(temp);
  190. break;
  191. }
  192. return res*1800/3.14;
  193. }