/** ****************************************************************************** * @author 泽耀科技 ASHINING * @version V3.0 * @date 2016-10-08 * @brief NRF24L01配置C文件 ****************************************************************************** * @attention * * 官网 : http://www.ashining.com * 淘宝 : https://shop105912646.taobao.com * 阿里巴巴: https://cdzeyao.1688.com ************************************************************************* */ //#define SI24R1 #include "RF24L01.h" #include "platform.h" #include "function.h" #ifdef SI24R1 //#define SPI1_BREAK 200 //SPI的通信速率 //#define RFCHK //保证无线模块不死机 /* */ static void DelayUs( unsigned short time ) { unsigned short i = 0; while( time-- ) { i = 6; //16M=2 while( i-- ) ; } } extern SPI_HandleTypeDef hspi1; static unsigned char drv_spi_read_write_byte( unsigned char TxData ) { // unsigned short retry = 0; // while( ( SPI1->SR & 1 << 1 ) == 0 ) // 等待发送空闲 // //while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) // { // retry++; // if( retry > SPI1_BREAK ) // { // return 0; // } // } // SPI1->DR = TxData; //发送 // retry = 0; // while( ( SPI1->SR & 1 << 0 ) == 0 ) //等待接收完成 // //while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) // { // retry++; // if( retry > SPI1_BREAK ) // { // return 0; // } // } // return SPI1->DR; //返回接收到的数据 //typedef enum //{ // HAL_OK = 0x00U, // HAL_ERROR = 0x01U, // HAL_BUSY = 0x02U, // HAL_TIMEOUT = 0x03U //} HAL_StatusTypeDef; HAL_StatusTypeDef rlst; unsigned char rx_data; rlst =HAL_SPI_TransmitReceive(&hspi1,&TxData,&rx_data,1, 5); if(rlst == HAL_OK) return rx_data; else return 0; } /** * @brief :NRF24L01读寄存器 * @param : @Addr:寄存器地址 * @note :地址在设备中有效 * @retval:读取的数据 */ static uint8_t NRF24L01_Read_Reg( uint8_t RegAddr ) { uint8_t btmp; RF24L01_SET_CS_LOW( ); //片选 drv_spi_read_write_byte( NRF_READ_REG | RegAddr ); //读命令 地址 btmp = drv_spi_read_write_byte( 0xFF ); //读数据 RF24L01_SET_CS_HIGH( ); //取消片选 return btmp; } /** * @brief :NRF24L01读指定长度的数据 * @param : * @reg:地址 * @pBuf:数据存放地址 * @len:数据长度 * @note :数据长度不超过255,地址在设备中有效 * @retval:读取状态 */ static void NRF24L01_Read_Buf( uint8_t RegAddr, uint8_t* pBuf, uint8_t len ) { uint8_t btmp; RF24L01_SET_CS_LOW( ); //片选 drv_spi_read_write_byte( NRF_READ_REG | RegAddr ); //读命令 地址 for( btmp = 0; btmp < len; btmp ++ ) { *( pBuf + btmp ) = drv_spi_read_write_byte( 0xFF ); //读数据 } RF24L01_SET_CS_HIGH( ); //取消片选 } /** * @brief :NRF24L01写寄存器 * @param :无 * @note :地址在设备中有效 * @retval:读写状态 */ static void NRF24L01_Write_Reg( uint8_t RegAddr, uint8_t Value ) { RF24L01_SET_CE_LOW( ); //pei只能在standby模式下修改!! RF24L01_SET_CS_LOW( ); //片选 drv_spi_read_write_byte( NRF_WRITE_REG | RegAddr ); //写命令 地址 drv_spi_read_write_byte( Value ); //写数据 RF24L01_SET_CS_HIGH( ); //取消片选 } /** * @brief :NRF24L01写指定长度的数据 * @param : * @reg:地址 * @pBuf:写入的数据地址 * @len:数据长度 * @note :数据长度不超过255,地址在设备中有效 * @retval:写状态 */ static void NRF24L01_Write_Buf( uint8_t RegAddr, uint8_t* pBuf, uint8_t len ) { uint8_t i; RF24L01_SET_CS_LOW( ); //片选 drv_spi_read_write_byte( NRF_WRITE_REG | RegAddr ); //写命令 地址 for( i = 0; i < len; i ++ ) { drv_spi_read_write_byte( *( pBuf + i ) ); //写数据 } RF24L01_SET_CS_HIGH( ); //取消片选 } /** * @brief :清空TX缓冲区 * @param :无 * @note :无 * @retval:无 */ static void NRF24L01_Flush_Tx_Fifo( void ) { RF24L01_SET_CS_LOW( ); //片选 drv_spi_read_write_byte( FLUSH_TX ); //清TX FIFO命令 RF24L01_SET_CS_HIGH( ); //取消片选 } /** * @brief :清空RX缓冲区 * @param :无 * @note :无 * @retval:无 */ static void NRF24L01_Flush_Rx_Fifo( void ) { RF24L01_SET_CS_LOW( ); //片选 drv_spi_read_write_byte( FLUSH_RX ); //清RX FIFO命令 RF24L01_SET_CS_HIGH( ); //取消片选 } /** * @brief :重新使用上一包数据 * @param :无 * @note :无 * @retval:无 */ //static void NRF24L01_Reuse_Tx_Payload( void ) //{ // RF24L01_SET_CS_LOW( ); //片选 // drv_spi_read_write_byte( REUSE_TX_PL ); //重新使用上一包命令 // RF24L01_SET_CS_HIGH( ); //取消片选 //} /** * @brief :NRF24L01空操作 * @param :无 * @note :无 * @retval:无 */ //static void NRF24L01_Nop( void ) //{ // RF24L01_SET_CS_LOW( ); //片选 // drv_spi_read_write_byte( NOP ); //空操作命令 // RF24L01_SET_CS_HIGH( ); //取消片选 //} /** * @brief :NRF24L01读状态寄存器 * @param :无 * @note :无 * @retval:RF24L01状态 */ static uint8_t NRF24L01_Read_Status_Register( void ) { uint8_t Status; RF24L01_SET_CS_LOW( ); //片选 Status = drv_spi_read_write_byte( NRF_READ_REG + STATUS ); //读状态寄存器 RF24L01_SET_CS_HIGH( ); //取消片选 return Status; } /** * @brief :NRF24L01清中断 * @param : @IRQ_Source:中断源 * @note :无 * @retval:清除后状态寄存器的值 */ static uint8_t NRF24L01_Clear_IRQ_Flag( uint8_t IRQ_Source ) { uint8_t btmp = 0; IRQ_Source &= ( 1 << RX_DR ) | ( 1 << TX_DS ) | ( 1 << MAX_RT ); //中断标志处理 btmp = NRF24L01_Read_Status_Register( ); //读状态寄存器 RF24L01_SET_CS_LOW( ); //片选 drv_spi_read_write_byte( NRF_WRITE_REG + STATUS ); //写状态寄存器命令 drv_spi_read_write_byte( IRQ_Source | btmp ); //清相应中断标志 RF24L01_SET_CS_HIGH( ); //取消片选 return ( NRF24L01_Read_Status_Register( ) ); //返回状态寄存器状态 } /** * @brief :读RF24L01中断状态 * @param :无 * @note :无 * @retval:中断状态 */ //static uint8_t RF24L01_Read_IRQ_Status( void ) //{ // return ( NRF24L01_Read_Status_Register( ) & ( ( 1 << RX_DR ) | ( 1 << TX_DS ) | ( 1 << MAX_RT ) ) ); //返回中断状态 //} /** * @brief :读FIFO中数据宽度 * @param :无 * @note :无 * @retval:数据宽度 */ static uint8_t NRF24L01_Read_Top_Fifo_Width( void ) { uint8_t btmp; RF24L01_SET_CS_LOW( ); //片选 drv_spi_read_write_byte( R_RX_PL_WID ); //读FIFO中数据宽度命令 btmp = drv_spi_read_write_byte( 0xFF ); //读数据 RF24L01_SET_CS_HIGH( ); //取消片选 return btmp; } /** * @brief :读接收到的数据 * @param :无 * @note :无 * @retval: @pRxBuf:数据存放地址首地址 */ static uint8_t NRF24L01_Read_Rx_Payload( uint8_t* pRxBuf ) { uint8_t volatile Width, PipeNum; PipeNum = ( NRF24L01_Read_Reg( STATUS ) >> 1 ) & 0x07; //读接收状态 //Width= NRF24L01_Read_Reg(RX_PW_P0);//读出为0 Width = NRF24L01_Read_Top_Fifo_Width( ); //读接收数据个数 if( Width > 32 ) //pei--好像出现不了 { NRF24L01_Flush_Rx_Fifo( ); return 0; } RF24L01_SET_CS_LOW( ); //片选 drv_spi_read_write_byte( RD_RX_PLOAD ); //读有效数据命令 for( PipeNum = 0; PipeNum < Width; PipeNum ++ ) { *( pRxBuf + PipeNum ) = drv_spi_read_write_byte( 0xFF ); //读数据 } RF24L01_SET_CS_HIGH( ); //取消片选 NRF24L01_Flush_Rx_Fifo( ); //清空RX FIFO --出现过读出是上一包情况后加---确实能模拟出现 //Width = NRF24L01_Read_Top_Fifo_Width( );//即使清除FIFO读出还是原来的值 //NRF24L01_Clear_IRQ_Flag( IRQ_ALL );//可以避免中断响应中又接收一包后模块不再产生中断,因为中断没清除标志 return Width; } /** * @brief :发送数据(带应答) * @param : * @pTxBuf:发送数据地址 * @len:长度 * @note :一次不超过32个字节 * @retval:无 */ //static void NRF24L01_Write_Tx_Payload_Ack( uint8_t* pTxBuf, uint8_t len ) //{ // uint8_t btmp; // uint8_t length = ( len > 32 ) ? 32 : len; //数据长达大约32 则只发送32个 // NRF24L01_Flush_Tx_Fifo( ); //清TX FIFO // RF24L01_SET_CS_LOW( ); //片选 // drv_spi_read_write_byte( WR_TX_PLOAD ); //发送命令 // for( btmp = 0; btmp < length; btmp ++ ) // { // drv_spi_read_write_byte( *( pTxBuf + btmp ) ); //发送数据 // } // RF24L01_SET_CS_HIGH( ); //取消片选 //} /** * @brief :发送数据(不带应答) * @param : * @pTxBuf:发送数据地址 * @len:长度 * @note :一次不超过32个字节 * @retval:无 */ static void NRF24L01_Write_Tx_Payload_NoAck( uint8_t* pTxBuf, uint8_t len ) { if( len > 32 || len == 0 ) { return ; //数据长度大于32 或者等于0 不执行 } RF24L01_SET_CS_LOW( ); //片选 drv_spi_read_write_byte( WR_TX_PLOAD_NACK ); //发送命令 while( len-- ) { drv_spi_read_write_byte( *pTxBuf ); //发送数据 pTxBuf++; } RF24L01_SET_CS_HIGH( ); //取消片选 } /** * @brief :在接收模式下向TX FIFO写数据(带ACK) * @param : * @pData:数据地址 * @len:长度 * @note :一次不超过32个字节 * @retval:无 */ //static void NRF24L01_Write_Tx_Payload_InAck( uint8_t* pData, uint8_t len ) //{ // uint8_t btmp; // len = ( len > 32 ) ? 32 : len; //数据长度大于32个则只写32个字节 // RF24L01_SET_CS_LOW( ); //片选 // drv_spi_read_write_byte( W_ACK_PLOAD ); //命令 // for( btmp = 0; btmp < len; btmp ++ ) // { // drv_spi_read_write_byte( *( pData + btmp ) ); //写数据 // } // RF24L01_SET_CS_HIGH( ); //取消片选 //} /** * @brief :设置发送地址 * @param : * @pAddr:地址存放地址 * @len:长度 * @note :无 * @retval:无 */ static void NRF24L01_Set_TxAddr( uint8_t* pAddr, uint8_t len ) { len = ( len > 5 ) ? 5 : len; //地址不能大于5个字节 NRF24L01_Write_Buf( TX_ADDR, pAddr, len ); //写地址 } /** * @brief :设置接收通道地址 * @param : * @PipeNum:通道 * @pAddr:地址存肥着地址 * @Len:长度 * @note :通道不大于5 地址长度不大于5个字节 * @retval:无 */ static void NRF24L01_Set_RxAddr( uint8_t PipeNum, uint8_t* pAddr, uint8_t Len ) { Len = ( Len > 5 ) ? 5 : Len; PipeNum = ( PipeNum > 5 ) ? 5 : PipeNum; //通道不大于5 地址长度不大于5个字节 NRF24L01_Write_Buf( RX_ADDR_P0 + PipeNum, pAddr, Len ); //写入地址 } /** * @brief :设置通信速度 * @param : * @Speed:速度 * @note :无 * @retval:无 */ static void NRF24L01_Set_Speed( nRf24l01SpeedType Speed ) { uint8_t btmp = 0; btmp = NRF24L01_Read_Reg( RF_SETUP ); btmp &= ~( ( 1 << 5 ) | ( 1 << 3 ) ); if( Speed == SPEED_250K ) //250K { btmp |= ( 1 << 5 ); } else if( Speed == SPEED_1M ) //1M { btmp &= ~( ( 1 << 5 ) | ( 1 << 3 ) ); } else if( Speed == SPEED_2M ) //2M { btmp |= ( 1 << 3 ); } NRF24L01_Write_Reg( RF_SETUP, btmp ); } /** * @brief :设置频率 * @param : * @FreqPoint:频率设置参数 * @note :值不大于127 * @retval:无 */ static void RF24L01_Chan( uint8_t FreqPoint ) { NRF24L01_Write_Reg( RF_CH, FreqPoint & 0x7F ); } /** * @brief :NRF24L01检测 * @param :无 * @note :无 * @retval:无 */ static void NRF24L01_check( void ) { uint8_t i; uint8_t buf[5] = { 0X11, 0X22, 0XA3, 0XA4, 0XA5 }; uint8_t read_buf[ 5 ] = { 0 }; NRF24L01_Write_Buf( TX_ADDR, buf, 5 ); //写入5个字节的地址 NRF24L01_Read_Buf( TX_ADDR, read_buf, 5 ); //读出写入的地址 for( i = 0; i < 5; i++ ) { if( buf[ i ] != read_buf[ i ] ) { break; } } } /** * @brief :设置模式 * @param : * @Mode:模式发送模式或接收模式 * @note :无 * @retval:无 */ static void RF24L01_Set_Mode( nRf24l01ModeType Mode ) { uint8_t controlreg = 0; controlreg = NRF24L01_Read_Reg( CONFIG ); if( Mode == MODE_TX ) { controlreg &= ~( 1 << PRIM_RX ); } else { if( Mode == MODE_RX ) { controlreg |= ( 1 << PRIM_RX ); } } NRF24L01_Write_Reg( CONFIG, controlreg ); } /** * @brief :NRF24L01发送一次数据 * @param : * @txbuf:待发送数据首地址 * @Length:发送数据长度 * @note :无 * @retval: * MAX_TX:达到最大重发次数 * TX_OK:发送完成 * 0xFF:其他原因 */ //static uint8_t NRF24L01_TxPacket( uint8_t* txbuf, uint8_t Length ) //{ //// uint8_t l_Status = 0; //// uint16_t l_MsTimes = 0; // RF24L01_SET_CS_LOW( ); //片选 // drv_spi_read_write_byte( FLUSH_TX ); // RF24L01_SET_CS_HIGH( ); // RF24L01_SET_CE_LOW( ); // NRF24L01_Write_Buf( WR_TX_PLOAD, txbuf, Length ); //写数据到TX BUF 32字节 TX_PLOAD_WIDTH // RF24L01_SET_CE_HIGH( ); //启动发送 // return 0xFF; //其他原因发送失败 //} /** * @brief :NRF24L01接收数据 * @param : * @rxbuf:接收数据存放地址 * @note :无 * @retval:接收的数据个数 */ //static uint8_t NRF24L01_RxPacket( uint8_t* rxbuf ) //{ // uint8_t l_Status = 0, l_RxLength = 0;//, l_100MsTimes = 0; // l_Status = NRF24L01_Read_Reg( STATUS ); //读状态寄存器 // NRF24L01_Write_Reg( STATUS, l_Status ); //清中断标志 // if( l_Status & RX_OK ) //接收到数据 // { // l_RxLength = NRF24L01_Read_Reg( R_RX_PL_WID ); //读取接收到的数据个数 // NRF24L01_Read_Buf( RD_RX_PLOAD, rxbuf, l_RxLength ); //接收到数据 // NRF24L01_Write_Reg( FLUSH_RX, 0xff ); //清除RX FIFO // return l_RxLength; // } // return 0; //没有收到数据 //} //#define NRF24L01 static void NRF24L01_SetPA( unsigned char level ) { uint8_t btmp; #ifdef NRF24L01 btmp = NRF24L01_Read_Reg( RF_SETUP ) & ~0x06; btmp |= ( (level<<1) & 6 ) |0x01; NRF24L01_Write_Reg( RF_SETUP, btmp ); #else btmp = NRF24L01_Read_Reg( RF_SETUP ) & ~0x07; btmp |= ( level & 7 ); NRF24L01_Write_Reg( RF_SETUP, btmp ); #endif } //切换到接收模式 static void RF24L01_RxOn() { RF24L01_SET_CE_LOW( );//standby才能设置 RF24L01_Set_Mode( MODE_RX ); RF24L01_SET_CE_HIGH( ); } //清除接收中断标志位,解除芯片接收死机 static void RF24L01_ClrIRQ() { NRF24L01_Clear_IRQ_Flag( IRQ_ALL ); } /* 设置频率点 */ void rf_setfreq(unsigned char freq) { //CLI(); RF24L01_Chan( freq ); RF24L01_RxOn();//设置频率后切换到接收模式 //SEI(); } /* 设置同步码 */ void rf_set_syncode(unsigned short sync) { uint8_t addr[5] = {INIT_ADDR}; //#define INIT_ADDR 0x19,0x98,0xA4,0x25,0x01 addr[2] = sync>>8; addr[3] = sync; //修改无线地址码,缺省A425 NRF24L01_Set_TxAddr( addr, 4 ); //设置TX地址 NRF24L01_Set_RxAddr( 0,addr, 4 ); //设置RX地址 通道0 } //基站设置功率,放在频点初始化函数里面 void rf_set_PA_Mode( unsigned char mode ) { //#ifdef FASTMATCH_LOWERPA if(check_fastmatch_lowerPA()) NRF24L01_SetPA( PWR_7DB ); else //#endif { switch( mode ) { case 1: NRF24L01_SetPA( PWR_F4DB ); break; case 2: NRF24L01_SetPA( PWR_F6DB ); break; case 3: NRF24L01_SetPA( PWR_F12DB ); break; default: NRF24L01_SetPA( PWR_0DB ); break; } } } //初始化 void rf_initial(void) { NRF24L01_check();//Gavin NRF24L01_Clear_IRQ_Flag( IRQ_ALL ); #if DYNAMIC_PACKET == 1 NRF24L01_Write_Reg( DYNPD, ( 1 << 0 ) ); //使能通道0动态数据长度 //NRF24L01_Write_Reg( FEATRUE, 0x07 ); NRF24L01_Write_Reg( FEATRUE, ( 1 << EN_DPL ) | //动态长度 //( 1 << EN_ACK_PAY ) | //带负载数据的ACK包, 允许无应答, ( 1 << EN_DYN_ACK ) ); //带负载应答: 关闭 NRF24L01_Read_Reg( DYNPD ); NRF24L01_Read_Reg( FEATRUE ); #elif DYNAMIC_PACKET == 0 L01_WriteSingleReg( L01REG_RX_PW_P0, FIXED_PACKET_LEN ); //固定数据长度 #endif //DYNAMIC_PACKET NRF24L01_Write_Reg( CONFIG, //( 1< 32 ) Length = 32; //#ifdef FASTMATCH_LOWERPA//add by Gavin if(check_fastmatch_lowerPA()) RF24L01_SET_PATX_LOW(); else RF24L01_SET_PATX_HIGH(); //#endif NRF24L01_Write_Tx_Payload_NoAck( txbuf, Length ); RF24L01_SET_CE_HIGH( ); //启动发送 DelayUs( 50 ); //10us就可以启动发送 RF24L01_SET_CE_LOW( ); } extern unsigned char keypad_rf_data_save(const unsigned char *rf_data); //无线中断响应 void rf_Irq(void) { unsigned char Status,tmp[64]; Status = NRF24L01_Read_Reg( STATUS ); //读状态寄存器 // DelayUs( 200 ); //供示波器观察 NRF24L01_Write_Reg( STATUS, Status ); //清中断标志---里面CE置低导致不再接收 if( Status & RX_OK ){ //接收到数据 // GPIO_SetBits( RF_PORT, RF_LNA ); tmp[0] = NRF24L01_Read_Rx_Payload(&tmp[1]); keypad_rf_data_save(tmp); } if( Status & TX_OK ){ } //#ifdef FASTMATCH_LOWERPA//add by Gavin RF24L01_SET_PATX_LOW(); //#endif //#ifdef RFCHK RF24L01_ClrIRQ();//排除接收死机的情况 //#endif RF24L01_RxOn(); } ////------------------------------------------------- FCCCE ----------------------------------------------------------------- ///* //Gavin 20180629 FCCCE //1,关闭 向键盘定时发送信标 --timer2.5ms中 //2,屏蔽 主程序循环中的应用; //3,将和pc通信的函数移动usb中断里直接处理,实现: // a,用sdk来切换各种测试模式 // b,利用sdk修改频点和基站本身的DFU //4, //*/ //#ifdef FCCCE ////FCC认证需要的特殊测试模式 ////1 连续发射模式(带调制) ////2 连续收信模式(带调制) ////3 无调制 连续发信模式 ////4 无调制 连续收信模式 //void FCC_Test(uchar Mode) //{ // uchar i; // // FccMode=Mode; // // switch (Mode){ // case 0: // case 1://连续MSK输出 // CLI(); // i=NRF24L01_Read_Reg(RF_SETUP); // //i |= (1<