调试备忘录

您所在的位置:网站首页 nrf24l01p 调试备忘录

调试备忘录

#调试备忘录| 来源: 网络整理| 查看: 265

目录--点击可快速直达

MCU:KEAZ64A

MDK:CodeWarrior 11.0

目录写在前面什么是nRF24L01P?nRF24L01P模块的简单介绍nRF24L01P的工作模式nRF24L01P模块的初始化简易配置nRF24L01P模块调试的一些小技巧附上源码

写在前面

因为最近在重写之前项目的代码,以提升系统的稳定性和代码的可读性,所以重新选择了一块nRF24L01P,进行调试。

以下算是一些调试的备忘录吧,如有问题可以通过私信或者邮箱联系我。

什么是nRF24L01P?

nRF24L01P是一颗工作在 2.4GHz ISM 频段,专为低功耗无线场合设计,集成嵌入式 ARQ基带协议引擎的无线收发器芯片。

工作频率范围为 2400MHz-2525MHz,共有 126 个 1MHz带宽的信道。

简单来说,就是一块基于民用频段的无线通信芯片,可以用于无线鼠标、无线键盘、遥控器、工业传感器等应用。

后面我要使用的模块是在某宝上买的泽耀的nRF24L01P无线通信模块,以下的一些图片也是截取自它家的产品资料。

nRF24L01P模块的简单介绍

nRF24L01P模块一共有八个引脚,其中4个SPI引脚,一共工作模式切换引脚和一个终端引脚。

推荐与MCU的连接图

nRF24L01P的工作模式

nRF24L01P使用SPI进行通讯,可以通过SPI设置nRF24L01P的寄存器来改变nRF24L01P的工作模式。

如图所示,nRF24L01P的工作模式有如上几种,我们主要使用的就是接收模式、发射模式以及在两者之间过渡的待机模式II。

通过改变CONFIG寄存器中的PRIM_RX的值和模块引脚CE的高低电平,就可以切换工作模式了。

工作模式之间切换是有延时的,如果不加延时,可能导致未知的问题。一定要按照芯片手册中的资料来增加延时。

nRF24L01P模块的初始化简易配置

(一对一模式,使用接收通道0,禁止自动重发)

寄存器 位名 推荐值 备注 TX_ADDR None 0x34 0x43 0x10 0x10 0x01 发射地址 RX_ADDR_P0 None 0x34 0x43 0x10 0x10 0x01 接收通道0地址 EN_AA None 0 禁止自动应答 SETUP_RETR None 0 禁止自动重发 EN_RXADDR ERX_P0 0x01 使能通道0 RF_CH None 40 设置通道频率 RX_PW_P0 None 0x05 设置P0通道的数据宽度 RF_SETUP None 0x07 设置发射功率以及数据传输数率 CONFIG None 0x3e 禁止发射中断,使能发射模式

注: 1.配置寄存器时,一定要按照SPI的指令格式进行配置。如下图。

nRF24L01P模块调试的一些小技巧

1.刚开始调试的时候一定要选择一个模块为发射模式,一个模块为接收模式。发射的开启发射中断,接收的开启接收中断。这样就可以用过在中断中加入显示(例如LED)开观察是否发射成功或者接收成功。

2.刚开启中断的时候一定要记得清除中断标志位,中断标志位有两个,一个是模块的中断标志位,一个是MCU的中断标志位。

3.对于发射模式,切换发射模式的时候,最好把发射地址(TX_ADDR)也重新写一遍,因为我在调试的时候发现,如果不重写一遍地址,就会出问题。当然,这个可能是模块的BUG,因人而异把。

4.如果有问题,记得使用示波器查看SPI引脚、CE和IRQ的运行情况。

5.写入寄存器的时候记得拉低CE引脚。

6.如果还是有未知的问题,可以试试延长一下操作IO的时间。

附上源码

软件模拟的SPI通信,方便移植。

