找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3236|回复: 0
收起左侧

基于51单片机的nrf24l01遥控小车程序

[复制链接]
ID:669379 发表于 2020-3-23 21:38 | 显示全部楼层 |阅读模式
用到了两块51单片机,一块遥控,另一块控制小车。小车上测得的距离传送到遥控的单片机上显示。屏幕用的是1602;

单片机源程序如下:
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #include <api.h>
  4. #include <duoji.h>
  5. #define uchar unsigned char
  6. #define uint unsigned int
  7. #define TX_ADR_WIDTH   5  // 5字节宽度的发送/接收地址
  8. #define TX_PLOAD_WIDTH 4  // 数据通道有效数据宽度

  9. unsigned long ultrasonic[5] = {0};
  10. unsigned int  time=0;//用于存放定时器时间值
  11. unsigned long S = 0;//用于存放距离的值//用于超声波测距

  12. uchar flag;
  13. static uint  aaa;//接受数据
  14. static uint dd;//存放距离

  15. uchar code TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};  // 定义一个静态发送地址
  16. uchar RX_BUF[TX_PLOAD_WIDTH];
  17. uchar TX_BUF[TX_PLOAD_WIDTH];
  18. uchar DATA = 0x01;
  19. uchar bdata sta;

  20. sbit  RX_DR         = sta^6;
  21. sbit  TX_DS         = sta^5;
  22. sbit  MAX_RT = sta^4;
  23. sbit TX=P3^7;           //超声波模块Trig        控制端
  24. sbit RX=P3^6;           //超声波模块Echo        接收端
  25. sbit hw1=P2^6;
  26. sbit hw2=P2^7;//红外循迹
  27. bit  fl =0; //量程溢出标志位

  28. void yaokong2(void);
  29. void init_io(void)
  30. {
  31.         CE  = 0;        // 待机
  32.         CSN = 1;        // SPI禁止
  33.         SCK = 0;        // SPI时钟置低
  34.         IRQ = 1;        // 中断复位

  35. }

  36. void delay_ms(uchar x)
  37. {
  38.     uchar i, j;
  39.     i = 0;
  40.     for(i=0; i<x; i++)
  41.     {
  42.        j = 250;
  43.        while(--j);
  44.            j = 250;
  45.        while(--j);
  46.     }
  47. }

  48. uchar SPI_RW(uchar byte)
  49. {
  50.         uchar i;
  51.            for(i=0; i<8; i++)          // 循环8次
  52.            {
  53.                    MOSI = (byte & 0x80);   // byte最高位输出到MOSI
  54.                    byte <<= 1;             // 低一位移位到最高位
  55.                    SCK = 1;                // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据
  56.                    byte |= MISO;               // 读MISO到byte最低位
  57.                    SCK = 0;                    // SCK置低
  58.            }
  59.     return(byte);                   // 返回读出的一字节
  60. }

  61. uchar SPI_RW_Reg(uchar reg, uchar value)
  62. {
  63.         uchar status;
  64.           CSN = 0;                   // CSN置低,开始传输数据
  65.           status = SPI_RW(reg);      // 选择寄存器,同时返回状态字
  66.           SPI_RW(value);             // 然后写数据到该寄存器
  67.           CSN = 1;                   // CSN拉高,结束数据传输
  68.           return(status);            // 返回状态寄存器
  69. }

  70. uchar SPI_Read(uchar reg)
  71. {
  72.         uchar reg_val;
  73.           CSN = 0;                    // CSN置低,开始传输数据
  74.           SPI_RW(reg);                // 选择寄存器
  75.           reg_val = SPI_RW(0);        // 然后从该寄存器读数据
  76.           CSN = 1;                    // CSN拉高,结束数据传输
  77.           return(reg_val);            // 返回寄存器数据
  78. }

  79. uchar SPI_Read_Buf(uchar reg, uchar * pBuf, uchar bytes)
  80. {
  81.         uchar status, i;
  82.           CSN = 0;                    // CSN置低,开始传输数据
  83.           status = SPI_RW(reg);       // 选择寄存器,同时返回状态字
  84.           for(i=0; i<bytes; i++)
  85.             pBuf[i] = SPI_RW(0);    // 逐个字节从nRF24L01读出
  86.           CSN = 1;                    // CSN拉高,结束数据传输
  87.           return(status);             // 返回状态寄存器
  88. }

  89. uchar SPI_Write_Buf(uchar reg, uchar * pBuf, uchar bytes)
  90. {
  91.         uchar status, i;
  92.           CSN = 0;                    // CSN置低,开始传输数据
  93.           status = SPI_RW(reg);       // 选择寄存器,同时返回状态字
  94.           for(i=0; i<bytes; i++)
  95.             SPI_RW(pBuf[i]);        // 逐个字节写入nRF24L01
  96.           CSN = 1;                    // CSN拉高,结束数据传输
  97.           return(status);             // 返回状态寄存器
  98. }
  99. void RX_Mode(void)
  100. {
  101.           CE = 0;
  102.           SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);  // 接收设备接收通道0使用和发送设备相同的发送地址
  103.           SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);               // 使能接收通道0自动应答
  104.           SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);           // 使能接收通道0
  105.           SPI_RW_Reg(WRITE_REG + RF_CH, 40);                 // 选择射频通道0x40
  106.           SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH);  // 接收通道0选择和发送通道相同有效数据宽度
  107.           SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);            // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益
  108.           SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);              // CRC使能,16位CRC校验,上电,接收模式
  109.           CE = 1;                                            // 拉高CE启动接收设备
  110. }

  111. void TX_Mode(uchar * BUF)
  112. {
  113.         CE = 0;
  114.           SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);     // 写入发送地址
  115.           SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);  // 为了应答接收设备,接收通道0地址和发送地址相同
  116.           SPI_Write_Buf(WR_TX_PLOAD, BUF, TX_PLOAD_WIDTH);                  // 写数据包到TX FIFO
  117.           SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);       // 使能接收通道0自动应答
  118.           SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);   // 使能接收通道0
  119.           SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x0a);  // 自动重发延时等待250us+86us,自动重发10次
  120.           SPI_RW_Reg(WRITE_REG + RF_CH, 40);         // 选择射频通道0x40
  121.           SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);    // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益
  122.           SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);      // CRC使能,16位CRC校验,上电
  123.         CE = 1;
  124. }

  125. uchar Check_ACK(bit clear)
  126. {
  127.         while(IRQ);
  128.         sta = SPI_RW(NOP);                    // 返回状态寄存器
  129.         if(MAX_RT)
  130.                 if(clear)                         // 是否清除TX FIFO,没有清除在复位MAX_RT中断标志后重发
  131.                         SPI_RW(FLUSH_TX);
  132.         SPI_RW_Reg(WRITE_REG + STATUS, sta);  // 清除TX_DS或MAX_RT中断标志
  133.         IRQ = 1;
  134.         if(TX_DS)
  135.                 return(0x00);
  136.         else
  137.                 return(0xff);
  138. }

  139. void delay__(uint count)      //delay
  140. {
  141.   uint i;
  142.   while(count)
  143.   {
  144.     i=200;
  145.     while(i>0)
  146.     i--;
  147.     count--;
  148.   }
  149. }                       
  150. void Delay10us(unsigned int i)            //10us延时函数
  151. {
  152.            unsigned int j;
  153.         do{
  154.                   j = 10;
  155.                   do
  156.                 {
  157.                            _nop_();
  158.                    }while(--j);
  159.         }while(--i);
  160. }  

  161. void  StartModule()                          //启动超声波模块
  162. {
  163.             TX=1;                                             //启动一次模块
  164.       Delay10us(2);
  165.             TX=0;
  166. }
  167. unsigned long conut1(void)  //测量一次距离
  168. {
  169.         unsigned long dis = 0;
  170.         time=TH1*256+TL1;
  171.         TH1=0;
  172.         TL1=0;
  173.        
  174.   dis=(float)(time*1.085)*0.17;
  175.         return dis;
  176. }


  177. void bubble(unsigned long *a, int n) //冒泡程序

  178. {
  179.         int i,j,temp;       
  180.         for(i = 0;i < n-1; i++)       
  181.         {       
  182.                 for(j = i + 1; j < n; j++)
  183.                 {
  184.                         if(a[i] > a[j])
  185.                         {
  186.                                 temp = a[i];               
  187.                                 a[i] = a[j];               
  188.                                 a[j] = temp;                       
  189.                         }
  190.                 }
  191.         }

  192. }
  193. uint distance22()
  194. {
  195.           uint dis;
  196.     RX = 1;
  197.           StartModule();                                
  198.     while(RX==0);   
  199.        
  200.     TR1=1;                            
  201.     while(RX);                       
  202.     TR1=0;                               
  203.    dis=conut1();
  204.         return dis;
  205. }
  206. unsigned long Distance(void)        //测距
  207. {
  208.         int num = 0;
  209.         unsigned long Distance = 0;
  210.         RX = 1;
  211.         StartModule();                                
  212.     while(RX==0);   
  213.        
  214.     TR1=1;                            
  215.     while(RX);                       
  216.     TR1=0;                               
  217.    
  218.         conut1();

  219.         while(num < 5) // 测5次数据
  220.         {
  221.                 RX = 1;
  222.                 StartModule();                                
  223.             while(RX==0);   
  224.        
  225.                   TR1=1;                            
  226.             while(RX);                       
  227.             TR1=0;                               
  228.             
  229.                 S = conut1();
  230.                 ultrasonic[num] = S;
  231.                 num++;
  232.         }
  233.         num = 0;
  234.         bubble(ultrasonic, 5);
  235.         Distance = (ultrasonic[1]+ultrasonic[2]+ultrasonic[3])/3;
  236.         return Distance;
  237. }
  238. void duobi(void)                                //避障程序
  239. {               
  240.          uint a[]={0,0};//zuoyoujuli
  241.         //        dd=Distance();
  242.   //         juli=distance;
  243.           z0();
  244. if(dd>600)//old接收到的为cm,distance为毫米
  245.                 {
  246.                         qj();
  247.           }//前进时发射距离
  248.           else
  249.         {
  250.                 t(10);
  251.           y90();    y90();    y90();
  252.                 delaydj(100);
  253.         a[1]=Distance();
  254.           z90();          z90();          z90();
  255.                 delaydj(100);
  256.         a[0]=Distance();
  257.                 z0();
  258.                 if   (a[0]>a[1] && a[1]>300)
  259.                 {
  260.                         z(900);
  261.                         t(50);
  262.                 }
  263.                 else if(a[0]<a[1] && a[0]>300)
  264.                 {
  265.                         y(900);
  266.                         t(50);
  267.                 }
  268.                 else if (a[0]>a[1] && a[1]<300 || a[0]<a[1] && a[1]<300)
  269.                 {
  270.                        
  271.                   ht(500);
  272.                         t(50);
  273.                         if(a[0]<a[1])
  274.                   y(820);
  275.                         else z(820);
  276.                 }
  277.                 else
  278.                 {
  279.                         if(a[0]<a[1])
  280.                         {hz(800);
  281.                         t(10);}
  282.                         else hy(800);
  283.                
  284.                 }
  285.         }
  286. }

  287. //void hongwai(void)
  288. //{
  289. //          EX0 = 1;//开外部中断0
  290. //          IT0 = 1;//外部中断0高电平触发
  291. //    EX1 = 1;//开外部中断0
  292. //          IT1 = 1;//外部中断0高电平触发
  293. //        switch (hms)
  294. //        {
  295. //                case 0:qjj(100);      break;
  296. //          case 1:{t(10);z(200);}break;
  297. //          case 2:{t(10);y(200);}break;
  298. //        }
  299. //        if(dd<200)
  300. //                duobi();
  301. //          hms=0;
  302. //}
  303. void fashe (uint b)                        //发射数据十六进制码
  304. {

  305.          b/=10;                          //转化为cm
  306.         TX_BUF[2]=TT;
  307.          if(fl!=1 && b<500 && b>250)
  308.         {  
  309.                 b-=250;
  310.                 b=0x01/0x01*b;
  311.                 TX_BUF[0]=250;
  312.                 TX_BUF[1]=b;
  313.           TX_Mode(TX_BUF);
  314.                  SPI_RW(FLUSH_TX);
  315.         SPI_RW_Reg(WRITE_REG + STATUS, sta);  // 清除TX_DS或MAX_RT中断标志
  316.         IRQ = 1;
  317.         }
  318.         else if(b<250)
  319.         {
  320.           b=0x01/0x01*b;
  321.                 TX_BUF[0]=b;
  322.                 TX_BUF[1]=0x00;
  323.           TX_Mode(TX_BUF);
  324.                  SPI_RW(FLUSH_TX);
  325.         SPI_RW_Reg(WRITE_REG + STATUS, sta);  // 清除TX_DS或MAX_RT中断标志
  326.         IRQ = 1;
  327.         }
  328.         else if(fl==1)
  329.                  {
  330.                           fl=0;
  331.                           TX_BUF[0]=0x01;
  332.               TX_BUF[1]=0x00;
  333.               TX_Mode(TX_BUF);
  334.               SPI_RW(FLUSH_TX);
  335.         SPI_RW_Reg(WRITE_REG + STATUS, sta);  // 清除TX_DS或MAX_RT中断标志
  336.         IRQ = 1;
  337.                  }
  338.                  SPI_RW_Reg(FLUSH_TX, 0x00); //清除寄存器
  339.                  init_io();
  340.                  RX_Mode();
  341.                
  342.         }

  343. uint jieshou(void)
  344. {       
  345.           sta = SPI_Read(STATUS);          // 读状态寄存器
  346.             if(RX_DR)                                  // 判断是否接受到数据
  347.                 {
  348.                         SPI_Read_Buf(RD_RX_PLOAD, RX_BUF, TX_PLOAD_WIDTH);  // 从RX FIFO读出数据
  349.                         flag = 1;
  350.                 }
  351.                 SPI_RW_Reg(WRITE_REG + STATUS, sta);  // 清除RX_DS中断标志
  352.                 if(flag)                           // 接受完成
  353.                 {  
  354.                         flag = 0;                       // 清标志
  355.                         aaa=RX_BUF[0];
  356. //                        if(aaa>15)  old=aaa;                //修改避障距离
  357.                 }
  358.                 SPI_RW_Reg(FLUSH_RX, 0xff);//清除寄存器
  359.                 return aaa;
  360. }
  361. void yaokong(uint a)
  362. {
  363.           switch (a)
  364.                         {
  365.                                 case 0: hz(300); break;
  366.                                 case 1: qjj(500);    break;
  367.                           case 2: hy(300); break;
  368.                                 case 3: duobi(); break;
  369.                                 case 4: z(400); break;
  370.                                 case 5: ht(400);break;
  371.                           case 6: y(500); break;
  372.                           case 8: yaokong2();break;
  373.                           case 15: t(1); break;
  374. //                  case 7: hongwai();break;
  375.                   }
  376. }
  377. void yaokong2(void)
  378. {
  379.         while(aaa!=15)//接收到3退出
  380.         {         TT=9;
  381.                 RX_Mode();
  382.                 aaa=jieshou();
  383.          switch(aaa)
  384.          {
  385.                  case 1:qjj(500);break;
  386.                  case 4:z(300); break;
  387.                  case 5:ht(500);break;
  388.            case 6:y(500);break;
  389.                  case 0:t(1);break;
  390. //                 case 9:{if(TT<9)++TT;}break;
  391. //                 case 10:{if(TT>4)--TT;}break;//加减速
  392.          }
  393.         if(aaa!=15)
  394.                 aaa=0;
  395.         }
  396. }
  397. //void gensui(void)
  398. //{
  399. //        uint pa;
  400. //          TT=4;
  401. //                if(hw1==0 && hw2==0)
  402. //                {
  403. //                        dd=Distance();
  404. //                        if(dd>30)
  405. //                        { pa=(dd/10-30)*25;qjj(pa);}
  406. //                 else {pa=(30-dd/10)*25;ht(pa);}
  407. //                       
  408. //                }
  409. //                else if(hw1==1 && hw2==1)
  410. //                {
  411. //                        dd=Distance();
  412. //                        if(dd>250 && dd<350)
  413. //                        t(1);
  414. //                        else
  415. //       {
  416. //         if (dd>300)
  417. //            { pa=(dd/10-30)*25;qjj(pa);}
  418. //                     else
  419. //             {pa=(30-dd/10)*25;ht(pa);}
  420. //                         }
  421. //                }
  422. //                else if(hw1==0 && hw2==1)
  423. //                y(400);
  424. //                else if(hw1==1 && hw2==0)
  425. //                        z(400);
  426. //}
  427. void sudu(void)
  428. {
  429.         if(dd>1000)   {TT=9;}
  430.         else if(dd>400&&dd<1000) {TT=dd/100;}
  431.         else TT=4;
  432. }
  433. void timer1() interrupt 3                  //T1 中断用来计数器溢出,超过测距范围
  434. {
  435.     fl=1;                                       //中断溢出标志
  436.     RX=0;
  437. }
  438. void timer0(void) interrupt 1//定时器0中断函数
  439. {
  440.           TR0 = 0;      //关闭定时器0
  441.     TH0 = 0xff;   //重装初值0.1ms
  442.     TL0 = 0xa3;

  443.                 kk++;
  444.          if(kk>=10)
  445.                 {
  446.                         kk=0;
  447. ……………………

  448. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
捕获.JPG
所有资料51hei提供下载:
遥控小车.zip (94.59 KB, 下载次数: 52)

评分

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

查看全部评分

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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