找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 19226|回复: 13
收起左侧

手势遥控智能小车制作

  [复制链接]
ID:104763 发表于 2016-7-17 12:21 | 显示全部楼层 |阅读模式
前不久参加学校挑战杯,然后自己做了个手势遥控小车,51单片机+mpu605+蓝牙,大约半天就搞定了,现在把这个分享出来 IMG_20160624_171256.jpg 左边那个是遥控器


IMG_20160624_204628.jpg

小车的程序
  1. #include<reg51.h>
  2. #include"lcd.h"
  3. #define uint unsigned int
  4. #define uchar unsigned char

  5. bit flag=0;
  6. bit flag_REC=0;

  7. uchar i=0;
  8. uchar dat=0;

  9. sbit M11=P2^1;
  10. sbit M12=P2^2;
  11. sbit M21=P2^3;
  12. sbit M22=P2^4; /*驱动控制*/



  13. void delayms(uint xms)
  14. {
  15.     uint i,j;
  16.     for(i=xms;i>0;i--)
  17.       for(j=110;j>0;j--);
  18. }

  19. void back()
  20. {
  21.     M11=1;
  22.     M12=0;
  23.     M21=1;
  24.     M22=0;   
  25. }

  26. void forward()
  27. {
  28.     M11=0;
  29.     M12=1;
  30.     M21=0;
  31.     M22=1;
  32. }
  33. void stop()
  34. {
  35.     M11=0;
  36.     M12=0;
  37.     M21=0;
  38.     M22=0;
  39. }

  40. void turn_left()
  41. {
  42.     M11=1;
  43.     M12=0;
  44.     M21=0;
  45.     M22=1;
  46. }

  47. void turn_right()
  48. {
  49.     M11=0;
  50.     M12=1;
  51.     M21=1;
  52.     M22=0;
  53. }

  54. void main()
  55. {
  56.     TMOD=0X20;
  57.     TH1=0XFD;
  58.     TL1=0XFD;
  59.     TR1=1;
  60.     REN=1;
  61.     SM0=0;
  62.     SM1=1;
  63.     EA=1;
  64.     ES=1;
  65.     while(1)
  66.     {
  67.         if(flag_REC==1)
  68.           {
  69.               flag_REC=0;
  70.                
  71.                 switch(dat)
  72.                 {
  73.                     case 'F':
  74.                        forward();break;
  75.                     case 'B':
  76.                        back();break;
  77.                     case 'l':
  78.                        turn_left();break;
  79.                     case 'r':
  80.                        turn_right();break;
  81.                     case 'S':
  82.                        stop();break;
  83.                 }
  84.    
  85.           }
  86.          
  87.     }
  88. }

  89. void bluet() interrupt 4  /*中断接收1个字节*/
  90. {
  91.     if(RI==1)
  92.     {
  93.         RI=0;
  94.           dat=SBUF;
  95.           flag_REC=1;
  96.          
  97.     }
  98. }
