找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 6412|回復(fù): 4
收起左側(cè)

2.4G遙控小車(chē)設(shè)計(jì) 超聲波數(shù)據(jù)回傳 舵機(jī)轉(zhuǎn)向 OLED顯示 STC8A8K64S4單片機(jī)程序+電路

  [復(fù)制鏈接]
ID:404207 發(fā)表于 2018-12-28 20:22 | 顯示全部樓層 |閱讀模式
在上一次用開(kāi)發(fā)板做小車(chē)后  繼續(xù)深入研究  把開(kāi)發(fā)板換成了PCB  遙控器用兩個(gè)模擬量搖桿,達(dá)到了玩小車(chē)的樂(lè)趣 , 又在原有的基礎(chǔ)上增加了超聲波數(shù)據(jù)回傳,實(shí)現(xiàn)了數(shù)據(jù)收發(fā),而且程序也有了很大的優(yōu)化 ,速度變得更快了點(diǎn),最重要的還是用了PCB ,買(mǎi)一些元器件就可以自己做電路,特別適合學(xué)生DIY,我也是用腐刻做板的,所以不用擔(dān)心很復(fù)雜。直接附上圖片吧。

制作出來(lái)的實(shí)物圖如下:
QQ圖片20181228201117.jpg QQ圖片20181228200123.jpg

Altium Designer畫(huà)的原理圖和PCB圖如下:(51hei附件中可下載工程文件)
96C]DBFSG~5EBK{Z%K{D@IO.png (0ABNU4}8YB_Z%}P@}@0RCO.png

nRF24L01無(wú)線(xiàn)發(fā)射檢測(cè):
1、將nRF24L01模塊按照正確方向插到J11端子上;
2、MINI USB連接線(xiàn)給開(kāi)發(fā)板通電下載程序,下載軟件中內(nèi)部IRC時(shí)鐘選擇11.0592MHZ;
3、下載程序后,開(kāi)發(fā)板藍(lán)色指示燈會(huì)不停閃爍,表示無(wú)線(xiàn)發(fā)送正常;
4、此時(shí),如果有下發(fā)接收程序的開(kāi)發(fā)板,則可以觀(guān)察到有表示接收到的紅色指示燈閃爍。
注:該實(shí)驗(yàn)需要配合接收實(shí)驗(yàn)進(jìn)行。

nRF24L01無(wú)線(xiàn)接收實(shí)驗(yàn):
1、將nRF24L01模塊按照正確方向插到J11端子上;
2、MINI USB連接線(xiàn)給開(kāi)發(fā)板通電下載程序,下載軟件中內(nèi)部IRC時(shí)鐘選擇11.0592MHZ;
3、下載程序后,開(kāi)發(fā)板紅色指示燈會(huì)常亮,表示沒(méi)有接收到無(wú)線(xiàn)信號(hào);
4、此時(shí),如果有下發(fā)發(fā)送程序的開(kāi)發(fā)板,則可以觀(guān)察到該接收板上的紅色指示燈閃爍。
注:該實(shí)驗(yàn)需要配合發(fā)送實(shí)驗(yàn)進(jìn)行。

