基於NRF24L01的無線通訊


一、 NRF24L01的 簡介

  NRF24L01無線模塊,采用的芯片是 NRF24L01 ,該芯片的主要特點如下

  1. 2.4G 全球開放的 ISM 頻段,免許可證使用。
  2. 最高工作速率 2Mbps ,高校的 GFSK 調制,抗干擾能力強。
  3. 125 個可選的頻道,滿足多點通信和調頻通信的需要。
  4. 內置 CRC 檢錯和點對多點的通信地址控 制。
  5. 低工作電壓 1.9~3.6V )。
  6. 可設置自動應答,確保數 據可靠傳輸。

  該芯片通過SPI 與外部 MCU 通信,最大的 SPI 速度可以達到 10Mhz 。本章我們用到的模
塊是深圳雲佳科技生產的 NRF24L01 ,該模塊已經被很多公司大量使用,成熟度和穩定性都是
相當不錯的。該模塊的外形和引腳圖如圖 36. 1.1 所示:
    

                36. 1.1 NRF24L01 無線模塊外觀引腳圖模塊
VCC 腳的電壓范圍為 1.9~3.6V ,建議不要超過 3.6V ,否則可能燒壞模塊,一般用 3.3V
電壓比較合適。除了 VCC 和 GND 腳,其他引腳都 可以和 5V 單片機的 IO 口直連,正是因為其
兼容 5V 單片機的 IO ,故使用上 具有很大優勢。
關於
NRF24L01 的詳細介紹,請參考 NRF24L01 的技術手冊。

 

二、硬件連接

硬件資源:
1,DS0(連接在PB5)
2,串口1(波特率:115200,PA9/PA10連接在板載USB轉串口芯片CH340上面)
3,ALIENTEK 2.8/3.5/4.3/7寸TFTLCD模塊(通過FSMC驅動,FSMC_NE4接LCD片選/A10接RS)
4,KEY0按鍵(連接在PE4)/KEY1按鍵(連接在PE3)
5,NRF24L01模塊(SPI2(PB13/PB14/PB15)/IRQ(PG6)/CS(PG7)/CE(PG8)).

 

 

三、軟件設計

要實現的功能:對NRF24L01模塊進行初步測試,即一塊帶有NRF24L01無線模塊的開發板按下KEY0進入接收模式,另一塊帶有NRF24L01無線模塊的開發板按下KEY1進入發送模式,並同時在發送開發板和接收開發板上的TFTLCD上顯示發送或者接收的數據。

在開發無線功能之前,我們先理清思路:

要實現NRF24L01模塊==〉

要先通過MCU(即主控芯片STM32f103ZET6)和NRF24L01模塊建立連接==>

SPI,通過SPI交流數據,對NRF24L01的參數進行配置==〉

配置好之后,發送的開發板才可發送數據到NRF24L01的調頻器===〉

接收的開發板需要NRF24L01的解調器,轉換成可被開發板識別的模擬信號

要實現以上功能,主要需要LCD、KEY、LED,USART,關鍵是SPI和NRF24L01

由於LCD、KEY、LED、USART的運用過於簡單,這里就不啰嗦了,大家來看一下SPI函數吧!

#ifndef __SPI_H
#define __SPI_H
#include "sys.h"                                                                              
void SPI2_Init(void);             //初始化SPI口
void SPI2_SetSpeed(u8 SpeedSet); //設置SPI速度   
u8 SPI2_ReadWriteByte(u8 TxData);//SPI總線讀寫一個字節
#endif
#include "spi.h"

