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

QQ登錄

只需一步,快速開始

帖子
查看: 3197|回復(fù): 1
打印 上一主題 下一主題
收起左側(cè)

6通遙控源碼

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
我做了個(gè) 2.4G 遙控器  下面有附圖  有源碼  有感興趣的 可以學(xué)學(xué) 了  。當(dāng)時(shí)做的時(shí)候也學(xué)習(xí)了很長(zhǎng)時(shí)間 。由于自己感興趣 ,就學(xué)下去了 收益匪淺啊。很適合初學(xué)者看看了 。本程序  做個(gè)小車 小船的  灼灼有余了 。

復(fù)制代碼
這是發(fā)射程序 #include <reg51.h>#include <intrins.h>

#define uchar unsigned char
#define uint  unsigned int
#define u8 unsigned char
#define u16  unsigned int
//STC12 系列新增寄存器
sfr IPH=0xb7;
sfr P4=0xc0;
sfr P4SW=0xbb;
sfr P1ASF=0x9d;
sfr P4M0=0xb4;
sfr P3M0=0xb2;
sfr P3M1=0xb1;
sfr P2M0=0x96;
sfr P0M0=0x94;
sfr ADC_CONTR=0xbc;
sfr ADC_RES=0xbd;
sfr ADC_RESL=0xbe;

sfr BRT=0x9c;
sfr AUXR=0x8e;
sfr WAKE_CLKO=0x8f;

sfr IAP_DATA=0xc2;
sfr IAP_ADDRH=0xc3;
sfr IAP_ADDRL=0xc4;
sfr IAP_CMD=0xc5;
sfr IAP_TRIG=0xc6;
sfr IAP_CONTR=0xc7;

sfr CCON        =   0xD8;           //PCA control register
sbit CCF0       =   CCON^0;         //PCA module-0 interrupt flag
sbit CCF1       =   CCON^1;         //PCA module-1 interrupt flag
sbit CR         =   CCON^6;         //PCA timer run control bit
sfr CMOD        =   0xD9;           //PCA mode register
sfr CL          =   0xE9;           //PCA base timer LOW
sfr CH          =   0xF9;           //PCA base timer HIGH
sfr CCAPM0      =   0xDA;           //PCA module-0 mode register
sfr CCAP0L      =   0xEA;           //PCA module-0 capture register LOW
sfr CCAP0H      =   0xFA;           //PCA module-0 capture register HIGH
sfr CCAPM1      =   0xDB;           //PCA module-1 mode registers
sfr CCAP1L      =   0xEB;           //PCA module-1 capture register LOW
sfr CCAP1H      =   0xFB;           //PCA module-1 capture register HIGH


/*************************************************/


/* STC15W404AS寄存器補(bǔ)充
sfr AUXR1 = 0XA2;
sfr AUXR = 0X8E;
sfr TH2 = 0XD6;
sfr TL2 = 0XD7;
sfr P4 = 0xc0;
sfr P5 = 0xc8;
sfr P3M0=0xB2;
sfr SPSTAT      =   0xCD;   //
sfr SPCTL       =   0xCE;   //
sfr SPDAT       =   0xCF;   */
//定時(shí)器2
//sfr T2H=0xd6;
//sfr T2L=0xd7;
//sfr IE2=0xaf;
//ADC
//sfr ADC_CONTR = 0xBC;        //帶AD系列
//sfr ADC_RES   = 0xBD;        //帶AD系列
//sfr ADC_RESL  = 0xBE;        //帶AD系列
//sfr P1ASF = 0x9D;
sfr PCON2   = 0x97;









#define ADC_POWER        0x80//ADC電源控制位
#define ADC_FLAG        0x10//ADC完成標(biāo)志
#define ADC_START        0x08//ADC起始控制位
#define ADC_SPEEDLL        0x00//540個(gè)時(shí)鐘轉(zhuǎn)換一次
#define ADC_SPEEDL        0x20//360時(shí)鐘
#define ADC_SPEEDH        0x40//180時(shí)鐘
#define ADC_SPEEDHH        0x60//90時(shí)鐘


unsigned char recv_buf[6]={0,0,0,0,1,1};//NRF24模塊可以一次發(fā)射32個(gè)字節(jié),這里只用6個(gè),代表6個(gè)通道。
sbit NRF_CE = P0^1;
sbit NRF_CSN = P0^0;
sbit NRF_MISO = P0^5;
sbit NRF_MOSI = P0^2;
sbit NRF_SCK = P0^3;
sbit NRF_IRQ = P0^4;




/*sbit NRF_IRQ = P5^5;
sbit NRF_MISO = P1^4;
sbit NRF_MOSI = P1^3;
sbit NRF_SCK = P1^5;
sbit NRF_CSN = P1^2;
sbit NRF_CE = P5^4;         */

sbit SW1=P3^7;//開關(guān)通道1
sbit SW2=P3^6;//開關(guān)通道2
sbit SW_Mix1=P3^5;//混控開關(guān)1
//sbit Beep=P3^4;//蜂鳴器
//sbit LED_Battery=P3^3;//1s電池低壓報(bào)警燈
sbit LED_NRF=P3^2;//NRF模塊信號(hào)不好報(bào)警燈

u8 TxAllCount=0;//發(fā)射總次數(shù)
u8 TxOKCount=0;//發(fā)射成功次數(shù)
u8 Time10Ms=0;//蜂鳴器鳴叫時(shí)間
/*
有些搖桿,阻值5K的,搖到最上方,還有大概1K的阻值,阻值并不是0的樣子。
有些搖桿,搖到最上邊阻值就是0了。
這樣搖不到底的搖桿,我不做轉(zhuǎn)換了,電調(diào)有行程調(diào)節(jié)的。
接舵機(jī)倒無所謂,大不了轉(zhuǎn)不了45度,我轉(zhuǎn)個(gè)30°也湊合了。
*/

u8 pianyi=25;//搖桿上限偏移范圍上限值,默認(rèn)25,你也可以修改。

/**********  你可以從這里復(fù)制NRF24L01的全部代碼了  ***********/