單片機(jī)源程序如下:
  1. /****************************************Copyright (c)****************************************************
  2. **                                       
  3. **                                 
  4. **
  5. **--------------File Info---------------------------------------------------------------------------------
  6. ** File name:                       
  7. ** Last modified Date:         
  8. ** Last Version:                  
  9. ** Descriptions:                                                       
  10. **--------------------------------------------------------------------------------------------------------
  11. ** Created by:                        FiYu
  12. ** Created date:                2018-2-1
  13. ** Version:                            1.0
  14. ** Descriptions:                nRF24L01無(wú)線(xiàn)發(fā)射程序(硬件SPI)                                       
  15. **--------------------------------------------------------------------------------------------------------
  16. ** Modified by:                        FiYu
  17. ** Modified date:                               
  18. ** Version:                                  
  19. ** Descriptions:               
  20. ** Rechecked by:                               
  21. **********************************************************************************************************/
  22. /****-----請(qǐng)閱讀ReadMe.txt進(jìn)行實(shí)驗(yàn)-----***********/


  23. #include        "STC8.H"
  24. #include "oled.h"
  25. #include  "intrins.h"
  26. #include  "delay.h"
  27. #include  "ADC.h"
  28. #include "NRF24L01.h"
  29. #include "timer.h"
  30.   bit ZF,CJ=0;
  31.         bit kaiqi=0;       
  32.         sbit Rled=P0^7;
  33.         sbit Gled=P0^6;
  34.         sbit Bled=P0^5;
  35. extern bit TIM,JS ;
  36. extern bit LEDK;         
  37. extern uint8  RxPayload[6];   //無(wú)線(xiàn)接收緩存
  38. extern uint8  TxPayload[6];   //無(wú)線(xiàn)發(fā)送緩存
  39. extern uint8 S2;
  40. void moter(uint8 zf,uint8 SD)        ;                                   //  電機(jī)驅(qū)動(dòng)函數(shù)
  41. void CSZX(uint16 y);
  42. void INT0_init();                //外部中斷0的初始化配置       
  43. void INT1_init();
  44. void led(bit x,bit y,bit z);
  45. void OLEDXS(void);
  46. void INT0_int (void) interrupt 0               
  47. {               
  48.      
  49.                 delay_ms(150);
  50.         if(P3^2==0)
  51.                 {
  52.                         kaiqi=~kaiqi;
  53.                 }
  54.        
  55.         }

  56. void INT1_int (void) interrupt 2               
  57. {               
  58.                 delay_ms(150);
  59.           if(P3^3==0){CJ=~CJ;}               
  60. }

  61. /***************************************************************************
  62. * 描  述 : 主函數(shù)
  63. * 入  參 : 無(wú)
  64. * 返回值 : 無(wú)
  65. **************************************************************************/
  66. int main()         
  67. {   
  68.                 uint16 n1=0;
  69.     bit M1=1;       
  70.                 TxPayload[0] = 0x5A;
  71.                 TxPayload[3] = 0xA5;
  72.                 OLED_Init() ;  
  73.                 delay_ms(20);                               
  74.                  OLEDXS();
  75.                 Init_NRF24L01_MA();                  //初始化
  76.                 Set_TxMode_MA();                                                  //配置nRF24L01為發(fā)送模式       
  77.           delay_ms(20);
  78.                 INT0_init();
  79.           INT1_init();
  80.     Timer1Init();
  81.                 EA=1;
  82.                 ADC_config();

  83.   while(1)
  84.   {
  85.         if(CJ==0&&kaiqi==0){led(1,1,1); led(0,1,1);Set_TxMode_MA();              //第0模式    發(fā)送停止不接受
  86.             while(CJ==0&&kaiqi==0){
  87.                         ADC1();                                //讀取AD的值
  88.                         ADC2();               
  89.                         if(kaiqi==0&&LEDK==1)
  90.                         {
  91.                                 Rled=~Rled;                                                
  92.                                 TxPayload[0] = 0x5A;       
  93.                                 TxPayload[1] = 50;       
  94.                                 TxPayload[2] = 50;       
  95.                                 TxPayload[3] = 0xA5;       
  96.                                 TxPayload[4] = 0;       
  97.                                 NRF24L01_TxPacket_MA(TxPayload);            //發(fā)送校驗(yàn)碼
  98.                                 NRF24L01_TxPacket_MA(TxPayload+1);          //發(fā)送數(shù)據(jù)               
  99.                                 NRF24L01_TxPacket_MA(TxPayload+2);    //發(fā)送數(shù)據(jù)
  100.                                 NRF24L01_TxPacket_MA(TxPayload+3);    //發(fā)送校驗(yàn)碼
  101.                                 NRF24L01_TxPacket_MA(TxPayload+4);    //發(fā)送啟動(dòng)標(biāo)志位

  102.                                 LEDK=0;
  103.                         }       
  104.                 }
  105.         }
  106.                        
  107. if(kaiqi==0&&CJ==1){led(1,0,1);                 //第1模式  接收和發(fā)送停止信號(hào)
  108.         while(CJ==1&&kaiqi==0){
  109.                         if(JS==1){Set_TxMode_MA();  
  110.             while(JS){        led(1,0,1);       
  111.                         ADC1();                                //讀取AD的值
  112.                         ADC2();               
  113.                         TxPayload[1] = 50;       
  114.                         TxPayload[2] = 50;                               
  115.                         TxPayload[4] = 1;       
  116.           
  117.                         NRF24L01_TxPacket_MA(TxPayload);            //發(fā)送校驗(yàn)碼
  118.                         NRF24L01_TxPacket_MA(TxPayload+1);          //發(fā)送數(shù)據(jù)               
  119.                         NRF24L01_TxPacket_MA(TxPayload+2);    //發(fā)送數(shù)據(jù)
  120.                         NRF24L01_TxPacket_MA(TxPayload+3);    //發(fā)送校驗(yàn)碼
  121.                         NRF24L01_TxPacket_MA(TxPayload+4);    //發(fā)送啟動(dòng)標(biāo)志位
  122.                         CSZX(70+20*TxPayload[1]/50);          //使控制超聲波的舵機(jī)轉(zhuǎn)到中間位置
  123.                                
  124.                                 if(TxPayload[2]<48)moter(0,(49-TxPayload[2])*80/45);   //用OLED顯示控制電機(jī)的PWM值  這里最大是80,可以修改到90以上,但不能是100,因?yàn)锳D的波動(dòng)值會(huì)直接超過(guò)一百
  125.                                          else if(TxPayload[2]<52)   moter(2,0);              //防止AD波動(dòng)造成誤啟動(dòng)
  126.                                                                 else  moter(1,(TxPayload[2]-52)*80/45);                                //正轉(zhuǎn)PWM值                       
  127.                 }
  128.         }                       
  129.                          if(JS==0){        Set_RxMode_MA();
  130.                         while(!JS){
  131.                   if(NRF24L01_RxPacket_MA(RxPayload) == RX_OK)          //如果接收成功
  132.                         {
  133.                         if(RxPayload[0] == 0x04)                                                                     //檢驗(yàn)校驗(yàn)碼
  134.                         {                               
  135.                         while( !(NRF24L01_RxPacket_MA(RxPayload+1)==RX_OK));                                //等待接收數(shù)據(jù)
  136.                          while( !(NRF24L01_RxPacket_MA(RxPayload+2)==RX_OK));                                //等待接收數(shù)據(jù)
  137.                                 while( !(NRF24L01_RxPacket_MA(RxPayload+3)==RX_OK));                        //檢驗(yàn)校驗(yàn)碼
  138.                         }
  139.                
  140.                         if(RxPayload[0] == 0x04 && RxPayload[3] == 0x05 )                 //符合校驗(yàn)碼的值 ,則中間的數(shù)據(jù)是正確的,不然亂碼,錯(cuò)位的數(shù)據(jù)就不對(duì)
  141.                                 {
  142.                                 n1= RxPayload[1]*256+RxPayload[2];
  143.                                         if(n1>=4000) LCD_P8x16Str(64, 6,"---.-");
  144.                                 if(n1/1000==0) OLED_ShowChar(64,6,' ');
  145.                                          else OLED_ShowChar(64,6,' '+16+n1/1000);
  146.                                                                 OLED_ShowChar(72,6,' '+16+n1%1000/100);
  147.                                                                 OLED_ShowChar(80,6,' '+16+n1%1000%100/10);
  148.                                                                 OLED_ShowChar(88,6,'.');       
  149.                                                                 OLED_ShowChar(96,6,' '+16+n1%1000%100%10);
  150.                                                                 RxPayload[0] = 0;
  151.                                                                 RxPayload[1] = 0;
  152.                                                                 RxPayload[2] = 0;
  153.                                                                 RxPayload[3] = 0;                               
  154.                                                                 }
  155.                                                         }
  156.                                                 }
  157.                                         }
  158.                                 }
  159.                         }
  160.        
  161. if(kaiqi==1&&CJ==0){ led(1,1,1);    led(1,1,0);         //第二模式  只發(fā)送不接收
  162.     Set_TxMode_MA();
  163. while(CJ==0&&kaiqi==1){
  164.                         ADC1();                                //讀取AD的值
  165.                         ADC2();                    
  166.                         TxPayload[4] =2;          
  167.                         NRF24L01_TxPacket_MA(TxPayload);            //發(fā)送校驗(yàn)碼
  168.                         NRF24L01_TxPacket_MA(TxPayload+1);          //發(fā)送數(shù)據(jù)               
  169.                         NRF24L01_TxPacket_MA(TxPayload+2);    //發(fā)送數(shù)據(jù)
  170.                         NRF24L01_TxPacket_MA(TxPayload+3);    //發(fā)送校驗(yàn)碼
  171.                         NRF24L01_TxPacket_MA(TxPayload+4);    //發(fā)送啟動(dòng)標(biāo)志位
  172.        
  173.                         CSZX(70+20*TxPayload[1]/50);          //使控制超聲波的舵機(jī)轉(zhuǎn)到中間位置               
  174.                                 if(TxPayload[2]<48)moter(0,(49-TxPayload[2])*80/45);   //用OLED顯示控制電機(jī)的PWM值  這里最大是80,可以修改到90以上,但不能是100,因?yàn)锳D的波動(dòng)值會(huì)直接超過(guò)一百
  175.                                          else if(TxPayload[2]<52)   moter(2,0);              //防止AD波動(dòng)造成誤啟動(dòng)
  176.                                                                 else  moter(1,(TxPayload[2]-52)*80/45);                                //正轉(zhuǎn)PWM值               
  177.                 }
  178.         }

  179. if(kaiqi==1&&CJ==1){led(1,1,1);}
  180. //if(kaiqi==1&&CJ==1){led(1,1,1);                 //第3模式  接收和發(fā)送
  181. //        while(CJ==1&&kaiqi==1){       
  182. //               
  183. //                        if(JS==1){Set_TxMode_MA();
  184. //            while(JS){led(0,0,0);
  185. //                        TxPayload[4] = 3;       
  186. //                        ADC1();                                //讀取AD的值
  187. //                        ADC2();                            
  188. //                        NRF24L01_TxPacket_MA(TxPayload);            //發(fā)送校驗(yàn)碼
  189. //                        NRF24L01_TxPacket_MA(TxPayload+1);          //發(fā)送數(shù)據(jù)               
  190. //                        NRF24L01_TxPacket_MA(TxPayload+2);    //發(fā)送數(shù)據(jù)
  191. //                        NRF24L01_TxPacket_MA(TxPayload+3);    //發(fā)送校驗(yàn)碼
  192. //                        NRF24L01_TxPacket_MA(TxPayload+4);    //發(fā)送啟動(dòng)標(biāo)志位
  193. //                        CSZX(70+20*TxPayload[1]/50);          //使控制超聲波的舵機(jī)轉(zhuǎn)到中間位置
  194. //                       
  195. //                                if(TxPayload[2]<48)moter(0,(49-TxPayload[2])*80/45);   //用OLED顯示控制電機(jī)的PWM值  這里最大是80,可以修改到90以上,但不能是100,因?yàn)锳D的波動(dòng)值會(huì)直接超過(guò)一百
  196. //                                         else if(TxPayload[2]<52)   moter(2,0);              //防止AD波動(dòng)造成誤啟動(dòng)
  197. //                                                                else  moter(1,(TxPayload[2]-52)*80/45);                                //正轉(zhuǎn)PWM值               
  198. //                }               
  199. //                       
  200. //                        if(JS==0){        Set_RxMode_MA();        led(1,1,1);
  201. //                        while(!JS){       
  202. //                  if(NRF24L01_RxPacket_MA(RxPayload) == RX_OK)          //如果接收成功
  203. //                        {
  204. //                        if(RxPayload[0] == 0x04)                                                                     //檢驗(yàn)校驗(yàn)碼
  205. //                        {                               
  206. //                        while( !(NRF24L01_RxPacket_MA(RxPayload+1)==RX_OK));                                //等待接收數(shù)據(jù)
  207. //                         while( !(NRF24L01_RxPacket_MA(RxPayload+2)==RX_OK));                                //等待接收數(shù)據(jù)
  208. //                                while( !(NRF24L01_RxPacket_MA(RxPayload+3)==RX_OK));                        //檢驗(yàn)校驗(yàn)碼
  209. //                        }
  210. //               
  211. //                        if(RxPayload[0] == 0x04 && RxPayload[3] == 0x05 )                 //符合校驗(yàn)碼的值 ,則中間的數(shù)據(jù)是正確的,不然亂碼,錯(cuò)位的數(shù)據(jù)就不對(duì)
  212. //                                {
  213. //                                n1= RxPayload[1]*256+RxPayload[2];
  214. //                                        if(n1>=5500) LCD_P8x16Str(56, 6,"---.-");
  215. //                                if(n1/1000==0) OLED_ShowChar(64,6,' ');
  216. //                                         else OLED_ShowChar(64,6,' '+16+n1/1000);
  217. //                                                                OLED_ShowChar(72,6,' '+16+n1%1000/100);
  218. //                                                                OLED_ShowChar(80,6,' '+16+n1%1000%100/10);
  219. //                                                                OLED_ShowChar(88,6,'.');       
  220. //                                                                OLED_ShowChar(96,6,' '+16+n1%1000%100%10);
  221. //                                                                RxPayload[0] = 0;
  222. //                                                                RxPayload[1] = 0;
  223. //                                                                RxPayload[2] = 0;
  224. //                                                                RxPayload[3] = 0;                               
  225. //                                                                }
  226. //                                                        }
  227. //                                                }
  228. //                                        }
  229. //                                }
  230. //                        }
  231. //                }

  232.         }
  233. }



  234. void led(bit x,bit y,bit z)
  235. {
  236.   Rled=x;
  237.         Gled=y;
  238.         Bled=z;
  239. }
  240. void OLEDXS(void)
  241. {                uint8 i;
  242.                 LCD_P8x16Str(56, 2,"X:");       //2.4G模塊用了SPI,所以O(shè)LED用IIC顯示
  243.                 LCD_P8x16Str(0, 2,"Y:");
  244.                 for(i=0;i<8;i++)        //遙控小車(chē)——發(fā)射
  245.            {
  246.                    LCD_P16x16Ch(i*16,0,i);                   
  247.                  };
  248.                  
  249.                          for(i=8;i<11;i++)
  250.            {
  251.                    LCD_P16x16Ch(i*16-16*8,4,i);        //轉(zhuǎn)向角           控制小車(chē)轉(zhuǎn)向的舵機(jī)
  252.                  };
  253.                  
  254.                  LCD_P8x16Str(48, 4,":");
  255.                 LCD_P8x16Str(80, 4,"'C");
  256.           LCD_P8x16Str(0, 6,"PWMY:");
  257.                 LCD_P8x16Str(104, 6,"CM");       
  258. }


  259. void moter(uint8 zf,uint8 SD)                                           //  電機(jī)驅(qū)動(dòng)函數(shù)  
  260. {   uint8 sudu,i;
  261.            sudu=SD;
  262.           ZF=zf;
  263.           
  264.                 OLED_ShowChar(40,6, ' '+16+sudu%100/10);
  265.                 OLED_ShowChar(48,6, ' '+16+sudu%100%10);
  266.        
  267.                         if(zf<1)                           
  268.                         {
  269.                                 for(i=13;i<15;i++)  //反轉(zhuǎn)
  270.                                  {
  271.                                         LCD_P16x16Ch(i*16-16*7,2,i);                   
  272.                                  }           
  273.                         }
  274.                                 else if(zf<2)      //正轉(zhuǎn)
  275.                                         {
  276.                                                 for(i=11;i<13;i++)
  277.                                          {
  278.                                                 LCD_P16x16Ch(i*16-16*5,2,i);                   
  279.                                          };  
  280.                                  }
  281.                                            else {
  282.                                                                          for(i=15;i<17;i++)  //停轉(zhuǎn)
  283.                                                                  {
  284.                                                                         LCD_P16x16Ch(i*16-16*9,2,i);                   
  285.                                                                  }
  286.                                                  }
  287.                                
  288.    
  289.                  
  290. }
  291. void CSZX(uint16 y)                  //超聲波初值顯示函數(shù)  ,沒(méi)加可屏蔽
  292. {               
  293.                 uint8 yy;
  294.            yy=y;       
  295.             
  296.                 OLED_ShowChar(56,4,' '+16+yy/100);
  297.                 OLED_ShowChar(64,4,' '+16+yy%100/10);
  298.                 OLED_ShowChar(72,4,' '+16+yy%100%10);
  299.                                
  300. }
  301. void INT0_init()                //外部中斷0的初始化配置       
  302. {
  303.         IE0  = 0;               //將INT0中斷請(qǐng)求標(biāo)志位清"0"
  304.         EX0 = 1;               //使能INT0中斷允許位
  305.         IT0 = 1;                   //選擇INT0為上升沿或下降沿觸發(fā)方式          1為下降沿,0為上升沿

  306. }

  307. void INT1_init()
  308. {
  309.                                                                                 //外部中斷1的初始化配置
  310.         IE1  = 0;                //將INT1中斷請(qǐng)求標(biāo)志位清"0"
  311.         EX1 = 1;                //使能INT1中斷允許位
  312.         IT1 = 1;                      //選擇INT1為下降沿觸發(fā)方式           1為下降沿,0為上升沿                  
  313. }
