找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6969|回复: 8
收起左侧

无线蓝牙小车—手势遥控 全套制作资料

  [复制链接]
ID:210249 发表于 2017-6-11 21:50 | 显示全部楼层 |阅读模式
本制作以STC89C52RC单片机和ADXL345加速度模块。加速度模块固定在手上时,当手向左倾斜,小车左转;手向右倾斜,小车右转;手向前倾斜,小车前进;手向后倾斜,小车倒退;手水平不动,小车停止任何动作。有效控制范围 10米(开阔地)。
0.png 0.png
0.png
0.png
资料在附件中。。。。。

加速度模块不同倾角时,向计算机发送不同数据
1 左偏时,发送0a
2 右偏时,发送a0
3 前偏时,发送aa
3 后偏是,发送55

发送数据时,数据类型具备优先级,当左右方向现有数据时,优先发送左右控制字符

优化了部分程序,删除了多余的测试程序
优化了数组,相比于版本3,删除了多余的数组

单片机源程序如下:
  1. #include  <REG52.H>        
  2. #include  <basic.h>
  3. #include  <math.h>    //Keil library  
  4. #include  <stdio.h>   //Keil library        
  5. #include  <INTRINS.H>
  6. sbit          SCL=P1^0;      //IIC时钟引脚定义
  7. sbit           SDA=P1^1;      //IIC数据引脚定义
  8. #define        SlaveAddress   0xA6          //定义器件在IIC总线中的从地址,根据ALT  ADDRESS地址引脚不同修改
  9.                               //ALT  ADDRESS引脚接地时地址为0xA6,接电源时地
  10. #define JudgeP_M  0x8000   //正负数判断
  11. #define Left_cmp  0x006e   //方向数据比较值,数值越小,越灵敏
  12. #define Right_cmp 0x006e
  13. #define Go_cmp    0x006e
  14. #define Back_cmp  0x006e
  15. #define Go    0xaa                   //小车实际动作控制字符,以实物为准
  16. #define Back  0x55
  17. #define Left  0xa0
  18. #define Right 0x0a
  19. #define Stop  0x00                   //停止控制字符
  20. Byte BUF[8];                         //接收数据缓存区
  21. Byte Sbuf[8];
  22. Word Wbuf[2];            
  23. int  dis_data;                       //变量
  24. void delay(unsigned int k);
  25. void Init_ADXL345(void);             //初始化ADXL345
  26. void WriteDataLCM(Byte dataW);
  27. void WriteCommandLCM(Byte CMD,Byte Attribc);
  28. void DisplayOneChar(Byte X,Byte Y,Byte DData);
  29. void conversion(Word temp_data);
  30. void  Single_Write_ADXL345(Byte REG_Address,Byte REG_data);   //单个写入数据
  31. Byte Single_Read_ADXL345(Byte REG_Address);                   //单个读取内部寄存器数据
  32. void  Multiple_Read_ADXL345();                                  //连续的读取内部寄存器数据
  33. //------------------------------------
  34. void Delay5us();
  35. void Delay5ms();
  36. void Delay20ms();
  37. void ADXL345_Start();
  38. void ADXL345_Stop();
  39. void ADXL345_SendACK(bit ack);
  40. bit  ADXL345_RecvACK();
  41. void ADXL345_SendByte(Byte dat);
  42. Byte ADXL345_RecvByte();
  43. void ADXL345_ReadPage();
  44. void ADXL345_WritePage();
  45. void send();
  46. void uart();
  47. void Data_Convert();
  48. void Data_Process();
  49. void direction_judge();


  50. //******主程序********
  51. void main()
  52. {
  53.         void Delay20ms();                                   //上电延时                                   
  54.         uart();        
  55.         Init_ADXL345();                         //初始化ADXL345
  56.         while(1)                                 //循环
  57.         {
  58.                 Multiple_Read_ADXL345();               //连续读出数据,存储在BUF中
  59.                 Data_Convert();
  60.         Data_Process();
  61.                 direction_judge();
  62.                 Delay20ms();                           //延时      
  63.         }
  64. }

  65. /*******************************/
  66. void Delay20ms()                //@11.0592MHz
  67. {
  68.         unsigned char i, j, k;

  69.         _nop_();
  70.         _nop_();
  71.         i = 1;
  72.         j = 216;
  73.         k = 35;
  74.         do
  75.         {
  76.                 do
  77.                 {
  78.                         while (--k);
  79.                 } while (--j);
  80.         } while (--i);
  81. }
  82.                                                                                 
  83. /*******************************/                                       
  84. /**************************************
  85. 延时5微秒(STC90C52RC@12M)
  86. 不同的工作环境,需要调整此函数,注意时钟过快时需要修改
  87. 当改用1T的MCU时,请调整此延时函数
  88. **************************************/
  89. void Delay5us()
  90. {
  91.     _nop_();_nop_();_nop_();_nop_();
  92.     _nop_();_nop_();_nop_();_nop_();
  93.         _nop_();_nop_();_nop_();_nop_();
  94. }

  95. /**************************************
  96. 延时5毫秒(STC90C52RC@12M)
  97. 不同的工作环境,需要调整此函数
  98. 当改用1T的MCU时,请调整此延时函数
  99. **************************************/
  100. void Delay5ms()
  101. {
  102.     Word n = 560;

  103.     while (n--);
  104. }
  105. /**************************************
  106. 起始信号
  107. **************************************/
  108. void ADXL345_Start()
  109. {
  110.     SDA = 1;                    //拉高数据线
  111.     SCL = 1;                    //拉高时钟线
  112.     Delay5us();                 //延时
  113.     SDA = 0;                    //产生下降沿
  114.     Delay5us();                 //延时
  115.     SCL = 0;                    //拉低时钟线
  116. }
  117. /**************************************
  118. 停止信号
  119. **************************************/
  120. void ADXL345_Stop()
  121. {
  122.     SDA = 0;                    //拉低数据线
  123.     SCL = 1;                    //拉高时钟线
  124.     Delay5us();                 //延时
  125.     SDA = 1;                    //产生上升沿
  126.     Delay5us();                 //延时
  127. }
  128. /**************************************
  129. 发送应答信号
  130. 入口参数:ack (0:ACK 1:NAK)
  131. **************************************/
  132. void ADXL345_SendACK(bit ack)
  133. {
  134.     SDA = ack;                  //写应答信号
  135.     SCL = 1;                    //拉高时钟线
  136.     Delay5us();                 //延时
  137.     SCL = 0;                    //拉低时钟线
  138.     Delay5us();                 //延时
  139. }
  140. /**************************************
  141. 接收应答信号
  142. **************************************/
  143. bit ADXL345_RecvACK()
  144. {
  145.     SCL = 1;                    //拉高时钟线
  146.     Delay5us();                 //延时
  147.     CY = SDA;                   //读应答信号
  148.     SCL = 0;                    //拉低时钟线
  149.     Delay5us();                 //延时

  150.     return CY;
  151. }
  152. /**************************************
  153. 向IIC总线发送一个字节数据
  154. **************************************/
  155. void ADXL345_SendByte(Byte dat)
  156. {
  157.     Byte i;

  158.     for (i=0; i<8; i++)         //8位计数器
  159.     {
  160.         dat <<= 1;              //移出数据的最高位
  161.         SDA = CY;               //送数据口
  162.         SCL = 1;                //拉高时钟线
  163.         Delay5us();             //延时
  164.         SCL = 0;                //拉低时钟线
  165.         Delay5us();             //延时
  166.     }
  167.     ADXL345_RecvACK();
  168. }
  169. //从IIC总线接收一个字节数据
  170. Byte ADXL345_RecvByte()
  171. {
  172.     Byte i;
  173.     Byte dat = 0;
  174.     SDA = 1;                    //使能内部上拉,准备读取数据,
  175.     for (i=0; i<8; i++)         //8位计数器
  176.     {
  177.         dat <<= 1;
  178.         SCL = 1;                //拉高时钟线
  179.         Delay5us();             //延时
  180.         dat |= SDA;             //读数据               
  181.         SCL = 0;                //拉低时钟线
  182.         Delay5us();             //延时
  183.     }
  184.     return dat;
  185. }
  186. //******单字节写入*******************************************
  187. void Single_Write_ADXL345(Byte REG_Address,Byte REG_data)
  188. {
  189.     ADXL345_Start();                  //起始信号
  190.     ADXL345_SendByte(SlaveAddress);   //发送设备地址+写信号
  191.     ADXL345_SendByte(REG_Address);    //内部寄存器地址,请参考中文pdf22页
  192.     ADXL345_SendByte(REG_data);       //内部寄存器数据,请参考中文pdf22页
  193.     ADXL345_Stop();                   //发送停止信号
  194. }
  195. //********单字节读取*****************************************
  196. Byte Single_Read_ADXL345(Byte REG_Address)
  197. {  Byte REG_data;
  198.     ADXL345_Start();                          //起始信号
  199.     ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号
  200.     ADXL345_SendByte(REG_Address);            //发送存储单元地址,从0开始        
  201.     ADXL345_Start();                          //起始信号
  202.     ADXL345_SendByte(SlaveAddress+1);         //发送设备地址+读信号
  203.     REG_data=ADXL345_RecvByte();              //读出寄存器数据
  204.         ADXL345_SendACK(1);   
  205.         ADXL345_Stop();                           //停止信号
  206.     return REG_data;
  207. }
  208. //连续读出ADXL345内部加速度数据,地址范围0x32~0x37
  209. void Multiple_read_ADXL345(void)
  210. {   Byte i;
  211.     ADXL345_Start();                          //起始信号
  212.     ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号
  213.     ADXL345_SendByte(0x32);                   //发送存储单元地址,从0x32开始        
  214.     ADXL345_Start();                          //起始信号
  215.     ADXL345_SendByte(SlaveAddress+1);         //发送设备地址+读信号
  216.          for (i=0; i<6; i++)                      //连续读取6个地址数据,存储中BUF
  217.     {
  218.         BUF[i] = ADXL345_RecvByte();          //BUF[0]存储0x32地址中的数据
  219.         if (i == 5)
  220.         {
  221.            ADXL345_SendACK(1);                //最后一个数据需要回NOACK
  222.         }
  223.         else
  224.         {
  225.           ADXL345_SendACK(0);                //回应ACK
  226.        }
  227.    }
  228.     ADXL345_Stop();                          //停止信号
  229.     Delay5ms();
  230. }
  231. //初始化ADXL345,根据需要请参考pdf进行修改************************
  232. void Init_ADXL345()
  233. {
  234.    Single_Write_ADXL345(0x31,0x0B);   //测量范围,正负16g,13位模式
  235.    Single_Write_ADXL345(0x2C,0x08);   //速率设定为12.5 参考pdf13页
  236.    Single_Write_ADXL345(0x2D,0x08);   //选择电源模式   参考pdf24页
  237.    Single_Write_ADXL345(0x2E,0x80);   //使能 DATA_READY 中断
  238.    Single_Write_ADXL345(0x1E,0x00);   //X 偏移量 根据测试传感器的状态写入pdf29页
  239.    Single_Write_ADXL345(0x1F,0x00);   //Y 偏移量 根据测试传感器的状态写入pdf29页
  240.    Single_Write_ADXL345(0x20,0x05);   //Z 偏移量 根据测试传感器的状态写入pdf29页
  241. }
  242. void uart()
  243. {
  244. SCON=0x50;
  245. TMOD=0x20;
  246. PCON=0x00;
  247. TH1=0xfd;
  248. TL1=0xfd;
  249. IE=0x90;
  250. TR1=1;
  251. }

  252. void send(unsigned char ch)
  253. {
  254. ES=0;
  255. SBUF=ch;
  256. while (TI==0);
  257. TI=0 ;
  258. ES=1;
  259. }
  260. void Data_Convert()                                                //将两个八位数据合成为一个16位数据
  261. {
  262.   Wbuf[0]=BUF[1]<<8|BUF[0];
  263.   Wbuf[1]=BUF[3]<<8|BUF[2];
  264.   Wbuf[2]=BUF[5]<<8|BUF[4];
  265. }
  266. void Data_Process()
  267. {
  268.    Word i=0;
  269.     i=Wbuf[0]&JudgeP_M;           //X轴数据处理
  270.   if(i==0x8000)                   //当结果为负数时
  271.   {
  272.    Wbuf[0]=~Wbuf[0]+1;
  273.    Wbuf[0]=Wbuf[0]&0x7fff;
  274.    if(Wbuf[0]>Left_cmp)
  275.    {
  276.    Sbuf[0]=Left;
  277.    }
  278.    else
  279.    {
  280.    Sbuf[0]=Stop;
  281.    }
  282.   }
  283.   else                                           //当结果为正数时
  284.   {
  285.    if(Wbuf[0]>Right_cmp)
  286.    {
  287.       Sbuf[0]=Right;
  288.    }
  289.    else
  290.    {
  291.            Sbuf[0]=Stop;
  292.    }
  293.   }
  294.   i=Wbuf[1]&JudgeP_M;                   //Y轴数据处理
  295.   if(i==0x8000)                   //当结果为负数时
  296.   {
  297. ……………………

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

所有资料51hei提供下载:
无线蓝牙小车-手势遥控全套代码资料.rar (1.14 MB, 下载次数: 109)

评分

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

查看全部评分

回复

使用道具 举报

ID:209421 发表于 2017-6-20 06:43 | 显示全部楼层
虽然看不懂,还是先收藏了
回复

使用道具 举报

ID:164602 发表于 2017-6-22 09:14 | 显示全部楼层
2016年,我在单片机微信上看到了这个,当时由于不理解蓝牙,所以没能做出来,虽然十分有兴趣。现在用手机做出来一个遥控小车,理解了蓝牙的使用,但这个加速度仪还是不会用,能读出加速度仪的数据,但还不理解它的数据含义,所以没有做出来。可惜。看到这全套的资料,也是无奈啊!
回复

使用道具 举报

ID:455377 发表于 2018-12-26 14:58 来自手机 | 显示全部楼层
太厉害了
回复

使用道具 举报

ID:457150 发表于 2018-12-28 11:38 | 显示全部楼层
好东西呀,正在学习这方面知识,顶起来!
回复

使用道具 举报

ID:483023 发表于 2019-4-3 18:53 | 显示全部楼层
把发射程序和接收程序一起烧入单片机吗?
回复

使用道具 举报

ID:250717 发表于 2019-4-4 14:30 | 显示全部楼层
楼主,能把用到的材料的淘宝链接发一下吗?我也想做一个。
回复

使用道具 举报

ID:483023 发表于 2019-4-12 09:52 来自手机 | 显示全部楼层
照着步骤做我都没成功,有成功的吗?
回复

使用道具 举报

ID:371529 发表于 2019-4-19 20:47 | 显示全部楼层
黑魔力 发表于 2019-4-12 09:52
照着步骤做我都没成功,有成功的吗?

我也没有,很是无奈,可能是蓝牙没有配对
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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