void SPI2_Init(void)
{
     GPIO_InitTypeDef GPIO_InitStructure;
      SPI_InitTypeDef  SPI_InitStructure;

    RCC_APB2PeriphClockCmd(    RCC_APB2Periph_GPIOB, ENABLE );//PORTB時鍾使能 (SPI2(PB13/PB14/PB15)
    RCC_APB1PeriphClockCmd(    RCC_APB1Periph_SPI2,  ENABLE );//SPI2時鍾使能    SPI2(SCK/MISO/MOSI) 
 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //PB13/14/15復用推挽輸出 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB

     GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);  //PB13/14/15上拉

    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //設置SPI單向或者雙向的數據模式:SPI設置為雙線雙向全雙工
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;        //設置SPI工作模式:設置為主SPI
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;        //設置SPI的數據大小:SPI發送接收8位幀結構
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;        //串行同步時鍾的空閑狀態為高電平
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;    //串行同步時鍾的第二個跳變沿(上升或下降)數據被采樣
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;        //NSS信號由硬件(NSS管腳)還是軟件(使用SSI位)管理:內部NSS信號有SSI位控制
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;        //定義波特率預分頻的值:波特率預分頻值為256
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;    //指定數據傳輸從MSB位還是LSB位開始:數據傳輸從MSB位開始
    SPI_InitStructure.SPI_CRCPolynomial = 7;    //CRC值計算的多項式
    SPI_Init(SPI2, &SPI_InitStructure);  //根據SPI_InitStruct中指定的參數初始化外設SPIx寄存器
 
    SPI_Cmd(SPI2, ENABLE); //使能SPI外設
    
    SPI2_ReadWriteByte(0xff);//啟動傳輸         
 

}   
//SPI 速度設置函數
//SpeedSet:
//SPI_BaudRatePrescaler_2   2分頻   
//SPI_BaudRatePrescaler_8   8分頻   
//SPI_BaudRatePrescaler_16  16分頻  
//SPI_BaudRatePrescaler_256 256分頻 
  
void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler)
{
      assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));
    SPI2->CR1&=0XFFC7;
    SPI2->CR1|=SPI_BaudRatePrescaler;    //設置SPI2速度 
    SPI_Cmd(SPI2,ENABLE); 

} 

//SPIx 讀寫一個字節
//TxData:要寫入的字節
//返回值:讀取到的字節
u8 SPI2_ReadWriteByte(u8 TxData)
{        
    u8 retry=0;                     
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //檢查指定的SPI標志位設置與否:發送緩存空標志位
        {
        retry++;
        if(retry>200)return 0;
        }              
    SPI_I2S_SendData(SPI2, TxData); //通過外設SPIx發送一個數據
    retry=0;

    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)//檢查指定的SPI標志位設置與否:接受緩存非空標志位
        {
        retry++;
        if(retry>200)return 0;
        }                                  
    return SPI_I2S_ReceiveData(SPI2); //返回通過SPIx最近接收的數據                        
}

spi.c里面主要是spi初始化函數void SPI2_Init(void)、spi速度設置函數void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler)和spi讀寫函數

u8 SPI2_ReadWriteByte(u8 TxData)。其中值得注意的是,但無線通訊NRF24L01進行通訊時,要通過SPI2_SetSpeed函數把速度

降低到10MHZ以下,不然NRF24L01將無法通訊。

 

接下來是NRF24L01的函數相關介紹

#ifndef __24L01_H
#define __24L01_H               
#include "sys.h"   
   
//NRF24L01寄存器操作命令
#define NRF_READ_REG    0x00  //讀配置寄存器,低5位為寄存器地址
#define NRF_WRITE_REG   0x20  //寫配置寄存器,低5位為寄存器地址
#define RD_RX_PLOAD     0x61  //讀RX有效數據,1~32字節
#define WR_TX_PLOAD     0xA0  //寫TX有效數據,1~32字節
#define FLUSH_TX        0xE1  //清除TX FIFO寄存器.發射模式下用
#define FLUSH_RX        0xE2  //清除RX FIFO寄存器.接收模式下用
#define REUSE_TX_PL     0xE3  //重新使用上一包數據,CE為高,數據包被不斷發送.
#define NOP             0xFF  //空操作,可以用來讀狀態寄存器     
//SPI(NRF24L01)寄存器地址
#define CONFIG          0x00  //配置寄存器地址;bit0:1接收模式,0發射模式;bit1:電選擇;bit2:CRC模式;bit3:CRC使能;
                              //bit4:中斷MAX_RT(達到最大重發次數中斷)使能;bit5:中斷TX_DS使能;bit6:中斷RX_DR使能
