找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4947|回复: 4
收起左侧

51单片机adxl345传感器的计步器程序源码

[复制链接]
ID:307792 发表于 2018-4-25 11:25 | 显示全部楼层 |阅读模式
稀缺资源
单片机源码:
  1. #include  <REG52.H>       
  2. #include  <INTRINS.H>
  3. #define   uchar unsigned char
  4. #define   uint unsigned int       
  5. #define   DataPort P0    //LCD1602数据端口
  6. sbit          SCL=P3^5;      //IIC时钟引脚定义;                                         
  7. sbit           SDA=P3^4;      //IIC数据引脚定义
  8. uchar code table_num[]="0123456789abcdefg";
  9.    /* *********** LCD1602设置 *************/
  10. sbit rs=P2^5;         //寄存器选择信号 H:数据寄存器          L:指令寄存器
  11. sbit rw=P2^6;         //寄存器选择信号 H:数据寄存器          L:指令寄存器
  12. sbit e =P2^7;         //片选信号   下降沿触发
  13.          /* ***********清零按键设置 ********/
  14. sbit key1 = P3^6;
  15. sbit key2 = P3^7;
  16. sbit key3 = P1^2;

  17. #define        SlaveAddress   0xA6          /*定义器件在IIC总线中的从地址,根据ALT  ADDRESS地址引脚不同修改ALT  ADDRESS引脚接地时地址为0xA6,接电源时地址为0x3A*/
  18. long bushu,zong;  //步数
  19. uchar BUF[8];                         //接收数据缓存区             
  20. uchar ge,shi,bai,qian,wan;           //显示变量
  21. int  dis_data;                       //变量
  22. int c;
  23. int s;
  24. int h=30.5;
  25. void  Multiple_Read_ADXL345();        //连续的读取内部寄存器数据
  26. #define RdCommand 0x01          //定义ISP的操作命令
  27. #define PrgCommand 0x02
  28. #define EraseCommand 0x03
  29. #define Error 1
  30. #define Ok 0
  31. #define WaitTime 0x01      //定义CPU的等待时间
  32. sfr ISP_DATA=0xe2;         //寄存器申明
  33. sfr ISP_ADDRH=0xe3;
  34. sfr ISP_ADDRL=0xe4;
  35. sfr ISP_CMD=0xe5;
  36. sfr ISP_TRIG=0xe6;
  37. sfr ISP_CONTR=0xe7;
  38. uchar a_a;
  39. /**************打开 ISP,IAP 功能 ********* */
  40. void ISP_IAP_enable(void)
  41. {
  42.          EA = 0;                  //关中断
  43.          ISP_CONTR = ISP_CONTR & 0x18;        // 0001,1000
  44.          ISP_CONTR = ISP_CONTR | WaitTime;    // 写入硬件延时
  45.          ISP_CONTR = ISP_CONTR | 0x80;         // ISPEN=1
  46. }
  47. /************** 关闭 ISP,IAP 功能 *************** */
  48. void ISP_IAP_disable(void)
  49. {
  50.          ISP_CONTR = ISP_CONTR & 0x7f;           // ISPEN = 0
  51.          ISP_TRIG = 0x00;
  52.          EA   =   1;           // 开中断
  53. }
  54. /*****************公用的触发代码********* */
  55. void ISPgoon(void)
  56. {
  57.          ISP_IAP_enable();        //打开 ISP,IAP 功能
  58.          ISP_TRIG = 0x46;     //触发ISP_IAP命令字节1
  59.          ISP_TRIG = 0xb9;            //触发ISP_IAP命令字节2
  60.          _nop_();
  61. }
  62. /**********字节读 *********** */
  63. unsigned char byte_read(unsigned int byte_addr)
  64. {
  65.         EA = 0;
  66.          ISP_ADDRH = (unsigned char)(byte_addr >> 8);    // 地址赋值
  67.          ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
  68.          ISP_CMD   = ISP_CMD & 0xf8;      //清除低3位  
  69.          ISP_CMD   = ISP_CMD | RdCommand;    // 写入读命令
  70.          ISPgoon();           //触发执行  
  71.          ISP_IAP_disable();       // 关闭ISP,IAP功能
  72.          EA  = 1;
  73.          return (ISP_DATA);       // 返回读到的数据
  74. }
  75. /************ 扇区擦除*********** */
  76. void SectorErase(unsigned int sector_addr)
  77. {
  78.          unsigned int iSectorAddr;
  79.          iSectorAddr = (sector_addr & 0xfe00);    // 取扇区地址
  80.          ISP_ADDRH = (unsigned char)(iSectorAddr >> 8);
  81.          ISP_ADDRL = 0x00;
  82.          ISP_CMD = ISP_CMD & 0xf8;      //清空低3位  
  83.          ISP_CMD = ISP_CMD | EraseCommand;    //擦除命令3
  84.          ISPgoon();        //触发执行  
  85.          ISP_IAP_disable();     //关闭ISP,IAP功能
  86. }
  87. /********** 字节写 ******* */
  88. void byte_write(unsigned int byte_addr, unsigned char original_data)
  89. {
  90.          EA  = 0;
  91. //         SectorErase(byte_addr);
  92.          ISP_ADDRH = (unsigned char)(byte_addr >> 8);  // 取地址
  93.          ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
  94.          ISP_CMD  = ISP_CMD & 0xf8;    // 清低3位
  95.          ISP_CMD  = ISP_CMD | PrgCommand;  //写命令2
  96.          ISP_DATA = original_data;   //写入数据准备
  97.          ISPgoon();       //触发执行
  98.          ISP_IAP_disable();     //关闭IAP功能
  99.          EA =1;
  100. }
  101. /**********把数据保存到单片机内部eeprom中**************/
  102. void write_eeprom()        //保存数据
  103. {
  104.         SectorErase(0x2000);
  105.         byte_write(0x2000, bushu);
  106.         byte_write(0x2001, bushu >> 8);
  107.         byte_write(0x2002, bushu >> 16);
  108.         byte_write(0x2003, zong);
  109.         byte_write(0x2004, zong >> 8);
  110.         byte_write(0x2005, zong >> 16);

  111.         byte_write(0x2055, a_a);       
  112. }
  113. /******************把数据从单片机内部eeprom中读出来*****************/
  114. void read_eeprom()         //读出保存数据
  115. {
  116.         bushu = byte_read(0x2002);
  117.         bushu <<= 8;
  118.         bushu |= byte_read(0x2001);  
  119.         bushu <<= 8;
  120.         bushu |= byte_read(0x2000);

  121.         zong = byte_read(0x2005);
  122.         zong <<= 8;
  123.         zong |= byte_read(0x2004);  
  124.         zong <<= 8;
  125.         zong |= byte_read(0x2003);
  126.         a_a    = byte_read(0x2055);
  127. }
  128. /**************开机自检eeprom初始化*****************/
  129. void init_eeprom()           //开始初始化保存的数据
  130. {
  131.         read_eeprom();         //读出保存数据
  132.         if(a_a != 14)                //新的单片机初始单片机内问eeprom
  133.         {
  134.             zong = 0;
  135.                 bushu = 0;
  136.                 a_a = 14;
  137.                 write_eeprom();        //保存数据
  138.         }       
  139. }
  140. void conversion(uint temp_data)  
  141. {  
  142.     wan=temp_data/10000+0x30 ;
  143.     temp_data=temp_data%10000;   //取余运算
  144.         qian=temp_data/1000+0x30 ;
  145.     temp_data=temp_data%1000;    //取余运算
  146.     bai=temp_data/100+0x30   ;
  147.     temp_data=temp_data%100;     //取余运算
  148.     shi=temp_data/10+0x30    ;
  149.     temp_data=temp_data%10;      //取余运算
  150.     ge=temp_data+0x30;        
  151. }
  152. void delay_1ms(uint q)
  153. {
  154.         uint i,j;
  155.         for(i=0;i<q;i++)
  156.                 for(j=0;j<120;j++);
  157. }
  158. void delay_uint(uint q)
  159. {
  160.         while(q--);
  161. }
  162. void write_com(uchar com)
  163. {
  164.         e=0;
  165.         rs=0;
  166.         rw=0;
  167.         P0=com;
  168.         delay_uint(25);
  169.         e=1;
  170.         delay_uint(100);
  171.         e=0;
  172. }
  173. void write_data(uchar dat)
  174. {
  175.         e=0;
  176.         rs=1;
  177.         rw=0;
  178.         P0=dat;
  179.         delay_uint(25);
  180.         e=1;
  181.         delay_uint(100);
  182.         e=0;       
  183. }
  184. /***********lcd1602上显示十进制数************/
  185. void write_bushu(uchar hang,uchar add,long date)
  186. {
  187.         if(hang==1)   
  188.                 write_com(0x80+add);
  189.         else
  190.                 write_com(0x80+0x40+add);
  191.         if(date >= 1000000)
  192.                 write_data(0x30+date/1000000%10);
  193.         if(date >= 100000)
  194.                 write_data(0x30+date/100000%10);
  195.         if(date >= 10000)
  196.                 write_data(0x30+date/10000%10);
  197.         if(date >= 1000)
  198.                 write_data(0x30+date/1000%10);
  199.         if(date >= 100)
  200.                 write_data(0x30+date/100%10);
  201.         if(date >= 10)
  202.                 write_data(0x30+date/10%10);
  203.         write_data(0x30+date%10);       
  204. }
  205. /*************lcd1602上显示这字符函数**************/
  206. void write_string(uchar hang,uchar add,uchar *p)
  207. {
  208.         if(hang==1)   
  209.                 write_com(0x80+add);
  210.         else
  211.                 write_com(0x80+0x40+add);
  212.                 while(1)                                                                                                                 
  213.                 {
  214.                         if(*p == '\0')  break;
  215.                         write_data(*p);
  216.                         p++;
  217.                 }       
  218. }
  219.                
  220. /***********lcd1602初始化设置*************/
  221. void init_1602()        //lcd1602初始化
  222. {
  223.         write_com(0x38);       
  224.         write_com(0x0c);
  225.         write_com(0x06);
  226.         delay_uint(1000);
  227.         write_string(1,0,"B:0      Z:0      ");       
  228.         write_string(2,0,"S:0      C:0      ");       
  229. }
  230. /**********lcd1602上显示特定的字符***********/
  231. void write_zifu(uchar hang,uchar add,uchar date)
  232. {
  233.         if(hang==1)   
  234.                 write_com(0x80+add);
  235.         else
  236.                 write_com(0x80+0x40+add);
  237.         write_data(date);       
  238. }
  239. void Delay5us()
  240. {
  241.     _nop_();_nop_();_nop_();_nop_();
  242.     _nop_();_nop_();_nop_();_nop_();
  243.         _nop_();_nop_();_nop_();_nop_();
  244. }
  245. void Delay5ms()
  246. {
  247.     uint n = 560;

  248.     while (n--);
  249. }
  250. /*********起始信号************/
  251. void ADXL345_Start()
  252. {
  253.     SDA = 1;                    //拉高数据线
  254.     SCL = 1;                    //拉高时钟线
  255.     Delay5us();                 //延时
  256.     SDA = 0;                    //产生下降沿
  257.     Delay5us();                 //延时
  258.     SCL = 0;                    //拉低时钟线
  259. }
  260. /******停止信号********/
  261. void ADXL345_Stop()
  262. {
  263.     SDA = 0;                    //拉低数据线
  264.     SCL = 1;                    //拉高时钟线
  265.     Delay5us();                 //延时
  266.     SDA = 1;                    //产生上升沿
  267.     Delay5us();                 //延时
  268. }
  269. /********发送应答信号  入口参数:ack (0:ACK 1:NAK)**********/
  270. void ADXL345_SendACK(bit ack)
  271. {
  272.     SDA = ack;                  //写应答信号
  273.     SCL = 1;                    //拉高时钟线
  274.     Delay5us();                 //延时
  275.     SCL = 0;                    //拉低时钟线
  276.     Delay5us();                 //延时
  277. }
  278. /**************************************
  279. 接收应答信号
  280. **************************************/
  281. bit ADXL345_RecvACK()
  282. {
  283.     SCL = 1;                    //拉高时钟线
  284.     Delay5us();                 //延时
  285.     CY = SDA;                   //读应答信号
  286.     SCL = 0;                    //拉低时钟线
  287.     Delay5us();                 //延时
  288.     return CY;
  289. }
  290. /**************************************
  291. 向IIC总线发送一个字节数据
  292. **************************************/
  293. void ADXL345_SendByte(uchar dat)
  294. {
  295.     uchar i;
  296.     for (i=0; i<8; i++)         //8位计数器
  297.     {
  298.         dat <<= 1;              //移出数据的最高位
  299.         SDA = CY;               //送数据口
  300.         SCL = 1;                //拉高时钟线
  301.         Delay5us();             //延时
  302.         SCL = 0;                //拉低时钟线
  303.         Delay5us();             //延时
  304.     }
  305.     ADXL345_RecvACK();
  306. }
  307. /*************从IIC总线接收一个字节数据*******/
  308. uchar ADXL345_RecvByte()
  309. {
  310.     uchar i;
  311.     uchar dat = 0;
  312.     SDA = 1;                    //使能内部上拉,准备读取数据,
  313.     for (i=0; i<8; i++)         //8位计数器
  314.     {
  315.         dat <<= 1;
  316.         SCL = 1;                //拉高时钟线
  317.         Delay5us();             //延时
  318.         dat |= SDA;             //读数据               
  319.         SCL = 0;                //拉低时钟线
  320.         Delay5us();             //延时
  321.     }
  322.     return dat;
  323. }
  324. //******单字节写入***********//
  325. void Single_Write_ADXL345(uchar REG_Address,uchar REG_data)
  326. {
  327.     ADXL345_Start();                  //起始信号
  328.     ADXL345_SendByte(SlaveAddress);   //发送设备地址+写信号
  329.     ADXL345_SendByte(REG_Address);    //内部寄存器地址,参考中文pdf22页
  330.     ADXL345_SendByte(REG_data);       //内部寄存器数据,参考中文pdf22页
  331.     ADXL345_Stop();                   //发送停止信号
  332. }
  333. //********单字节读取************//
  334. uchar Single_Read_ADXL345(uchar REG_Address)
  335. {  uchar REG_data;
  336.     ADXL345_Start();                          //起始信号
  337.     ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号
  338.     ADXL345_SendByte(REG_Address);            //发送存储单元地址,从0开始       
  339.     ADXL345_Start();                          //起始信号
  340.     ADXL345_SendByte(SlaveAddress+1);         //发送设备地址+读信号
  341.     REG_data=ADXL345_RecvByte();              //读出寄存器数据
  342.         ADXL345_SendACK(1);   
  343.         ADXL345_Stop();                           //停止信号
  344.     return REG_data;
  345. }
  346. //*****连续读出ADXL345内部加速度数据,地址范围0x32~0x37*****//
  347. void Multiple_read_ADXL345(void)
  348. {   uchar i;
  349.     ADXL345_Start();                          //起始信号
  350.     ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号
  351.     ADXL345_SendByte(0x32);                   //发送存储单元地址,从0x32开始       
  352.     ADXL345_Start();                          //起始信号
  353.     ADXL345_SendByte(SlaveAddress+1);         //发送设备地址+读信号
  354.          for (i=0; i<6; i++)                      //连续读取6个地址数据,存储中BUF
  355.     {
  356.         BUF[i] = ADXL345_RecvByte();          //BUF[0]存储0x32地址中的数据
  357.         if (i == 5)
  358.         {
  359.            ADXL345_SendACK(1);                //最后一个数据需要回NOACK
  360.         }
  361.         else
  362.         {
  363.           ADXL345_SendACK(0);                //回应ACK
  364.        }
  365.    }
  366.     ADXL345_Stop();                          //停止信号
  367.     Delay5ms();
  368. }
  369. //******初始化ADXL345,根据需要请参考pdf进行修改***//
  370. void Init_ADXL345()
  371. {
  372.    Single_Write_ADXL345(0x31,0x0B);   //测量范围,正负16g,13位模式
  373.    Single_Write_ADXL345(0x2C,0x08);   //速率设定为12.5 参考pdf13页
  374.    Single_Write_ADXL345(0x2D,0x08);   //选择电源模式   参考pdf24页
  375.    Single_Write_ADXL345(0x2E,0x80);   //使能 DATA_READY 中断
  376.    Single_Write_ADXL345(0x1E,0x00);   //X 偏移量 根据测试传感器的状态写入pdf29页
  377.    Single_Write_ADXL345(0x1F,0x00);   //Y 偏移量 根据测试传感器的状态写入pdf29页
  378.    Single_Write_ADXL345(0x20,0x05);   //Z 偏移量 根据测试传感器的状态写入pdf29页
  379. }
  380. //*******显示x轴*******//
  381. void display_y()
  382. {     
  383.         static uchar flag_en,flag_fu;
  384.         float temp;
  385.     dis_data=(BUF[3]<<8)+BUF[2];  //合成数据   
  386.         if(dis_data<0)
  387.         {
  388.                 dis_data=-dis_data;
  389.                 flag_fu = 1;
  390.         }
  391.         else
  392.         {
  393.                 flag_en = 1;
  394.                 flag_fu = 0;
  395.         }
  396.     temp=(float)dis_data*3.9;       //计算数据和显示,查考ADXL345快速入门第4页
  397.         if(temp > 100)     //步数加1
  398.         {                    
  399.                 if((flag_en == 1) && (flag_fu == 1))
  400.                 {
  401.                         flag_en = 0;
  402.                         bushu ++;
  403.                         zong ++;
  404.                         s=bushu*h;
  405.                         c=bushu*1.5;       
  406.                         write_eeprom();            //保存数据
  407.                         write_bushu(1,2,bushu);                //显示步数
  408.                         write_bushu(1,11,zong);                //显示总步数
  409.                         write_bushu(2,2,s);
  410.                         write_bushu(2,11,c);
  411.                 }
  412.         }
  413.         if(temp < 70)  
  414.         {
  415.                 flag_en = 1;       
  416.         }
  417. }
  418. //******按键控制程序*******//
  419. void key()
  420. {
  421.         if(key1 == 0)
  422.         {
  423.                 delay_1ms(1);
  424.                 if(key1 == 0)
  425.                 {
  426.                         zong = 0;
  427.                         write_string(1,11,"      ");
  428.                         write_bushu(1,2,bushu);                //显示步数
  429.                         write_bushu(1,11,zong);                //显示总步数
  430.                         write_eeprom();        //保存数据               
  431.                 }
  432.                 while(key1 == 0);  //松手检测
  433.         }
  434.         if(key2 == 0)
  435.         {
  436.                 delay_1ms(1);
  437.                 if(key2 == 0)
  438.                 {
  439.                         bushu = 0;
  440.                         write_string(1,2,"     ");
  441.                         write_bushu(1,2,bushu);                //显示步数
  442.                         write_bushu(1,11,zong);                //显示总步数
  443.                         write_eeprom();        //保存数据               
  444.                 }
  445.                 while(key2 == 0);  //松手检测
  446.         }
  447. }
  448. //******主程序********//
  449. void main()
  450. {
  451.         static uint flag_value;
  452.         uchar devid;
  453.         init_1602();        //lcd1602初始化
  454.         Init_ADXL345();                         //初始化ADXL345
  455.         devid=Single_Read_ADXL345(0X00);        //读出的数据为0XE5,表示正确
  456.         delay_1ms(20);
  457.         init_eeprom();                 //开始初始化保存的数据
  458.         write_bushu(1,11,zong);                //显示总步数
  459.         bushu=0;
  460.         while(1)                      //循环
  461.         {        
  462.         if(key3==0)
  463.         {delay_1ms(1);
  464.           if(key3==0)
  465.             h=h+1.5;}
  466.     if(h==38)
  467.            { h=30.5;}
  468.                
  469.                 key();          //按键程序
  470.                 flag_value ++;
  471.                 if(flag_value >= 100)           //100ms
  472.                 {
  473.                         flag_value = 0;
  474.                         Init_ADXL345();                         //初始化ADXL345
  475.                         devid=Single_Read_ADXL345(0X00);        //读出的数据为0XE5,表示正确
  476.                         if(devid!=0XE5)
  477.                         {                       
  478.                                 write_string(2,11,"error");                       
  479.                         }
  480.                         else
  481.                         {                       
  482.                                 Multiple_Read_ADXL345();               //连续读出数据,存储在BUF中
  483.                                 display_y();                           //---------显示Y轴
  484.                         }     
  485.                 }
  486.                 delay_1ms(1);                            //延时  
  487.         }
  488. }

复制代码

所有资料51hei提供下载:
2、程序.rar (133.75 KB, 下载次数: 89)

评分

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

查看全部评分

回复

使用道具 举报

ID:308041 发表于 2018-5-19 15:42 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

ID:320407 发表于 2018-5-22 15:09 | 显示全部楼层
为什么只是亮屏  没有显示步数,是不是doc>代码里面的直接打开计步器计步器u4vision4  文件
回复

使用道具 举报

ID:744258 发表于 2020-5-5 00:22 | 显示全部楼层
谢谢楼主,
回复

使用道具 举报

ID:904038 发表于 2021-4-21 14:45 | 显示全部楼层
空小白格 发表于 2018-5-22 15:09
为什么只是亮屏  没有显示步数,是不是doc>代码里面的直接打开计步器计步器u4vision4  文件

解决了不,我的也是
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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