標(biāo)題: 游戲用無線方向盤的制作 單片機(jī)加ADXL345傳感器打造 [打印本頁]

作者: 51hei小胡    時(shí)間: 2017-3-23 23:28
標(biāo)題: 游戲用無線方向盤的制作 單片機(jī)加ADXL345傳感器打造
本作品Chinked-out工作室版權(quán)所有,給大家分享一款游戲用的無線方向盤的制作方法,是用51單片機(jī)加上ADXL345加速度傳感器打造的,源碼和原理圖都有分享給51黑電子論壇的朋友們吧,大家先看下面的視頻。

視頻演示:
http://v.youku.com/v_show/id_XMTU3MjY1Nzc5Ng==.html

無線方向盤重要說明
藍(lán)牙模塊使用注意:
(1)當(dāng)藍(lán)牙模塊連接到電路中后,會影響到單片機(jī)的程序下載,在下載程序之前,必須移除藍(lán)牙串口模塊。
(2)藍(lán)牙串口模塊在上單后會自行配對,但在配對過程中,藍(lán)牙模塊會自動(dòng)溢出數(shù)據(jù),從而影響到接收端單片機(jī),進(jìn)而導(dǎo)致單片機(jī)向PC機(jī)發(fā)送亂碼。
為避免這種情況的發(fā)生,可上電后等待藍(lán)牙模塊配對成功后在打開單片機(jī)電源開關(guān)(原理圖中已經(jīng)是這樣設(shè)計(jì)了)。
或在已經(jīng)出現(xiàn)發(fā)送亂碼的情況下,將單片機(jī)復(fù)位即可。

發(fā)送端原理圖:


接收端原理圖:



元件清單:
名稱規(guī)格數(shù)量備注
萬能板9x15cm2
單片機(jī):STC12C5A60S2DIP402
40P單片機(jī)母座
2
晶振11.0592Mhz2
陶瓷電容22pF4
電解電容22uF2
10K電阻
2
撥動(dòng)開關(guān)
2
排針1組40P1
杜邦線1組40P1
6x6x7.3mm方頭按鍵
7
A44圓形按鍵帽顏色自選5按鍵帽與按鍵需匹配
5P排針母座
2用于固定ADXL345
4P排針母座
2用于固定藍(lán)牙模塊
ADXL345傳感器
1
USB轉(zhuǎn)TTL下載器CH340系列1
USB線母對母1
CH376S模塊
2
藍(lán)牙串口模塊HC-052


