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

QQ登錄

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

搜索
查看: 1619|回復(fù): 2
打印 上一主題 下一主題
收起左側(cè)

NRF24L01使用問(wèn)題 附單片機(jī)代碼

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:985217 發(fā)表于 2022-3-9 21:53 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
NRF24L01使用出了問(wèn)題,但找不到原因,發(fā)此帖向各位前輩請(qǐng)教一下
需求:采用NRF24L01作無(wú)線傳輸,接收端接收到特定數(shù)組,蜂鳴器就會(huì)響,當(dāng)接收到數(shù)組不為此數(shù)組時(shí),蜂鳴器關(guān)閉
問(wèn)題:接收端不能正常工作
部分代碼如下:

(一)NRF24L01配置
  1. #include "bsp_spi_nrf.h"

  2. u8 RX_BUF[RX_PLOAD_WIDTH];                //接收數(shù)據(jù)緩存
  3. u8 TX_BUF[TX_PLOAD_WIDTH];                //發(fā)射數(shù)據(jù)緩存
  4. u8 TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};  // 定義一個(gè)靜態(tài)發(fā)送地址
  5. u8 RX_ADDRESS[RX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};

  6. void Delay(__IO u32 nCount)
  7. {
  8.   for(; nCount != 0; nCount--);
  9. }


  10. /*------------------------------------------------------------SPI的 I/O配置-------------------------------------------------------------------*/
  11. void SPI_NRF_Init(void)
  12. {
  13.   SPI_InitTypeDef  SPI_InitStructure;
  14.   GPIO_InitTypeDef GPIO_InitStructure;

  15.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA
  16.                          |NRF_CSN_GPIO_CLK
  17.                          |NRF_CE_GPIO_CLK
  18.                          |NRF_IRQ_GPIO_CLK,ENABLE);

  19.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

  20.   /*SCK,MISO,MOSI引腳(PA5,PA6,PA7)*/
  21.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
  22.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  23.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用功能
  24.   GPIO_Init(GPIOA, &GPIO_InitStructure);  

  25.   /*CSN引腳*/
  26.   GPIO_InitStructure.GPIO_Pin = NRF_CSN_PIN;
  27.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  28.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  29.   GPIO_Init(NRF_CSN_GPIO_PORT, &GPIO_InitStructure);

  30.   /*CE引腳*/  
  31.   GPIO_InitStructure.GPIO_Pin = NRF_CE_PIN;
  32.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  33.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  34.   GPIO_Init(NRF_CE_GPIO_PORT, &GPIO_InitStructure);


  35.   /*IRQ引腳*/
  36.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
  37.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  38.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;  //上拉輸入
  39.   GPIO_Init(NRF_IRQ_GPIO_PORT, &GPIO_InitStructure);
  40.                   
  41.   NRF_CSN_HIGH(); //拉高csn引腳,NRF進(jìn)入空閑狀態(tài)

  42.   /*配置SPI*/
  43.   SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;           //雙線全雙工
  44.   SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                                                            //主模式
  45.   SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                                                    //數(shù)據(jù)大小8位
  46.   SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                                                        //時(shí)鐘極性,空閑時(shí)為低
  47.   SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;                                                           //第1個(gè)邊沿有效,上升沿為采樣時(shí)刻
  48.   SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                                                                      //NSS信號(hào)由軟件產(chǎn)生
  49.   SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;           //8分頻,9MHz
  50.   SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                                             //高位在前
  51.   SPI_InitStructure.SPI_CRCPolynomial = 7;
  52.   SPI_Init(SPI1, &SPI_InitStructure);

  53.   SPI_Cmd(SPI1, ENABLE);//使能SPI
  54. }

  55. /*----------------------------------------------------向NRF讀/寫一字節(jié)數(shù)據(jù)--------------------------------------------------------------*/
  56. u8 SPI_NRF_RW(u8 dat)
  57. {         

  58.   while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);     //當(dāng)SPI發(fā)送緩沖器非空時(shí)等待
  59.   SPI_I2S_SendData(SPI1, dat);                                                  //通過(guò)SPI發(fā)送一字節(jié)數(shù)據(jù)
  60.   while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);    //當(dāng)SPI接收緩沖器為空時(shí)等待
  61.   return SPI_I2S_ReceiveData(SPI1);                                   //返回從SPI接收到的數(shù)據(jù)
  62. }

  63. /*---------------------------------------------------向NRF特定的寄存器寫入數(shù)據(jù)----------------------------------------------------------------*/   
  64. //reg:NRF的命令+寄存器地址\
  65.   dat:將要向寄存器寫入的數(shù)據(jù)\
  66. status:NRF的status寄存器的狀態(tài)

  67. u8 SPI_NRF_WriteReg(u8 reg,u8 dat)
  68. {
  69.          u8 status;

  70.         NRF_CE_LOW();
  71.     NRF_CSN_LOW();                       //置低CSN,使能SPI傳輸

  72.         status = SPI_NRF_RW(reg);      //發(fā)送命令及寄存器號(hào)
  73.     SPI_NRF_RW(dat);               //向寄存器寫入數(shù)據(jù)

  74.           NRF_CSN_HIGH();                       //CSN拉高,完成        

  75.         return(status);                //返回狀態(tài)寄存器的值
  76. }

  77. /*--------------------------------------------------從NRF特定的寄存器讀出數(shù)據(jù)-----------------------------------------------------------------*/
  78. //reg:NRF的命令+寄存器地址\
  79.   reg_val:寄存器中的數(shù)據(jù)

  80. u8 SPI_NRF_ReadReg(u8 reg)
  81. {
  82.          u8 reg_val;

  83.         NRF_CE_LOW();
  84.          NRF_CSN_LOW();                        //置低CSN,使能SPI傳輸        

  85.         SPI_NRF_RW(reg);                //發(fā)送寄存器號(hào)
  86.     reg_val = SPI_NRF_RW(NOP);      //讀取寄存器的值

  87.         NRF_CSN_HIGH();                            //CSN拉高,完成
  88.            
  89.         return reg_val;
  90. }        

  91. /*------------------------------------------------------向NRF的寄存器中寫入一串?dāng)?shù)據(jù)----------------------------------------------------------*/
  92. //reg : NRF的命令+寄存器地址\
  93.   pBuf:用于存儲(chǔ)將被讀出的寄存器數(shù)據(jù)的數(shù)組,外部定義\
  94.   bytes: pBuf的數(shù)據(jù)長(zhǎng)度\
  95.   status:NRF的status寄存器的狀態(tài)\

  96. u8 SPI_NRF_ReadBuf(u8 reg,u8 *pBuf,u8 bytes)
  97. {
  98.          u8 status, byte_cnt;

  99.         NRF_CE_LOW();        
  100.         NRF_CSN_LOW();                                   //置低CSN,使能SPI傳輸
  101.                
  102.                         
  103.         status = SPI_NRF_RW(reg);                        //發(fā)送寄存器號(hào)
  104.     for(byte_cnt=0;byte_cnt<bytes;byte_cnt++)                 //讀取緩沖區(qū)數(shù)據(jù)
  105.            pBuf[byte_cnt] = SPI_NRF_RW(NOP);

  106.         NRF_CSN_HIGH();                                         //CSN拉高,完成
  107.                
  108.          return status;                                             //返回寄存器狀態(tài)值
  109. }

  110. /*-----------------------------------------------------向NRF的寄存器中寫入一串?dāng)?shù)據(jù)-------------------------------------------------------------*/
  111. //reg : NRF的命令+寄存器地址\
  112.   pBuf:存儲(chǔ)了將要寫入寫寄存器數(shù)據(jù)的數(shù)組,外部定義\
  113.   bytes: pBuf的數(shù)據(jù)長(zhǎng)度\
  114.   status: NRF的status寄存器的狀態(tài)

  115. u8 SPI_NRF_WriteBuf(u8 reg ,u8 *pBuf,u8 bytes)
  116. {
  117.          u8 status,byte_cnt;

  118.          NRF_CE_LOW();         
  119.          NRF_CSN_LOW();                                              //置低CSN,使能SPI傳輸

  120.            status = SPI_NRF_RW(reg);                    //發(fā)送寄存器號(hào)        
  121.           for(byte_cnt=0;byte_cnt<bytes;byte_cnt++)    //向緩沖區(qū)寫入數(shù)據(jù)
  122.                 SPI_NRF_RW(*pBuf++);                                       
  123.         
  124.         NRF_CSN_HIGH();                                              //CSN拉高,完成

  125.           return (status);                                  //返回NRF24L01的狀態(tài)                 
  126. }

  127. /*----------------------------------------------------------配置并進(jìn)入接收模式-------------------------------------------------------------*/
  128. void NRF_RX_Mode(void)

  129. {
  130.    NRF_CE_LOW();        

  131.    SPI_NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH);//寫RX節(jié)點(diǎn)地址
  132.    SPI_NRF_WriteReg(NRF_WRITE_REG+EN_AA,0x01);                        //使能通道0的自動(dòng)應(yīng)答   
  133.    SPI_NRF_WriteReg(NRF_WRITE_REG+EN_RXADDR,0x01);                    //使能通道0的接收地址   
  134.    SPI_NRF_WriteReg(NRF_WRITE_REG+RF_CH,CHANAL);                      //設(shè)置RF通信頻率   
  135.    SPI_NRF_WriteReg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);           //選擇通道0的有效數(shù)據(jù)寬度      
  136.    SPI_NRF_WriteReg(NRF_WRITE_REG+RF_SETUP,0x0f);                     //設(shè)置TX發(fā)射參數(shù),0db增益,2Mbps,低噪聲增益開(kāi)啟   
  137.    SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG, 0x0f);                      //配置基本工作模式的參數(shù);PWR_UP,EN_CRC,16BIT_CRC,接收模式

  138.    NRF_CE_HIGH();          //CE拉高,進(jìn)入接收模式

  139. }   

  140. /*----------------------------------------------------------配置發(fā)送模式-----------------------------------------------------------*/
  141. void NRF_TX_Mode(void)
  142. {  
  143.    NRF_CE_LOW();               

  144.    SPI_NRF_WriteBuf(NRF_WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH);    //寫TX節(jié)點(diǎn)地址
  145.    SPI_NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH); //設(shè)置TX節(jié)點(diǎn)地址,主要為了使能ACK   
  146.    SPI_NRF_WriteReg(NRF_WRITE_REG+EN_AA,0x01);                         //使能通道0的自動(dòng)應(yīng)答   
  147.    SPI_NRF_WriteReg(NRF_WRITE_REG+EN_RXADDR,0x01);                     //使能通道0的接收地址  
  148.    SPI_NRF_WriteReg(NRF_WRITE_REG+SETUP_RETR,0x1a);                    //設(shè)置自動(dòng)重發(fā)間隔時(shí)間:500us + 86us;最大自動(dòng)重發(fā)次數(shù):10次
  149.    SPI_NRF_WriteReg(NRF_WRITE_REG+RF_CH,CHANAL);                       //設(shè)置RF通道為CHANAL
  150.    SPI_NRF_WriteReg(NRF_WRITE_REG+RF_SETUP,0x0f);                      //設(shè)置TX發(fā)射參數(shù),0db增益,2Mbps,低噪聲增益開(kāi)啟   
  151.    SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG,0x0e);                        //配置基本工作模式的參數(shù);PWR_UP,EN_CRC,16BIT_CRC,發(fā)射模式,開(kāi)啟所有中斷

  152.    NRF_CE_HIGH();  //CE拉高,進(jìn)入發(fā)送模式
  153.    Delay(0xffff); //CE要拉高一段時(shí)間才進(jìn)入發(fā)送模式
  154. }

  155. /*---------------------------------------------------------主要用于NRF與MCU是否正常連接--------------------------------------------------------*/
  156. //retval: SUCCESS/ERROR 連接正常/連接失敗

  157. u8 NRF_Check(void)
  158. {
  159.         u8 buf[5]={0xC2,0xC2,0xC2,0xC2,0xC2};
  160.         u8 buf1[5];
  161.         u8 i;
  162.          
  163.         
  164.         SPI_NRF_WriteBuf(NRF_WRITE_REG+TX_ADDR,buf,5);//寫入5個(gè)字節(jié)的地址        
  165.         SPI_NRF_ReadBuf(TX_ADDR,buf1,5);              //讀出寫入的地址               
  166.         for(i=0;i<5;i++)                              //判斷是否連接成功
  167.         {
  168.                 if(buf1[i]!=0xC2)
  169.                 break;
  170.         }               
  171.         if(i==5)
  172.                 return SUCCESS ;        //MCU與NRF成功連接
  173.         else
  174.                 return ERROR ;        //MCU與NRF不正常連接
  175. }

  176. /*-----------------------------------------------------向NRF的發(fā)送緩沖區(qū)中寫入數(shù)據(jù)--------------------------------------------------------------*/
  177. //txBuf:存儲(chǔ)了將要發(fā)送的數(shù)據(jù)的數(shù)組,外部定義\
  178.   retval: 發(fā)送結(jié)果,成功返回TXDS,失敗返回MAXRT或ERROR

  179. u8 NRF_Tx_Dat(u8 *txbuf)
  180. {
  181.         u8 state;  

  182.         NRF_CE_LOW();                                           //CE為低,進(jìn)入待機(jī)模式1                                                        
  183.     SPI_NRF_WriteBuf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//寫數(shù)據(jù)到TX BUF 最大 32個(gè)字節(jié)     
  184.          NRF_CE_HIGH();                                     //CE為高,txbuf非空,發(fā)送數(shù)據(jù)包
  185.                                              
  186.         while(NRF_Read_IRQ()!=0);                                //等待發(fā)送完成中斷
  187.         state = SPI_NRF_ReadReg(STATUS);                   //讀取狀態(tài)寄存器的值
  188.     SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS,state);            //清除TX_DS或MAX_RT中斷標(biāo)志
  189.     SPI_NRF_WriteReg(FLUSH_RX,NOP);                    //清除TX FIFO寄存器

  190.          /*判斷中斷類型*/   
  191.         if(state&MAX_RT)                     //達(dá)到最大重發(fā)次數(shù)
  192.                          return MAX_RT;

  193.         else if(state&TX_DS)                 //發(fā)送完成
  194.                          return TX_DS;
  195.          else                                                  
  196.                         return ERROR;                //其他原因發(fā)送失敗
  197. }

  198. /*--------------------------------------------------------從NRF的接收緩沖區(qū)中讀出數(shù)據(jù)------------------------------------------------------------*/
  199. //rxBuf :用于接收該數(shù)據(jù)的數(shù)組,外部定義\
  200.   retval: 接收結(jié)果

  201. u8 NRF_Rx_Dat(u8 *rxbuf)
  202. {
  203.         u8 state;
  204.         NRF_CE_HIGH();         //進(jìn)入接收狀態(tài)

  205.          /*輪詢標(biāo)志*/
  206.         while(NRF_Read_IRQ()==0)
  207.   {
  208.     NRF_CE_LOW();                                               //進(jìn)入待機(jī)狀態(tài)               
  209.     state=SPI_NRF_ReadReg(NRF_READ_REG+STATUS);          //讀取status寄存器的值         
  210.     SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS,state);        //清除中斷標(biāo)志

  211.     /*判斷是否接收到數(shù)據(jù)*/
  212.     if(state&RX_DR)                                      //接收到數(shù)據(jù)
  213.     {
  214.       SPI_NRF_ReadBuf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH); //讀取數(shù)據(jù)
  215.       SPI_NRF_WriteReg(FLUSH_RX,NOP);                    //清除RX FIFO寄存器
  216.       return RX_DR;
  217.     }
  218.     else   
  219.       return ERROR;                    //沒(méi)收到任何數(shù)據(jù)
  220.   }
  221.   return ERROR;                    //沒(méi)收到任何數(shù)據(jù)
  222. }


  223. void Beep_ON(void)
  224. {
  225.         GPIO_InitTypeDef  GPIO_InitBeep;
  226.         
  227.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
  228.         
  229.         GPIO_InitBeep.GPIO_Mode=GPIO_Mode_Out_PP;
  230.         GPIO_InitBeep.GPIO_Pin=GPIO_Pin_0;
  231.         GPIO_InitBeep.GPIO_Speed=GPIO_Speed_50MHz;
  232.         GPIO_Init(GPIOC,&GPIO_InitBeep);
  233.         
  234.         GPIO_SetBits(GPIOC, GPIO_Pin_0);
  235. }


  236. void Beep_OFF(void)
  237. {
  238.         GPIO_InitTypeDef  GPIO_InitBeep;
  239.         
  240.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
  241.         
  242.         GPIO_InitBeep.GPIO_Mode=GPIO_Mode_Out_PP;
  243.         GPIO_InitBeep.GPIO_Pin=GPIO_Pin_0;
  244.         GPIO_InitBeep.GPIO_Speed=GPIO_Speed_50MHz;
  245.         GPIO_Init(GPIOC,&GPIO_InitBeep);
  246.         
  247.         GPIO_ResetBits(GPIOC, GPIO_Pin_0);
  248. }

  249. (二)接收端main.c部分代碼
  250. int compare(u8 x[],u8 y[])
  251. {   
  252.     int a=0;
  253.     for(i=0;i<32;i++)
  254.     {
  255.         if(x[i]==y[i])
  256.             a++;
  257.     }
  258.     if(a==32)
  259.         return 1;
  260.     else
  261.         return 0;
  262. }



  263. void main(void)
  264. {
  265.     int ans=0;
  266.     SPI_NRF_Init();
  267.     LED_GPIO_Config();

  268.     NRF_RX_Mode();
  269.     for(i=0;i<32;i++)
  270.        mishi[i]=i;
  271.     while(1)
  272.     {        
  273.         status=NRF_Rx_Dat(rxbuf);
  274.         if(status==RX_DR)
  275.             ans=compare(rxbuf,mishi);
  276.         if(ans==1)
  277.             Beep_ON();
  278.         else
  279.             Beep_OFF();
  280.     }
  281. //    LED_RGB('R');
  282. }

  283. (三)發(fā)射端部分代碼
  284. SPI_NRF_Init();
  285. NRF_TX_Mode();


  286. if (count>57600)        
  287.     {
  288.         //Beep_ON();
  289.         NRF_Tx_Dat(mishi);
  290.     }
  291.     else NRF_Tx_Dat(errorbuf);
復(fù)制代碼
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:45879 發(fā)表于 2022-3-10 09:32 | 只看該作者
排查思路:
1.檢查SPI讀寫功能
2.檢查雙方的地址,配置模式等等
3.接收方嘗試通過(guò)串口打印信息
回復(fù)

使用道具 舉報(bào)

板凳
ID:115923 發(fā)表于 2022-3-26 21:51 | 只看該作者
接收 建議用 中斷, 你這樣 接收程序要改一下。 要么你 在while里面加一個(gè)延時(shí)50ms試一試。
發(fā)送程序基本沒(méi)有問(wèn)題。如果間隔發(fā)送時(shí)間在50ms以上。
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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