/** ****************************************************************************** * @file drv_spi.c * @author xxx * @version V1.0 * @date 2020-1-04 * @brief SPI配置C文件 ****************************************************************************** */ #include "common.h" /* * PTB2->SCK PTF0->CE * PTB3->MOSI PTE2->MISO * PTD2->CSN IRQ->PTA6 * * PTE0->SCK PTG3->CE * PTE1->MOSI PTE2->MISO * PTE3->CSN IRQ->PTC7 */ void spi_set_clk_low( ) { //GPIO_Set_IO_Value(PORT_B,GPIO_PIN_2,OUTPUT_LOW); GPIO_Set_IO_Value(PORT_E,GPIO_PIN_0,OUTPUT_LOW); } void spi_set_clk_high( ) { //GPIO_Set_IO_Value(PORT_B,GPIO_PIN_2,OUTPUT_HIGH); GPIO_Set_IO_Value(PORT_E,GPIO_PIN_0,OUTPUT_HIGH); } void spi_set_mosi_low( ) { GPIO_Set_IO_Value(PORT_E,GPIO_PIN_1,OUTPUT_LOW); } void spi_set_mosi_hight( ) { GPIO_Set_IO_Value(PORT_E,GPIO_PIN_1,OUTPUT_HIGH); } unsigned char spi_get_miso( ) { return GPIO_Get_IO_Value(PORT_E,GPIO_PIN_2); } void spi_set_nss_low( ) { GPIO_Set_IO_Value(PORT_E,GPIO_PIN_3,OUTPUT_LOW); } void spi_set_nss_high( ) { GPIO_Set_IO_Value(PORT_E,GPIO_PIN_3,OUTPUT_HIGH); } /** 软件SPI */ /** * @brief :SPI初始化(软件) * @param :无 * @note :无 * @retval:无 */ void drv_spi_init( void ) { /*GPIO_Init_IO(PORT_B,GPIO_PIN_2,OUTPUT); GPIO_Init_IO(PORT_B,GPIO_PIN_3,OUTPUT); GPIO_Init_IO(PORT_E,GPIO_PIN_2,INPUT); GPIO_Init_IO(PORT_D,GPIO_PIN_2,OUTPUT);*/ GPIO_Init_IO(PORT_E,GPIO_PIN_0,OUTPUT); GPIO_Init_IO(PORT_E,GPIO_PIN_3,OUTPUT); GPIO_Init_IO(PORT_E,GPIO_PIN_2,INPUT); GPIO_Init_IO(PORT_E,GPIO_PIN_1,OUTPUT); } /** * @brief :SPI收发一个字节 * @param : * @TxByte: 发送的数据字节 * @note :非堵塞式,一旦等待超时,函数会自动退出 * @retval:接收到的字节 */ uint8_t drv_spi_read_write_byte( uint8_t TxByte ) { uint8_t i = 0, Data = 0; spi_set_clk_low( ); for( i = 0; i < 8; i++ ) //一个字节8byte需要循环8次 { /** 发送 */ if( 0x80 == ( TxByte & 0x80 )) { spi_set_mosi_hight( ); //如果即将要发送的位为 1 则置高IO引脚 } else { spi_set_mosi_low( ); //如果即将要发送的位为 0 则置低IO引脚 } TxByte MISO * PTD2->CSN IRQ->PTA6 * * PTE0->SCK PTG3->CE * PTE1->MOSI PTE2->MISO * PTE3->CSN IRQ->PTC7 */ void RF24L01_SET_CS_LOW() { GPIO_Set_IO_Value(PORT_E,GPIO_PIN_3,OUTPUT_LOW); } void RF24L01_SET_CS_HIGH() { GPIO_Set_IO_Value(PORT_E,GPIO_PIN_3,OUTPUT_HIGH); } void RF24L01_SET_CE_LOW() { GPIO_Set_IO_Value(PORT_G,GPIO_PIN_3,OUTPUT_LOW); } void RF24L01_SET_CE_HIGH() { GPIO_Set_IO_Value(PORT_G,GPIO_PIN_3,OUTPUT_HIGH); } unsigned char RF24L01_GET_IRQ_STATUS() { return GPIO_Get_IO_Value(PORT_C,GPIO_PIN_7); } /** * @brief :NRF24L01读寄存器 * @param : @Addr:寄存器地址 * @note :地址在设备中有效 * @retval:读取的数据 */ 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:读取状态 */ 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:读写状态 */ void NRF24L01_Write_Reg( uint8_t RegAddr, uint8_t Value ) { 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:写状态 */ 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:无 */ 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:无 */ 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:无 */ 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:无 */ void NRF24L01_Nop( void ) { RF24L01_SET_CS_LOW( ); //片选 drv_spi_read_write_byte( NOP ); //空操作命令 RF24L01_SET_CS_HIGH( ); //取消片选 } /** * @brief :NRF24L01读状态寄存器 * @param :无 * @note :无 * @retval:RF24L01状态 */ 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:清除后状态寄存器的值 */ uint8_t NRF24L01_Clear_IRQ_Flag( uint8_t IRQ_Source ) { uint8_t btmp = 0; //IRQ_Source &= ( 1 5 ) ? 5 : len; //地址不能大于5个字节 NRF24L01_Write_Buf( TX_ADDR, pAddr, len ); //写地址 } /** * @brief :设置接收通道地址 * @param : * @PipeNum:通道 * @pAddr:地址存肥着地址 * @Len:长度 * @note :通道不大于5 地址长度不大于5个字节 * @retval:无 */ 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:无 */ void NRF24L01_Set_Speed( nRf24l01SpeedType Speed ) { uint8_t btmp = 0; btmp = NRF24L01_Read_Reg( RF_SETUP ); btmp &= ~( ( 1


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3