/**********  NRF24L01寄存器操作命令  ***********/
#define READ_REG        0x00  //讀配置寄存器,低5位為寄存器地址
#define WRITE_REG       0x20  //寫配置寄存器,低5位為寄存器地址
#define RD_RX_PLOAD     0x61  //讀RX有效數(shù)據(jù),1~32字節(jié)
#define WR_TX_PLOAD     0xA0  //寫TX有效數(shù)據(jù),1~32字節(jié)
#define FLUSH_TX        0xE1  //清除TX FIFO寄存器.發(fā)射模式下用
#define FLUSH_RX        0xE2  //清除RX FIFO寄存器.接收模式下用
#define REUSE_TX_PL     0xE3  //重新使用上一包數(shù)據(jù),CE為高,數(shù)據(jù)包被不斷發(fā)送.
#define NRF_NOP         0xFF  //空操作,可以用來讀狀態(tài)寄存器         
/**********  NRF24L01寄存器地址   *************/
#define CONFIG          0x00  //配置寄存器地址                             
#define EN_AA           0x01  //使能自動(dòng)應(yīng)答功能
#define EN_RXADDR       0x02  //接收地址允許
#define SETUP_AW        0x03  //設(shè)置地址寬度(所有數(shù)據(jù)通道)
#define SETUP_RETR      0x04  //建立自動(dòng)重發(fā)
#define RF_CH           0x05  //RF通道
#define RF_SETUP        0x06  //RF寄存器
#define STATUS          0x07  //狀態(tài)寄存器
#define OBSERVE_TX      0x08  // 發(fā)送檢測(cè)寄存器
#define CD              0x09  // 載波檢測(cè)寄存器
#define RX_ADDR_P0      0x0A  // 數(shù)據(jù)通道0接收地址
#define RX_ADDR_P1      0x0B  // 數(shù)據(jù)通道1接收地址
#define RX_ADDR_P2      0x0C  // 數(shù)據(jù)通道2接收地址
#define RX_ADDR_P3      0x0D  // 數(shù)據(jù)通道3接收地址
#define RX_ADDR_P4      0x0E  // 數(shù)據(jù)通道4接收地址
#define RX_ADDR_P5      0x0F  // 數(shù)據(jù)通道5接收地址
#define TX_ADDR         0x10  // 發(fā)送地址寄存器
#define RX_PW_P0        0x11  // 接收數(shù)據(jù)通道0有效數(shù)據(jù)寬度(1~32字節(jié))
#define RX_PW_P1        0x12  // 接收數(shù)據(jù)通道1有效數(shù)據(jù)寬度(1~32字節(jié))
#define RX_PW_P2        0x13  // 接收數(shù)據(jù)通道2有效數(shù)據(jù)寬度(1~32字節(jié))
#define RX_PW_P3        0x14  // 接收數(shù)據(jù)通道3有效數(shù)據(jù)寬度(1~32字節(jié))
#define RX_PW_P4        0x15  // 接收數(shù)據(jù)通道4有效數(shù)據(jù)寬度(1~32字節(jié))
#define RX_PW_P5        0x16  // 接收數(shù)據(jù)通道5有效數(shù)據(jù)寬度(1~32字節(jié))
#define FIFO_STATUS     0x17  // FIFO狀態(tài)寄存器
/*————————————————————————————————————————————————————————————————————*/

/******   STATUS寄存器bit位定義      *******/
#define MAX_TX          0x10  //達(dá)到最大發(fā)送次數(shù)中斷
#define TX_OK           0x20  //TX發(fā)送完成中斷
#define RX_OK           0x40  //接收到數(shù)據(jù)中斷
/*——————————————————————————————————————————————————*/

/*********     24L01發(fā)送接收數(shù)據(jù)寬度定義          ***********/
#define TX_ADR_WIDTH    5   //5字節(jié)地址寬度
#define RX_ADR_WIDTH    5   //5字節(jié)地址寬度
#define TX_PLOAD_WIDTH  6  //32字節(jié)有效數(shù)據(jù)寬度
#define RX_PLOAD_WIDTH  6  //32字節(jié)有效數(shù)據(jù)寬度

uchar xdata TX_ADDRESS[TX_ADR_WIDTH]={0x68,0x86,0x66,0x88,0x28};
uchar xdata RX_ADDRESS[RX_ADR_WIDTH]={0x68,0x86,0x66,0x88,0x28};

void Delay1ms()                //@12.000MHz   軟件延時(shí)1ms
{
        unsigned char i, j;

        i = 12;
        j = 169;
        do
        {
                while (--j);
        } while (--i);
}

void delay_ms(unsigned char i)         //延時(shí)n毫秒  0~255ms
{
   while(--i)
   {
         Delay1ms();
   }          
}

void DelayMs(unsigned int i)  //延時(shí)N毫秒,0~65535ms
{
   while(--i)
   {
         Delay1ms();
   }  
}

/**********************/
/* 初始化硬件SPI口    */
/*
void SPI_Init(void)        //如果用模擬SPI,這個(gè)就不要調(diào)用了,它是開啟硬件SPI
{
        SPSTAT |= 0xC0; //SPI狀態(tài)寄存器全部清0          SPIF和WCOL清0
        SPCTL = 0xD0;  //0xD0=11010000 ,表示SPI開啟,主機(jī)模式,SPI頻率為主頻四分之一
}        */

/**********************/
/* SPI數(shù)據(jù)收發(fā)函數(shù) 硬件SPI   */
/*
uchar SPI_RW(uchar tr_data)
{
        uchar i=0;
       
        SPSTAT |= 0xc0; //SPI狀態(tài)寄存器全部清0          SPIF和WCOL清0
        SPDAT=tr_data;  //將數(shù)據(jù)放到SPI數(shù)據(jù)寄存器中
        while(((SPSTAT&0x80)!=0x80)&&(i<20)) //SPSTAT&0x80 SPI數(shù)據(jù)傳輸完成標(biāo)志        如果沒完成傳輸,就延時(shí)1ms
        {
                i++;
                delay_ms(1);                                         //20ms內(nèi)沒完成,則跳出
        }
        return SPDAT;                                                 //返回傳輸?shù)臄?shù)據(jù)值
} */

// 下面是“模擬SPI”  如果不用硬件SPI,可以用模擬SPI
uchar SPI_RW(uchar byte)
{
        uchar bit_ctr;
        for(bit_ctr=0;bit_ctr<8;bit_ctr++) // 輸出8位
        {
                NRF_MOSI=(byte&0x80); // MSB TO MOSI
                byte=(byte<<1);        // shift next bit to MSB
                NRF_SCK=1;
                byte|=NRF_MISO;                // capture current MISO bit
                NRF_SCK=0;
        }
        return byte;
}