無線方向盤發(fā)送端單片機(jī)源程序:
  1. #include "STC12C5A60S2.h"
  2. #include"intrins.h"
  3. #define key1  0x1d          //黑色           剎車 Z
  4. #define key2  0xE1          //黃色           left shift
  5. #define key3  0x04          //紅色           油門         A
  6. #define key4  0x4f          //右                   右轉(zhuǎn)         →
  7. #define key5  0x50          //左                   左轉(zhuǎn)         ←
  8. sbit SCL=P0^6;      //IIC時(shí)鐘引腳定義
  9. sbit SDA=P0^7;      //IIC數(shù)據(jù)引腳定義
  10. unsigned char idata BUF[6]; //接收數(shù)據(jù)緩存區(qū)  X軸高八位,X軸低八位; Y軸高八位,Y軸低八位; Z軸高八位,Z軸第低八位
  11. unsigned char idata key_buf[5]={0x00,0x00,0x00,0x00,0x00};
  12. unsigned char code key_judge_tab[]={0x01,0x02,0x04,0x08,0x10};
  13. void UartInit(void);
  14. void Send();
  15. void Clear();
  16. void Input_Data_Process();

  17. void Init_ADXL345(void);             //初始化ADXL345
  18. void  Single_Write_ADXL345(unsigned char REG_Address,unsigned char REG_data);   //單個(gè)寫入數(shù)據(jù)
  19. void  Multiple_Read_ADXL345();                                  //連續(xù)的讀取內(nèi)部寄存器數(shù)據(jù)
  20. void ADXL345_Start();
  21. void ADXL345_Stop();
  22. void ADXL345_SendACK(bit ack);
  23. bit  ADXL345_RecvACK();
  24. void ADXL345_SendByte(unsigned char dat);
  25. unsigned char ADXL345_RecvByte();
  26. void ADXL345_Data_Process();

  27. void Delay5us();
  28. void Delay5ms();
  29. void Delay50ms();
  30. void Delay150ms();

  31. signed int idata X_data;
  32. unsigned char Data,judge;
  33. bit key_flag=0,flag;

  34. void main()
  35. {
  36.     Delay150ms();
  37.         P0M1=0x00;
  38.         P0M0=0x00;
  39.         UartInit();
  40.         Init_ADXL345();
  41.         while(1)
  42.         {        
  43.                
  44.                 Data=~P2&0x1f;                                 //讀取按鍵狀態(tài)
  45.    
  46.                 Multiple_Read_ADXL345();     //讀取ADXL345數(shù)據(jù)
  47.         ADXL345_Data_Process();                 //ADXL345數(shù)據(jù)分析、處理
  48.                 Input_Data_Process();                 //按鍵數(shù)據(jù)分析、處理
  49.                 Send();                                                 //發(fā)送鍵盤代碼
  50.                 Clear();                                         //清空緩存數(shù)據(jù)
  51.                 Delay50ms();        
  52.         }
  53. }
  54. void ADXL345_Data_Process()                                          
  55. {
  56.         X_data=BUF[1]<<8|BUF[0];
  57.         if(X_data<-50)Data=Data|0x10;
  58.         if(X_data>50) Data=Data|0x08;
  59. }
  60. void Input_Data_Process()
  61. {
  62.         unsigned char i;
  63.         for(i=0;i<5;i++)
  64.         {
  65.                 judge=Data&key_judge_tab[i];
  66.                 switch (judge)
  67.                 {
  68.                         case 0x00: break;
  69.                         case 0x01: key_buf[0]=key1;break;
  70.                         case 0x02: key_buf[1]=key2;break;
  71.                         case 0x04: key_buf[2]=key3;break;
  72.                         case 0x08: key_buf[3]=key4;break;
  73.                         case 0x10: key_buf[4]=key5;break;
  74.                         default:break;
  75.                 }
  76.         }        
  77. }
  78. void Multiple_read_ADXL345()
  79. {   
  80.         unsigned char i;
  81.     ADXL345_Start();                          //起始信號
  82.     ADXL345_SendByte(0xA6);           //發(fā)送設(shè)備地址+寫信號
  83.     ADXL345_SendByte(0x32);                   //發(fā)送存儲單元地址,從0x32開始        
  84.     ADXL345_Start();                          //起始信號
  85.     ADXL345_SendByte(0xA7);         //發(fā)送設(shè)備地址+讀信號
  86.          for (i=0; i<6; i++)                      //連續(xù)讀取6個(gè)地址數(shù)據(jù),存儲中BUF
  87.     {
  88.         BUF[i] = ADXL345_RecvByte();          //BUF[0]存儲0x32地址中的數(shù)據(jù)
  89.         if (i == 5)ADXL345_SendACK(1);//最后一個(gè)數(shù)據(jù)需要回NOACK
  90.         else ADXL345_SendACK(0); //回應(yīng)ACK
  91.    }
  92.     ADXL345_Stop();                          //停止信號
  93.     Delay5ms();
  94. }
  95. void Init_ADXL345()
  96. {
  97.    Single_Write_ADXL345(0x2C,0x08);   //速率設(shè)定為12.5
  98.    Single_Write_ADXL345(0x2D,0x08);   //選擇電源模式   
  99.    Single_Write_ADXL345(0x31,0x0B);   //測量范圍,正負(fù)16g,13位模式
  100. }
  101. void Single_Write_ADXL345(unsigned char REG_Address,unsigned char REG_data)
  102. {
  103.     ADXL345_Start();                  //起始信號
  104.     ADXL345_SendByte(0xA6);   //發(fā)送設(shè)備地址
  105.     ADXL345_SendByte(REG_Address);    //內(nèi)部寄存器地址
  106.     ADXL345_SendByte(REG_data);       //內(nèi)部寄存器數(shù)據(jù)
  107.     ADXL345_Stop();                   //發(fā)送停止信號
  108. }
  109. void ADXL345_Start()
  110. {
  111.     SDA = 1;                    //拉高數(shù)據(jù)線
  112.     SCL = 1;                    //拉高時(shí)鐘線
  113.     Delay5us();                 //延時(shí)
  114.     SDA = 0;                    //產(chǎn)生下降沿
  115.     Delay5us();                 //延時(shí)
  116.     SCL = 0;                    //拉低時(shí)鐘線
  117. }
  118. void ADXL345_Stop()
  119. {
  120.     SDA = 0;                    //拉低數(shù)據(jù)線
  121.     SCL = 1;                    //拉高時(shí)鐘線
  122.     Delay5us();                 //延時(shí)
  123.     SDA = 1;                    //產(chǎn)生上升沿
  124.     Delay5us();                 //延時(shí)
  125. }
  126. void ADXL345_SendACK(bit ack)
  127. {
  128.     SDA = ack;                  //寫應(yīng)答信號
  129.     SCL = 1;                    //拉高時(shí)鐘線
  130.     Delay5us();                 //延時(shí)
  131.     SCL = 0;                    //拉低時(shí)鐘線
  132.     Delay5us();                 //延時(shí)
  133. }
  134. bit ADXL345_RecvACK()
  135. {
  136.     SCL = 1;                    //拉高時(shí)鐘線
  137.     Delay5us();                 //延時(shí)
  138.     flag = SDA;                   //讀應(yīng)答信號
  139.     SCL = 0;                    //拉低時(shí)鐘線
  140.     Delay5us();                 //延時(shí)

  141.     return flag;
  142. }
  143. void ADXL345_SendByte(unsigned char dat)
  144. {
  145.     unsigned char i;

  146.     for (i=0; i<8; i++)         //8位計(jì)數(shù)器
  147.     {
  148.                 SDA=dat&0x80;
  149.         SCL = 1;                //拉高時(shí)鐘線
  150.         Delay5us();             //延時(shí)
  151.         SCL = 0;                //拉低時(shí)鐘線
  152.         Delay5us();             //延時(shí)
  153.                 dat <<= 1;
  154.     }
  155.     ADXL345_RecvACK();
  156. }
  157. unsigned char ADXL345_RecvByte()
  158. {
  159.     unsigned char i;
  160.     unsigned char dat = 0;
  161.     SDA = 1;                    //使能內(nèi)部上拉,準(zhǔn)備讀取數(shù)據(jù),
  162.     for (i=0; i<8; i++)         //8位計(jì)數(shù)器
  163.     {
  164.         dat <<= 1;
  165.         SCL = 1;                //拉高時(shí)鐘線
  166.         Delay5us();             //延時(shí)
  167.         dat |= SDA;             //讀數(shù)據(jù)               
  168.         SCL = 0;                //拉低時(shí)鐘線
  169.         Delay5us();             //延時(shí)
  170.     }
  171.     return dat;
  172. }
  173. void Send()                                
  174. {
  175.         unsigned char i;
  176.                 for(i=0;i<5;i++)
  177.                 {
  178.                         SBUF=key_buf[i];
  179.                         while(!TI);
  180.                         TI=0;
  181.                 }
  182. }
  183. void Clear()
  184. {
  185.         unsigned char i;
  186.         for(i=0;i<5;i++)
  187.         {
  188.                 key_buf[i]=0x00;
  189.         }
  190. }


  191. void UartInit(void)                //9600bps@11.0592MHz
  192. {
  193.         EA=1;
  194.         PCON &= 0x7F;                //波特率不倍速
  195.         SCON = 0x50;                //8位數(shù)據(jù),可變波特率
  196.         AUXR |= 0x04;                //獨(dú)立波特率發(fā)生器時(shí)鐘為Fosc,即1T
  197.         BRT = 0xDC;                //設(shè)定獨(dú)立波特率發(fā)生器重裝值
  198.         AUXR |= 0x01;                //串口1選擇獨(dú)立波特率發(fā)生器為波特率發(fā)生器
  199.         AUXR |= 0x10;                //啟動(dòng)獨(dú)立波特率發(fā)生器
  200. }


  201.                                                                                 
  202. void Delay5us()                //@11.0592MHz
  203. {
  204.         unsigned char i;

  205.         _nop_();
  206.         _nop_();
  207.         _nop_();
  208.         i = 10;
  209.         while (--i);
  210. }

  211. void Delay5ms()                //@11.0592MHz
  212. {
  213.         unsigned char i, j;

  214.         _nop_();
  215.         _nop_();
  216.         i = 54;
  217.         j = 198;
  218.         do
  219.         {
  220.                 while (--j);
  221.         } while (--i);
  222. }
  223. void Delay50ms()                //@11.0592MHz
  224. {
  225.         unsigned char i, j, k;

  226.         _nop_();
  227.         _nop_();
  228.         i = 3;
  229.         j = 26;
  230.         k = 223;
  231.         do
  232.         {
  233.                 do
  234.                 {
  235.                         while (--k);
  236.                 } while (--j);
  237.         } while (--i);
  238. }

  239. void Delay150ms()                //@11.0592MHz
  240. {
  241.         unsigned char i, j, k;

  242.         _nop_();
  243.         _nop_();
  244.         i = 7;
  245.         j = 78;
  246.         k = 167;
  247.         do
  248.         {
  249.                 do
  250.                 {
  251.                         while (--k);
  252.                 } while (--j);
  253.         } while (--i);
  254. }