復(fù)制代碼
0.png
所有資料51hei提供下載:
PCB 圖.zip (55.86 KB, 下載次數(shù): 77)
遙控小車(chē)PCB版.zip (4.38 MB, 下載次數(shù): 107)




評(píng)分

參與人數(shù) 2黑幣 +65 收起 理由
shineyunze978 + 15 贊一個(gè)!
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:243748 發(fā)表于 2019-2-24 20:57 來(lái)自手機(jī) | 顯示全部樓層
好資料,希望能用得七
回復(fù)

使用道具 舉報(bào)

ID:260743 發(fā)表于 2019-4-28 15:44 | 顯示全部樓層
PCB封裝庫(kù)不全,根本打不開(kāi),文件大小才5KB
回復(fù)

使用道具 舉報(bào)

ID:310993 發(fā)表于 2021-3-30 01:41 | 顯示全部樓層
15932885***@是高手玩家!編程水平較高!電路板設(shè)計(jì)也很到位!細(xì)節(jié)也做的比較到位!只是習(xí)慣了51編程,變量名稱(chēng)太隨意,說(shuō)明及關(guān)鍵理解性說(shuō)明,太少有點(diǎn)可惜了!系統(tǒng)分析師可能會(huì)認(rèn)為,這種習(xí)慣不適合做大型程序!但做玩家那是高手!
回復(fù)

使用道具 舉報(bào)

ID:417804 發(fā)表于 2021-12-3 16:31 | 顯示全部樓層
請(qǐng)問(wèn)小車(chē)底盤(pán)是從哪里弄的?
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表