<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > STM32 驅(qū)動(dòng)無線NRF24L01 完成串口數(shù)據(jù)傳輸

          STM32 驅(qū)動(dòng)無線NRF24L01 完成串口數(shù)據(jù)傳輸

          作者: 時(shí)間:2016-12-03 來源:網(wǎng)絡(luò) 收藏
          2401 一個(gè)簡單的SPI 接口的 2.4G 射頻模塊 淘寶價(jià)20¥,DIY 的17¥ ,算是廉價(jià)。
          這個(gè)版本的穩(wěn)定修正http://ntn314.blog.163.com/blog/static/16174358420106211118944/
          接口CMOS電平3.3V STM32 可直接連接。接受完成 發(fā)送完成 出錯(cuò) 都有IRQ 低電平中斷產(chǎn)生。程序中 我將其連接至一IO口在外部中斷中處里各類事件 但也發(fā)現(xiàn)這種處理方式并不是特別靈活,或許直接判斷更加靈活。
          NRF20L01一次可以傳輸 1~32個(gè)字節(jié)比較靈活。最初我是根據(jù)字符串長來不停的轉(zhuǎn)換每次傳輸?shù)拈L度,這樣做十分麻煩最后用截取有效串長的方法實(shí)現(xiàn)效果很好。
          程序修修改過 總算穩(wěn)定了 不過在傳輸大于32個(gè)字節(jié)的信息時(shí)出錯(cuò)的概率很大,原因暫時(shí)不清楚,不過能自動(dòng)恢復(fù)過來。另外在帶有硬件的在線仿真調(diào)試的時(shí)候一定要運(yùn)行前斷開外部硬件的電源再重新連接,保證外部器件的正常初始化。
          /***********************s****************************/
          u8 tran=0; //中斷標(biāo)志
          u8 sta; //定義一個(gè)可位尋址的變量sta
          uc8 TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};
          char RX_BUF[256];
          uchar TX_BUF[256];

          /**************************************************/
          void RF_SPI_Config(void)
          {
          SPI_InitTypeDef SPI_InitStructure;
          GPIO_InitTypeDef GPIO_InitStructure;
          EXTI_InitTypeDef EXTI_InitStructure;
          RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);

          /* PB15-MOSI2,PB13-SCK2*/
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 |GPIO_Pin_14 | GPIO_Pin_15;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
          GPIO_Init(GPIOB, &GPIO_InitStructure);
          //IRQ
          GPIO_SetBits(GPIOB, GPIO_Pin_0);
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
          GPIO_Init(GPIOB, &GPIO_InitStructure);
          GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);
          /* 配置中斷線0為下降觸發(fā)*/
          EXTI_InitStructure.EXTI_Line = EXTI_Line0;
          EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
          EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
          EXTI_InitStructure.EXTI_LineCmd = ENABLE;
          EXTI_Init(&EXTI_InitStructure);
          /*PB2-CS*/
          GPIO_SetBits(GPIOB, GPIO_Pin_2);//預(yù)置為高
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
          GPIO_Init(GPIOB, &GPIO_InitStructure);
          /*PC4-A0*/
          GPIO_SetBits(GPIOC, GPIO_Pin_4);//預(yù)置為高
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
          GPIO_Init(GPIOC, &GPIO_InitStructure);
          /*LED*/
          GPIO_SetBits(GPIOB, GPIO_Pin_12);//預(yù)置為高
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
          GPIO_Init(GPIOB, &GPIO_InitStructure);
          /* SPI2 configuration */
          SPI_Cmd(SPI2, DISABLE); //必須先禁能,才能改變MODE
          SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//兩線全雙工
          SPI_InitStructure.SPI_Mode = SPI_Mode_Master;//主
          SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//8位
          SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;//CPOL=0 時(shí)鐘懸空低
          SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;//CPHA=0 數(shù)據(jù)捕獲第1個(gè)
          SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;//軟件NSS
          SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64 ;//64分頻
          SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//高位在前
          SPI_InitStructure.SPI_CRCPolynomial = 7;//CRC7

          SPI_Init(SPI2, &SPI_InitStructure);
          SPI_Cmd(SPI2, ENABLE);
          }
          /**************************************************************
          但切記不可忽略SPI的硬件接收,因?yàn)樽xSPI_DR才能清除RXEN
          ***************************************************************/
          u8 SPI_RW(u8 byte)
          {
          /*等待發(fā)送寄存器空*/
          while((SPI2->SR & SPI_I2S_FLAG_TXE)==RESET);
          /*發(fā)送一個(gè)字節(jié)*/
          SPI2->DR = byte;
          /* 等待接收寄存器有效*/
          while((SPI2->SR & SPI_I2S_FLAG_RXNE)==RESET);
          return(SPI2->DR);
          }
          /**************************************************
          函數(shù):SPI_RW_Reg()
          描述:寫數(shù)據(jù)value到reg寄存器
          *************************************************/
          u8 SPI_RW_Reg(u8 reg, u8 value)
          {
          u8 status;
          CSN_L; // CSN置低,開始傳輸數(shù)據(jù)
          status = SPI_RW(reg); // 選擇寄存器,同時(shí)返回狀態(tài)字
          SPI_RW(value); // 然后寫數(shù)據(jù)到該寄存器
          CSN_H; // CSN拉高,結(jié)束數(shù)據(jù)傳輸
          return(status); // 返回狀態(tài)寄存器
          }
          /**************************************************
          函數(shù): init_io()
          描述:初始化IO
          *************************************************/
          void RX_Mode(void);
          void init_io(void)
          {
          CE_L; // 待機(jī)
          CSN_H; // SPI禁止
          LED1;// 關(guān)閉指示燈
          RX_Mode();//接收
          }
          /**************************************************
          函數(shù):SPI_Read()
          描述:從reg寄存器讀一字節(jié)
          *************************************************/
          u8 SPI_Read(u8 reg)
          {
          u8 reg_val;
          CSN_L; // CSN置低,開始傳輸數(shù)據(jù)
          SPI_RW(reg); // 選擇寄存器
          reg_val = SPI_RW(0); // 然后從該寄存器讀數(shù)據(jù)
          CSN_H; // CSN拉高,結(jié)束數(shù)據(jù)傳輸
          return(reg_val); // 返回寄存器數(shù)據(jù)
          }
          /**************************************************
          函數(shù):SPI_Read_Buf()
          描述:從reg寄存器讀出bytes個(gè)字節(jié),通常用來讀取接收通道
          數(shù)據(jù)或接收/發(fā)送地址
          *************************************************/
          uchar SPI_Read_Buf(uchar reg, char * pBuf, uchar bytes)
          {
          uchar status, i;
          CSN_L; // CSN置低,開始傳輸數(shù)據(jù)
          status = SPI_RW(reg); // 選擇寄存器,同時(shí)返回狀態(tài)字
          for(i=0; i pBuf[i] = SPI_RW(0); // 逐個(gè)字節(jié)從nRF24L01讀出
          CSN_H; // CSN拉高,結(jié)束數(shù)據(jù)傳輸
          return(status); // 返回狀態(tài)寄存器
          }
          /**************************************************
          函數(shù):SPI_Write_Buf()
          描述:把pBuf緩存中的數(shù)據(jù)寫入到nRF24L01,通常用來寫入發(fā)
          射通道數(shù)據(jù)或接收/發(fā)送地址
          *************************************************/
          uchar SPI_Write_Buf(uchar reg, uchar * pBuf, uchar bytes)
          {
          uchar status, i;
          CSN_L; // CSN置低,開始傳輸數(shù)據(jù)
          status = SPI_RW(reg); // 選擇寄存器,同時(shí)返回狀態(tài)字
          for(i=0; i SPI_RW(pBuf[i]); // 逐個(gè)字節(jié)寫入nRF24L01
          CSN_H; // CSN拉高,結(jié)束數(shù)據(jù)傳輸
          return(status); // 返回狀態(tài)寄存器
          }
          /**************************************************
          函數(shù):RX_Mode()
          描述:這個(gè)函數(shù)設(shè)置nRF24L01為接收模式,等待接收發(fā)送設(shè)備的數(shù)據(jù)包
          *************************************************/
          void RX_Mode(void)
          {
          CE_L;
          SPI_Write_Buf(RF_WRITE_REG + RX_ADDR_P0, (u8*)TX_ADDRESS, TX_ADR_WIDTH); // 接收設(shè)備接收通道0使用和發(fā)送設(shè)備相同的發(fā)送地址
          SPI_RW_Reg(RF_WRITE_REG + EN_AA, 0x01); // 使能接收通道0自動(dòng)應(yīng)答
          SPI_RW_Reg(RF_WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0
          SPI_RW_Reg(RF_WRITE_REG + RF_CH, 40); // 選擇射頻通道0x40
          SPI_RW_Reg(RF_WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // 接收通道0選擇和發(fā)送通道相同有效數(shù)據(jù)寬度
          SPI_RW_Reg(RF_WRITE_REG + RF_SETUP, 0x07); // 數(shù)據(jù)傳輸率1Mbps,發(fā)射功率0dBm,低噪聲放大器增益
          SPI_RW_Reg(RF_WRITE_REG + CONFIG, 0x0f); // CRC使能,16位CRC校驗(yàn),上電,接收模式
          CE_H; // 拉高CE啟動(dòng)接收設(shè)備
          }
          /**************************************************
          函數(shù):TX_Mode()
          描述:
          這個(gè)函數(shù)設(shè)置nRF24L01為發(fā)送模式,(CE=1持續(xù)至少10us),
          130us后啟動(dòng)發(fā)射,數(shù)據(jù)發(fā)送結(jié)束后,發(fā)送模塊自動(dòng)轉(zhuǎn)入接收
          模式等待應(yīng)答信號。
          *************************************************/
          void TX_Mode(uchar * BUF)
          {
          CE_L;
          SPI_Write_Buf(RF_WRITE_REG + TX_ADDR, (u8*)TX_ADDRESS, TX_ADR_WIDTH); // 寫入發(fā)送地址
          SPI_Write_Buf(RF_WRITE_REG + RX_ADDR_P0, (u8*)TX_ADDRESS, TX_ADR_WIDTH); // 為了應(yīng)答接收設(shè)備,接收通道0地址和發(fā)送地址相同
          SPI_Write_Buf(WR_TX_PLOAD, BUF, TX_PLOAD_WIDTH); // 寫數(shù)據(jù)包到TX FIFO
          SPI_RW_Reg(RF_WRITE_REG + EN_AA, 0x01); // 使能接收通道0自動(dòng)應(yīng)答
          SPI_RW_Reg(RF_WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0
          SPI_RW_Reg(RF_WRITE_REG + SETUP_RETR, 0x0a); // 自動(dòng)重發(fā)延時(shí)等待250us+86us,自動(dòng)重發(fā)10次
          SPI_RW_Reg(RF_WRITE_REG + RF_CH, 40); // 選擇射頻通道0x40
          SPI_RW_Reg(RF_WRITE_REG + RF_SETUP, 0x07); // 數(shù)據(jù)傳輸率1Mbps,發(fā)射功率0dBm,低噪聲放大器增益
          SPI_RW_Reg(RF_WRITE_REG + CONFIG, 0x0e); // CRC使能,16位CRC校驗(yàn),上電
          CE_H;CE_H;delay_ms(1);
          }
          /**************************************************
          函數(shù):Check_ACK()
          描述:
          檢查接收設(shè)備有無接收到數(shù)據(jù)包,設(shè)定沒有收到應(yīng)答信
          號是否重發(fā)
          ***************************************************/
          uchar Check_ACK(u8 clear)
          {
          while(IRQ);
          sta = SPI_RW(NOP); // 返回狀態(tài)寄存器
          if(MAX_RT)
          if(clear) // 是否清除TX FIFO,若沒有清除在清除MAX_RT中斷標(biāo)志后重發(fā)
          SPI_RW(FLUSH_TX);
          SPI_RW_Reg(RF_WRITE_REG + STATUS, sta); // 清除TX_DS或MAX_RT中斷標(biāo)志
          IRQ_H;
          if(TX_DS)
          return(0x00);
          else
          return(0xff);
          }

          void sent_data(u8* fp,u16 flong)
          {
          u16 i=65535;
          TX_Mode((u8*)&flong); //傳送長度
          while(!tran&&i>1)i--; //等待完成
          tran=0;
          flong=flong/33+1;
          for(i=0;i<20000;i++);//130uS*2延時(shí)
          while(flong)
          {
          if(MAX_RT) return;//無應(yīng)答返回
          TX_Mode(fp); //傳送數(shù)據(jù)
          while(!tran&&i>1)i--; //等待完成
          tran=0;
          for(i=0;i<20000;i++);//130uS*2延時(shí)
          fp+=32;flong--;
          }
          }
          extern u8 RX_NU;
          void test (void)
          {
          if (Uart2_Get_Flag!=0&&Timer2==0)
          {
          sent_data(TX_BUF,(u16)Uart2_Get_Flag);
          Uart2_Get_Flag=0;
          }

          if(Timer2==0&&RX_NU==2)
          {
          RX_NU=1;
          USART2_Puts("傳輸錯(cuò)誤 ");
          USART2_Puts("rn");
          }
          }
          兩個(gè)中斷 串口 和 外部中斷
          /*******************************************************************************
          * Function Name : EXTI0_IRQHandler
          * Description : This function handles External interrupt Line 0 request.
          * Input : None
          * Output : None
          * Return : None
          *******************************************************************************/
          extern u8 sta;
          extern char RX_BUF[256];
          extern uchar TX_BUF[256];
          extern u8 SPI_RW_Reg(u8 reg, u8 value);
          extern void RX_Mode(void);
          extern uchar SPI_Read_Buf(uchar reg, char * pBuf, uchar bytes);
          u8 RX_NU=1;//1接收長度 2接收數(shù)據(jù)
          u16 rectnu,onerc; //接收串長,接收次數(shù)
          char* PRX_BUF=RX_BUF;
          void EXTI0_IRQHandler(void)
          {
          EXTI_ClearITPendingBit(EXTI_Line0);
          tran=1;
          CSN_L;
          sta=SPI_RW(NOP); // 返回狀態(tài)寄存器
          CSN_H;

          if(MAX_RT)
          {
          USART2_Puts("對方無應(yīng)答 ");
          CSN_L;
          SPI_RW(FLUSH_TX); // 清除TX FIFO,若沒有清除在清除MAX_RT中斷標(biāo)志后重發(fā)
          CSN_H;
          SPI_RW_Reg(RF_WRITE_REG + STATUS, sta);
          }

          if(TX_DS)
          {
          SPI_RW_Reg(RF_WRITE_REG + STATUS, sta); // 清除TX_DS或MAX_RT中斷標(biāo)志
          }
          if(RX_DR) // 判斷是否接受到數(shù)據(jù)
          {

          if(RX_NU==1)
          {
          CE_L;
          SPI_Read_Buf(RD_RX_PLOAD, RX_BUF, TX_PLOAD_WIDTH); // 從RX FIFO讀出數(shù)據(jù)
          SPI_RW_Reg(RF_WRITE_REG + STATUS, sta); // 清除RX_DS中斷標(biāo)志
          rectnu=RX_BUF[0];rectnu|=RX_BUF[1]<<8; //接收串長
          onerc=rectnu/33+1; //計(jì)算接收次數(shù)
          RX_NU=2;RX_Mode();Timer2=500;/*超時(shí)時(shí)間*/
          return;
          }
          if(RX_NU==2)
          {
          CE_L;
          SPI_Read_Buf(RD_RX_PLOAD, PRX_BUF, TX_PLOAD_WIDTH); // 從RX FIFO讀出數(shù)據(jù)
          SPI_RW_Reg(RF_WRITE_REG + STATUS, sta); // 清除RX_DS中斷標(biāo)志
          onerc--;PRX_BUF+=32; //接收計(jì)數(shù) 接收指針移動(dòng)
          if(!onerc)
          {
          RX_BUF[rectnu]=看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();