/*********************************************/
/* 函數(shù)功能:給24L01的寄存器寫值(一個(gè)字節(jié)) */
/* 入口參數(shù):reg   要寫的寄存器地址          */
/*           value 給寄存器寫的值            */
/* 出口參數(shù):status 狀態(tài)值                   */
/*********************************************/
uchar NRF24L01_Write_Reg(uchar reg,uchar value)
{
        uchar status;

        NRF_CSN=0;                  //CSN=0;   
          status = SPI_RW(reg);//發(fā)送寄存器地址,并讀取狀態(tài)值
        SPI_RW(value);
        NRF_CSN=1;                  //CSN=1;

        return status;
}
/*************************************************/
/* 函數(shù)功能:讀24L01的寄存器值 (一個(gè)字節(jié))      */
/* 入口參數(shù):reg  要讀的寄存器地址               */
/* 出口參數(shù):value 讀出寄存器的值                */
/*************************************************/
uchar NRF24L01_Read_Reg(uchar reg)
{
        uchar value;

        NRF_CSN=0;              //CSN=0;   
          SPI_RW(reg);//發(fā)送寄存器值(位置),并讀取狀態(tài)值
        value = SPI_RW(NRF_NOP);
        NRF_CSN=1;             //CSN=1;

        return value;
}
/*********************************************/
/* 函數(shù)功能:讀24L01的寄存器值(多個(gè)字節(jié))   */
/* 入口參數(shù):reg   寄存器地址                */
/*           *pBuf 讀出寄存器值的存放數(shù)組    */
/*           len   數(shù)組字節(jié)長(zhǎng)度              */
/* 出口參數(shù):status 狀態(tài)值                   */
/*********************************************/
uchar NRF24L01_Read_Buf(uchar reg,uchar *pBuf,uchar len)
{
        uchar status,u8_ctr;
        NRF_CSN=0;                   //CSN=0      
          status=SPI_RW(reg);//發(fā)送寄存器地址,并讀取狀態(tài)值             
        for(u8_ctr=0;u8_ctr<len;u8_ctr++)
        pBuf[u8_ctr]=SPI_RW(0XFF);//讀出數(shù)據(jù)
        NRF_CSN=1;                 //CSN=1
          return status;        //返回讀到的狀態(tài)值
}
/**********************************************/
/* 函數(shù)功能:給24L01的寄存器寫值(多個(gè)字節(jié))  */
/* 入口參數(shù):reg  要寫的寄存器地址            */
/*           *pBuf 值的存放數(shù)組               */
/*           len   數(shù)組字節(jié)長(zhǎng)度               */
/**********************************************/
uchar NRF24L01_Write_Buf(uchar reg, uchar *pBuf, uchar len)
{
        uchar status,u8_ctr;
        NRF_CSN=0;
          status = SPI_RW(reg);//發(fā)送寄存器值(位置),并讀取狀態(tài)值
          for(u8_ctr=0; u8_ctr<len; u8_ctr++)
        SPI_RW(*pBuf++); //寫入數(shù)據(jù)
        NRF_CSN=1;
          return status;          //返回讀到的狀態(tài)值
}                                                                                                    
//為避免編譯器函數(shù)重入錯(cuò)誤,所以又改名復(fù)制的函數(shù),和上面的函數(shù)一個(gè)樣
uchar NRF24L01_Write_BufData(uchar reg, uchar *pBuf, uchar len)
{
        uchar status,u8_ctr;
        NRF_CSN=0;
          status = SPI_RW(reg);//發(fā)送寄存器值(位置),并讀取狀態(tài)值
          for(u8_ctr=0; u8_ctr<len; u8_ctr++)
        SPI_RW(*pBuf++); //寫入數(shù)據(jù)
        NRF_CSN=1;
          return status;          //返回讀到的狀態(tài)值
}
/*********************************************/
/* 函數(shù)功能:24L01接收數(shù)據(jù)                   */
/* 入口參數(shù):rxbuf 接收數(shù)據(jù)數(shù)組              */
/* 返回值: 0   成功收到數(shù)據(jù)                 */
/*          1   沒有收到數(shù)據(jù)                 */
/*********************************************/
uchar NRF24L01_RxPacket(uchar *rxbuf)
{
        uchar state;
         
        state=NRF24L01_Read_Reg(STATUS);  //讀取狀態(tài)寄存器的值             
        NRF24L01_Write_Reg(WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中斷標(biāo)志
        if(state&RX_OK)//接收到數(shù)據(jù)
        {
                NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//讀取數(shù)據(jù)
                NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
                return 0;
        }          
        return 1;//沒收到任何數(shù)據(jù)
}
/**********************************************/
/* 函數(shù)功能:設(shè)置24L01為發(fā)送模式              */
/* 入口參數(shù):txbuf  發(fā)送數(shù)據(jù)數(shù)組              */
/* 返回值; 0x10    達(dá)到最大重發(fā)次數(shù),發(fā)送失敗*/
/*          0x20    成功發(fā)送完成              */
/*          0xff    發(fā)送失敗                  */
/**********************************************/
uchar NRF24L01_TxPacket(uchar *txbuf)
{
        uchar state;
//        uchar i;

        NRF_CE=0;//CE拉低,使能24L01配置
          NRF24L01_Write_BufData(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//寫數(shù)據(jù)到TX BUF  32個(gè)字節(jié)
        NRF_CE=1;//CE置高,使能發(fā)送          
        while(NRF_IRQ==1);//等待發(fā)送完成
        state=NRF24L01_Read_Reg(STATUS);  //讀取狀態(tài)寄存器的值          
        NRF24L01_Write_Reg(WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中斷標(biāo)志
        if(state&MAX_TX)//達(dá)到最大重發(fā)次數(shù)
        {
                NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器
                return MAX_TX;
        }
        if(state&TX_OK)//發(fā)送完成
        {
                return TX_OK;
        }
        return 0xff;//發(fā)送失敗
}
/********************************************/
/* 函數(shù)功能:檢測(cè)24L01是否存在              */
/* 返回值;  0  存在                        */
/*           1  不存在                      */
/********************************************/
//檢測(cè)原理就是存入NRF模塊一段數(shù)據(jù),然后再讀出來比較一下是否一致
uchar NRF24L01_Check(void)
{
        uchar check_in_buf[5]={0x11,0x22,0x33,0x44,0x55};
        uchar check_out_buf[5]={0x00};

        NRF_CE=0;

        NRF24L01_Write_Buf(WRITE_REG+TX_ADDR, check_in_buf, 5);

        NRF24L01_Read_Buf(READ_REG+TX_ADDR, check_out_buf, 5);

        if((check_out_buf[0] == 0x11)&&\
           (check_out_buf[1] == 0x22)&&\
           (check_out_buf[2] == 0x33)&&\
           (check_out_buf[3] == 0x44)&&\
           (check_out_buf[4] == 0x55))return 0;
        else return 1;
}       

void NRF24L01_SET_TX_Mode(void)
{
        NRF_CE=0;
        NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0e); // 配置為無線發(fā)送模式
        NRF_CE=1;

}

void NRF24L01_SET_RX_Mode(void)
{
        NRF_CE=0;
        NRF24L01_Write_Reg(WRITE_REG+CONFIG, 0x0f); // 配置為無線接收模式
        NRF_CE=1;

}


void NRF24L01_RT_Init(void)         //NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0e); 發(fā)射時(shí)0x0e,記得修改
{       
        NRF_CE=0;  //進(jìn)行配置,要首先禁止模塊功能                  
          NRF24L01_Write_Reg(WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//選擇通道0的有效數(shù)據(jù)寬度
        NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器   
          NRF24L01_Write_Buf(WRITE_REG+TX_ADDR,(uchar*)TX_ADDRESS,TX_ADR_WIDTH);//寫TX節(jié)點(diǎn)地址
          NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P0,(uchar*)RX_ADDRESS,RX_ADR_WIDTH); //設(shè)置TX節(jié)點(diǎn)地址,主要為了使能ACK          
          NRF24L01_Write_Reg(WRITE_REG+EN_AA,0x01);     //使能通道0的自動(dòng)應(yīng)答   
          NRF24L01_Write_Reg(WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址  
          NRF24L01_Write_Reg(WRITE_REG+SETUP_RETR,0x1a);//設(shè)置自動(dòng)重發(fā)間隔時(shí)間:500us + 86us;最大自動(dòng)重發(fā)次數(shù):10次
          NRF24L01_Write_Reg(WRITE_REG+RF_CH,40);       //設(shè)置RF通道為125
          NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x27);  //7db增益,250kbps
          NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0e);    //配置基本工作模式的參數(shù);PWR_UP,EN_CRC,16BIT_CRC,接收模式,開啟所有中斷
        NRF_CE=1;        //CE置1,恢復(fù)功能           //0x0e發(fā)射 0x0f接收
}                                                  //記得發(fā)送程序和接收程序的配置,要改0e和0f的數(shù)值,要不就要單獨(dú)要用一次發(fā)射或者接收設(shè)置。

/**********  NRF24L01的全部代碼復(fù)制完成了  ***********/

/*void BEEP(u8 i)          //蜂鳴器叫兩聲
{
  Beep=1;
  DelayMs(i);
  Beep=0;
  DelayMs(i);
  Beep=1;
  DelayMs(i);
  Beep=0;
}

/*void TimeBEEP()        //用定時(shí)器2讓蜂鳴器間隔鳴叫
{
        AUXR=0x10;//打開定時(shí)器2
}
   */
void InitADC(void)        //ADC初始化
{
  P1ASF=0xc3;//打開P1.0,P1.1,P1.6,P1.7的ADC轉(zhuǎn)換功能  因?yàn)檫@里就用了4個(gè)腳 0xc3=11000011 對(duì)應(yīng)P1.7~P1.0 8個(gè)腳
  ADC_RES=0;//ADC的值清0
  ADC_CONTR=ADC_POWER | ADC_SPEEDLL;//打開ADC的電源 540個(gè)時(shí)鐘轉(zhuǎn)換一次
  delay_ms(2);//延遲2ms等待穩(wěn)定
}

u16 Get_ADC10bitResult(u8 channel) //獲取10位精度的ADC值
{
    u16        adc;
        u8        i;
        if(channel > 7)        return        1024;        //錯(cuò)誤,返回1024, ADC通道號(hào)0~7,不能超過7       
        ADC_RES = 0; //高位ADC清零
        ADC_RESL = 0;//低位ADC清零

        ADC_CONTR = (ADC_CONTR & 0xe0) | ADC_START | channel; //打開指定通道的ADC轉(zhuǎn)換
        _nop_();
        _nop_();
        _nop_();
        _nop_(); //對(duì)ADC_CONTR操作后要4T之后才能訪問

        for(i=0; i<250; i++)                //250us內(nèi)要轉(zhuǎn)換完成,否則超時(shí)跳出
        {
                if(ADC_CONTR & ADC_FLAG) //轉(zhuǎn)換完成后,ADC_FLAG=1,所以這里判斷ADC_FLAG是不是為1
                {
                        ADC_CONTR &= ~ADC_FLAG;        //ADC_FLAG手工清0
                        if(PCON2 &  (1<<5))//根據(jù)ADRJ判斷ADC轉(zhuǎn)換值放在哪里 如果是1               
                        {
                                adc = (u16)(ADC_RES & 3); //10位AD結(jié)果的高2位放ADC_RES的低2位,低8位在ADC_RESL。
                                adc = (adc << 8) | ADC_RESL;  //3=二進(jìn)制的11 &3是獲取低2位的值  <<8 | ADC_RESL 是獲取低8位的值
                        }
                        else                //10位AD結(jié)果的高8位放ADC_RES,低2位在ADC_RESL的低2位。
                        {
                                adc = (u16)ADC_RES;
                                adc = (adc << 2) | (ADC_RESL & 3);
                        }
                        return        adc;
                }
        }
        return        1024;        //如果超時(shí),返回1024,調(diào)用的程序判斷

}

/*******************************************
注意:下載時(shí),下載界面"硬件選項(xiàng)"中下面的項(xiàng)要固定如下設(shè)置:

不勾選        允許低壓復(fù)位(禁止低壓中斷)

                低壓檢測(cè)電壓 3.70V
               
                選擇CPU-CORE最高電壓  2.74V

******************************************
void CheckLiBattery()        //檢測(cè)電池電壓
{
    if(PCON & (1<<5))//檢測(cè)到低電壓
        {
          LED_Battery=1; //低壓報(bào)警LED燈亮
          TimeBEEP();         //蜂鳴器叫
        }
        else
        {
          LED_Battery=0; //關(guān)燈
        }
        PCON &= ~(1<<5);//低壓檢測(cè)標(biāo)志清0 ,為下次檢測(cè)做準(zhǔn)備
}
   */
//u8 GetNewYM(u8 ym,u8 minym,u8 maxym)//根據(jù)最大和最小油門,轉(zhuǎn)換到0~255范圍的新油門值
//{
//  //最小油門 中點(diǎn)值固定128 最大油門  轉(zhuǎn)為成0   128   255
////  return ym;
//  if(ym<128)return (ym-minym)*128/(128-minym); //等比例縮小
//  else
//  if(ym>128)return 127+(ym-128)*128/(maxym-128);//等比例放大
//  else
//  return 128;
//}

void GetNRFTxDate()       
{
  u8 fy,sj;
  recv_buf[0]=Get_ADC10bitResult(0)>>2;//P1.0 一通副翼 >>2的意思就是除以4  10位精度再轉(zhuǎn)8位的
  recv_buf[1]=Get_ADC10bitResult(1)>>2;//P1.1  二通升降
  recv_buf[2]=Get_ADC10bitResult(6)>>2;//P1.6  三通油門
  recv_buf[3]=Get_ADC10bitResult(7)>>2;//P1.7  四通方向
  recv_buf[4]=SW1;//P3.7  五通 開關(guān)通道
  recv_buf[5]=SW2;//P3.6  六通 開關(guān)通道

  fy=recv_buf[0];
  sj=recv_buf[1];

  if (SW_Mix1==0)//當(dāng)混控開關(guān)1打開
  {
      //這里混控可以根據(jù)混控開關(guān),做成副翼和升降混控  方向和油門插速混控等模式
            //我只設(shè)定了一個(gè)混控開關(guān),郁悶了�;炜匦问教啵瑔纹瑱C(jī)引腳不夠用了……你們自己改吧
          /*  混控一
            比如我改個(gè)副翼和升降的混控        也就是一通道和二通道進(jìn)行混控
                升降的時(shí)候,兩個(gè)舵機(jī)同一個(gè)方向
                副翼的時(shí)候,兩個(gè)舵機(jī)方向相反
          */

           /* 混控二
                 雙電機(jī)的飛機(jī),方向用電機(jī)差速控制,也就是副翼和油門的混控,一通道和三通道混控
                 加減油門,兩個(gè)舵機(jī)同一方向
                 副翼的時(shí)候,兩個(gè)舵機(jī)方向相反
          */
          
          //下面我只寫混控一,混控x之類的,大家可以模仿著寫。其實(shí)我也沒寫過。我連架紙飛機(jī)都沒。
          //先判斷是搖桿是升降還是副翼         加上75作為誤差值
          if (fy-pianyi>=128||fy+pianyi<=128)//副翼搖桿移動(dòng)
          {
            recv_buf[1]=255-fy;   //升降通道要反相
          };      

          //先判斷是搖桿是升降還是副翼
          if (sj-pianyi>=128||sj+pianyi<=128)//升降搖桿移動(dòng)
          {
                recv_buf[0]=sj;  //升降要同相
          };      

  }   
}


void Timer0Init(void)                //19毫秒@12.000MHz
{
        AUXR &= 0x7F;                //定時(shí)器時(shí)鐘12T模式
        TMOD &= 0xF0;                //設(shè)置定時(shí)器模式
        TL0 = 0xC8;                //設(shè)置定時(shí)初值
        TH0 = 0xB5;                //設(shè)置定時(shí)初值
        TF0 = 0;                //清除TF0標(biāo)志
        TR0 = 1;                //定時(shí)器0開始計(jì)時(shí)
    ET0 = 1;                //開通定時(shí)器0中斷
        EA  = 1;        //開啟全部中斷
}

/*void Timer2Init(void)                //10毫秒@12.000MHz
{
        AUXR &= 0xFB;                //定時(shí)器時(shí)鐘12T模式
        T2L = 0xF0;                //設(shè)置定時(shí)初值
        T2H = 0xD8;                //設(shè)置定時(shí)初值
        IE2 |=0x04;   //ET2=1         //允許定時(shí)器2的中斷
        EA  = 1;        //開啟全部中斷
        AUXR=0;//禁止定時(shí)器2運(yùn)行
        //AUXR |= 0x10;                //定時(shí)器2開始計(jì)時(shí)
}
   */

void main(void)
{
        delay_ms(100); // 延時(shí)待系統(tǒng)穩(wěn)定
        SW1=1;//初始化開關(guān)通道1
        SW2=1;//初始化開關(guān)通道2
        SW_Mix1=1;//初始化混控開關(guān)1
        LED_NRF=0;//關(guān)掉報(bào)警燈
//        LED_Battery=0;//關(guān)掉狀態(tài)燈
//        Beep=0;//關(guān)掉蜂鳴器
//        PCON &= ~(1<<5);//低壓檢測(cè)標(biāo)志清0, 上電時(shí)標(biāo)志為1
//        P3M0=0x10; //P3.4 推挽輸出,要不蜂鳴器聲音太小
        InitADC();//初始化ADC
//        SPI_Init(); // 初始化SPI口
        while(NRF24L01_Check())         // 等待檢測(cè)到NRF24L01,程序才會(huì)向下執(zhí)行
        {
           LED_NRF=1;//狀態(tài)LED燈常亮表示NRF24L01模塊出錯(cuò)。
        };
        NRF24L01_RT_Init(); // 配置NRF24L01為發(fā)射模式  
//        BEEP(250);//嗶嗶一聲表示OK
        Timer0Init();//定時(shí)器0初始化
  //        Timer2Init();//定時(shí)器2初始化
  while(1)
  {
//        CheckLiBattery();//檢測(cè)電池電壓
  };

}


//定時(shí)器0  用來發(fā)射6通道數(shù)據(jù)給接收器
void Timer0() interrupt 1
{
   GetNRFTxDate();        //查詢方式獲得4個(gè)通道ADC值和2個(gè)開關(guān)通道值
   TxAllCount++;        //總發(fā)射次數(shù)+1
   if(NRF24L01_TxPacket(recv_buf)==TX_OK)//如果發(fā)射沒有失敗
   {
             TxOKCount++; //發(fā)射成功次數(shù)+1
   }
   if (TxAllCount==50)        //發(fā)射50次以后,計(jì)算成功率
   {
          if (TxOKCount<40)//丟包大于80%,報(bào)警 如果接收器沒上電,也會(huì)報(bào)警
          {
                 LED_NRF=1;          //NRF模塊指示燈亮起
                 TimeBEEP();  //蜂鳴器報(bào)警
          }
          else
          {
             LED_NRF=0;         //關(guān)報(bào)警燈
          }

          TxAllCount=0;          //重置計(jì)數(shù)
          TxOKCount=0;
   }
}

//定時(shí)器2        功能就是讓蜂鳴器發(fā)出200毫秒的一個(gè)鳴叫,然后關(guān)掉。
/*void Timer2() interrupt 12          
{
  Time10Ms++;
  if(Time10Ms<=20) //開始叫
  {
     Beep=1;
  }
  if(Time10Ms>20)//超過200毫秒停叫
  {
     Beep=0;
  }
  if(Time10Ms>40)
  {
         Time10Ms=0;
         AUXR=0;//關(guān)掉定時(shí)器2
  }                  
}
         */


下面是接收 程序  

#include <reg51.h>
#include <intrins.h>

#define uchar unsigned char
#define uint  unsigned int
#define u8 unsigned char
#define u16  unsigned int
//STC12 系列新增寄存器
sfr IPH=0xb7;
sfr P4=0xc0;
sfr P4SW=0xbb;
sfr P1ASF=0x9d;
sfr P4M0=0xb4;
sfr P3M0=0xb2;
sfr P3M1=0xb1;
sfr P2M0=0x96;
sfr P0M0=0x94;
sfr ADC_CONTR=0xbc;
sfr ADC_RES=0xbd;
sfr ADC_RESL=0xbe;

sfr BRT=0x9c;
sfr AUXR=0x8e;
sfr WAKE_CLKO=0x8f;

sfr IAP_DATA=0xc2;
sfr IAP_ADDRH=0xc3;
sfr IAP_ADDRL=0xc4;
sfr IAP_CMD=0xc5;
sfr IAP_TRIG=0xc6;
sfr IAP_CONTR=0xc7;

sfr CCON        =   0xD8;           //PCA control register
sbit CCF0       =   CCON^0;         //PCA module-0 interrupt flag
sbit CCF1       =   CCON^1;         //PCA module-1 interrupt flag
sbit CR         =   CCON^6;         //PCA timer run control bit
sfr CMOD        =   0xD9;           //PCA mode register
sfr CL          =   0xE9;           //PCA base timer LOW
sfr CH          =   0xF9;           //PCA base timer HIGH
sfr CCAPM0      =   0xDA;           //PCA module-0 mode register
sfr CCAP0L      =   0xEA;           //PCA module-0 capture register LOW
sfr CCAP0H      =   0xFA;           //PCA module-0 capture register HIGH
sfr CCAPM1      =   0xDB;           //PCA module-1 mode registers
sfr CCAP1L      =   0xEB;           //PCA module-1 capture register LOW
sfr CCAP1H      =   0xFB;           //PCA module-1 capture register HIGH


/*************************************************/


/* STC15W404AS寄存器補(bǔ)充
sfr AUXR1 = 0XA2;
sfr AUXR = 0X8E;
sfr TH2 = 0XD6;
sfr TL2 = 0XD7;
sfr P4 = 0xc0;
sfr P5 = 0xc8;
sfr P3M0=0xB2;
sfr SPSTAT      =   0xCD;   //
sfr SPCTL       =   0xCE;   //
sfr SPDAT       =   0xCF;   //
sfr P1M0=0x92;
//ADC
sfr ADC_CONTR = 0xBC;        //帶AD系列
sfr ADC_RES   = 0xBD;        //帶AD系列
sfr ADC_RESL  = 0xBE;        //帶AD系列
sfr P1ASF = 0x9D;
sfr PCON2   = 0x97;

//定時(shí)器2
sfr T2H=0xd6;
sfr T2L=0xd7;
sfr IE2=0xaf;

#define ADC_POWER        0x80//ADC電源控制位
#define ADC_FLAG        0x10//ADC完成標(biāo)志
#define ADC_START        0x08//ADC起始控制位
#define ADC_SPEEDLL        0x00//540個(gè)時(shí)鐘轉(zhuǎn)換一次
#define ADC_SPEEDL        0x20//360時(shí)鐘
#define ADC_SPEEDH        0x40//180時(shí)鐘
#define ADC_SPEEDHH        0x60//90時(shí)鐘  */


unsigned char recv_buf[6]={0,0,0,0,1,1};//NRF24模塊可以一次發(fā)射32個(gè)字節(jié),這里只用6個(gè),代表6個(gè)通道。

/*sbit NRF_IRQ = P5^5;
sbit NRF_MISO = P1^4;
sbit NRF_MOSI = P1^3;
sbit NRF_SCK = P1^5;
sbit NRF_CSN = P1^2;
sbit NRF_CE = P5^4;         */

sbit NRF_CE = P0^1;
sbit NRF_CSN = P0^0;
sbit NRF_MISO = P0^5;
sbit NRF_MOSI = P0^2;
sbit NRF_SCK = P0^3;
sbit NRF_IRQ = P0^4;






sbit CH1=P3^2;//通道1
sbit CH2=P3^3;//通道2
sbit CH3=P3^6;//通道3
sbit CH4=P3^7;//通道4
sbit CH5=P1^0;//通道5
sbit CH6=P1^1;//通道6

u8 n=0;//定時(shí)器0的中斷次數(shù)

/**********  你可以從這里復(fù)制NRF24L01的全部代碼了  ***********/

/**********  NRF24L01寄存器操作命令  ***********/
#define READ_REG        0x00  //讀配置寄存器,低5位為寄存器地址
#define WRITE_REG       0x20  //寫配置寄存器,低5位為寄存器地址
#define RD_RX_PLOAD     0x61  //讀RX有效數(shù)據(jù),1~32字節(jié)
#define WR_TX_PLOAD     0xA0  //寫TX有效數(shù)據(jù),1~32字節(jié)
#define FLUSH_TX        0xE1  //清除TX FIFO寄存器.發(fā)射模式下用
#define FLUSH_RX        0xE2  //清除RX FIFO寄存器.接收模式下用
#define REUSE_TX_PL     0xE3  //重新使用上一包數(shù)據(jù),CE為高,數(shù)據(jù)包被不斷發(fā)送.
#define NRF_NOP         0xFF  //空操作,可以用來讀狀態(tài)寄存器         
/**********  NRF24L01寄存器地址   *************/
#define CONFIG          0x00  //配置寄存器地址                             
#define EN_AA           0x01  //使能自動(dòng)應(yīng)答功能
#define EN_RXADDR       0x02  //接收地址允許
#define SETUP_AW        0x03  //設(shè)置地址寬度(所有數(shù)據(jù)通道)
#define SETUP_RETR      0x04  //建立自動(dòng)重發(fā)
#define RF_CH           0x05  //RF通道
#define RF_SETUP        0x06  //RF寄存器
#define STATUS          0x07  //狀態(tài)寄存器
#define OBSERVE_TX      0x08  // 發(fā)送檢測(cè)寄存器
#define CD              0x09  // 載波檢測(cè)寄存器
#define RX_ADDR_P0      0x0A  // 數(shù)據(jù)通道0接收地址
#define RX_ADDR_P1      0x0B  // 數(shù)據(jù)通道1接收地址
#define RX_ADDR_P2      0x0C  // 數(shù)據(jù)通道2接收地址
#define RX_ADDR_P3      0x0D  // 數(shù)據(jù)通道3接收地址
#define RX_ADDR_P4      0x0E  // 數(shù)據(jù)通道4接收地址
#define RX_ADDR_P5      0x0F  // 數(shù)據(jù)通道5接收地址
#define TX_ADDR         0x10  // 發(fā)送地址寄存器
#define RX_PW_P0        0x11  // 接收數(shù)據(jù)通道0有效數(shù)據(jù)寬度(1~32字節(jié))
#define RX_PW_P1        0x12  // 接收數(shù)據(jù)通道1有效數(shù)據(jù)寬度(1~32字節(jié))
#define RX_PW_P2        0x13  // 接收數(shù)據(jù)通道2有效數(shù)據(jù)寬度(1~32字節(jié))
#define RX_PW_P3        0x14  // 接收數(shù)據(jù)通道3有效數(shù)據(jù)寬度(1~32字節(jié))
#define RX_PW_P4        0x15  // 接收數(shù)據(jù)通道4有效數(shù)據(jù)寬度(1~32字節(jié))
#define RX_PW_P5        0x16  // 接收數(shù)據(jù)通道5有效數(shù)據(jù)寬度(1~32字節(jié))
#define FIFO_STATUS     0x17  // FIFO狀態(tài)寄存器
/*————————————————————————————————————————————————————————————————————*/

/******   STATUS寄存器bit位定義      *******/
#define MAX_TX          0x10  //達(dá)到最大發(fā)送次數(shù)中斷
#define TX_OK           0x20  //TX發(fā)送完成中斷
#define RX_OK           0x40  //接收到數(shù)據(jù)中斷
/*——————————————————————————————————————————————————*/

/*********     24L01發(fā)送接收數(shù)據(jù)寬度定義          ***********/
#define TX_ADR_WIDTH    5   //5字節(jié)地址寬度
#define RX_ADR_WIDTH    5   //5字節(jié)地址寬度
#define TX_PLOAD_WIDTH  6  //32字節(jié)有效數(shù)據(jù)寬度
#define RX_PLOAD_WIDTH  6  //32字節(jié)有效數(shù)據(jù)寬度

uchar xdata TX_ADDRESS[TX_ADR_WIDTH]={0x68,0x86,0x66,0x88,0x28};
uchar xdata RX_ADDRESS[RX_ADR_WIDTH]={0x68,0x86,0x66,0x88,0x28};


void Delay1ms()                //@12.000MHz
{
        unsigned char i, j;

        i = 12;
        j = 169;
        do
        {
                while (--j);
        } while (--i);
}
void Delay4us()                //@12.000MHz
{
        unsigned char i;

        _nop_();
        _nop_();
        i = 9;
        while (--i);
}
void Delay_4us(unsigned char i)
{
  while(--i)
  {
    Delay4us();
  }
}

void delay_ms(unsigned char i)
{
   while(--i)
   {
         Delay1ms();
   }          
}

void DelayMs(unsigned int i)
{
   while(--i)
   {
         Delay1ms();
   }  
}



/* 初始化硬件SPI口    */
/*
void SPI_Init(void)        //如果用模擬SPI,這個(gè)就不要調(diào)用了,它是開啟硬件SPI
{
        SPSTAT |= 0xC0; //SPI狀態(tài)寄存器全部清0          SPIF和WCOL清0
        SPCTL = 0xD0;  //0xD0=11010000 ,表示SPI開啟,主機(jī)模式,SPI頻率為主頻四分之一
}

/**********************/
/* SPI數(shù)據(jù)收發(fā)函數(shù) 硬件SPI   */
/*
uchar SPI_RW(uchar tr_data)
{
        uchar i=0;
       
        SPSTAT |= 0xc0; //SPI狀態(tài)寄存器全部清0          SPIF和WCOL清0
        SPDAT=tr_data;  //將數(shù)據(jù)放到SPI數(shù)據(jù)寄存器中
        while(((SPSTAT&0x80)!=0x80)&&(i<20)) //SPSTAT&0x80 SPI數(shù)據(jù)傳輸完成標(biāo)志        如果沒完成傳輸,就延時(shí)1ms
        {
                i++;
                delay_ms(1);                                         //20ms內(nèi)沒完成,則跳出
        }
        return SPDAT;                                                 //返回傳輸?shù)臄?shù)據(jù)值
}         */

    //下面是“模擬SPI”
uchar SPI_RW(uchar byte)
{
        uchar bit_ctr;
        for(bit_ctr=0;bit_ctr<8;bit_ctr++) // 輸出8位
        {
                NRF_MOSI=(byte&0x80); // MSB TO MOSI
                byte=(byte<<1);        // shift next bit to MSB
                NRF_SCK=1;
                byte|=NRF_MISO;                // capture current MISO bit
                NRF_SCK=0;
        }
        return byte;
}


/*********************************************/
/* 函數(shù)功能:給24L01的寄存器寫值(一個(gè)字節(jié)) */
/* 入口參數(shù):reg   要寫的寄存器地址          */
/*           value 給寄存器寫的值            */
/* 出口參數(shù):status 狀態(tài)值                   */
/*********************************************/
uchar NRF24L01_Write_Reg(uchar reg,uchar value)
{
        uchar status;

        NRF_CSN=0;                  //CSN=0;   
          status = SPI_RW(reg);//發(fā)送寄存器地址,并讀取狀態(tài)值
        SPI_RW(value);
        NRF_CSN=1;                  //CSN=1;

        return status;
}
/*************************************************/
/* 函數(shù)功能:讀24L01的寄存器值 (一個(gè)字節(jié))      */
/* 入口參數(shù):reg  要讀的寄存器地址               */
/* 出口參數(shù):value 讀出寄存器的值                */
/*************************************************/
uchar NRF24L01_Read_Reg(uchar reg)
{
        uchar value;

        NRF_CSN=0;              //CSN=0;   
          SPI_RW(reg);//發(fā)送寄存器值(位置),并讀取狀態(tài)值
        value = SPI_RW(NRF_NOP);
        NRF_CSN=1;             //CSN=1;

        return value;
}
/*********************************************/
/* 函數(shù)功能:讀24L01的寄存器值(多個(gè)字節(jié))   */
/* 入口參數(shù):reg   寄存器地址                */
/*           *pBuf 讀出寄存器值的存放數(shù)組    */
/*           len   數(shù)組字節(jié)長(zhǎng)度              */
/* 出口參數(shù):status 狀態(tài)值                   */
/*********************************************/
uchar NRF24L01_Read_Buf(uchar reg,uchar *pBuf,uchar len)
{
        uchar status,u8_ctr;
        NRF_CSN=0;                   //CSN=0      
          status=SPI_RW(reg);//發(fā)送寄存器地址,并讀取狀態(tài)值             
        for(u8_ctr=0;u8_ctr<len;u8_ctr++)
        pBuf[u8_ctr]=SPI_RW(0XFF);//讀出數(shù)據(jù)
        NRF_CSN=1;                 //CSN=1
          return status;        //返回讀到的狀態(tài)值
}
/**********************************************/
/* 函數(shù)功能:給24L01的寄存器寫值(多個(gè)字節(jié))  */
/* 入口參數(shù):reg  要寫的寄存器地址            */
/*           *pBuf 值的存放數(shù)組               */
/*           len   數(shù)組字節(jié)長(zhǎng)度               */
/**********************************************/
uchar NRF24L01_Write_Buf(uchar reg, uchar *pBuf, uchar len)
{
        uchar status,u8_ctr;
        NRF_CSN=0;
          status = SPI_RW(reg);//發(fā)送寄存器值(位置),并讀取狀態(tài)值
          for(u8_ctr=0; u8_ctr<len; u8_ctr++)
        SPI_RW(*pBuf++); //寫入數(shù)據(jù)
        NRF_CSN=1;
          return status;          //返回讀到的狀態(tài)值
}                                                                                                    

uchar NRF24L01_Write_BufData(uchar reg, uchar *pBuf, uchar len) //為避免函數(shù)重入錯(cuò)誤而加的額外函數(shù)
{
        uchar status,u8_ctr;
        NRF_CSN=0;
          status = SPI_RW(reg);//發(fā)送寄存器值(位置),并讀取狀態(tài)值
          for(u8_ctr=0; u8_ctr<len; u8_ctr++)
        SPI_RW(*pBuf++); //寫入數(shù)據(jù)
        NRF_CSN=1;
          return status;          //返回讀到的狀態(tài)值
}
/*********************************************/
/* 函數(shù)功能:24L01接收數(shù)據(jù)                   */
/* 入口參數(shù):rxbuf 接收數(shù)據(jù)數(shù)組              */
/* 返回值: 0   成功收到數(shù)據(jù)                 */
/*          1   沒有收到數(shù)據(jù)                 */
/*********************************************/
uchar NRF24L01_RxPacket(uchar *rxbuf)
{
        uchar state;
         
        state=NRF24L01_Read_Reg(STATUS);  //讀取狀態(tài)寄存器的值             
        NRF24L01_Write_Reg(WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中斷標(biāo)志
        if(state&RX_OK)//接收到數(shù)據(jù)
        {
                NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//讀取數(shù)據(jù)
                NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
                return 0;
        }          
        return 1;//沒收到任何數(shù)據(jù)
}
/**********************************************/
/* 函數(shù)功能:設(shè)置24L01為發(fā)送模式              */
/* 入口參數(shù):txbuf  發(fā)送數(shù)據(jù)數(shù)組              */
/* 返回值; 0x10    達(dá)到最大重發(fā)次數(shù),發(fā)送失敗*/
/*          0x20    成功發(fā)送完成              */
/*          0xff    發(fā)送失敗                  */
/**********************************************/
uchar NRF24L01_TxPacket(uchar *txbuf)
{
        uchar state;
//        uchar i;

        NRF_CE=0;//CE拉低,使能24L01配置
          NRF24L01_Write_BufData(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//寫數(shù)據(jù)到TX BUF  32個(gè)字節(jié)
        NRF_CE=1;//CE置高,使能發(fā)送          
        while(NRF_IRQ==1);//等待發(fā)送完成
        state=NRF24L01_Read_Reg(STATUS);  //讀取狀態(tài)寄存器的值          
        NRF24L01_Write_Reg(WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中斷標(biāo)志
        if(state&MAX_TX)//達(dá)到最大重發(fā)次數(shù)
        {
                NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器
                return MAX_TX;
        }
        if(state&TX_OK)//發(fā)送完成
        {
                return TX_OK;
        }
        return 0xff;//發(fā)送失敗
}
/********************************************/
/* 函數(shù)功能:檢測(cè)24L01是否存在              */
/* 返回值;  0  存在                        */
/*           1  不存在                      */
/********************************************/
//檢測(cè)原理就是存入NRF模塊一段數(shù)據(jù),然后再讀出來比較一下是否一致
uchar NRF24L01_Check(void)
{
        uchar check_in_buf[5]={0x11,0x22,0x33,0x44,0x55};
        uchar check_out_buf[5]={0x00};

        NRF_CE=0;

        NRF24L01_Write_Buf(WRITE_REG+TX_ADDR, check_in_buf, 5);

        NRF24L01_Read_Buf(READ_REG+TX_ADDR, check_out_buf, 5);

        if((check_out_buf[0] == 0x11)&&\
           (check_out_buf[1] == 0x22)&&\
           (check_out_buf[2] == 0x33)&&\
           (check_out_buf[3] == 0x44)&&\
           (check_out_buf[4] == 0x55))return 0;
        else return 1;
}       

void NRF24L01_SET_TX_Mode(void)
{
        NRF_CE=0;
        NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0e); // 配置為無線發(fā)送模式
        NRF_CE=1;

}

void NRF24L01_SET_RX_Mode(void)
{
        NRF_CE=0;
        NRF24L01_Write_Reg(WRITE_REG+CONFIG, 0x0f); // 配置為無線接收模式
        NRF_CE=1;

}


void NRF24L01_RT_Init(void)          //NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0f); 接收是0x0f,記得修改
{       
        NRF_CE=0;                  
          NRF24L01_Write_Reg(WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//選擇通道0的有效數(shù)據(jù)寬度
        NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器   
          NRF24L01_Write_Buf(WRITE_REG+TX_ADDR,(uchar*)TX_ADDRESS,TX_ADR_WIDTH);//寫TX節(jié)點(diǎn)地址
          NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P0,(uchar*)RX_ADDRESS,RX_ADR_WIDTH); //設(shè)置TX節(jié)點(diǎn)地址,主要為了使能ACK          
          NRF24L01_Write_Reg(WRITE_REG+EN_AA,0x01);     //使能通道0的自動(dòng)應(yīng)答   
          NRF24L01_Write_Reg(WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址  
          NRF24L01_Write_Reg(WRITE_REG+SETUP_RETR,0x1a);//設(shè)置自動(dòng)重發(fā)間隔時(shí)間:500us + 86us;最大自動(dòng)重發(fā)次數(shù):10次
          NRF24L01_Write_Reg(WRITE_REG+RF_CH,40);       //設(shè)置RF通道為125
          NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x27);  //7db增益,250kbps
          NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0f);    //配置基本工作模式的參數(shù);PWR_UP,EN_CRC,16BIT_CRC,接收模式,開啟所有中斷
        NRF_CE=1;        //CE置高                          //0x0e發(fā)射 0x0f接收
}                                                                         //記得發(fā)送程序和接收程序的配置,要改0e和0f的數(shù)值,要不就要單獨(dú)要用一次發(fā)射或者接收設(shè)置。

/**********  NRF24L01的全部代碼復(fù)制完成了  ***********/

void Timer0Init(void)                //3毫秒@12.000MHz
{
        AUXR &= 0x7F;                //定時(shí)器時(shí)鐘12T模式
        TMOD &= 0xF0;                //設(shè)置定時(shí)器模式
        TL0 = 0x48;                //設(shè)置定時(shí)初值
        TH0 = 0xF4;                //設(shè)置定時(shí)初值
        TF0 = 0;                //清除TF0標(biāo)志
        TR0 = 1;                //定時(shí)器0開始計(jì)時(shí)
    ET0 = 1;                //開通定時(shí)器0中斷
        EA  = 1;        //開啟全部中斷
}

/*void Timer2Init(void)                //10毫秒@12.000MHz
{
        AUXR &= 0xFB;                //定時(shí)器時(shí)鐘12T模式
        T2L = 0xF0;                //設(shè)置定時(shí)初值
        T2H = 0xD8;                //設(shè)置定時(shí)初值
        IE2 |=0x04;   //ET2=1         //允許定時(shí)器2的中斷
        EA  = 1;        //開啟全部中斷
        AUXR=0;//禁止定時(shí)器2運(yùn)行
        //AUXR |= 0x10;                //定時(shí)器2開始計(jì)時(shí)

}
        */

void main(void)
{
        u16 i; //定義一個(gè)16位的計(jì)數(shù)變量
        delay_ms(100); // 延時(shí)待系統(tǒng)穩(wěn)定
//        P1M0=0x03;//P1.0 1 為強(qiáng)推挽,銀燕金屬舵機(jī),STC15W408如果不強(qiáng)推挽,動(dòng)都不動(dòng),折騰了我半夜
        P3M0=0xCC;//P3.2 3 6 7為強(qiáng)推挽,否則一些金屬舵機(jī)會(huì)驅(qū)動(dòng)不了,垃圾輝盛倒一點(diǎn)問題都沒
        //SPI_Init(); // 初始化硬件SPI,如果你用模擬SPI口,這個(gè)就不要調(diào)用
        while(NRF24L01_Check());         // 等待檢測(cè)到NRF24L01,程序才會(huì)向下執(zhí)行
        //如果NRF24L01模塊出錯(cuò),程序就卡死在這里了。沒引腳來做報(bào)警了,,,殘念。
        NRF24L01_RT_Init(); // 配置NRF24L01為接收模式  
        Timer0Init();//定時(shí)器0初始化
          //Timer2Init();//定時(shí)器2初始化
         

       
  while(1)
  {
    i++;        //每次累計(jì)大概1us
        if(NRF_IRQ==0)//查詢方式來接收數(shù)據(jù)
        {
          NRF24L01_RxPacket(recv_buf);//讀取數(shù)據(jù)
          i=0; //收到數(shù)據(jù)則清0累計(jì)值
        }
    /*if(i>60000)         //累計(jì)60000次是600ms,0.6秒的樣子。
        {                         //超過0.6秒收不到數(shù)據(jù),則改成平飛滑翔。聽天由命吧
                     //0~255對(duì)應(yīng)1ms~2sm,所以125就是1.5ms,置中
           recv_buf[0]=125;        //副翼舵機(jī)擺臂置90°  
           recv_buf[1]=125;        //升降舵機(jī)擺臂置90°
           recv_buf[2]=0;   //電調(diào)油門置0
           recv_buf[3]=125;        //方向舵機(jī)擺臂置90°
           recv_buf[4]=1;        //關(guān)掉開關(guān)通道1
           recv_buf[5]=1;        //關(guān)掉開關(guān)通道2
        } */
  }
}


//定時(shí)器0  
//這里和蘿莉一樣,還是用延時(shí)吧,雖然不是同步輸出,但是舵機(jī)理論上能達(dá)到250段分級(jí),移動(dòng)很平滑
//我用100us定時(shí)器同步輸出,只有10段分級(jí),移動(dòng)不平滑,如果分成100段,定時(shí)時(shí)間太短難以控制。
void Timer0() interrupt 1         //用定時(shí)器0輪流輸出6個(gè)通道的PPM
{
   n++; //定義的全局變量,用來做通道自增的
  if(n==6)n=0;//輪流輸出6通道信號(hào),整個(gè)周期18ms,反正PPM的20ms周期也不是那么嚴(yán)格
  if(recv_buf[0]==0)recv_buf[0]=1; //加1,防止延時(shí)的時(shí)候,0-1=255溢出
  if(recv_buf[1]==0)recv_buf[1]=1; //加1,防止延時(shí)的時(shí)候,0-1=255溢出
  if(recv_buf[2]==0)recv_buf[2]=1; //加1,防止延時(shí)的時(shí)候,0-1=255溢出
  if(recv_buf[3]==0)recv_buf[3]=1; //加1,防止延時(shí)的時(shí)候,0-1=255溢出
  switch(n)
        {        //每個(gè)通道固定1ms高電平,然后根據(jù)通道的ADC,延時(shí)4us*通道AD值的高電平,然后改成低低電平。
            //通道AD值的范圍是0~255,所以延時(shí)的電平時(shí)間就是1ms+0~1ms+4*255us,即1ms~2ms高電平 255約等于250
                //實(shí)際應(yīng)用中,舵機(jī)用1ms~2ms的高電平來控制,而不是理論上的0.5~2.5ms
                //舵機(jī)的擺臂范圍是45°~90°~135°之間移動(dòng)。分別對(duì)應(yīng)1ms~ 1.5ms~ 2ms高電平
                case 0:CH1=1,Delay1ms(),Delay_4us(recv_buf[0]),CH1=0;break;//1通道PPM輸出  副翼
                case 1:CH2=1,Delay1ms(),Delay_4us(recv_buf[1]),CH2=0;break;//2通道PPM輸出  升降
                case 2:CH3=1,Delay1ms(),Delay_4us(recv_buf[2]),CH3=0;break;//3通道PPM輸出  油門
                case 3:CH4=1,Delay1ms(),Delay_4us(recv_buf[3]),CH4=0;break;//4通道PPM輸出  方向
                case 4:         //5通道開關(guān)通道 1ms高電平是關(guān)  2ms高電平是開
                {
                  CH5=1;
                  Delay1ms();//固定1ms高電平
                  if(recv_buf[4]==0)Delay_4us(250);//0表示通道開,1表示通道關(guān)
                  CH5=0;
                  break;  
                  
                }
                case 5: //6通道開關(guān)通道 1ms高電平是關(guān)  2ms高電平是開
                {
                  CH6=1;
                  Delay1ms();//固定1ms高電平
                  if(recv_buf[5]==0)Delay_4us(250);//0表示通道開,1表示通道關(guān)
                  CH6=0;
                  break;

               
          
                 }
        }
}

//定時(shí)器2  沒用,空著吧
//void Timer2() interrupt 12
//{
                
//}



照片 214.jpg (1.95 MB, 下載次數(shù): 87)

照片 214.jpg

照片 212.jpg (2.15 MB, 下載次數(shù): 75)

照片 212.jpg

照片 213.jpg (1.99 MB, 下載次數(shù): 69)

照片 213.jpg

照片 169.jpg (2.11 MB, 下載次數(shù): 47)

照片 169.jpg
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:79544 發(fā)表于 2018-10-8 17:52 | 只看該作者
樓主強(qiáng)大頂起。感謝分享�。。。。。。�!
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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