单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1656|回复: 4
打印 上一主题 下一主题
收起左侧

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

[复制链接]
跳转到指定楼层
楼主
sssss12123 发表于 2018-4-12 22:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这是自己做的一个小程序,用到了STC12C5160S2这块单片机芯片做控制,实现ADXL345倾角传感器模块测量角度

单片机源程序如下:
  1. /********************************************************************
  2. * 文件名  :GY-29 ADXL345 测角度,角度值显示
  3. * 创建人  :飞翔的猫
  4. * 描述    : 该文件实现了用GY-29 ADXL345角度的采集,并在数码管上显示出来。
  5.                         使用单片机STC89C51
  6. *晶振          :11.0592M
  7. *显示     :LCD1602
  8. *编译环境 :Keil uVision4
  9. ****************************************/
  10. #include  <REG51.H>       
  11. #include  <math.h>    //Keil library  
  12. #include  <stdio.h>   //Keil library       
  13. #include  <INTRINS.H>
  14. #define   uchar unsigned char
  15. #define   uint unsigned int       

  16. //这个一定要根据自己接的引脚来改,否则不出数据
  17. sbit          SCL=P2^0;      //IIC时钟引脚定义
  18. sbit           SDA=P2^1;      //IIC数据引脚定义

  19. #define   DataPort P0    //LCD1602数据端口
  20. sbit      LCM_RS=P2^4;   //LCD1602命令端口               
  21. sbit      LCM_RW=P2^5;   //LCD1602命令端口               
  22. sbit      LCM_EN=P2^7;   //LCD1602命令端口

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

  27. BYTE BUF[8];                         //接收数据缓存区             
  28. uchar ge,shi,bai,qian,wan;           //显示变量
  29. int  dis_data;                       //变量
  30. int  data_xyz[3];



  31. void delay(unsigned int k);
  32. void InitLcd();                      //初始化lcd1602
  33. void Init_ADXL345(void);             //初始化ADXL345

  34. void WriteDataLCM(uchar dataW);
  35. void WriteCommandLCM(uchar CMD,uchar Attribc);
  36. void DisplayOneChar(uchar X,uchar Y,uchar DData);
  37. void conversion(uint temp_data);

  38. void  Single_Write_ADXL345(uchar REG_Address,uchar REG_data);   //单个写入数据
  39. uchar Single_Read_ADXL345(uchar REG_Address);                   //单个读取内部寄存器数据
  40. void Mutiple_Read_ADXL345(void);     
  41. void clear(void);                               //连续的读取内部寄存器数据
  42. //------------------------------------
  43. void Delay5us();
  44. void Delay5ms();
  45. void ADXL345_Start();
  46. void ADXL345_Stop();
  47. void ADXL345_SendACK(bit ack);
  48. bit  ADXL345_RecvACK();
  49. void ADXL345_SendByte(BYTE dat);
  50. BYTE ADXL345_RecvByte();
  51. void ADXL345_ReadPage();
  52. void ADXL345_WritePage();
  53. //-----------------------------------

  54. //*********************************************************
  55. void conversion(uint temp_data)  
  56. {  
  57.     wan=temp_data/10000+0x30 ;
  58.     temp_data=temp_data%10000;   //取余运算
  59.         qian=temp_data/1000+0x30 ;
  60.     temp_data=temp_data%1000;    //取余运算
  61.     bai=temp_data/100+0x30   ;
  62.     temp_data=temp_data%100;     //取余运算
  63.     shi=temp_data/10+0x30    ;
  64.     temp_data=temp_data%10;      //取余运算
  65.     ge=temp_data+0x30;        
  66. }

  67. /*******************************/
  68. void delay(unsigned int k)       
  69. {                                               
  70. unsigned int i,j;                               
  71. for(i=0;i<k;i++)
  72. {                       
  73. for(j=0;j<121;j++)                       
  74. {;}}                                               
  75. }
  76. /*******************************/
  77. void WaitForEnable(void)       
  78. {                                       
  79. DataPort=0xff;               
  80. LCM_RS=0;LCM_RW=1;_nop_();
  81. LCM_EN=1;_nop_();_nop_();
  82. while(DataPort&0x80);       
  83. LCM_EN=0;                               
  84. }                                       
  85. /*******************************/
  86. void WriteCommandLCM(uchar CMD,uchar Attribc)
  87. {                                       
  88. if(Attribc)WaitForEnable();       
  89. LCM_RS=0;LCM_RW=0;_nop_();
  90. DataPort=CMD;_nop_();       
  91. LCM_EN=1;_nop_();_nop_();LCM_EN=0;
  92. }                                       
  93. /*******************************/
  94. void WriteDataLCM(uchar dataW)
  95. {                                       
  96. WaitForEnable();               
  97. LCM_RS=1;LCM_RW=0;_nop_();
  98. DataPort=dataW;_nop_();       
  99. LCM_EN=1;_nop_();_nop_();LCM_EN=0;
  100. }               
  101. /***********************************/
  102. void InitLcd()                        //液晶显示器的设置       
  103. {                       
  104. WriteCommandLCM(0x38,1);       
  105. WriteCommandLCM(0x08,1);       
  106. WriteCommandLCM(0x01,1);       
  107. WriteCommandLCM(0x06,1);       
  108. WriteCommandLCM(0x0c,1);
  109. }                       
  110. /***********************************/
  111. void DisplayOneChar(uchar X,uchar Y,uchar DData)
  112. {                                               
  113. Y&=1;                                               
  114. X&=15;                                               
  115. if(Y)X|=0x40;                                       
  116. X|=0x80;                       
  117. WriteCommandLCM(X,0);               
  118. WriteDataLCM(DData);               
  119. }                                               

  120. /**************************************
  121. 延时5微秒(STC90C52RC@12M)
  122. 不同的工作环境,需要调整此函数,注意时钟过快时需要修改
  123. 当改用1T的MCU时,请调整此延时函数
  124. **************************************/
  125. void Delay5us()
  126. {
  127.     _nop_();_nop_();_nop_();_nop_();
  128.     _nop_();_nop_();_nop_();_nop_();
  129.         _nop_();_nop_();_nop_();_nop_();
  130. }

  131. /**************************************
  132. 延时5毫秒(STC90C52RC@12M)
  133. 不同的工作环境,需要调整此函数
  134. 当改用1T的MCU时,请调整此延时函数
  135. **************************************/
  136. void Delay5ms()
  137. {
  138.     WORD n = 560;

  139.     while (n--);
  140. }

  141. /**************************************
  142. 起始信号
  143. **************************************/
  144. void ADXL345_Start()
  145. {
  146.     SDA = 1;                    //拉高数据线
  147.     SCL = 1;                    //拉高时钟线
  148.     Delay5us();                 //延时
  149.     SDA = 0;                    //产生下降沿
  150.     Delay5us();                 //延时
  151.     SCL = 0;                    //拉低时钟线
  152. }

  153. /**************************************
  154. 停止信号
  155. **************************************/
  156. void ADXL345_Stop()
  157. {
  158.     SDA = 0;                    //拉低数据线
  159.     SCL = 1;                    //拉高时钟线
  160.     Delay5us();                 //延时
  161.     SDA = 1;                    //产生上升沿
  162.     Delay5us();                 //延时
  163. }

  164. /**************************************
  165. 发送应答信号
  166. 入口参数:ack (0:ACK 1:NAK)
  167. **************************************/
  168. void ADXL345_SendACK(bit ack)
  169. {
  170.     SDA = ack;                  //写应答信号
  171.     SCL = 1;                    //拉高时钟线
  172.     Delay5us();                 //延时
  173.     SCL = 0;                    //拉低时钟线
  174.     Delay5us();                 //延时
  175. }

  176. /**************************************
  177. 接收应答信号
  178. **************************************/
  179. bit ADXL345_RecvACK()
  180. {
  181.     SCL = 1;                    //拉高时钟线
  182.     Delay5us();                 //延时
  183.     CY = SDA;                   //读应答信号
  184.     SCL = 0;                    //拉低时钟线
  185.     Delay5us();                 //延时

  186.     return CY;
  187. }

  188. /**************************************
  189. 向IIC总线发送一个字节数据
  190. **************************************/
  191. void ADXL345_SendByte(BYTE dat)
  192. {
  193.     BYTE i;

  194.     for (i=0; i<8; i++)         //8位计数器
  195.     {
  196.         dat <<= 1;              //移出数据的最高位
  197.         SDA = CY;               //送数据口
  198.         SCL = 1;                //拉高时钟线
  199.         Delay5us();             //延时
  200.         SCL = 0;                //拉低时钟线
  201.         Delay5us();             //延时
  202.     }
  203.     ADXL345_RecvACK();
  204. }

  205. /**************************************
  206. 从IIC总线接收一个字节数据
  207. **************************************/
  208. BYTE ADXL345_RecvByte()
  209. {
  210.     BYTE i;
  211.     BYTE dat = 0;

  212.     SDA = 1;                    //使能内部上拉,准备读取数据,
  213.     for (i=0; i<8; i++)         //8位计数器
  214.     {
  215.         dat <<= 1;
  216.         SCL = 1;                //拉高时钟线
  217.         Delay5us();             //延时
  218.         dat |= SDA;             //读数据               
  219.         SCL = 0;                //拉低时钟线
  220.         Delay5us();             //延时
  221.     }
  222.     return dat;
  223. }

  224. //******单字节写入*******************************************

  225. void Single_Write_ADXL345(uchar REG_Address,uchar REG_data)
  226. {
  227.     ADXL345_Start();                  //起始信号
  228.     ADXL345_SendByte(SlaveAddress);   //发送设备地址+写信号
  229.     ADXL345_SendByte(REG_Address);    //内部寄存器地址,请参考中文pdf22页
  230.     ADXL345_SendByte(REG_data);       //内部寄存器数据,请参考中文pdf22页
  231.     ADXL345_Stop();                   //发送停止信号
  232. }

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

  276. void clear(void)
  277. {   uchar i;
  278.     ADXL345_Start();  
  279.                                 //起始信号
  280.     ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号
  281.     ADXL345_SendByte(0x32);                   //发送存储单元地址,从0x32开始       
  282.     ADXL345_Start();                          //起始信号
  283.     ADXL345_SendByte(SlaveAddress+1);         //发送设备地址+读信号
  284.          for (i=0; i<6; i++)                      //连续读取6个地址数据,存储中BUF
  285.     {
  286.         //BUF[i] = ADXL345_RecvByte();          //BUF[0]存储0x32地址中的数据
  287.                 BUF[i]=i;
  288.         if (i == 5)
  289.         {
  290.            ADXL345_SendACK(1);                //最后一个数据需要回NOACK
  291.         }
  292.         else
  293.         {
  294.            ADXL345_SendACK(0);                //回应ACK
  295.        }
  296.    }
  297.     ADXL345_Stop();                          //停止信号
  298.     Delay5ms();
  299. }
  300. //*****************************************************************

  301. //初始化ADXL345,根据需要请参考pdf进行修改************************
  302. void Init_ADXL345()
  303. {
  304.    Single_Write_ADXL345(0x31,0x0B);   //测量范围,正负16g,13位模式
  305.    Single_Write_ADXL345(0x2C,0x08);   //速率设定为12.5 参考pdf13页
  306.    Single_Write_ADXL345(0x2D,0x08);   //选择电源模式   参考pdf24页
  307.    Single_Write_ADXL345(0x2E,0x80);   //使能 DATA_READY 中断
  308.    Single_Write_ADXL345(0x1E,0x00);   //X 偏移量 根据测试传感器的状态写入pdf29页
  309.    Single_Write_ADXL345(0x1F,0x00);   //Y 偏移量 根据测试传感器的状态写入pdf29页
  310.    Single_Write_ADXL345(0x20,0x05);   //Z 偏移量 根据测试传感器的状态写入pdf29页
  311. }
  312. //***********************************************************************
  313. //显示x轴
  314. void display_x()
  315. {   float temp;
  316.     dis_data=(BUF[1]<<8)+BUF[0];  //合成数据   
  317.         if(dis_data<0){
  318.         dis_data=-dis_data;
  319.     DisplayOneChar(2,0,'-');      //显示正负符号位
  320.         }
  321.         else DisplayOneChar(2,0,' '); //显示空格

  322.     temp=(float)dis_data*3.9;  //计算数据和显示,查考ADXL345快速入门第4页
  323.     conversion(temp);          //转换出显示需要的数据
  324.         DisplayOneChar(0,0,'X');   //第0行,第0列 显示X
  325.     DisplayOneChar(1,0,':');
  326.     DisplayOneChar(3,0,qian);
  327.         DisplayOneChar(4,0,'.');
  328.     DisplayOneChar(5,0,bai);
  329.     DisplayOneChar(6,0,shi);
  330.         DisplayOneChar(7,0,'g');
  331. }

  332. //***********************************************************************
  333. //显示y轴
  334. void display_y()
  335. {     float temp;
  336.     dis_data=(BUF[3]<<8)+BUF[2];  //合成数据   
  337.         if(dis_data<0){
  338.         dis_data=-dis_data;
  339.     DisplayOneChar(2,1,'-');      //显示正负符号位
  340.         }
  341.         else DisplayOneChar(2,1,' '); //显示空格

  342.     temp=(float)dis_data*3.9;  //计算数据和显示,查考ADXL345快速入门第4页
  343.     conversion(temp);          //转换出显示需要的数据
  344.         DisplayOneChar(0,1,'Y');   //第1行,第0列 显示y
  345.     DisplayOneChar(1,1,':');
  346.     DisplayOneChar(3,1,qian);
  347.         DisplayOneChar(4,1,'.');
  348.     DisplayOneChar(5,1,bai);
  349.     DisplayOneChar(6,1,shi);  
  350.         DisplayOneChar(7,1,'g');  
  351. }

  352. //***********************************************************************
  353. //显示z轴
  354. void display_z()
  355. {      float temp;
  356.     dis_data=(BUF[5]<<8)+BUF[4];    //合成数据   
  357.         if(dis_data<0){
  358.         dis_data=-dis_data;
  359.     DisplayOneChar(10,1,'-');       //显示负符号位
  360.         }
  361.         else DisplayOneChar(10,1,' ');  //显示空格

  362.     temp=(float)dis_data*3.9;  //计算数据和显示,查考ADXL345快速入门第4页
  363.     conversion(temp);          //转换出显示需要的数据
  364.         DisplayOneChar(10,0,'Z');  //第0行,第10列 显示Z
  365.     DisplayOneChar(11,0,':');
  366.     DisplayOneChar(11,1,qian);
  367.         DisplayOneChar(12,1,'.');
  368.     DisplayOneChar(13,1,bai);
  369.     DisplayOneChar(14,1,shi);
  370.         DisplayOneChar(15,1,'g');  
  371. }



  372. //串口通讯函数  自己加的程序段,将ADXL的角度值写到串口中
  373. void uart_initial_with_interrupt(void);
  374. void uart_adxl(void);
  375. int uart_i;
  376. void uart_initial_with_interrupt(void)
  377. {   
  378.         //TOMD 定时器工作模式寄存器
  379.         //TCON 中断控制寄存器:定时器中断和外部中断
  380.         //IE   中断允许控制寄存器

  381.         TMOD=0x20;           //设置定时器工作模式,定时器1工作在模式2,8位自动重装

  382.         TH1=0xfd;           //定时器1设置,产生9600波特率,开启定时器1
  383.         TL1=0xfd;
  384.         TR1=1;

  385.         SM0=0;
  386.         SM1=1;
  387.         REN=1;

  388.         EA=1;  //允许总中断
  389.         ES=1;  //允许串口中断       
  390. }
  391. void  uart_adxl(void) interrupt 4
  392. {
  393.         uchar ch;
  394.         if(RI)
  395.         {
  396.                 ch='a';               
  397.         }

  398. }
  399. int Roll_int,Pitch_int;
  400. uchar Roll_int_high,Roll_int_low;
  401. uchar Pitch_int_high,Pitch_int_low;
  402. //*********************************************************
  403. //******主程序********
  404. //*********************************************************
  405. void main()
  406. {         int d;
  407.           uchar devid;
  408.         float Roll,Pitch,Q,T,K;

  409.         //打开串口中断
  410.         uart_initial_with_interrupt();
  411.                        
  412.         Init_ADXL345();                 //初始化ADXL345
  413.         devid=Single_Read_ADXL345(0X00);//读出的数据为0XE5,表示正确
  414.        
  415.     while(1)                         //循环
  416.     {
  417.             
  418.                 //测试串口工作情况
  419.                 for(uart_i=0;uart_i<2;uart_i++)
  420.                 {
  421.                          SBUF=0;
  422.                         while(!TI);
  423.                         TI=0;
  424.                         delay(500);
  425.                 }


  426.                 Init_ADXL345();                     //初始化ADXL345
  427.        //连续读出数据,存储在BUF       
  428.                 Mutiple_Read_ADXL345();
  429.                 data_xyz[0]=(BUF[1]<<8)|BUF[0];  //合成数据    【改动】将+ 改成了 |
  430.                 data_xyz[1]=(BUF[3]<<8)|BUF[2];  //合成数据   
  431.                 data_xyz[2]=(BUF[5]<<8)|BUF[4];  //合成数据  
  432.                
  433.                  
  434.                 //测试是否有数据改变
  435.                 for(d=0;d<3;d++){
  436.                 SBUF=data_xyz[d];
  437.                 while(!TI);
  438. ……………………

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

所有资料51hei提供下载:
ADXL345-angle.rar (44.98 KB, 下载次数: 39)


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 转播转播 分享分享 分享淘帖 顶 踩
回复

使用道具 举报

沙发
hidled 发表于 2019-3-15 20:25 | 只看该作者
能修改一下控制LED闪烁吗 不要显示!
回复

使用道具 举报

板凳
1113634577 发表于 2019-4-3 09:18 | 只看该作者
结合飞行器做个项目
回复

使用道具 举报

地板
liuliyue 发表于 2019-4-3 09:40 | 只看该作者
学到了学到了
回复

使用道具 举报

5#
海上风 发表于 2019-4-9 18:02 | 只看该作者
高手老师,能不能做个倾角传感器采集角度后,通过GSM通信传输到手机上,十分感谢
回复

使用道具 举报

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

本版积分规则

QQ|手机版|小黑屋|单片机论坛 |51黑电子论坛5群 联系QQ:125739409;技术交流QQ群174280738

Powered by 单片机教程网

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