#define EN_AA           0x01  //使能自動應答功能  bit0~5,對應通道0~5
#define EN_RXADDR       0x02  //接收地址允許,bit0~5,對應通道0~5
#define SETUP_AW        0x03  //設置地址寬度(所有數據通道):bit1,0:00,3字節;01,4字節;02,5字節;
#define SETUP_RETR      0x04  //建立自動重發;bit3:0,自動重發計數器;bit7:4,自動重發延時 250*x+86us
#define RF_CH           0x05  //RF通道,bit6:0,工作通道頻率;
#define RF_SETUP        0x06  //RF寄存器;bit3:傳輸速率(0:1Mbps,1:2Mbps);bit2:1,發射功率;bit0:低噪聲放大器增益
#define STATUS          0x07  //狀態寄存器;bit0:TX FIFO滿標志;bit3:1,接收數據通道號(最大:6);bit4,達到最多次重發
                              //bit5:數據發送完成中斷;bit6:接收數據中斷;
#define MAX_TX          0x10  //達到最大發送次數中斷
#define TX_OK           0x20  //TX發送完成中斷
#define RX_OK           0x40  //接收到數據中斷

#define OBSERVE_TX      0x08  //發送檢測寄存器,bit7:4,數據包丟失計數器;bit3:0,重發計數器
#define CD              0x09  //載波檢測寄存器,bit0,載波檢測;
#define RX_ADDR_P0      0x0A  //數據通道0接收地址,最大長度5個字節,低字節在前
#define RX_ADDR_P1      0x0B  //數據通道1接收地址,最大長度5個字節,低字節在前
#define RX_ADDR_P2      0x0C  //數據通道2接收地址,最低字節可設置,高字節,必須同RX_ADDR_P1[39:8]相等;
#define RX_ADDR_P3      0x0D  //數據通道3接收地址,最低字節可設置,高字節,必須同RX_ADDR_P1[39:8]相等;
#define RX_ADDR_P4      0x0E  //數據通道4接收地址,最低字節可設置,高字節,必須同RX_ADDR_P1[39:8]相等;
#define RX_ADDR_P5      0x0F  //數據通道5接收地址,最低字節可設置,高字節,必須同RX_ADDR_P1[39:8]相等;
#define TX_ADDR         0x10  //發送地址(低字節在前),ShockBurstTM模式下,RX_ADDR_P0與此地址相等
#define RX_PW_P0        0x11  //接收數據通道0有效數據寬度(1~32字節),設置為0則非法
#define RX_PW_P1        0x12  //接收數據通道1有效數據寬度(1~32字節),設置為0則非法
#define RX_PW_P2        0x13  //接收數據通道2有效數據寬度(1~32字節),設置為0則非法
#define RX_PW_P3        0x14  //接收數據通道3有效數據寬度(1~32字節),設置為0則非法
#define RX_PW_P4        0x15  //接收數據通道4有效數據寬度(1~32字節),設置為0則非法
#define RX_PW_P5        0x16  //接收數據通道5有效數據寬度(1~32字節),設置為0則非法
#define NRF_FIFO_STATUS 0x17  //FIFO狀態寄存器;bit0,RX FIFO寄存器空標志;bit1,RX FIFO滿標志;bit2,3,保留
                              //bit4,TX FIFO空標志;bit5,TX FIFO滿標志;bit6,1,循環發送上一數據包.0,不循環;
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//24L01操作線
#define NRF24L01_CE   PGout(8) //24L01片選信號
#define NRF24L01_CSN  PGout(7) //SPI片選信號       
#define NRF24L01_IRQ  PGin(6)  //IRQ主機數據輸入
//24L01發送接收數據寬度定義
#define TX_ADR_WIDTH 5
#define RX_ADR_WIDTH 5
#define RD_RX_PLOAD_WIDTH 32
#define WR_TX_PLOAD_WIDTH 32
void NRF24L01_Init(void);
u8 NRF24L01_Write_Reg(u8 Reg,u8 Value);
u8 NRF24L01_Read_Reg(u8 Reg);
u8 NRF24L01_Check(void);
u8 NRF24L01_WriteBuf(u8 WriteAddr,u8* pBuf,u8 len);
u8 NRF24L01_ReadBuf(u8 ReadAddr,u8* pBuf,u8 len);

void NRF24L01_RX_Mode(void);
u8 NRF24L01_RxPacket(u8* tem_buf);
void NRF24L01_TX_Mode(void);
u8 NRF24L01_TxPacket(u8* tem_buf);
#endif
#include "spi.h"
#include "24l01.h"
const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x44,0x41,0x20,0x10,0x02}; // 發送地址
const u8 RX_ADDRESS[RX_ADR_WIDTH]={0x44,0x41,0x20,0x10,0x02}; // 發送地址