復(fù)制代碼


接收端程序:
  1. #include "STC12C5A60S2.h"
  2. #include "CH375INC.H"
  3. unsigned char CMD=0xff;
  4. sbit  CH375_INT_WIRE = P3^2;                        //P3.2, INT0, 連接CH375的INT#引腳,用于查詢中斷狀態(tài) */
  5. unsigned char idata buf[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
  6. unsigned char idata Recbuf[6]={0x00,0x00,0x00,0x00,0x00,0x00};
  7. unsigned char Rec_count=0;
  8. typedef        union _REQUEST_PACK{
  9.         unsigned char  buffer[8];
  10.         struct{
  11.                 unsigned char         bmReuestType;            //標(biāo)準(zhǔn)請求字
  12.                 unsigned char         bRequest;                           //請求代碼
  13.                 unsigned int     wValue;                        //特性選擇高
  14.                 unsigned int     wIndx;                                //索引
  15.                 unsigned int     wLength;                                //數(shù)據(jù)長度
  16.         }r;
  17. } mREQUEST_PACKET,        *mpREQUEST_PACKET;

  18. //設(shè)備描述符
  19. unsigned char  code DevDes[]={
  20.         0x12                        //描述符大小                        
  21. ,         0x01                        //常數(shù)DEVICE
  22. ,         0x10                        //USB規(guī)范版本信息
  23. ,         0x01
  24. ,   0x00                        //類別碼,
  25. ,          0x00                        //子類別碼        
  26. ,   0x00                        //協(xié)議碼
  27. ,          0x08                        //端點(diǎn)0的最大信息包大小
  28. ,          0x3c                        //廠商ID
  29. ,   0x41
  30. ,   0x03                        //產(chǎn)品ID        
  31. ,   0x20
  32. ,   0x00                        //設(shè)備版本信息
  33. ,   0x02
  34. ,   0x01                        //索引值        
  35. ,   0x02
  36. ,   0x00
  37. ,   0x01                        //可能配置的數(shù)目        
  38. };
  39. //配置描述符
  40. unsigned char   code ConDes[]={                        //配置描述符
  41.                                            0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x04, 0xa0,  0x23,//配置描述符
  42.                                0x09, 0x04, 0x00, 0x00, 0x01, 0x03, 0x01, 0x01, 0x05,//接口描述符
  43.                                            0x09, 0x21, 0x10, 0x01, 0x00, 0x01, 0x22, 0x41, 0x00,//HID類描述符
  44.                                0x07, 0x05, 0x81, 0x03, 0x08, 0x00, 0x18   //端點(diǎn)描述符,只配置了輸入端點(diǎn),輸出端點(diǎn)用0端點(diǎn)
  45.                                 };                //配置描述符

  46. /*報(bào)表描述符*/
  47. unsigned char code Hid_des[]={
  48. 0x05, 0x01, 0x09, 0x06,  0xa1, 0x01, 0x05, 0x07,  0x19, 0xe0,
  49. 0x29, 0xe7, 0x15, 0x00,  0x25, 0x01, 0x75, 0x01,  0x95, 0x08,
  50. 0x81, 0x02, 0x95, 0x01,  0x75, 0x08, 0x81, 0x01,  0x95, 0x03, 0x75, 0x01,        
  51. 0x05, 0x08, 0x19, 0x01,  0x29, 0x03, 0x91, 0x02,  0x95, 0x01, 0x75, 0x05,  
  52. 0x91, 0x01, 0x95, 0x06,  0x75, 0x08, 0x15, 0x00,  0x26, 0xff, 0x00, 0x05,
  53. 0x07, 0x19, 0x00, 0x2a,  0xff, 0x00, 0x81, 0x00,  0xc0
  54. };
  55. /*關(guān)于全局變量的定義*/
  56. unsigned char mVarSetupRequest;                                                //        ;USB請求碼
  57. unsigned char mVarSetupLength;                                                //        后續(xù)數(shù)據(jù)長度
  58. unsigned char  code * VarSetupDescr;                                //描述符偏移地址
  59. unsigned char VarUsbAddress        ;                                                
  60. unsigned char idata UPDATA_FLAG;
  61. bit CH375FLAGERR;                                                                        //錯(cuò)誤清0
  62. bit        CH375CONFLAG;

  63. mREQUEST_PACKET  request;

  64. /*硬件定義,根據(jù)硬件修改*/
  65. unsigned char volatile xdata CH375_CMD_PORT _at_ 0x81ff;                /* CH375命令端口的I/O地址 */
  66. unsigned char volatile xdata CH375_DAT_PORT _at_ 0x80ff;                /* CH375數(shù)據(jù)端口的I/O地址 */

  67. …………余下代碼請下載附件…………
復(fù)制代碼

工作室交流討論群:231931086
視頻中測試游戲?yàn)椤稑O品飛車14》,若用于其他游戲,根據(jù)游戲的操作鍵修改Send程序中key1至Key5對應(yīng)的鍵盤代碼即可。受8位單片機(jī)機(jī)能限制,當(dāng)前程序一次性最多發(fā)送6個(gè)不同鍵盤代碼。


制作資料下載:
無線方向盤資料包.zip (1.65 MB, 下載次數(shù): 60)

作者: easee    時(shí)間: 2017-7-22 14:29
厲害了word姐
作者: OPJH    時(shí)間: 2017-12-16 17:58
這兩個(gè)程序會編譯錯(cuò)誤應(yīng)該怎么改,急,謝謝
作者: OPJH    時(shí)間: 2017-12-16 18:00
這兩個(gè)程序會編譯錯(cuò)誤應(yīng)該怎么改,急,謝謝
作者: OPJH    時(shí)間: 2017-12-16 18:03
為什么我編譯這兩個(gè)程序時(shí)出錯(cuò),。怎么改
作者: imfly89    時(shí)間: 2018-3-24 16:51
請教一下:你的搖桿方式就是模擬了兩個(gè)鍵盤上的←和→的按下指令嗎?
能不能做到根據(jù)搖桿的幅度去控制游戲里面車的方向盤擺幅?
作者: 1979759100Ls    時(shí)間: 2018-4-27 11:06
聲卡才是亮點(diǎn)吧




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1