复制代码
这是遥控器
  1. #include <REG52.H>        
  2. #include <math.h>    //Keil library  
  3. #include <stdio.h>   //Keil library        
  4. #include <INTRINS.H>
  5. typedef unsigned char  uchar;
  6. typedef unsigned short ushort;
  7. typedef unsigned int   uint;
  8. //****************************************
  9. // 定义51单片机端口
  10. //****************************************
  11. #define DataPort P2                //LCD1602数据端口

  12. sbit    SCL=P1^1;
  13. sbit    SDA=P1^0;
  14. sbit    LCM_RS=P0^7
  15. sbit    LCM_RW=P0^6;
  16. sbit    LCM_EN=P0^5;
  17. //****************************************
  18. sbit led=P1^2;


  19. // 定义MPU6050内部地址
  20. //****************************************
  21. #define        SMPLRT_DIV                0x19        //陀螺仪采样率,典型值:0x07(125Hz)
  22. #define        CONFIG                        0x1A        //低通滤波频率,典型值:0x06(5Hz)
  23. #define        GYRO_CONFIG                0x1B        //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
  24. #define        ACCEL_CONFIG        0x1C        //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
  25. #define        ACCEL_XOUT_H        0x3B
  26. #define        ACCEL_XOUT_L        0x3C
  27. #define        ACCEL_YOUT_H        0x3D
  28. #define        ACCEL_YOUT_L        0x3E
  29. #define        ACCEL_ZOUT_H        0x3F
  30. #define        ACCEL_ZOUT_L        0x40
  31. #define        TEMP_OUT_H                0x41
  32. #define        TEMP_OUT_L                0x42
  33. #define        GYRO_XOUT_H                0x43
  34. #define        GYRO_XOUT_L                0x44        
  35. #define        GYRO_YOUT_H                0x45
  36. #define        GYRO_YOUT_L                0x46
  37. #define        GYRO_ZOUT_H                0x47
  38. #define        GYRO_ZOUT_L                0x48
  39. #define        PWR_MGMT_1                0x6B        //电源管理,典型值:0x00(正常启用)
  40. #define        WHO_AM_I                0x75        //IIC地址寄存器(默认数值0x68,只读)
  41. #define        SlaveAddress        0xD0        //IIC写入时的地址字节数据,+1为读取
  42. //****************************************
  43. //定义类型及变量
  44. //****************************************
  45. uchar dis[4];        //显示数字(-511至512)的字符数组
  46. int        dis_data;        //变量

  47. void  delay(unsigned int k);//延时
  48. //LCD相关函数
  49. void  InitLcd();//初始化lcd1602
  50. void  lcd_printf(uchar *s,int temp_data);
  51. void  WriteDataLCM(uchar dataW);//LCD数据
  52. void  WriteCommandLCM(uchar CMD,uchar Attribc);        //LCD指令
  53. void  DisplayOneChar(uchar X,uchar Y,uchar DData);//显示一个字符
  54. void  DisplayListChar(uchar X,uchar Y,uchar *DData,L);        //显示字符串
  55. //MPU6050操作函数
  56. void  InitMPU6050();//初始化MPU6050
  57. void  Delay5us();
  58. void  I2C_Start();
  59. void  I2C_Stop();
  60. void  I2C_SendACK(bit ack);
  61. bit   I2C_RecvACK();
  62. void  I2C_SendByte(uchar dat);
  63. uchar I2C_RecvByte();
  64. void  I2C_ReadPage();
  65. void  I2C_WritePage();
  66. void  display_ACCEL_x();
  67. void  display_ACCEL_y();
  68. void  display_ACCEL_z();
  69. uchar Single_ReadI2C(uchar REG_Address);
  70. void  Single_WriteI2C(uchar REG_Address,uchar REG_data)
  71. //****************************************
  72. //整数转字符串
  73. //****************************************
  74. void lcd_printf(uchar *s,int temp_data)
  75. {
  76.         if(temp_data<0)
  77.         {
  78.                 temp_data=-temp_data;
  79.                 *s='-';
  80.         }
  81.         else *s=' ';
  82.         *++s =temp_data/100+0x30;
  83.         temp_data=temp_data%100;     //取余运算
  84.         *++s =temp_data/10+0x30;
  85.         temp_data=temp_data%10;      //取余运算
  86.         *++s =temp_data+0x30;         
  87. }
  88. //****************************************
  89. //延时
  90. //****************************************
  91. void delay(unsigned int k)        
  92. {                                                
  93.         unsigned int i,j;                                
  94.         for(i=0;i<k;i++)
  95.         {                        
  96.                 for(j=0;j<121;j++);
  97.         }                                                
  98. }
  99. //****************************************
  100. //LCD1602初始化
  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.         DisplayOneChar(0,0,'A');
  110. }                        
  111. //****************************************
  112. //LCD1602写允许
  113. //****************************************
  114. void WaitForEnable(void)        
  115. {                                       
  116.         DataPort=0xff;               
  117.         LCM_RS=0;LCM_RW=1;_nop_();
  118.         LCM_EN=1;_nop_();_nop_();
  119.         //while(DataPort&0x80);        
  120.         LCM_EN=0;                                
  121. }                                       
  122. //****************************************
  123. //LCD1602写入命令
  124. //****************************************
  125. void WriteCommandLCM(uchar CMD,uchar Attribc)
  126. {                                       
  127.         if(Attribc)
  128.          WaitForEnable();
  129.         LCM_RS=0;LCM_RW=0;_nop_();
  130.         DataPort=CMD;_nop_();        
  131.         LCM_EN=1;_nop_();_nop_();LCM_EN=0;
  132. }                                       
  133. //****************************************
  134. //LCD1602写入数据
  135. //****************************************
  136. void WriteDataLCM(uchar dataW)
  137. {                                       
  138.         WaitForEnable();               
  139.         LCM_RS=1;LCM_RW=0;_nop_();
  140.         DataPort=dataW;_nop_();        
  141.         LCM_EN=1;_nop_();_nop_();LCM_EN=0;
  142. }               
  143. //****************************************
  144. //LCD1602写入一个字符
  145. //****************************************
  146. void DisplayOneChar(uchar X,uchar Y,uchar DData)
  147. {                                                
  148.         Y&=1;                                                
  149.         X&=15;                                                
  150.         if(Y)X|=0x40;                                       
  151.         X|=0x80;                        
  152.         WriteCommandLCM(X,0);               
  153.         WriteDataLCM(DData);               
  154. }                                                
  155. //****************************************
  156. //LCD1602显示字符串
  157. //****************************************
  158. void DisplayListChar(uchar X,uchar Y,uchar *DData,L)
  159. {
  160.         uchar ListLength=0;
  161.         Y&=0x1;               
  162.         X&=0xF;               
  163.         while(L--)            
  164.         {                       
  165.                 DisplayOneChar(X,Y,DData[ListLength]);
  166.                 ListLength++;  
  167.                 X++;                        
  168.         }   
  169. }
  170. //**************************************
  171. //延时5微秒(STC90C52RC@12M)
  172. //不同的工作环境,需要调整此函数
  173. //当改用1T的MCU时,请调整此延时函数
  174. //**************************************
  175. void Delay5us()
  176. {
  177.         _nop_();_nop_();_nop_();_nop_();
  178.         _nop_();_nop_();_nop_();_nop_();
  179.         _nop_();_nop_();_nop_();_nop_();
  180.         _nop_();_nop_();_nop_();_nop_();
  181.         _nop_();_nop_();_nop_();_nop_();
  182.         _nop_();_nop_();_nop_();_nop_();
  183. }
  184. //**************************************
  185. //I2C起始信号
  186. //**************************************
  187. void I2C_Start()
  188. {
  189.     SDA = 1;                    //拉高数据线
  190.     SCL = 1;                    //拉高时钟线
  191.     Delay5us();                 //延时
  192.     SDA = 0;                    //产生下降沿
  193.     Delay5us();                 //延时
  194.     SCL = 0;                    //拉低时钟线
  195. }
  196. //**************************************
  197. //I2C停止信号
  198. //**************************************
  199. void I2C_Stop()
  200. {
  201.     SDA = 0;                    //拉低数据线
  202.     SCL = 1;                    //拉高时钟线
  203.     Delay5us();                 //延时
  204.     SDA = 1;                    //产生上升沿
  205.     Delay5us();                 //延时
  206. }
  207. //**************************************
  208. //I2C发送应答信号
  209. //入口参数:ack (0:ACK 1:NAK)
  210. //**************************************
  211. void I2C_SendACK(bit ack)
  212. {
  213.     SDA = ack;                  //写应答信号
  214.     SCL = 1;                    //拉高时钟线
  215.     Delay5us();                 //延时
  216.     SCL = 0;                    //拉低时钟线
  217.     Delay5us();                 //延时
  218. }
  219. //**************************************
  220. //I2C接收应答信号
  221. //**************************************
  222. bit I2C_RecvACK()
  223. {
  224.     SCL = 1;                    //拉高时钟线
  225.     Delay5us();                 //延时
  226.     CY = SDA;                   //读应答信号
  227.     SCL = 0;                    //拉低时钟线
  228.     Delay5us();                 //延时
  229.     return CY;
  230. }
  231. //**************************************
  232. //向I2C总线发送一个字节数据
  233. //**************************************
  234. void I2C_SendByte(uchar dat)
  235. {
  236.     uchar i;
  237.     for (i=0; i<8; i++)         //8位计数器
  238.     {
  239.         dat <<= 1;              //移出数据的最高位
  240.         SDA = CY;               //送数据口
  241.         SCL = 1;                //拉高时钟线
  242.         Delay5us();             //延时
  243.         SCL = 0;                //拉低时钟线
  244.         Delay5us();             //延时
  245.     }
  246.     I2C_RecvACK();
  247. }
  248. //**************************************
  249. //从I2C总线接收一个字节数据
  250. //**************************************
  251. uchar I2C_RecvByte()
  252. {
  253.     uchar i;
  254.     uchar dat = 0;
  255.     SDA = 1;                    //使能内部上拉,准备读取数据,
  256.     for (i=0; i<8; i++)         //8位计数器
  257.     {
  258.         dat <<= 1;
  259.         SCL = 1;                //拉高时钟线
  260.         Delay5us();             //延时
  261.         dat |= SDA;             //读数据               
  262.         SCL = 0;                //拉低时钟线
  263.         Delay5us();             //延时
  264.     }
  265.     return dat;
  266. }
  267. //**************************************
  268. //向I2C设备写入一个字节数据
  269. //**************************************
  270. void Single_WriteI2C(uchar REG_Address,uchar REG_data)
  271. {
  272.     I2C_Start();                  //起始信号
  273.     I2C_SendByte(SlaveAddress);   //发送设备地址+写信号
  274.     I2C_SendByte(REG_Address);    //内部寄存器地址,
  275.     I2C_SendByte(REG_data);       //内部寄存器数据,
  276.     I2C_Stop();                   //发送停止信号
  277. }
  278. //**************************************
  279. //从I2C设备读取一个字节数据
  280. //**************************************
  281. uchar Single_ReadI2C(uchar REG_Address)
  282. {
  283.         uchar REG_data;
  284.         I2C_Start();                   //起始信号
  285.         I2C_SendByte(SlaveAddress);    //发送设备地址+写信号
  286.         I2C_SendByte(REG_Address);     //发送存储单元地址,从0开始        
  287.         I2C_Start();                   //起始信号
  288.         I2C_SendByte(SlaveAddress+1);  //发送设备地址+读信号
  289.         REG_data=I2C_RecvByte();       //读出寄存器数据
  290.         I2C_SendACK(1);                //接收应答信号
  291.         I2C_Stop();                    //停止信号
  292.         return REG_data;
  293. }
  294. //**************************************
  295. //初始化MPU6050
  296. //**************************************
  297. void InitMPU6050()
  298. {
  299.         Single_WriteI2C(PWR_MGMT_1, 0x00);        //解除休眠状态
  300.         Single_WriteI2C(SMPLRT_DIV, 0x07);
  301.         Single_WriteI2C(CONFIG, 0x06);
  302.         Single_WriteI2C(GYRO_CONFIG, 0x18);
  303.         Single_WriteI2C(ACCEL_CONFIG, 0x01);
  304. }
  305. //**************************************
  306. //合成数据
  307. //**************************************
  308. int GetData(uchar REG_Address)
  309. {
  310.         char H,L;
  311.         int value;
  312.         H=Single_ReadI2C(REG_Address);
  313.         L=Single_ReadI2C(REG_Address+1);
  314.         //return (H<<8)+L;   //合成数据
  315.         value=(H<<8)+L;
  316.         value/=64;
  317.         return value;
  318. }
  319. //**************************************
  320. //在1602上显示10位数据
  321. //**************************************
  322. void Display10BitData(int value,uchar x,uchar y) //num为XYZ的代表12
  323. {
  324.         //value/=64;        //转换为10位数据
  325.         lcd_printf(dis, value);        //转换数据显示
  326.         DisplayListChar(x,y,dis,4);        //启始列,行,显示数组,显示长度
  327. }

  328. void send(uchar pd)
  329. {
  330.     SBUF=pd
  331.     while(!TI);
  332.     TI=0;
  333.    
  334. }
  335. void send_init()
  336. {
  337.     TMOD=0X20;
  338.      TH1=0XFD;
  339.      TL1=0XFD;
  340.      TR1=1;
  341.      SM0=0;
  342.      SM1=1;
  343.      EA=1;
  344.      ES=1;
  345. }



  346. void main()
  347. {
  348.         int y;
  349.         led=0;
  350.         delay(500);                //上电延时               
  351.         InitLcd();                //液晶初始化
  352.         InitMPU6050();
  353.         send_init();
  354.         delay(150);
  355.         while(1)
  356.         {
  357.                 y=0;
  358.                
  359.                 Display10BitData(GetData(ACCEL_XOUT_H),2,0);
  360.                                 

  361.                 if(GetData(ACCEL_YOUT_H)>200)
  362.                 {
  363.                         send('f');
  364.                         led=1;
  365.                 }
  366.                 else if(GetData(ACCEL_YOUT_H)<=(-200))
  367.                 {
  368.                         send('b');
  369.                         led=1;
  370.                         
  371.                 }

  372.                 Display10BitData(GetData(ACCEL_YOUT_H),7,0)
  373.                 if(GetData(ACCEL_XOUT_H)>200)
  374.                 {
  375.                         send('r');
  376.                         y=1;
  377.                         led=1;
  378.                 }
  379.                 else if(GetData(ACCEL_XOUT_H)<(-200))
  380.                 {
  381.                         send('l');
  382.                         y=1;
  383.                         led=1;
  384.                 }

  385.                 if(GetData(ACCEL_YOUT_H)<200&&GetData(ACCEL_YOUT_H)>(-200)&&y==0)
  386.                 {
  387.                         send('s');
  388.                         led=1;
  389.                         
  390.                 }
  391.                 Display10BitData(GetData(ACCEL_ZOUT_H),12,0);
  392.                
  393.         
  394.                
  395.                 delay(500);
  396.         }
  397. }