void NRF24L01_Init(void)
{
    GPIO_InitTypeDef GPIO_InitType;
    SPI_InitTypeDef SPI_InitType;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOG,ENABLE);
    
    GPIO_InitType.GPIO_Pin = GPIO_Pin_12;                                 //PB12上拉 防止W25X的干擾
     GPIO_InitType.GPIO_Mode = GPIO_Mode_Out_PP;                      //推挽輸出
     GPIO_InitType.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_Init(GPIOB, &GPIO_InitType);    //初始化指定IO
     GPIO_SetBits(GPIOB,GPIO_Pin_12);//上拉
    
    GPIO_InitType.GPIO_Pin=GPIO_Pin_7|GPIO_Pin_8;        //IRQ(PG6)/CS(PG7)/CE(PG8) 
    GPIO_InitType.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitType.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOG,&GPIO_InitType);
    
    GPIO_InitType.GPIO_Pin=GPIO_Pin_6;
    GPIO_InitType.GPIO_Mode=GPIO_Mode_IPD;
    GPIO_Init(GPIOG,&GPIO_InitType);
    GPIO_ResetBits(GPIOG,GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8);
    
    SPI2_Init();            //SPI 初始化
    SPI_Cmd(SPI2,DISABLE);
    SPI_InitType.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_16;
    SPI_InitType.SPI_CPHA=SPI_CPHA_1Edge;
    SPI_InitType.SPI_CPOL=SPI_CPOL_Low;
    SPI_InitType.SPI_CRCPolynomial=0x7;
    SPI_InitType.SPI_DataSize=SPI_DataSize_8b;
    SPI_InitType.SPI_Direction=SPI_Direction_2Lines_FullDuplex;
    SPI_InitType.SPI_FirstBit=SPI_FirstBit_MSB;
    SPI_InitType.SPI_Mode=SPI_Mode_Master;
    SPI_InitType.SPI_NSS=SPI_NSS_Soft;
    SPI_Init(SPI2,&SPI_InitType);
    SPI_Cmd(SPI2,ENABLE);
    NRF24L01_CSN=1;
    NRF24L01_CE=0;
}


//檢查是否有RF24L01這個器件
//給TX_ADDR寄存器寫入5個字節的地址,然后在讀取TX_ADDR 寄存器的值
//比較是否各個都是0xA5,假如不是返回非0值,否則返回0(正確時)
u8 NRF24L01_Check(void)
{

    u8 i=0;
    u8 Buf[5]={0xA5,0xA5,0xA5,0xA5,0xA5};
    SPI2_SetSpeed(SPI_BaudRatePrescaler_4);
    NRF24L01_WriteBuf(NRF_WRITE_REG+TX_ADDR,Buf,5);
    NRF24L01_ReadBuf(NRF_READ_REG+TX_ADDR,Buf,5);
    for(i=0;i<5;i++)
    {
        if(Buf[i]!=0xA5) break;
    }
    if(i!=5) return 1;
    return 0;    
}




    
//給那個寄存器寫入一個值
u8 NRF24L01_Write_Reg(u8 Reg,u8 Value)
{
    u8 status;
    NRF24L01_CSN=0;
    status=SPI2_ReadWriteByte(Reg);
    SPI2_ReadWriteByte(Value);
    NRF24L01_CSN=1;
    return status;
}


//從那個寄存器讀取一個值
u8 NRF24L01_Read_Reg(u8 Reg)
{
    u8 reg_val;
    NRF24L01_CSN=0;
    SPI2_ReadWriteByte(Reg);
    reg_val=SPI2_ReadWriteByte(0xFF);
    NRF24L01_CSN=1;
    return reg_val;
}

//給那個寄存器寫入一些數據
u8 NRF24L01_WriteBuf(u8 WriteAddr,u8* pBuf,u8 len)
{
    u8 status,i=0;
    NRF24L01_CSN=0;
    status=SPI2_ReadWriteByte(WriteAddr);
    for(i=0;i<len;i++)
    {
        SPI2_ReadWriteByte(*pBuf++);
    }
    NRF24L01_CSN=1;
    return status;
}

