首先看两个版本关于NRF的宏定义:
开发板:
遥控器:
1,最基本的读写函数,函数的返回值就是读来的数据,形参就是写入的数据
stm32mini开发板例程中:
u8 SPI1_ReadWriteByte(u8 TxData)
{
u8 retry=0;
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET)
{
retry++;
if(retry>200)return 0;
}
SPI_I2S_SendData(SPI1, TxData);
retry=0;
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)
{
retry++;
if(retry>200)return 0;
}
return SPI_I2S_ReceiveData(SPI1);
}
mini遥控器中:
static u8 SPI_RWByte(SPI_TypeDef* SPIx , u8 TxData)
{
SPI_I2S_SendData(SPIx, TxData);
while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
return SPI_I2S_ReceiveData(SPIx);
}
区别:开发板多了个超时退出,这个貌似作用不大
2,写寄存器函数
stm32mini开发板例程中:
u8 NRF24L01_Write_Reg(u8 reg,u8 value)
{
u8 status;
NRF24L01_CSN=0;
status =SPI1_ReadWriteByte(reg);
SPI1_ReadWriteByte(value);
NRF24L01_CSN=1;
return(status);
}
mini遥控器中:
static u8 writeReg(u8 reg,u8 value)
{
u8 status;
SPI2_CSN_L();
status=SPI_RWByte(NRF_SPI,reg|CMD_W_REG);
SPI_RWByte(NRF_SPI , value);
SPI2_CSN_H();
return status;
}
对比可知,形参一致,区别在开发板的status =SPI1_ReadWriteByte(reg);//发送寄存器号 和遥控器的status=SPI_RWByte(NRF_SPI,reg|CMD_W_REG);
其实最终都是一样的,只是在使用时,给的形参不同,
在开发板中,这样调用的
寄存器操作命令+寄存器地址
NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta);
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);
或者直接寄存器操作命令
NRF24L01_Write_Reg(FLUSH_RX,0xff);
NRF24L01_Write_Reg(FLUSH_TX,0xff);
在遥控器中,这样调用的
writeReg(REG_STATUS,0x70);
writeReg(REG_RF_CH, channel);
writeReg(REG_RF_SETUP,reg_rf);
writeReg(CMD_FLUSH_TX,0xff);
writeReg(CMD_FLUSH_RX,0xff);
全都一个,不用管寄存器指令,直接传入地址,就因为区别在开发板的status =SPI1_ReadWriteByte(reg);//发送寄存器号 和遥控器的status=SPI_RWByte(NRF_SPI,reg|CMD_W_REG);,遥控器的函数是直接在函数内部将写写配置寄存器与寄存器地址融合,通过按位或,为什么可以这样呢?
因为寄存器操作命令中写配置寄存器为0x20,也就是0010 0000,低5位为寄存器地址,然后下方的寄存器地址刚好就是用了5位,000x xxxx,如NRF_FIFO_STATUS 0x17就是0001 0111,那么两者按位或的结果就是两者的和。
个人觉得遥控器的这个函数不错,可以推测其读寄存器函数也这样干的。
3,读寄存器
stm32mini开发板例程中:
sta=NRF24L01_Read_Reg(STATUS);
搜索一下,发现没有使用 寄存器操作命令+寄存器地址的参数,只用到这一个,或许用不到这个寄存器操作命令,就是算用的,也是0x00,即0000 0000,零和任何数相加都等于那个数
mini遥控器中:
所以这里的这个CMD_R_REG 0x00 // 读寄存器指令和任何数或都等于那个数。
4,在指定位置写指定长度的数据
stm32mini开发板例程中:
u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len)
{
u8 status,u8_ctr;
NRF24L01_CSN = 0;
status = SPI1_ReadWriteByte(reg);
for(u8_ctr=0; u8_ctr<len; u8_ctr++)
SPI1_ReadWriteByte(*pBuf++);
NRF24L01_CSN = 1;
return status;
}
传给形参reg的是寄存器操作命令(读/写寄存器指令)+寄存器地址,和 寄存器操作命令(其他寄存器指令) 用来写待发送的连续数据(字节)到TX BUF 寄存器,和把地址写入到接收应答的通道0——RX_ADDR_P0,发送地址寄存器TX_ADDRESS,接收地址寄存器RX_ADDRESS,如:
NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,buf,5);
NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);
NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);
mini遥控器中:
static u8 writeBuf(u8 cmd,u8 *pBuf,u8 len)
{
u8 status,i;
SPI2_CSN_L();
status=SPI_RWByte(NRF_SPI,cmd);
for(i=0;i<len;i++)
SPI_RWByte(NRF_SPI,*pBuf++);
SPI2_CSN_H();
return status;
}
和开发板一样的,但是他的形参是cmd命令的意思,寄存器操作命令(读/写寄存器指令)+寄存器地址就是个完整的命令,而其他寄存器指令不用加地址,就是一个完整的命令,注意到:writeBuf(u8 cmd,u8 *pBuf,u8 len)和writeReg(u8 reg,u8 value)函数的第一个形参不同,都是写操作,但writeBuf里面没有reg|CMD_W_REG,所以叫cmd,需把完整命令传给cmd,而writeBuf传被写的寄存器地址就行。
cmd完整命令:寄存器操作命令(读/写寄存器指令)+寄存器地址
reg 寄存器:寄存器地址
5,在指定位置读出指定长度的数据
stm32mini开发板例程中:
u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len)
{
u8 status,u8_ctr;
NRF24L01_CSN = 0;
status=SPI1_ReadWriteByte(reg);
for(u8_ctr=0;u8_ctr<len;u8_ctr++)
pBuf[u8_ctr]=SPI1_ReadWriteByte(0XFF);
NRF24L01_CSN=1;
return status;
}
传给形参reg的是寄存器操作命令(读/写寄存器指令)+寄存器地址,和**寄存器操作命令(其他寄存器指令)**用来读寄存器值里连续地址的数据
NRF24L01_Read_Buf(TX_ADDR,buf,5);
NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);
mini遥控器中:
static u8 readBuf(u8 cmd,u8 *pBuf,u8 len)
{
u8 status,i;
SPI2_CSN_L();
status=SPI_RWByte(NRF_SPI,cmd);
for(i=0;i<len;i++)
pBuf[i]=SPI_RWByte(NRF_SPI,0XFF);
SPI2_CSN_H();
return status;
}
形参是cmd命令的意思,寄存器操作命令(读/写寄存器指令)+寄存器地址就是个完整的命令,而其他寄存器指令不用加地址,就是一个完整的命令
6,发送数据包
stm32mini开发板例程中:
u8 NRF24L01_TxPacket(u8 *txbuf)
{
u8 sta;
SPI1_SetSpeed(SPI_BaudRatePrescaler_8);
NRF24L01_CE=0;
NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,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);
return MAX_TX;
}
if(sta&TX_OK)
{
return TX_OK;
}
return 0xff;
}
开发板的发送包函数,里面内容比较多,起发送作用的就一句:
NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);
剩下的代码就是做一些“善后工作”,即等待发送完成,查询状态寄存器,清除标志位,如MAX_RT标志置1后,无法再次发送,需要写1清除该标志位就能再次启动发送,工作在自动应答模式下,只有当接收到应答信号后TX_DS标志位置位1代表发送成功(对方成功接收),写1清0,所以用sta写sta,还清除TX FIFO寄存器 。
mini遥控器中:
void nrf_txPacket(u8 *tx_buf,u8 len)
{
NRF_CE_L();
writeBuf(CMD_W_TX_PAYLOAD,tx_buf,len);
NRF_CE_H();
}
遥控器里的没有做“善后工作”,可能得和其他函数搭配使用。
被下面函数调用
u8 nrf_sendPacketWaitACK(u8 *sendBuf, u8 len, u8 *ackBuf, u8 *acklen)
{
if(len==0) return 0;
nrf_txPacket(sendBuf,len);
while((readReg(REG_STATUS)&0x70) == 0);
nrfEvent_e nrfEvent = nrf_checkEventandRxPacket(ackBuf, acklen);
if(nrfEvent == MAX_RT)
return 0;
return 1;
}
其中while((readReg(REG_STATUS)&0x70) == 0);里,0x07,写为二进制就是0111 0000,REG_STATUS和0x70位与就是得到状态寄存器的4,5,6位的情况,4-MAX-RT:达到最大重发次数,5—TX_DS发送完成,6-RX-DR有效数据来了,只要有一个事件发生,结果 (readReg(REG_STATUS)&0x70) !=0,退出while循环,一个都没发生者循环空语句,即等待。3个中断事件如下
还有调用查询事件并接收数据包函数:nrf_checkEventandRxPacket(ackBuf, acklen);原型如下:
nrfEvent_e nrf_checkEventandRxPacket(u8 *ackBuf, u8 *acklen)
{
nrfEvent_e nrfEvent = IDLE;
*acklen = 0;
u8 status = readReg(REG_STATUS);
if(status&BIT_MAX_RT)
{
writeReg(CMD_FLUSH_TX,0xff);
nrfEvent = MAX_RT;
}
else if(status&BIT_RX_DR)
{
*acklen = nrf_rxPacket(ackBuf);
nrfEvent = RX_DR;
}
else if(status&BIT_TX_DS)
{
nrfEvent = TX_DS;
}
writeReg(REG_STATUS,0x70);
u8 status1 = readReg(REG_STATUS);
status1 = status1;
return nrfEvent;
}
该函数实际操作的还是查询状态寄存器:readReg(REG_STATUS);/读事件标志寄存器/,
看看事件状态(标志)寄存器的4,5,6位的情况是哪种情况发生了,并返回标志,设计了一个枚举,
当没有事件发生时是空闲:nrfEvent_e nrfEvent = IDLE;如果有哪个标志置1就返回该标志:
如果是最大次数标志置位,代表重发失败,得清空该标志,模块才能启动发送:writeReg(CMD_FLUSH_TX,0xff);返回的枚举变量nrfEvent = MAX_RT;
如果是数据到来了,那就调用上面的接收包函数:*acklen = nrf_rxPacket(ackBuf);,存储包,同时存储返回值——包长度,返回的枚举变量nrfEvent = RX_DR;
如果发生成功(即接收到了接收端的自动应答ACK),则返回的枚举变量nrfEvent = TX_DS;。
说明,此函数有三个功能,调用它,就可以知道是重发失败,还是发生成功,还是有数据来了,若是还自动接收数据,代码逻辑上,如果这三种情况都是,那一下就做了三件事,但接收和发生不能同时发生,所以返回值是其中的一种。最后writeReg(REG_STATUS,0x70);/清除标志/,最后两句代码不知道为什么,感觉有点多余
再回到nrf_sendPacketWaitACK函数,它里面就调用nrfEvent_e nrfEvent = nrf_checkEventandRxPacket(ackBuf, acklen);
结合上面的nrf_txPacket(sendBuf,len);
和这个大函数的名字sendPacketWaitACK,可知是NFR在发送模式下掉用的,那只要两种情况,因为使能了重发,结果要么是重发失败,要么是发送成功即收到了应答信号。所以最后判断if(nrfEvent == MAX_RT),返回1就是后种情况。
对比一下开发板的u8 NRF24L01_TxPacket(u8 * txbuf)函数和nrf_sendPacketWaitACK(u8 * sendBuf, u8 len, u8 * ackBuf, u8 * acklen)函数,是不是很有感觉——过程相似? 但在遥控器代码里居然没被调用过,,,,
猜测接收包也有这种类似功能的函数,继续探索,,,,,
7,接收数据包,
stm32mini开发板例程中:
u8 NRF24L01_RxPacket(u8 *rxbuf)
{
u8 sta;
SPI1_SetSpeed(SPI_BaudRatePrescaler_8);
sta=NRF24L01_Read_Reg(STATUS);
NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta);
if(sta&RX_OK)
{
NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);
NRF24L01_Write_Reg(FLUSH_RX,0xff);
return 0;
}
return 1;
}
设置spi速度的那句可以放在spi初始化时调用,起发送包作用的也是一句:
NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);
其他代码有 “善前工作:查询状态有没有接到数据收” 和“善后工作:清除RX FIFO寄存器 ”。还可以用利用中断来提示该接收数据了,如:while(NRF24L01_IRQ!=0);//等待数据到达,因为当数据到达该引脚也会被拉低,这和TX_DS标志位,MAX_RT标志位一样,中断来了就拉低IRQ。
mini遥控器中:
查询事件并接收数据包 函数,nrfEvent_e nrf_checkEventandRxPacket(u8 * ackBuf, u8 * acklen)类似开发板的u8 NRF24L01_RxPacket(u8 * rxbuf函数
nrfEvent_e nrf_checkEventandRxPacket(u8 *ackBuf, u8 *acklen)
{
nrfEvent_e nrfEvent = IDLE;
*acklen = 0;
u8 status = readReg(REG_STATUS);
if(status&BIT_MAX_RT)
{
writeReg(CMD_FLUSH_TX,0xff);
nrfEvent = MAX_RT;
}
else if(status&BIT_RX_DR)
{
*acklen = nrf_rxPacket(ackBuf);
nrfEvent = RX_DR;
}
else if(status&BIT_TX_DS)
{
nrfEvent = TX_DS;
}
writeReg(REG_STATUS,0x70);
u8 status1 = readReg(REG_STATUS);
status1 = status1;
return nrfEvent;
}
里面调用
u8 nrf_rxPacket(u8 *rx_buf)
{
u8 rx_len = readReg(CMD_RX_PL_WID);
if(rx_len>0 && rx_len<33)
{
NRF_CE_L();
readBuf(CMD_R_RX_PAYLOAD,rx_buf,rx_len);
NRF_CE_H();
}
else
rx_len = 0;
writeReg(CMD_FLUSH_RX,0xff);
return rx_len;
}
也是通过
readBuf(CMD_R_RX_PAYLOAD,rx_buf,rx_len);
在调用之前,做了检查工作,查询数据长度是否合理,然后再接收,最后冲洗RX_FIFO,两函数返回值代表的含义不同,0表示失败,len表示成功。而开发板的返回值0代表成功,1代表失败。
8,检查NRF24L01是不是工作正常,ok不ok?
stm32mini开发板例程中:
u8 NRF24L01_Check(void)
{
u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
u8 i;
SPI1_SetSpeed(SPI_BaudRatePrescaler_8);
NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,buf,5);
NRF24L01_Read_Buf(TX_ADDR,buf,5);
for(i=0;i<5;i++)if(buf[i]!=0XA5)break;
if(i!=5)return 1;
return 0;
}
NRF_WRITE_REG+TX_ADDR 寄存器写命令+寄存器地址,
mini遥控器中:
ErrorStatus nrf_check(void)
{
uint64_t addr = 0;
NRF_Init();
writeBuf(CMD_W_REG |REG_TX_ADDR,(u8*)&nrfAddress,5);
readBuf(CMD_R_REG|REG_TX_ADDR,(u8*)&addr,5);
if(nrfAddress==addr)
return SUCCESS;
else
return ERROR;
}
CMD_W_REG |REG_TX_ADDR,就是前面讲述过的:寄存器写命令+寄存器地址,是先通过按位或的方式(结果相当于加法),变成一个完整的操作指令传给cmd。
都是通过写一个地址数据到寄存器,然后都出来,这个过程能实现,说明MCU与24l01是否通讯正常。
9,收发模式设置
stm32mini开发板例程中:
发送和接收模式分开
该函数初始化NRF24L01到RX模式
void NRF24L01_RX_Mode(void)
{
NRF24L01_CE=0;
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);
NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);
NRF24L01_CE = 1;
该函数初始化NRF24L01到TX模式
void NRF24L01_TX_Mode(void)
{
NRF24L01_CE=0;
NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);
NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e);
NRF24L01_CE=1;
}
mini遥控器中:
一个函数,用来初始化设置模式
void nrfInit(enum nrfMode model)
{
NRF_Init();
nrf_setAddress(nrfAddress);
nrf_setChannel(DEFAULT_CHANNEL);
nrf_setDataRate(DEFAULT_DATARATE);
nrf_setPower(DEFAULT_POWR);
nrf_setArd();
nrf_setArc(3);
if(model==PRX_MODE)
{
writeReg(REG_CONFIG, 0x0f);
writeReg(REG_DYNPD,0x01);
writeReg(REG_FEATURE,0x06);
writeReg(REG_EN_AA,0x01);
writeReg(CMD_FLUSH_TX,0xff);
writeReg(CMD_FLUSH_RX,0xff);
}
else
{
writeReg(REG_CONFIG, 0x0e);
writeReg(REG_DYNPD,0x01);
writeReg(REG_FEATURE,0x07);
writeReg(CMD_FLUSH_TX,0xff);
writeReg(CMD_FLUSH_RX,0xff);
}
}
遥控器里的代码把设置NRF24L01的模块工作的参数用单独的函数封装起来了:
1)设置发射和接收应答通道0的地址
/* 这里收发地址一致 ,传一个地址参数*/
void nrf_setAddress(uint64_t address)
{
writeBuf(CMD_W_REG |REG_RX_ADDR_P0,(u8*)&address,5);
writeBuf(CMD_W_REG |REG_TX_ADDR,(u8*)&address,5);
}
参考文档:
在增强型 ShockBurstTM 模式下 RX_ADDR_P0与TX_ADDR地址相等。
接收自动应答通道0的地址0x0A
发送通道地址0x10
通过writeBuf函数在指定位置写入连续字节,最多5个字节,40位。自动应答接收通道只能是接收通道0
2)/* 设置频率通道,channel:0~125 */
void nrf_setChannel(u8 channel)
{
if(channel<=125)
writeReg(REG_RF_CH, channel);
}
参考文档:
通过writeReg函数写入一个字节,设置工作通道频率,共7个可编程位,2的7次方=128,足够用来编0-125这126个通道
3)/* 设置传输速率,dr:0->250KHz、1->1MHz、2->2MHz。 */
void nrf_setDataRate(enum nrfRate dataRate)
{
u8 reg_rf = readReg(REG_RF_SETUP);
reg_rf &= ~((1<<5)|(1<<3));
switch(dataRate)
{
case DATA_RATE_250K:
reg_rf |= 0x20;
break;
case DATA_RATE_1M:
reg_rf |= 0x00;
break;
case DATA_RATE_2M:
reg_rf |= 0x08;
break;
}
writeReg(REG_RF_SETUP,reg_rf);
}
参考文档:
中文版有些错误,对着英文版参考
看手册可知,速率由RF_SRTUP这个地址的第5位RF_DR_LOW和第3位RF_DR_HIGH 决定
[ 第5位 , 第3位 ]
[RF_DR_LOW, RF_DR_HIGH]:
‘00’ – 1Mbps
‘01’ – 2Mbps
‘10’ – 250kbps
‘11’ – Reserved
接下来就涉及到数字电子电路的知识了:
函数第一句就是读该寄存器(REG_RF_SETUP)的值了,也就是得到上面那8个位的情况,用reg_rf存着
第二句:reg_rf &= ~((1<<5)|(1<<3));从右往左看,就是先得到 第5位和第3位 的情况,取反,再和原理的自己位与,这样就只把 第5位和第3位清零了,其他位不变。结果还存在reg_rf。从右往左看,如下运算
reg_rf = (reg_rf )&(~((1<<5)|(1<<3)));
再详细分析一波:
1<<5就是0010 0000
1<<3就是0000 1000
(1<<5)|(1<<3)就是0010 1000
~(1<<5)|(1<<3)就是1101 0111
reg_rf=reg_rf&1101 0111,
0和(0,1)相位与都为0,1和(0,1)相位与都为(0,1),这样一操作结果变成第5位和第3位清零
4)/* 设置发射功率,power: 0->-18dB 1->-12dB 2->-6dB 3->0dB */
void nrf_setPower(enum nrfPower power)
{
u8 reg_rf = readReg(REG_RF_SETUP);
reg_rf &= 0xF8;
switch(power)
{
case POWER_M18dBm:
reg_rf |= 0x00;
break;
case POWER_M12dBm:
reg_rf |= 0x02;
break;
case POWER_M6dBm:
reg_rf |= 0x04;
break;
case POWER_0dBm:
reg_rf |= 0x07;
break;
}
writeReg(REG_RF_SETUP,reg_rf);
}
操作的还是RF_SETUP,只不过是2:1两个位,配置如下
操作过程和上面一样,先把对应的位清零,再或一个要设置的值:
reg_rf &= 0xF8;/* 清除原设功率 */
0xF8就是1111 1000,最低位不用管,也就是2:1位起作用,要设置的也是这两位
dBm —— 2:1
18dBm——00——0000 0000——0x00
12dBm——01——0000 0010——0x02
6 dBm——10——0000 0100——0x04
0 dBm——11——0000 0110——0x06
所以,我怀疑它最后一句reg_rf |= 0x07;是错误的
5)/* 设置重发时间间隔,根据速率及收发字节大小设置 */
void nrf_setArd(void)
{
u8 reg_rf,reg_retr;
reg_rf=readReg(REG_RF_SETUP);
reg_retr=readReg(REG_SETUP_RETR);
if(!(reg_rf&0x20))
reg_retr|= 1<<4;
else
reg_retr|= 5<<4;
writeReg(REG_SETUP_RETR,reg_retr);
}
涉及到两个寄存器,RF_SETUP的状态值与0x20相与,reg_rf&0x20,这个0x20,就是0010 0000,对应到第5位RF_DR_LOW=1, RF_DR_HIGH=0,‘10’ – 250kbps,
如果是250K则间隔reg_retr设置为500us,如果1M或者2M则设置为1500us。在SETUP_RETR寄存器7:4位设置间隔,左移4位,就是对高四位进行操作。但是应该有个对高四位清零的操作reg_retr&=0x01吧,不清0 假如原来reg_retr的高四位ARD为0101,想设置为1001,使用reg_retr|= 5<<4,结果变成了1101.
6)/* 设置重发次数,arc:0~15 */
void nrf_setArc(u8 arc)
{
u8 reg_retr;
if(arc>15)
return;
reg_retr=readReg(REG_SETUP_RETR);
reg_retr|= arc;
writeReg(REG_SETUP_RETR,reg_retr);
}
也是在SETUP_RETR寄存器3:0位设置
也需要对ARC这低四位先清0
10,
mini遥控器中其他几个相关函数:
/* 获取重发失败次数 */
u8 nrf_getTxRetry(void)
{
return readReg(REG_OBSERVE_TX)&0x0F;
}
/* 获取接收功率检测 */
u8 nrf_getRpd(void)
{
return readReg(REG_RPD);
}
void nrf_setIterruptCallback(void(*cb)(void))
{
interruptCb = cb;
}
void EXTI15_10_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line13)==SET)
{
if(interruptCb)
{
interruptCb();
}
EXTI_ClearITPendingBit(EXTI_Line13);
}
}
最后回到
void nrfInit(enum nrfMode model)
{
NRF_Init();
nrf_setAddress(nrfAddress);
nrf_setChannel(DEFAULT_CHANNEL);
nrf_setDataRate(DEFAULT_DATARATE);
nrf_setPower(DEFAULT_POWR);
nrf_setArd();
nrf_setArc(3);
if(model==PRX_MODE)
{
writeReg(REG_CONFIG, 0x0f);
writeReg(REG_DYNPD,0x01);
writeReg(REG_FEATURE,0x06);
writeReg(REG_EN_AA,0x01);
writeReg(CMD_FLUSH_TX,0xff);
writeReg(CMD_FLUSH_RX,0xff);
}
else
{
writeReg(REG_CONFIG, 0x0e);
writeReg(REG_DYNPD,0x01);
writeReg(REG_FEATURE,0x07);
writeReg(CMD_FLUSH_TX,0xff);
writeReg(CMD_FLUSH_RX,0xff);
}
}
有点不是很懂,比如writeReg(REG_FEATURE,0x07); 使能动态长度是做什么的?????
该函数只在函数总调用,只是发送模式,不用接收么???
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)