复制代码




评分

参与人数 2黑币 +105 收起 理由
andongni + 5 赞一个!
admin + 100 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:143842 发表于 2016-10-23 00:18 来自手机 | 显示全部楼层
厉害  
回复

使用道具 举报

ID:79544 发表于 2017-5-19 19:08 | 显示全部楼层
多谢楼主分享,赞!!!!!!!!
回复

使用道具 举报

ID:145130 发表于 2017-6-7 10:01 | 显示全部楼层
受教了
回复

使用道具 举报

ID:238009 发表于 2017-11-15 11:13 来自手机 | 显示全部楼层
51有你更精彩
回复

使用道具 举报

ID:87193 发表于 2017-11-30 14:54 | 显示全部楼层
厉害厉害,作品看着不错
回复

使用道具 举报

ID:353100 发表于 2018-6-17 10:02 来自手机 | 显示全部楼层
不错,值得学习
回复

使用道具 举报

ID:388016 发表于 2018-9-18 21:18 | 显示全部楼层
赞一个
回复

使用道具 举报

ID:399179 发表于 2018-9-30 09:45 来自手机 | 显示全部楼层
楼主好厉害!
回复

使用道具 举报

ID:148126 发表于 2018-10-26 13:24 | 显示全部楼层
厉害了
回复

使用道具 举报

ID:441552 发表于 2018-12-7 14:46 来自手机 | 显示全部楼层
控制器程序编的的很厉害
回复

使用道具 举报

ID:602799 发表于 2019-11-15 21:05 | 显示全部楼层
这个是实现手势遥控小车的吗
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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