//讀取那個寄存器的一些數據
u8 NRF24L01_ReadBuf(u8 ReadAddr,u8* pBuf,u8 len)
{
    u8 status,i=0;
    NRF24L01_CSN=0;
    status=SPI2_ReadWriteByte(ReadAddr);
    for(i=0;i<len;i++)
    {
        pBuf[i]=SPI2_ReadWriteByte(0xFF);
    }
    NRF24L01_CSN=1;
    return status;
}

void NRF24L01_RX_Mode(void)
{
    NRF24L01_CE=0;
    NRF24L01_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);//給接收地址寫入數據
    NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);                    //使能通道0自動應答功能
    NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);            //使能通道0地址接受允許
    NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,0x40);                    //設置通道接受的頻段(共有125個可選的頻段)
    NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RD_RX_PLOAD_WIDTH);//選擇通道0的有效數據寬度
    NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);            //設置通道的發射功率及速度
    NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0f);                //屏蔽中斷及模式
    NRF24L01_CE=1;

}
    

u8 NRF24L01_RxPacket(u8* tem_buf)
{
    u8 sta;
    SPI2_SetSpeed (SPI_BaudRatePrescaler_8);// 36/8=4.5Mhz
    sta=NRF24L01_Read_Reg(STATUS);                    //讀取接收狀態
    NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta);    //寫入‘1’取消中斷
    if(sta&RX_OK)                                                        //假如是發送完成中斷,則開始接收
    {
        NRF24L01_ReadBuf(RD_RX_PLOAD,tem_buf,RD_RX_PLOAD_WIDTH);
//        while(NRF24L01_IRQ!=0);                                     //等待接收完成
        NRF24L01_Write_Reg(FLUSH_RX,0xFF);                //接收之后開始清除接收BUFF
        return 0;
    }
    return 1;
}


void NRF24L01_TX_Mode(void)
{

        NRF24L01_CE=0;        
      NRF24L01_WriteBuf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//寫TX節點地址 
      NRF24L01_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); //設置TX節點地址,主要為了使能ACK      

      NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);     //使能通道0的自動應答    
      NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址  
      NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);//設置自動重發間隔時間:500us + 86us;最大自動重發次數:10次
      NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,0x40);       //設置RF通道為40
      NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);  //設置TX發射參數,0db增益,2Mbps,低噪聲增益開啟   
      NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e);    //配置基本工作模式的參數;PWR_UP,EN_CRC,16BIT_CRC,接收模式,開啟所有中斷
        NRF24L01_CE=1;//CE為高,10us后啟動發送
}

u8 NRF24L01_TxPacket(u8* tem_buf)
{
    u8 sta;
    SPI2_SetSpeed (SPI_BaudRatePrescaler_8);    // 4.5Mhz
    NRF24L01_CE=0;
    NRF24L01_WriteBuf(WR_TX_PLOAD,tem_buf,WR_TX_PLOAD_WIDTH);
    NRF24L01_CE=1;                                                         //啟動發送
    while(NRF24L01_IRQ!=0);                                     //等待發送完成
    sta=NRF24L01_Read_Reg(STATUS);    
    NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta);    //讀取狀態值后清除發送中斷或者重發超限中斷
    if(sta&MAX_TX)
    {
        NRF24L01_Write_Reg(FLUSH_TX,0xFF);                    //重發次數超限,則清理發送BUFF,重新開始發送並計數
        return MAX_TX;
    }
    if(sta&TX_OK)
    {
        return TX_OK;                                                            //發送中斷則返回中斷標志
    }
    return 0xff;                                                                //其他情況返回錯誤標志0xFF
}

 

