找回密码
 立即注册

QQ登录

只需一步,快速开始

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

ADXL345计步器单片机程序,找不到器件地址

[复制链接]
跳转到指定楼层
楼主
ID:515167 发表于 2019-4-19 15:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. #include  <REG51.H>        
  2. #include  <INTRINS.H>

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

  6. sbit          SCL=P1^5;      //IIC时钟引脚定义
  7. sbit           SDA=P1^4;      //IIC数据引脚定义

  8. uchar code table_num[]="0123456789abcdefg";

  9. sbit rs=P1^0;         //寄存器选择信号 H:数据寄存器          L:指令寄存器
  10. sbit rw=P1^1;         //寄存器选择信号 H:数据寄存器          L:指令寄存器
  11. sbit e =P1^2;         //片选信号   下降沿触发

  12. sbit key1 = P1^6;
  13. sbit key2 = P1^7;


  14. #define        SlaveAddress   0xA6          //定义器件在IIC总线中的从地址,根据ALT  ADDRESS地址引脚不同修改
  15.                               //ALT  ADDRESS引脚接地时地址为0xA6,接电源时地址为0x3A
  16. long bushu,zong;  //步数

  17. uchar BUF[8];                         //接收数据缓存区              
  18. uchar ge,shi,bai,qian,wan;           //显示变量
  19. int  dis_data;                       //变量

  20. void  Multiple_Read_ADXL345();                                  //连续的读取内部寄存器数据

  21. #define RdCommand 0x01 //定义ISP的操作命令
  22. #define PrgCommand 0x02
  23. #define EraseCommand 0x03
  24. #define Error 1
  25. #define Ok 0
  26. #define WaitTime 0x01 //定义CPU的等待时间
  27. sfr ISP_DATA=0xe2;  //寄存器申明
  28. sfr ISP_ADDRH=0xe3;
  29. sfr ISP_ADDRL=0xe4;
  30. sfr ISP_CMD=0xe5;
  31. sfr ISP_TRIG=0xe6;
  32. sfr ISP_CONTR=0xe7;
  33. uchar a_a;

  34. /* ================ 打开 ISP,IAP 功能 ================= */
  35. void ISP_IAP_enable(void)
  36. {
  37.          EA = 0;       /* 关中断   */
  38.          ISP_CONTR = ISP_CONTR & 0x18;       /* 0001,1000 */
  39.          ISP_CONTR = ISP_CONTR | WaitTime; /* 写入硬件延时 */
  40.          ISP_CONTR = ISP_CONTR | 0x80;       /* ISPEN=1  */
  41. }
  42. /* =============== 关闭 ISP,IAP 功能 ================== */
  43. void ISP_IAP_disable(void)
  44. {
  45.          ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */
  46.          ISP_TRIG = 0x00;
  47.          EA   =   1;   /* 开中断 */
  48. }
  49. /* ================ 公用的触发代码 ==================== */
  50. void ISPgoon(void)
  51. {
  52.          ISP_IAP_enable();   /* 打开 ISP,IAP 功能 */
  53.          ISP_TRIG = 0x46;  /* 触发ISP_IAP命令字节1 */
  54.          ISP_TRIG = 0xb9;  /* 触发ISP_IAP命令字节2 */
  55.          _nop_();
  56. }
  57. /* ==================== 字节读 ======================== */
  58. unsigned char byte_read(unsigned int byte_addr)
  59. {
  60.         EA = 0;
  61.          ISP_ADDRH = (unsigned char)(byte_addr >> 8);/* 地址赋值 */
  62.          ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
  63.          ISP_CMD   = ISP_CMD & 0xf8;   /* 清除低3位  */
  64.          ISP_CMD   = ISP_CMD | RdCommand; /* 写入读命令 */
  65.          ISPgoon();       /* 触发执行  */
  66.          ISP_IAP_disable();    /* 关闭ISP,IAP功能 */
  67.          EA  = 1;
  68.          return (ISP_DATA);    /* 返回读到的数据 */
  69. }
  70. /* ================== 扇区擦除 ======================== */
  71. void SectorErase(unsigned int sector_addr)
  72. {
  73.          unsigned int iSectorAddr;
  74.          iSectorAddr = (sector_addr & 0xfe00); /* 取扇区地址 */
  75.          ISP_ADDRH = (unsigned char)(iSectorAddr >> 8);
  76.          ISP_ADDRL = 0x00;
  77.          ISP_CMD = ISP_CMD & 0xf8;   /* 清空低3位  */
  78.          ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3  */
  79.          ISPgoon();       /* 触发执行  */
  80.          ISP_IAP_disable();    /* 关闭ISP,IAP功能 */
  81. }
  82. /* ==================== 字节写 ======================== */
  83. void byte_write(unsigned int byte_addr, unsigned char original_data)
  84. {
  85.          EA  = 0;
  86.          SectorErase(byte_addr);
  87.          ISP_ADDRH = (unsigned char)(byte_addr >> 8);  /* 取地址  */
  88.          ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
  89.          ISP_CMD  = ISP_CMD & 0xf8;    /* 清低3位 */
  90.          ISP_CMD  = ISP_CMD | PrgCommand;  /* 写命令2 */
  91.          ISP_DATA = original_data;   /* 写入数据准备 */
  92.          ISPgoon();       /* 触发执行  */
  93.          ISP_IAP_disable();     /* 关闭IAP功能 */
  94.          EA =1;
  95. }

  96. /******************把数据保存到单片机内部eeprom中******************/
  97. void write_eeprom()        //保存数据
  98. {
  99.         SectorErase(0x2000);
  100.         byte_write(0x2000, bushu);
  101.         byte_write(0x2001, bushu >> 8);
  102.         byte_write(0x2002, bushu >> 16);

  103.         byte_write(0x2003, zong);
  104.         byte_write(0x2004, zong >> 8);
  105.         byte_write(0x2005, zong >> 16);

  106.         byte_write(0x2055, a_a);        
  107. }

  108. /******************把数据从单片机内部eeprom中读出来*****************/
  109. void read_eeprom()         //读出保存数据
  110. {
  111.         bushu = byte_read(0x2002);
  112.         bushu <<= 8;
  113.         bushu |= byte_read(0x2001);  
  114.         bushu <<= 8;
  115.         bushu |= byte_read(0x2000);

  116.         zong = byte_read(0x2005);
  117.         zong <<= 8;
  118.         zong |= byte_read(0x2004);  
  119.         zong <<= 8;
  120.         zong |= byte_read(0x2003);
  121.         a_a    = byte_read(0x2055);
  122. }

  123. ///**************开机自检eeprom初始化*****************/
  124. void init_eeprom()         ////开始初始化保存的数据
  125. {
  126.         read_eeprom();         //读出保存数据
  127.         if(a_a != 14)                //新的单片机初始单片机内问eeprom
  128.         {
  129.             zong = 0;
  130.                 bushu = 0;
  131.                 a_a = 14;
  132.                 write_eeprom();        //保存数据
  133.         }        
  134. }

  135. /***************************************************************
  136. * 名称 : delay_1ms()
  137. * 功能 : 延时1ms函数
  138. * 输入 : q
  139. * 输出 : 无
  140. ****************************************************************/
  141. void delay_1ms(uint q)
  142. {
  143.         uint i,j;
  144.         for(i=0;i<q;i++)
  145.                 for(j=0;j<120;j++);
  146. }
  147. /********************************************************************
  148. * 名称 : delay_uint()
  149. * 功能 : 小延时。
  150. * 输入 : 无
  151. * 输出 : 无
  152. ***********************************************************************/
  153. void delay_uint(uint q)
  154. {
  155.         while(q--);
  156. }

  157. /********************************************************************
  158. * 名称 : write_com(uchar com)
  159. * 功能 : 1602命令函数
  160. * 输入 : 输入的命令值
  161. * 输出 : 无
  162. ***********************************************************************/
  163. void write_com(uchar com)
  164. {
  165.         e=0;
  166.         rs=0;
  167.         rw=0;
  168.         P0=com;
  169.         delay_uint(25);
  170.         e=1;
  171.         delay_uint(100);
  172.         e=0;
  173. }

  174. /********************************************************************
  175. * 名称 : write_data(uchar dat)
  176. * 功能 : 1602写数据函数
  177. * 输入 : 需要写入1602的数据
  178. * 输出 : 无
  179. ***********************************************************************/
  180. void write_data(uchar dat)
  181. {
  182.         e=0;
  183.         rs=1;
  184.         rw=0;
  185.         P0=dat;
  186.         delay_uint(25);
  187.         e=1;
  188.         delay_uint(100);
  189.         e=0;        
  190. }


  191. /***********************lcd1602上显示十进制数************************/
  192. void write_bushu(uchar hang,uchar add,long date)
  193. {
  194.         if(hang==1)   
  195.                 write_com(0x80+add);
  196.         else
  197.                 write_com(0x80+0x40+add);
  198.         if(date >= 1000000)
  199.                 write_data(0x30+date/1000000%10);
  200.         if(date >= 100000)
  201.                 write_data(0x30+date/100000%10);
  202.         if(date >= 10000)
  203.                 write_data(0x30+date/10000%10);
  204.         if(date >= 1000)
  205.                 write_data(0x30+date/1000%10);
  206.         if(date >= 100)
  207.                 write_data(0x30+date/100%10);
  208.         if(date >= 10)
  209.                 write_data(0x30+date/10%10);
  210.         write_data(0x30+date%10);        
  211. }

  212. /***********************lcd1602上显示这字符函数************************/
  213. void write_string(uchar hang,uchar add,uchar *p)
  214. {
  215.         if(hang==1)   
  216.                 write_com(0x80+add);
  217.         else
  218.                 write_com(0x80+0x40+add);
  219.                 while(1)                                                                                                                 
  220.                 {
  221.                         if(*p == '\0')  break;
  222.                         write_data(*p);
  223.                         p++;
  224.                 }        
  225. }
  226.                
  227. /***********************lcd1602初始化设置************************/
  228. void init_1602()        //lcd1602初始化
  229. {
  230.         write_com(0x38);        
  231.         write_com(0x0c);
  232.         write_com(0x06);
  233.         delay_uint(1000);
  234.         write_string(1,0,"bushu:0            ");        
  235.         write_string(2,0," zong:0            ");        

  236. }
  237.                                 

  238. /**************************************
  239. 延时5微秒(STC90C52RC---12MHz---12T)
  240. 不同的工作环境,需要调整此函数,注意时钟过快时需要修改
  241. 当改用1T的MCU时,请调整此延时函数
  242. **************************************/
  243. void Delay5us()
  244. {
  245.     _nop_();_nop_();_nop_();_nop_();
  246.     _nop_();_nop_();_nop_();_nop_();
  247.         _nop_();_nop_();_nop_();_nop_();
  248. }

  249. /**************************************
  250. 延时5毫秒(STC90C52RC@12M)
  251. 不同的工作环境,需要调整此函数
  252. 当改用1T的MCU时,请调整此延时函数
  253. **************************************/
  254. void Delay5ms()
  255. {
  256.     uint n = 560;

  257.     while (n--);
  258. }

  259. /**************************************
  260. 起始信号
  261. **************************************/
  262. void ADXL345_Start()
  263. {
  264.     SDA = 1;                    //拉高数据线
  265.     SCL = 1;                    //拉高时钟线
  266.     Delay5us();                 //延时
  267.     SDA = 0;                    //产生下降沿
  268.     Delay5us();                 //延时
  269.     SCL = 0;                    //拉低时钟线
  270. }

  271. /**************************************
  272. 停止信号
  273. **************************************/
  274. void ADXL345_Stop()
  275. {
  276.     SDA = 0;                    //拉低数据线
  277.     SCL = 1;                    //拉高时钟线
  278.     Delay5us();                 //延时
  279.     SDA = 1;                    //产生上升沿
  280.     Delay5us();                 //延时
  281. }

  282. /**************************************
  283. 发送应答信号
  284. 入口参数:ack (0:ACK 1:NAK)
  285. **************************************/
  286. void ADXL345_SendACK(bit ack)
  287. {
  288.     SDA = ack;                  //写应答信号
  289.     SCL = 1;                    //拉高时钟线
  290.     Delay5us();                 //延时
  291.     SCL = 0;                    //拉低时钟线
  292.     Delay5us();                 //延时
  293. }

  294. /**************************************
  295. 接收应答信号
  296. **************************************/
  297. bit ADXL345_RecvACK()
  298. {
  299.     SCL = 1;                    //拉高时钟线
  300.     Delay5us();                 //延时
  301.     CY = SDA;                   //读应答信号
  302.     SCL = 0;                    //拉低时钟线
  303.     Delay5us();                 //延时

  304.     return CY;
  305. }

  306. /**************************************
  307. 向IIC总线发送一个字节数据
  308. **************************************/
  309. void ADXL345_SendByte(uchar dat)
  310. {
  311.     uchar i;

  312.     for (i=0; i<8; i++)         //8位计数器
  313.     {
  314.         dat <<= 1;              //移出数据的最高位
  315.         SDA = CY;               //送数据口
  316.         SCL = 1;                //拉高时钟线
  317.         Delay5us();             //延时
  318.         SCL = 0;                //拉低时钟线
  319.         Delay5us();             //延时
  320.     }
  321.     ADXL345_RecvACK();
  322. }

  323. /**************************************
  324. 从IIC总线接收一个字节数据
  325. **************************************/
  326. uchar ADXL345_RecvByte()
  327. {
  328.     uchar i;
  329.     uchar dat = 0;

  330.     SDA = 1;                    //使能内部上拉,准备读取数据,
  331.     for (i=0; i<8; i++)         //8位计数器
  332.     {
  333.         dat <<= 1;
  334.         SCL = 1;                //拉高时钟线
  335.         Delay5us();             //延时
  336.         dat |= SDA;             //读数据               
  337.         SCL = 0;                //拉低时钟线
  338.         Delay5us();             //延时
  339.     }
  340.     return dat;
  341. }

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

  343. void Single_Write_ADXL345(uchar REG_Address,uchar REG_data)
  344. {
  345.     ADXL345_Start();                  //起始信号
  346.     ADXL345_SendByte(SlaveAddress);   //发送设备地址+写信号
  347.     ADXL345_SendByte(REG_Address);    //内部寄存器地址,请参考中文pdf22页
  348.     ADXL345_SendByte(REG_data);       //内部寄存器数据,请参考中文pdf22页
  349.     ADXL345_Stop();                   //发送停止信号
  350. }

  351. //********单字节读取*****************************************
  352. uchar Single_Read_ADXL345(uchar REG_Address)
  353. {  uchar REG_data;
  354.     ADXL345_Start();                          //起始信号
  355.     ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号
  356.     ADXL345_SendByte(REG_Address);            //发送存储单元地址,从0开始        
  357.     REG_data=ADXL345_RecvByte();              //读出寄存器数据
  358.         ADXL345_SendACK(1);   
  359.         ADXL345_Stop();                           //停止信号
  360.     return REG_data;
  361. }
  362. //*********************************************************
  363. //
  364. //连续读出ADXL345内部加速度数据,地址范围0x32~0x37
  365. //
  366. //*********************************************************
  367. void Multiple_read_ADXL345(void)
  368. {   uchar i;
  369.     ADXL345_Start();                          //起始信号
  370.     ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号
  371.     ADXL345_SendByte(0x32);                   //发送存储单元地址,从0x32开始        
  372.          for (i=0; i<6; i++)                      //连续读取6个地址数据,存储中BUF
  373.     {
  374.         BUF[i] = ADXL345_RecvByte();          //BUF[0]存储0x32地址中的数据
  375.         if (i == 5)
  376.         {
  377.            ADXL345_SendACK(1);                //最后一个数据需要回NOACK
  378.         }
  379.         else
  380.         {
  381.           ADXL345_SendACK(0);                //回应ACK
  382.        }
  383.    }
  384.     ADXL345_Stop();                          //停止信号
  385.     Delay5ms();
  386. }


  387. //*****************************************************************

  388. //初始化ADXL345,根据需要请参考pdf进行修改************************
  389. void Init_ADXL345()
  390. {
  391.    Single_Write_ADXL345(0x31,0x2B);   //测量范围,正负16g,13位模式
  392.    Single_Write_ADXL345(0x2C,0x08);   //速率设定为12.5 参考pdf13页
  393.    Single_Write_ADXL345(0x2D,0x08);
  394.    Single_Write_ADXL345(0x2E,0x80);   //使能 DATA_READY 中断
  395.    Single_Write_ADXL345(0x1F,0x00);   // 偏移量 根据测试传感器的状态写入pdf29页
  396.    Single_Write_ADXL345(0x20,0x05);   // 偏移量 根据测试传感器的状态写入pdf29页
  397. }

  398. //***********************************************************************
  399. //显示y轴
  400. void display_y()
  401. {     
  402.         static uchar flag_en,flag_fu;
  403.         float temp;
  404.     dis_data=(BUF[3]<<8)+BUF[2];  //合成数据   
  405.         if(dis_data<0)
  406.         {
  407.                 dis_data=-dis_data;
  408.                 flag_fu = 1;
  409.         }
  410.         else
  411.         {
  412.                 flag_en = 1;
  413.                 flag_fu = 0;
  414.         }
  415.          temp = dis_data;
  416.          if(temp > 100)   //步数加1
  417.         {
  418.                 if((flag_en == 1) && (flag_fu == 1))
  419.                 {
  420.                         flag_en = 0;
  421.                         bushu ++;
  422.                         zong ++;        
  423.                         write_eeprom();        //保存数据
  424.                         write_bushu(1,6,bushu);                //显示步数
  425.                         write_bushu(2,6,zong);                //显示总步数
  426.                 }
  427.         }
  428.         if(temp < 70)  
  429.         {
  430.                 flag_en = 1;        
  431.         }
  432. }

  433. //   按键控制程序
  434. void key()
  435. {
  436.         if(key1 == 0)
  437.         {
  438.                 delay_1ms(1);
  439.                 if(key1 == 0)
  440.                 {
  441.                         zong = 0;
  442.                         write_string(2,6,"        ");
  443.                         write_bushu(1,6,bushu);                //显示步数
  444.                         write_bushu(2,6,zong);                //显示总步数
  445.                         write_eeprom();        //保存数据               
  446.                 }
  447.                 while(key1 == 0);  //松手检测
  448.         }
  449.         if(key2 == 0)
  450.         {
  451.                 delay_1ms(1);
  452.                 if(key2 == 0)
  453.                 {
  454.                         bushu = 0;
  455.                         write_string(1,6,"        ");
  456.                         write_bushu(1,6,bushu);                //显示步数
  457.                         write_bushu(2,6,zong);                //显示总步数
  458.                         write_eeprom();        //保存数据               
  459.                 }
  460.                 while(key2 == 0);  //松手检测
  461.         }
  462. }


  463. //*********************************************************
  464. //******主程序********
  465. //*********************************************************
  466. void main()
  467. {
  468.         static uint flag_value;
  469.         uchar devid;
  470.         init_1602();        //lcd1602初始化
  471.         Init_ADXL345();                         //初始化ADXL345
  472.         devid=Single_Read_ADXL345(0X00);        //读出的数据为0XE5,表示正确
  473.         delay_1ms(20);
  474.         init_eeprom();         ////开始初始化保存的数据
  475.         write_bushu(1,6,bushu);                //显示步数
  476.         write_bushu(2,6,zong);                //显示总步数
  477.         while(1)                                 //循环
  478.         {                 
  479.                 key();          //按键程序
  480.                 flag_value ++;
  481.                 if(flag_value >= 100)           //100ms
  482.                 {
  483.                         flag_value = 0;
  484.                         Init_ADXL345();                         //初始化ADXL345
  485.                         devid=Single_Read_ADXL345(0X00);        //读出的数据为0XE5,表示正确
  486.                         if(devid!=0XE5)
  487.                         {                        
  488.                                 write_string(2,11,"error");                        
  489.                         }
  490.                         else
  491.                         {                        
  492.                                 Multiple_Read_ADXL345();               //连续读出数据,存储在BUF中

  493.                                 display_y();                           //---------显示Y轴
  494.                         }     
  495.                 }
  496.                 delay_1ms(1);                            //延时  
  497.         }
  498. }
复制代码
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:515167 发表于 2019-4-19 15:56 | 只看该作者
一直显示error
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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