uint32 nrf_rx(uint8 *rxbuf, uint32 len) { uint32 tmplen = 0; uint8 tmp; while( (nrf_rx_flag != QUEUE_EMPTY) && (len != 0) ) { if(len < DATA_PACKET) { vcan_cpy(rxbuf, (uint8 *)&(NRF_ISR_RX_FIFO[nrf_rx_front]), len); NRF_CE_LOW(); //进入待机状态 nrf_rx_front++; //由于非空,所以可以直接出队列 if(nrf_rx_front >= RX_FIFO_PACKET_NUM) { nrf_rx_front = 0; //重头开始 } tmp = nrf_rx_rear; if(nrf_rx_front == tmp) //追到屁股了,接收队列空 { nrf_rx_flag = QUEUE_EMPTY; } NRF_CE_HIGH(); //进入接收模式 tmplen += len; return tmplen; } vcan_cpy(rxbuf, (uint8 *)&(NRF_ISR_RX_FIFO[nrf_rx_front]), DATA_PACKET); rxbuf += DATA_PACKET; len -= DATA_PACKET; tmplen += DATA_PACKET; NRF_CE_LOW(); //进入待机状态 nrf_rx_front++; //由于非空,所以可以直接出队列 if(nrf_rx_front >= RX_FIFO_PACKET_NUM) { nrf_rx_front = 0; //重头开始 } tmp = nrf_rx_rear; if(nrf_rx_front == tmp) //追到屁股了,接收队列空 { nrf_rx_flag = QUEUE_EMPTY; } else { nrf_rx_flag = QUEUE_NORMAL; } NRF_CE_HIGH(); //进入接收模式 } return tmplen; }
/* * 函数名:NRF_RX_Mode * 描述 :配置并进入接收模式 * 输入 :无 * 输出 :无 * 调用 :外部调用 */ void NRF_RX_Mode(void) { NRF_CE_LOW(); NRF_WriteReg(NRF_WRITE_REG+EN_AA,0x01); //使能通道0的自动应答 NRF_WriteReg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址 NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址 NRF_WriteReg(NRF_WRITE_REG+CONFIG, 0x0B | (IS_CRC16<<2)); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式 #if 1 /* 清除中断标志*/ NRF_WriteReg(NRF_WRITE_REG+STATUS,0xff); NRF_WriteReg(FLUSH_RX,NOP); //清除RX FIFO寄存器 #endif /*CE拉高,进入接收模式*/ NRF_CE_HIGH(); nrf_mode = RX_MODE; }
/*! * @brief NRF24L01+进入发送模式 * @since v5.0 */ void nrf_tx_mode(void) { volatile uint32 i; NRF_CE_LOW(); //DELAY_MS(1); nrf_writebuf(NRF_WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); //写TX节点地址 nrf_writebuf(NRF_WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); //设置RX节点地址 ,主要为了使能ACK nrf_writereg(NRF_WRITE_REG + CONFIG, 0x0A | (IS_CRC16 << 2)); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,发射模式,开启所有中断 /*CE拉高,进入发送模式*/ NRF_CE_HIGH(); nrf_mode = TX_MODE; i = 0x0fff; while(i--); //CE要拉高一段时间才进入发送模式 //DELAY_MS(1); }
/* * 函数名:NRF_Tx_Dat * 描述 :用于向NRF的发送缓冲区中写入数据 * 输入 :txBuf:存储了将要发送的数据的数组,外部定义 * 输出 :发送结果,成功返回TXDS,失败返回MAXRT或ERROR * 调用 :外部调用 */ u8 NRF_Tx_Dat(u8 *txbuf) { u8 state; /*ce为低,进入待机模式1*/ NRF_CE_LOW(); /*写数据到TX BUF 最大 32个字节*/ SPI_NRF_WriteBuf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH); /*CE为高,txbuf非空,发送数据包 */ NRF_CE_HIGH(); /*等待发送完成中断 */ while(NRF_Read_IRQ()!=0); /*读取状态寄存器的值 */ state = SPI_NRF_ReadReg(STATUS); /*清除TX_DS或MAX_RT中断标志*/ SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS,state); SPI_NRF_WriteReg(FLUSH_TX,NOP); //清除TX FIFO寄存器 /*判断中断类型*/ if(state&MAX_RT) //达到最大重发次数 return MAX_RT; else if(state&TX_DS) //发送完成 return TX_DS; else return ERROR; //其他原因发送失败 }
/** * @brief 用于从NRF的接收缓冲区中读出数据 * @param * @arg rxBuf :用于接收该数据的数组,外部定义 * @retval * @arg 接收结果 */ u8 NRF_Rx_Dat(u8 *rxbuf) { u8 state; u16 link_count=0; NRF_CE_HIGH(); //进入接收状态 /*等待接收中断*/ while(NRF_Read_IRQ()!=0) { link_count ++; if(link_count == 5000) //5000为最大重连次数 return ERROR; } NRF_CE_LOW(); //进入待机状态 /*读取status寄存器的值 */ state=SPI_NRF_ReadReg(STATUS); /* 清除中断标志*/ SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS,state); /*判断是否接收到数据*/ if(state&RX_DR) //接收到数据 { SPI_NRF_ReadBuf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据 SPI_NRF_WriteReg(FLUSH_RX,NOP); //清除RX FIFO寄存器 return RX_DR; } else return ERROR; //没收到任何数据 }
/* * 函数名:NRF_ReadBuf * 描述 :用于从NRF的寄存器中读出一串数据 * 输入 :reg:NRF的命令+寄存器地址。 pBuf:用于存储将被读出的寄存器数据的数组,外部定义 bytes: pBuf的数据长度 * 输出 :NRF的status寄存器的状态 * 调用 :外部调用 */ u8 NRF_ReadBuf(u8 reg,u8 *pBuf,u8 len) { u8 status, byte_cnt; // u8 time=0xff; NRF_CE_LOW(); /*置低CSN,使能SPI传输*/ NRF_PCSN_LOW(); for(byte_cnt = 0 ;byte_cnt < len;byte_cnt++) { pBuf[byte_cnt] = NOP; } /*发送寄存器号*/ status = NRF_RW(reg); /*读取缓冲区数据*/ spi_WR(NRF_SPI,pBuf,len); /*CSN拉高,完成*/ NRF_PCSN_HIGH(); return status; //返回寄存器状态值 }
void nrf_send_frame (uint8_t * frame, int send_mode) { int ret; if (mode != MODE_NOMODE) return; UART2PutStr ("sf\n\r"); nrf_write_reg (R_CONFIG, R_CONFIG_PWR_UP | R_CONFIG_EN_CRC); NRF_CS_LOW (); mLED_2_On (); SPI2_xmit (C_W_TX_PAYLOAD); SPI2_transmit (frame, 32); mLED_2_Off (); NRF_CS_HIGH (); NRF_CE_HIGH (); while (1) { ret = nrf_read_reg (R_FIFO_STATUS); if (send_mode) { if ((ret & R_FIFO_STATUS_TX_EMPTY) == R_FIFO_STATUS_TX_EMPTY) break; } else { if ((ret & R_FIFO_STATUS_TX_FULL) == 0) break; } } NRF_CE_LOW (); }
//传输一次,数据最长为 32字节 static u8 NRF_TX_Dat_Once(u8 *txbuf) { u8 state; /*ce为低,进入待机模式1*/ NRF_CE_LOW(); /*写数据到TX BUF 最大 32个字节*/ NRF_WriteBuf(WR_TX_PLOAD,txbuf,MAX_ONCE_TX_NUM); /*CE为高,txbuf非空,发送数据包 */ NRF_CE_HIGH(); /*等待发送完成中断 */ while(NRF_Read_IRQ()!=0); /*读取状态寄存器的值 */ state = NRF_ReadReg(STATUS); /*清除TX_DS或MAX_RT中断标志*/ NRF_WriteReg(NRF_WRITE_REG+STATUS,state); NRF_WriteReg(FLUSH_TX,NOP); //清除TX FIFO寄存器 /*判断中断类型*/ return state; }
/** * @brief Set ACK payload for RX device * @note require NRF_ACK_PAY_ENABLE, NRF_DPL_ENABLE and enable DynamicPayload on a specific datapipe * @param Pointer to nRF24L01P_Object. * @retval STATUS register in nRF24L01P. */ uint8_t NRF_SetACKPayload(nRF24L01P_Object* nrf) { uint8_t bytecnt, status; if(nrf->MasterMode == NRF_MASTER_MODE_RX) { /* Reset CE pin to enable register write */ NRF_CE_LOW(nrf); /* Reset CS pin to initiate an SPI transmission */ NRF_CS_LOW(nrf); /* Send NRF_W_ACK_PAYLOAD command */ assert_param(nrf->ACKPayload.PayloadWidth <= NRF_MAX_PAYLOAD_WIDTH); status = NRF_SPI_SendByte(nrf, NRF_W_ACK_PAYLOAD); /* Send payload contents */ for(bytecnt = 0; bytecnt < nrf->ACKPayload.PayloadWidth; bytecnt++) { NRF_SPI_SendByte(nrf, nrf->ACKPayload.Payload[bytecnt]); } /* Set CS pin to complete transmission */ NRF_CS_HIGH(nrf); NRF_CE_HIGH(nrf); } return status; }
/** * @brief Send a payload which does not require acknowledgement from RX device. * @note * @param Pointer to nRF24L01P_Object. * @retval STATUS register in nRF24L01P. */ uint8_t NRF_SendPayload_NOACK(nRF24L01P_Object* nrf) { uint8_t bytecnt, status; /* Reset CE pin to enable register write */ NRF_CE_LOW(nrf); /* Reset CS pin to initiate an SPI transmission */ NRF_CS_LOW(nrf); /* Send NRF_W_TX_PAYLOAD_NOACK command */ assert_param(nrf->PayloadToSend.PayloadWidth <= NRF_MAX_PAYLOAD_WIDTH); status = NRF_SPI_SendByte(nrf, NRF_W_TX_PAYLOAD_NOACK); /* Send payload contents */ for(bytecnt = 0; bytecnt < nrf->PayloadToSend.PayloadWidth; bytecnt++) { NRF_SPI_SendByte(nrf, nrf->PayloadToSend.Payload[bytecnt]); } /* Set CS pin to complete transmission */ NRF_CS_HIGH(nrf); /* Hold CE high for at least 10us to send payload */ NRF_CE_HIGH(nrf); return status; }
/* * 函数名:NRF_Rx_Dat * 描述 :用于从NRF的接收缓冲区中读出数据 * 输入 :rxBuf:用于接收该数据的数组,外部定义 * 输出 :接收结果, * 调用 :外部调用 */ u8 NRF_Rx_Dat(u8 *rxbuf) { u8 state; if( nrf_mode != RX_MODE) { NRF_RX_Mode(); } NRF_CE_HIGH(); //进入接收状态 /*等待接收中断*/ while(NRF_Read_IRQ()!=0); NRF_CE_LOW(); //进入待机状态 /*读取status寄存器的值 */ state=NRF_ReadReg(STATUS); /* 清除中断标志*/ NRF_WriteReg(NRF_WRITE_REG+STATUS,state); /*判断是否接收到数据*/ if(state & RX_DR) //接收到数据 { NRF_ReadBuf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据 NRF_WriteReg(FLUSH_RX,NOP); //清除RX FIFO寄存器 return RX_DR; } else { return ERROR; //没收到任何数据 } }
void nrf_reset (void) { NRF_POWER_OFF (); NRF_CS_HIGH (); NRF_CE_LOW (); delay_ms (10); NRF_POWER_ON (); delay_ms (100); // see nRF24L01+ Product Specification Page 22 }
//由中断服务函数调用 void NRF_ISR_Rx_Handler(void) { u8 state; NRF_CE_LOW(); //进入待机状态 /*读取status寄存器的值 */ state=NRF_ReadReg(STATUS); /* 清除中断标志*/ NRF_WriteReg(NRF_WRITE_REG+STATUS,state); if(re_flag == QUEUE_FULL) //满了就直接清FIFO,退出 { NRF_WriteReg(FLUSH_RX,NOP); //清除RX FIFO寄存器 NRF_CE_HIGH(); //进入接收模式 return; //接收队列满了,不进行处理 } //还没满,则继续接收 /*判断是否接收到数据*/ if(state & RX_DR) //接收到数据 { NRF_ReadBuf(RD_RX_PLOAD,(u8 *)&(RX_ISR_FIFO[rear]),RX_PLOAD_WIDTH); //读取数据 NRF_WriteReg(FLUSH_RX,NOP); //清除RX FIFO寄存器 rear++; if(rear >= RX_ISR_FIFO_PACKET) { rear=0; //重头开始 } if(rear == front) //追到屁股了,满了 { re_flag = QUEUE_FULL; } else { re_flag = QUEUE_NORMAL; } } else { //没收到任何数据 } NRF_CE_HIGH(); //进入接收模式 }
//中断发送函数,仅仅发送一次,就等待中断发送 void NRF_ISR_Tx_Dat_Once(void) { if(isr_L > 0) { /*ce为低,进入待机模式1*/ NRF_CE_LOW(); /*写数据到TX BUF 最大 32个字节*/ NRF_WriteBuf(WR_TX_PLOAD,(u8 *)isr_addr,MAX_ONCE_TX_NUM); /*CE为高,txbuf非空,发送数据包 */ NRF_CE_HIGH(); isr_L--; } }
/* * 函数名:NRF_Init * 描述 :SPI的 I/O配置 * 输入 :无 * 输出 :无 * 调用 :外部调用 */ void NRF_Init(void) { //配置NRF管脚复用 spi_init(NRF_SPI,MASTER); //初始化SPI,主机模式 gpio_init(PORTE,28, GPO,LOW); //初始化CE,默认进入待机模式 //gpio_init(PORTE,27, GPI,LOW); //初始化IRQ管脚为输入 gpio_init(PORTA,14, GPO,HIGH); //初始化PCSN管脚为输出,低电平选中 #if IS_USE_ISR exti_init(PORTE,27, falling_up); //初始化IRQ管脚为 :下降沿触发,内部上拉 #else gpio_init(PORTE,27, GPI,LOW); //初始化IRQ管脚为输入 #endif //配置NRF寄存器 NRF_CE_LOW(); NRF_WriteReg(NRF_WRITE_REG+SETUP_AW,ADR_WIDTH - 2); //设置地址长度为 TX_ADR_WIDTH NRF_WriteReg(NRF_WRITE_REG+RF_CH,CHANAL); //设置RF通道为CHANAL NRF_WriteReg(NRF_WRITE_REG+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启 NRF_WriteReg(NRF_WRITE_REG+EN_AA,0x01); //使能通道0的自动应答 NRF_WriteReg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址 //RX模式配置 //NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址 NRF_WriteReg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH); //选择通道0的有效数据宽度 //TX模式配置 //NRF_WriteBuf(NRF_WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH); //写TX节点地址 ,主要为了使能ACK NRF_WriteReg(NRF_WRITE_REG+SETUP_RETR,0x0F); //设置自动重发间隔时间:250us + 86us;最大自动重发次数:15次 #if IS_AUTO_RX_MODE NRF_RX_Mode(); //默认进入接收模式 #endif NRF_CE_HIGH(); while(NRF_Check() == 0); //检测无线模块是否插入:如果卡在这里,说明没检测到无线模块 }
/*! * @brief NRF24L01+初始化,默认进入接收模式 * @return 初始化成功标记,0为初始化失败,1为初始化成功 * @since v5.0 * Sample usage: while(!nrf_init()) //初始化NRF24L01+ ,等待初始化成功为止 { printf("\n NRF与MCU连接失败,请重新检查接线。\n"); } printf("\n NRF与MCU连接成功!\n"); */ uint8 nrf_init(void) { //配置NRF管脚复用 spi_init(NRF_SPI, NRF_CS, MASTER,12500*1000); //初始化SPI,主机模式 gpio_init(NRF_CE_PTXn, GPO, LOW); //初始化CE,默认进入待机模式 gpio_init(NRF_IRQ_PTXn, GPI, LOW); //初始化IRQ管脚为输入 port_init_NoALT(NRF_IRQ_PTXn, IRQ_FALLING | PULLUP); //初始化IRQ管脚为下降沿 触发中断 //配置NRF寄存器 NRF_CE_LOW(); nrf_writereg(NRF_WRITE_REG + SETUP_AW, ADR_WIDTH - 2); //设置地址长度为 TX_ADR_WIDTH nrf_writereg(NRF_WRITE_REG + RF_CH, CHANAL); //设置RF通道为CHANAL nrf_writereg(NRF_WRITE_REG + RF_SETUP, 0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启 nrf_writereg(NRF_WRITE_REG + EN_AA, 0x01); //使能通道0的自动应答 nrf_writereg(NRF_WRITE_REG + EN_RXADDR, 0x01); //使能通道0的接收地址 //RX模式配置 nrf_writebuf(NRF_WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); //写RX节点地址 nrf_writereg(NRF_WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //选择通道0的有效数据宽度 nrf_writereg(FLUSH_RX, NOP); //清除RX FIFO寄存器 //TX模式配置 nrf_writebuf(NRF_WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); //写TX节点地址 nrf_writereg(NRF_WRITE_REG + SETUP_RETR, 0x0F); //设置自动重发间隔时间:250us + 86us;最大自动重发次数:15次 nrf_writereg(FLUSH_TX, NOP); //清除TX FIFO寄存器 nrf_rx_mode(); //默认进入接收模式 NRF_CE_HIGH(); return nrf_link_check(); }
/* * 函数名:SPI_NRF_ReadReg * 描述 :用于从NRF特定的寄存器读出数据 * 输入 :reg:NRF的命令+寄存器地址。 * 输出 :寄存器中的数据 * 调用 :内部调用 */ u8 SPI_NRF_ReadReg(u8 reg) { u8 reg_val; NRF_CE_LOW(); /*置低CSN,使能SPI传输*/ NRF_CSN_LOW(); /*发送寄存器号*/ SPI_NRF_RW(reg); /*读取寄存器的值 */ reg_val = SPI_NRF_RW(NOP); /*CSN拉高,完成*/ NRF_CSN_HIGH(); return reg_val; }
/* * 函数名:SPI_NRF_WriteReg * 描述 :用于向NRF特定的寄存器写入数据 * 输入 :reg:NRF的命令+寄存器地址。 dat:将要向寄存器写入的数据 * 输出 :NRF的status寄存器的状态 * 调用 :内部调用 */ u8 SPI_NRF_WriteReg(u8 reg,u8 dat) { u8 status; NRF_CE_LOW(); /*置低CSN,使能SPI传输*/ NRF_CSN_LOW(); /*发送命令及寄存器号 */ status = SPI_NRF_RW(reg); /*向寄存器写入数据*/ SPI_NRF_RW(dat); /*CSN拉高,完成*/ NRF_CSN_HIGH(); /*返回状态寄存器的值*/ return(status); }
/* * 函数名:SPI_NRF_WriteBuf * 描述 :用于向NRF的寄存器中写入一串数据 * 输入 :reg:NRF的命令+寄存器地址。 pBuf:存储了将要写入写寄存器数据的数组,外部定义 bytes: pBuf的数据长度 * 输出 :NRF的status寄存器的状态 * 调用 :外部调用 */ u8 SPI_NRF_WriteBuf(u8 reg ,u8 *pBuf,u8 bytes) { u8 status,byte_cnt; NRF_CE_LOW(); /*置低CSN,使能SPI传输*/ NRF_CSN_LOW(); /*发送寄存器号*/ status = SPI_NRF_RW(reg); /*向缓冲区写入数据*/ for(byte_cnt=0;byte_cnt<bytes;byte_cnt++) SPI_NRF_RW(*pBuf++); //写数据到缓冲区 /*CSN拉高,完成*/ NRF_CSN_HIGH(); return (status); //返回NRF24L01的状态 }
/* * 函数名:SPI_NRF_ReadBuf * 描述 :用于从NRF的寄存器中读出一串数据 * 输入 :reg:NRF的命令+寄存器地址。 pBuf:用于存储将被读出的寄存器数据的数组,外部定义 bytes: pBuf的数据长度 * 输出 :NRF的status寄存器的状态 * 调用 :外部调用 */ u8 SPI_NRF_ReadBuf(u8 reg,u8 *pBuf,u8 bytes) { u8 status, byte_cnt; NRF_CE_LOW(); /*置低CSN,使能SPI传输*/ NRF_CSN_LOW(); /*发送寄存器号*/ status = SPI_NRF_RW(reg); /*读取缓冲区数据*/ for(byte_cnt=0;byte_cnt<bytes;byte_cnt++) pBuf[byte_cnt] = SPI_NRF_RW(NOP); //从NRF24L01读取数据 /*CSN拉高,完成*/ NRF_CSN_HIGH(); return status; //返回寄存器状态值 }
u8 NRF_ISR_Rx_Dat(u8 *rxbuf) { if( nrf_mode != RX_MODE) { NRF_RX_Mode(); } else { NRF_CE_HIGH(); //进入接收状态 } if(re_flag == QUEUE_EMPTY) //空,直接返回0 { return 0; } //复制数据 nrf_cpy(rxbuf,(u8 *)&(RX_ISR_FIFO[front]),MAX_ONCE_TX_NUM); NRF_CE_LOW(); //进入待机状态 front++; //由于非空,所以可以直接出队列 if(front >= RX_ISR_FIFO_PACKET) { front=0; //重头开始 } if(front == rear) //追到屁股了,接收队列空 { re_flag = QUEUE_EMPTY; // front=0; //重头开始(可以省掉) // rear=0; } NRF_CE_HIGH(); //进入接收模式 return RX_DR; }
/* * 函数名:NRF_TX_Mode * 描述 :配置发送模式 * 输入 :无 * 输出 :无 * 调用 :外部调用 */ void NRF_TX_Mode(void) { u32 i; NRF_CE_LOW(); NRF_WriteBuf(NRF_WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH); //写TX节点地址 NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH); //设置RX节点地址 ,主要为了使能ACK NRF_WriteReg(NRF_WRITE_REG+CONFIG,0x0A | (IS_CRC16<<2)); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,发射模式,开启所有中断 /*CE拉高,进入发送模式*/ NRF_CE_HIGH(); i=0xffff; while(i--); //CE要拉高一段时间才进入发送模式 //DELAY_MS(1); nrf_mode = TX_MODE; }
/* * 函数名:NRF_RX_Mode * 描述 :配置并进入接收模式 * 输入 :无 * 输出 :无 * 调用 :外部调用 */ void NRF_RX_Mode(void) { NRF_CE_LOW(); SPI_NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址 SPI_NRF_WriteReg(NRF_WRITE_REG+EN_AA,0x01); //使能通道0的自动应答 SPI_NRF_WriteReg(NRF_WRITE_REG+EN_RXADDR,0x01);//使能通道0的接收地址 SPI_NRF_WriteReg(NRF_WRITE_REG+RF_CH,CHANAL); //设置RF通信频率 SPI_NRF_WriteReg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度 SPI_NRF_WriteReg(NRF_WRITE_REG+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启 SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG, 0x0f); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式 /*CE拉高,进入接收模式*/ NRF_CE_HIGH(); }
uint8 nrf_tx(uint8 *txbuf, uint32 len) { nrf_irq_tx_flag = 0; //复位标志位 if((txbuf == 0 ) || (len == 0)) { return 0; } if(nrf_irq_tx_addr == 0 ) { // nrf_irq_tx_pnum = (len - 1) / DATA_PACKET; // 进 1 求得 包 的数目 nrf_irq_tx_addr = txbuf; if( nrf_mode != TX_MODE) { nrf_tx_mode(); } //需要 先发送一次数据包后才能 中断发送 /*ce为低,进入待机模式1*/ NRF_CE_LOW(); /*写数据到TX BUF 最大 32个字节*/ nrf_writebuf(WR_TX_PLOAD, txbuf, DATA_PACKET); /*CE为高,txbuf非空,发送数据包 */ NRF_CE_HIGH(); return 1; } else { return 0; } }
void nrf_send_frame (uint8_t * frame) { int ret; nrf_write_reg (R_CONFIG, R_CONFIG_PWR_UP | R_CONFIG_EN_CRC); for (ret = 0; ret < 32; ret++) { UART2PutHex (frame[ret]); UART2PutStr (" "); } UART2PutStr ("\n\r"); NRF_CS_LOW (); SPI2_xmit (C_W_TX_PAYLOAD); SPI2_transmit (frame, 32); NRF_CS_HIGH (); NRF_CE_HIGH (); while (1) { ret = nrf_read_reg (R_FIFO_STATUS); if ((ret & R_FIFO_STATUS_TX_EMPTY) == R_FIFO_STATUS_TX_EMPTY) break; } NRF_CE_LOW (); nrf_write_reg (R_STATUS, R_CONFIG_MASK_RX_DR | R_CONFIG_MASK_TX_DS | R_CONFIG_MASK_MAX_RT); ret = nrf_cmd_status (C_NOP); }
/* * 函数名:NRF_TX_Mode * 描述 :配置发送模式 * 输入 :无 * 输出 :无 * 调用 :外部调用 */ void NRF_TX_Mode(void) { NRF_CE_LOW(); SPI_NRF_WriteBuf(NRF_WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH); //写TX节点地址 SPI_NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK SPI_NRF_WriteReg(NRF_WRITE_REG+EN_AA,0x01); //使能通道0的自动应答 SPI_NRF_WriteReg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址 SPI_NRF_WriteReg(NRF_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次 SPI_NRF_WriteReg(NRF_WRITE_REG+RF_CH,CHANAL); //设置RF通道为CHANAL SPI_NRF_WriteReg(NRF_WRITE_REG+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启 SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG,0x0e); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,发射模式,开启所有中断 /*CE拉高,进入发送模式*/ NRF_CE_HIGH(); Delay(0xffff); //CE要拉高一段时间才进入发送模式 }
void nrf_handler(void) { uint8 state; uint8 tmp; /*读取status寄存器的值 */ nrf_readreg(STATUS, &state); /* 清除中断标志*/ nrf_writereg(NRF_WRITE_REG + STATUS, state); if(state & RX_DR) //接收到数据 { NRF_CE_LOW(); if(nrf_rx_flag != QUEUE_FULL) { //还没满,则继续接收 //printf("+"); nrf_readbuf(RD_RX_PLOAD, (uint8 *)&(NRF_ISR_RX_FIFO[nrf_rx_rear]), RX_PLOAD_WIDTH); //读取数据 nrf_rx_rear++; if(nrf_rx_rear >= RX_FIFO_PACKET_NUM) { nrf_rx_rear = 0; //重头开始 } tmp = nrf_rx_front; if(nrf_rx_rear == tmp) //追到屁股了,满了 { nrf_rx_flag = QUEUE_FULL; } else { nrf_rx_flag = QUEUE_NORMAL; } } else { nrf_writereg(FLUSH_RX, NOP); //清除RX FIFO寄存器 } NRF_CE_HIGH(); //进入接收模式 } if(state & TX_DS) //发送完数据 { if(nrf_irq_tx_pnum == 0) { nrf_irq_tx_addr = 0; // 注意: nrf_irq_tx_pnum == 0 表示 数据 已经全部发送到FIFO 。 nrf_irq_tx_addr == 0 才是 全部发送完了 //发送完成后 默认 进入 接收模式 #if 1 if( nrf_mode != RX_MODE) { nrf_rx_mode(); } #endif //发送长度 为 0个包,即发送完成 //nrf_writereg(FLUSH_TX, NOP); //清除TX FIFO寄存器 } else { if( nrf_mode != TX_MODE) { nrf_tx_mode(); } //还没发送完成,就继续发送 nrf_irq_tx_addr += DATA_PACKET; //指向下一个地址 nrf_irq_tx_pnum --; //包数目减少 /*ce为低,进入待机模式1*/ NRF_CE_LOW(); /*写数据到TX BUF 最大 32个字节*/ nrf_writebuf(WR_TX_PLOAD, (uint8 *)nrf_irq_tx_addr, DATA_PACKET); /*CE为高,txbuf非空,发送数据包 */ NRF_CE_HIGH(); } } if(state & MAX_RT) //发送超时 { nrf_irq_tx_flag = 1; //标记发送失败 nrf_writereg(FLUSH_TX, NOP); //清除TX FIFO寄存器 //有可能是 对方也处于 发送状态 //放弃本次发送 nrf_irq_tx_addr = 0; nrf_irq_tx_pnum = 0; nrf_rx_mode(); //进入 接收状态 //printf("\nMAX_RT"); } if(state & TX_FULL) //TX FIFO 满 { //printf("\nTX_FULL"); } }
/** * @brief Initialize nRF24L01P registers * @note Pointer to nRF24L01P_Object * @param None * @retval None */ uint8_t NRF_Device_Config(nRF24L01P_Object* nrf) { uint8_t bytecnt; uint8_t bufferA[7]; //for register NRF_CONFIG to NRF_RF_SETUP uint8_t bufferB[2]; //for NRF_DYNPD and NRF_FEATURE /* Parameter check */ assert_param(IS_NRF_INT_MASK(nrf->InterruptMask) && \ IS_NRF_CRC(nrf->IntegratedCRC) && \ IS_NRF_CRC_ENCODING(nrf->CRCEncodingScheme) && \ IS_NRF_MASTER_MODE(nrf->MasterMode) && \ IS_NRF_DATAPIPE(nrf->AutoACKEnabledPipe) && \ IS_NRF_DATAPIPE(nrf->RXAddressEnabledPipe) && \ IS_NRF_AFW(nrf->AddressFieldWidth) && \ IS_NRF_ARD(nrf->AutoRetransmitDelay) && \ IS_NRF_ARC(nrf->AutoRetransmitCount) && \ IS_NRF_RF_CHN(nrf->RFChannel) && \ IS_NRF_CCT(nrf->ContinuousCarrierTransmit) && \ IS_NRF_PLL_LOCK(nrf->PLL_Lock) && \ IS_NRF_RF_DR(nrf->AirDataRate) && \ IS_NRF_RF_PWR(nrf->RF_Power) && \ IS_NRF_DATAPIPE(nrf->DynamicPayloadEnabledPipe) && \ IS_NRF_DPL(nrf->DynamicPayloadLength) && \ IS_NRF_ACK_PAY(nrf->PayloadWithACK) && \ IS_NRF_DYN_ACK(nrf->DynamicACK)); // Ensure desired data range // assert_param(((NRF_InitStructure->NRF_DynamicPayloadEnabledPipe) & \ ~(NRF_InitStructure->NRF_AutoACKEnabledPipe)) || \ (!(NRF_InitStructure->NRF_DynamicPayloadLength) && \ (NRF_InitStructure->NRF_DynamicPayloadEnabledPipe))); // Prevent conflict between configurations: // Can not enable dynamic payload when AutoACK or NRF_DPL is disabled /* Assemble contents to send */ bufferA[0] = nrf->InterruptMask | \ nrf->IntegratedCRC | \ nrf->CRCEncodingScheme | \ NRF_PWR_UP | \ nrf->MasterMode; bufferA[1] = nrf->AutoACKEnabledPipe; bufferA[2] = nrf->RXAddressEnabledPipe; bufferA[3] = nrf->AddressFieldWidth - 2; bufferA[4] = nrf->AutoRetransmitDelay | \ nrf->AutoRetransmitCount; bufferA[5] = nrf->RFChannel; bufferA[6] = nrf->ContinuousCarrierTransmit | \ nrf->PLL_Lock | \ nrf->AirDataRate | \ nrf->RF_Power; bufferB[0] = nrf->DynamicPayloadEnabledPipe; bufferB[1] = nrf->DynamicPayloadLength | \ nrf->PayloadWithACK | \ nrf->DynamicACK; NRF_CE_LOW(nrf); /* Send register contents through SPI */ for(bytecnt = 0; bytecnt < 7; bytecnt++) { NRF_WriteReg(nrf, NRF_CONFIG + bytecnt, *(bufferA + bytecnt)); } NRF_WriteMultiByteReg(nrf, NRF_RX_ADDR_P0, nrf->RX_Address_P0, nrf->AddressFieldWidth); NRF_WriteMultiByteReg(nrf, NRF_RX_ADDR_P1, nrf->RX_Address_P1, nrf->AddressFieldWidth); NRF_WriteMultiByteReg(nrf, NRF_TX_ADDR, nrf->TX_Address, nrf->AddressFieldWidth); NRF_WriteReg(nrf, NRF_RX_ADDR_P2, nrf->RX_Address_P2); NRF_WriteReg(nrf, NRF_RX_ADDR_P3, nrf->RX_Address_P3); NRF_WriteReg(nrf, NRF_RX_ADDR_P4, nrf->RX_Address_P4); NRF_WriteReg(nrf, NRF_RX_ADDR_P5, nrf->RX_Address_P5); NRF_WriteReg(nrf, NRF_DYNPD, *bufferB); return NRF_WriteReg(nrf, NRF_FEATURE, *(bufferB + 1)); }