四、在main函數中的運用

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"     
#include "24l01.h"      
#include "math.h"
#include "string.h"
/************************************************
 ALIENTEK精英STM32開發板實驗31
 MPU6050六軸傳感器 實驗     
 技術支持:www.openedv.com
 淘寶店鋪:http://eboard.taobao.com 
 關注微信公眾平台微信號:"正點原子",免費獲取STM32資料。
 廣州市星翼電子科技有限公司  
 作者:正點原子 @ALIENTEK
************************************************/
u8 rx_buf[32]={49,50,51,52,53,54,55,56,57,58,49,50,51,52,53,54,55,56,57,58,49,50,51,52,53,54,55,56,57,58,61,0};


 int main(void)
 {    
    u8 i=0;
    u8 key,mode;
    u16 t=0;             
    u8 tmp_buf[33];            
    delay_init();             //延時函數初始化      
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設置中斷優先級分組為組2:2位搶占優先級,2位響應優先級
    uart_init(115200);         //串口初始化為115200
     LED_Init();                      //初始化與LED連接的硬件接口
    KEY_Init();                    //初始化按鍵
    LCD_Init();                       //初始化LCD  
     NRF24L01_Init();            //初始化NRF24L01 
     POINT_COLOR=RED;            //設置字體為紅色 
    LCD_ShowString(30,50,200,16,16,"ELITE STM32");    
    LCD_ShowString(30,70,200,16,16,"NRF24L01 TEST");    
    LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
    LCD_ShowString(30,110,200,16,16,"2015/1/17"); 
    while(NRF24L01_Check())
    {
        LCD_ShowString(30,130,200,16,16,"NRF24L01 Error");
        delay_ms(200);
        LCD_Fill(30,130,239,130+16,WHITE);
         delay_ms(200);
    }
    LCD_ShowString(30,130,200,16,16,"NRF24L01 OK");      
     while(1)
    {    
        key=KEY_Scan(0);
        if(key==KEY0_PRES)
        {
            mode=0;   
            break;
        }else if(key==KEY1_PRES)
        {
            mode=1;
            break;
        }
        t++;
        if(t==100)LCD_ShowString(10,150,230,16,16,"KEY0:RX_Mode  KEY1:TX_Mode"); //閃爍顯示提示信息
         if(t==200)
        {    
            LCD_Fill(10,150,230,150+16,WHITE);
            t=0; 
        }
        delay_ms(5);      
    }   
     LCD_Fill(10,150,240,166,WHITE);//清空上面的顯示          
     POINT_COLOR=BLUE;//設置字體為藍色       
    if(mode==0)//RX模式
    {
        LCD_ShowString(30,150,200,16,16,"NRF24L01 RX_Mode");    
        LCD_ShowString(30,170,200,16,16,"Received DATA:");    
        NRF24L01_RX_Mode();          
        while(1)
        {                                               
            if(NRF24L01_RxPacket(rx_buf)==0)//一旦接收到信息,則顯示出來.
            {
                LCD_ShowString(0,190,lcddev.width-1,32,16,rx_buf); //接收到數據就在LCD上顯示出來
                delay_ms(500);                                                                            //半秒之后清除接收到的數據
                memset(rx_buf,0,32);
                break;                                                                                        //跳出循環體
            }else delay_us(100);                                               //接收失敗,延時100us
            t++;
            if(t==10000)//大約1s鍾改變一次狀態
            {
                t=0;
                LED0=!LED0;
            }                     
        };    

    }else//TX模式
    {                                
        LCD_ShowString(30,150,200,16,16,"NRF24L01 TX_Mode");    
        NRF24L01_TX_Mode();
        mode=' ';//從空格鍵開始  
        while(1)
        {                                  
            if(NRF24L01_TxPacket(rx_buf)==TX_OK)                    //發送成功
            {
                
                LCD_ShowString(30,170,239,32,16,"Sended DATA:");        //顯示發送的數據
                LCD_ShowString(0,190,lcddev.width-1,32,16,rx_buf);
                delay_ms(500);                                                                            //延時500ms
                i++;
                printf("TXText%d",i);                                                                //串口1調試用,可看出本次是第幾次發送
                break;
                
            }else
            {                                               
                 LCD_Fill(0,170,lcddev.width,170+16*3,WHITE);//清空顯示               
                LCD_ShowString(30,170,lcddev.width-1,32,16,"Send Failed "); 
            };
            LED0=!LED0;
            delay_ms(1500);                    
        };
    } 
}

調試過程中,出現問題:

按下KEY0按鍵可進入接收模式,按下KEY1按鍵可進入發送模式,可是前兩次進入發送模式之后,break可打破while(1)發送循環體,使發送完數據就退出發送循環函數,怎么第3次就退不出來了?

留待以后思考:

現在,我覺得主要是不是break不能打破並離開循環體呢?可是前面2次都可以通過break離開循環體,這就奇怪了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM