0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

CW32L012/F030灵眸X1智能小车——使用NRF24L01通信

CW32生态社区 来源:CW32生态社区 2026-04-01 16:49 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

一、NRF24L01模块介绍

引脚介绍

wKgZO2nLxH2AAWOnAABcaF83udk820.jpg

NRF24L01所使用的通讯协议为SPI,SPI又可分为软件SPI和硬件SPI。

硬件SPI与软件SPI相比,硬件SPI是靠硬件上面的SPI控制器,所有的时钟边缘采样,时钟发生,还有时序控制,都是由硬件完成的。它降低了CPU的使用率,提高了运行速度。软件SPI就是用代码控制IO输出高低电平,模拟SPI的时序,这种方法通信速度较慢,且不可靠。

想要使用硬件SPI驱动,需要确定使用的引脚是否有SPI外设功能。可以通过用户手册146页进行查看。

当前使用的是硬件SPI接口,而NRF24L01我们需要与它发送数据也需要接收数据,故使用的是4线的SPI,使用到了时钟线SCK、主机输出从机输入线MOSI、主机输入从机输出线MISO和软件控制的片选线NSS。所以除了这些引脚需要使用硬件SPI功能的引脚外,其他引脚都可以使用开发板上其他的GPIO。这里选择使用PB13/PB14/PB15的SPI复用功能 。其他对应接入的引脚请按照你的需要。这里选择的引脚见下表。

wKgZPGnLxH2AHjwaAAArJpmLA8w159.jpg

模块在开发板上的接线为:

GND ->GND

VCC ->3.3V

CSN ->PA10

CE ->PA9

MOSI->PB15

MISO->PB14

SCK ->PB13

IRQ ->PB8

模块接口原理图

wKgZO2nLxH6AKXHvAAAnaIrGWGI454.jpg

在我们小车主控板中,NRF24L01接口如上,注意不要插反。

二、工程代码

在NRF24L01.H文件中宏定义引脚以及寄存器

//通信引脚
#define IRQ_Pin  GPIO_PIN_8
#define CE_Pin   GPIO_PIN_9
#define CS_Pin   GPIO_PIN_10
#define SCK_Pin  GPIO_PIN_13
#define MISO_Pin GPIO_PIN_14
#define MOSI_Pin GPIO_PIN_15
//寄存器地址代码
#define CONFIG      0x00  // 配置寄存器
#define EN_AA       0x01  // 自动应答功能使能寄存器
#define EN_RXADDR   0x02  // 接收地址使能寄存器
#define SETUP_AW    0x03  // 设置地址宽度寄存器
#define SETUP_RETR  0x04  // 设置重发寄存器
#define RF_CH       0x05  // 射频通道寄存器
#define RF_SETUP    0x06  // 射频设置寄存器
#define STATUS      0x07  // 状态寄存器
#define OBSERVE_TX  0x08  // 发送观察寄存器
#define CD          0x09  // 载波检测寄存器
#define RX_ADDR_P0  0x0A  // 接收地址数据通道0
#define RX_ADDR_P1  0x0B  // 接收地址数据通道1
#define RX_ADDR_P2  0x0C  // 接收地址数据通道2
#define RX_ADDR_P3  0x0D  // 接收地址数据通道3
#define RX_ADDR_P4  0x0E  // 接收地址数据通道4
#define RX_ADDR_P5  0x0F  // 接收地址数据通道5
#define TX_ADDR     0x10  // 发送地址寄存器
#define RX_PW_P0    0x11  // 接收数据通道0有效数据宽度
#define RX_PW_P1    0x12  // 接收数据通道1有效数据宽度
#define RX_PW_P2    0x13  // 接收数据通道2有效数据宽度
#define RX_PW_P3    0x14  // 接收数据通道3有效数据宽度
#define RX_PW_P4    0x15  // 接收数据通道4有效数据宽度
#define RX_PW_P5    0x16  // 接收数据通道5有效数据宽度
#define FIFO_STATUS 0x17  // FIFO状态寄存器
#define DYNPD       0x1C  // 动态有效数据长度寄存器
#define FEATURE     0x1D  // 特性寄存器
//操作指令代码
#define R_REGISTER    0x00  // 读寄存器命令
#define W_REGISTER    0x20  // 写寄存器命令
#define R_RX_PAYLOAD  0x61  // 读取接收有效数据命令
#define W_TX_PAYLOAD  0xA0  // 写入发送有效数据命令
#define FLUSH_TX      0xE1  // 清空发送FIFO命令
#define FLUSH_RX      0xE2  // 清空接收FIFO命令
#define NOP           0xFF  // 无操作命令
//状态
#define RX_OK         0X40
#define TX_OK         0X20
#define MAX_OK        0X10

然后在NRF24L01.C文件中先配置SPI,随后配置NRF24L01寄存器

void NRF24L01_GPIO_Init(void)
{
        RCC_APBPeriphClk_Enable1(RCC_APB1_PERIPH_SPI2,ENABLE);

        __RCC_GPIOA_CLK_ENABLE();
        __RCC_GPIOB_CLK_ENABLE();

        PB13_AFx_SPI2SCK();//开启引脚复用功能
        PB14_AFx_SPI2MISO();
        PB15_AFx_SPI2MOSI();

        GPIO_InitTypeDef GPIO_InitStruct; 
        GPIO_InitStruct.IT=GPIO_IT_NONE;
        GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Pins=MOSI_Pin | SCK_Pin;
        GPIO_InitStruct.Speed=GPIO_SPEED_HIGH;
        GPIO_Init(CW_GPIOB, &GPIO_InitStruct);

        GPIO_InitStruct.IT=GPIO_IT_NONE;
        GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Pins=CS_Pin | CE_Pin;
        GPIO_InitStruct.Speed=GPIO_SPEED_HIGH;
        GPIO_Init(CW_GPIOA, &GPIO_InitStruct);

        GPIO_InitStruct.IT=GPIO_IT_NONE;
        GPIO_InitStruct.Mode=GPIO_MODE_INPUT_PULLUP;
        GPIO_InitStruct.Pins=MISO_Pin | IRQ_Pin;
        GPIO_InitStruct.Speed=GPIO_SPEED_HIGH;
        GPIO_Init(CW_GPIOB, &GPIO_InitStruct);

        W_CS(1);

        SPI_InitTypeDef  SPI_InitStructure; // SPI 初始化结构体
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;    // 双线全双工
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                         // 主机模式
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                     // 帧数据长度为8bit
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                            // 时钟空闲电平为低
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;                          // 第1个边沿采样
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                             // 片选信号由SSI寄存器控制
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;    // 波特率为PCLK的8分频
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                    // 最高有效位 MSB 收发在前
        SPI_InitStructure.SPI_Speed = SPI_Speed_Low;                          // 低速SPI

        SPI_Init(CW_SPI2, &SPI_InitStructure);   // 初始化
        SPI_Cmd(CW_SPI2, ENABLE);   // 使能SPI1
}
uint8_t SPI_SwapByte(uint8_t TxByte)
{
        uint16_t l_Data = 0;
        while(SPI_GetFlagStatus(CW_SPI2, SPI_FLAG_TXE) == RESET);
  SPI_SendData(CW_SPI2, TxByte);
  while(SPI_GetFlagStatus(CW_SPI2, SPI_FLAG_RXNE) == RESET);
  l_Data = SPI_ReceiveData(CW_SPI2);//读取接收数据    
        return l_Data;                //返回
}
void W_Reg(uint8_t Reg,uint8_t value)//写字节
{
        W_CS(0);
        SPI_SwapByte(Reg);
        SPI_SwapByte(value);
        W_CS(1);
}
uint8_t R_Reg(uint8_t Reg)//读字节
{
        uint8_t value;
        W_CS(0);
        SPI_SwapByte(Reg);
        value=SPI_SwapByte(NOP);
        W_CS(1);

        return value;
}
void W_Buf(uint8_t Reg, uint8_t* Buf, uint8_t Len)//连续写
{
        uint8_t i;
        W_CS(0);
        SPI_SwapByte(Reg);
        for(i=0;i< Len;i++)
        {
                SPI_SwapByte(Buf[i]);
        }
        W_CS(1);
}
void R_Buf(uint8_t Reg, uint8_t* Buf, uint8_t Len)//连续读
{
        uint8_t i;
        W_CS(0);
        SPI_SwapByte(Reg);
        for(i=0;i< Len;i++)
        {
                Buf[i]=SPI_SwapByte(NOP);
        }
        W_CS(1);
}
void NRF24L01_Init(void)//初始化
{
        NRF24L01_GPIO_Init();

        W_CE(0);
        W_Buf(W_REGISTER+TX_ADDR,T_ADDR,5);
        W_Buf(W_REGISTER+RX_ADDR_P0,R_ADDR,5);
        W_Reg(W_REGISTER+CONFIG,0x0F);
        W_Reg(W_REGISTER+EN_AA,0x01);
        W_Reg(W_REGISTER+RF_CH,0x00);
        W_Reg(W_REGISTER+RX_PW_P0,32);
        W_Reg(W_REGISTER+EN_RXADDR,0X01);
        W_Reg(W_REGISTER+SETUP_RETR,0X1A);
        W_Reg(FLUSH_RX,NOP);
        W_CE(1);

}
void Receive(uint8_t *Buf)//数据接收
{
        uint8_t Status;
        Status=R_Reg(R_REGISTER+STATUS);
        if(Status & RX_OK)
        {
                R_Buf(R_RX_PAYLOAD,Buf,32);
                W_Reg(FLUSH_RX,NOP);
                W_Reg(W_REGISTER+STATUS,Status);
                RX_Flag=1;
                Delay_us(150);
        }
}
uint8_t Send(uint8_t *Buf)//数据发送
{
        uint8_t Status;
        W_Buf(W_TX_PAYLOAD,Buf,32);

        W_CE(0);
        W_Reg(W_REGISTER+CONFIG,0x0E);
        W_CE(1);

        while(R_IRQ==1);
        Status=R_Reg(R_REGISTER+STATUS);
        if(Status & MAX_OK)
        {
                W_Reg(FLUSH_TX,NOP);
                W_Reg(W_REGISTER+STATUS,Status);
                return MAX_OK;
        }
        if(Status & TX_OK)
        {
                W_Reg(W_REGISTER+STATUS,Status);
                return TX_OK;
        }
}
uint8_t Receive_Flag(void)//接收标志位
{
        if(RX_Flag==1)
        {
                RX_Flag=0;
                return 1;
        }
        else{
                return 0;
        }
}

三、实验现象

在发送端main函数中写入如下代码

int main(void)
{
        uint8_t Buf[32]={0x00,0x67,0x68,0x69,0x70},num=0;
        OLED_Init();//初始化
        NRF24L01_Init();
        OLED_ShowString(1,1,"Send ok");
        while(1)
        {
                num++;
                Buf[0]=num;
                Send(Buf);
                Delay_s(1);
        }
}

在接收端main函数中写入如下代码

int main(void)
{
        uint8_t Buf[32]={0};
        OLED_Init();//初始化
        NRF24L01_Init();
        OLED_ShowString(1,1,"Receive ok");
        while(1)
        {
                Receive(Buf);
                if(Receive_Flag()==1)
                {
                        OLED_ShowNum(3,1,Buf[0],3);
                        OLED_ShowHexNum(2,4,Buf[1],2);
                        OLED_ShowHexNum(2,7,Buf[2],2);
                        OLED_ShowHexNum(2,10,Buf[3],2);
                        OLED_ShowHexNum(2,13,Buf[4],2);
                }
        }
}

然后现象如下

发送端发送四个十六进制数据以及一个递增的十进制数据,OLED屏幕显示 Send ok

wKgZPGnLxH-ANNBrAB-4h0sRRSI601.jpg

接收端第一行显示Receive OK,第二行显示接收到的固定十六进制数据,第三行显示接收到的十进制数据

wKgZO2nLxICABrnXAA1T1MDbySs891.jpg

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • SPI
    SPI
    +关注

    关注

    17

    文章

    1897

    浏览量

    102081
  • 智能小车
    +关注

    关注

    87

    文章

    565

    浏览量

    83516
  • CW32
    +关注

    关注

    1

    文章

    323

    浏览量

    1953
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    nrf24l01遥控小车

    一个nrf24l01的遥控小车 可以当做学习NRF24L01的学习资料哦 我找了很多才找到的
    发表于 06-17 20:16

    基于nRF24L01的无线通信系统

    介绍一种由nRF24L01型无线数字传输器和ARM系列MCU组成的无线数字传输系统;详细阐述了硬件和软件的设计要点;给出了基于LPC214x设计的nRF24L01硬件接口电路和程序代码;讨论了该系统
    发表于 12-22 17:05 261次下载

    NRF24l01无线232通信_底层文件版本

    NRF24l01无线232通信 底层文件
    发表于 12-08 14:00 0次下载

    基于nRF24L01的通用无线通信模块设计

    基于nRF24L01的通用无线通信模块设计
    发表于 01-04 15:25 64次下载

    NRF24L01编程心得

    51版NRF24L01双向通信详细资料及程序,调试成功
    发表于 03-22 11:26 0次下载

    NRF24L01程序

    NRF24L01 51,stm32,430程序
    发表于 12-29 20:56 25次下载

    nRF24L01无线2.4G通信模块的详细研究资料说明

     承接上文,本节将从零开始带你认识无线2.4G模块,了解其控制和通信指令,从而封装一个nRF24L01底层的驱动函数,并最终写一个3-3通信的小实验验证我们的封装。在Quick Know部分你将快速
    发表于 05-29 17:57 23次下载
    <b class='flag-5'>nRF24L01</b>无线2.4G<b class='flag-5'>通信</b>模块的详细研究资料说明

    nrf24l01是什么模块_nrf24l01工作原理

    本文首先阐述了nrf24l01概念,其次介绍了nrf24l01的性能参数,最后介绍了nrf24l01的工作原理。
    发表于 04-24 08:47 2.1w次阅读

    nrf24l01发射功率测试_nrf24l01可以做什么

    本文主要阐述了nrf24l01发射功率测试步骤及nrf24l01的应用领域。
    发表于 04-24 08:55 8306次阅读

    基于NRF24L01的AVR双机通信

    基于NRF24L01的AVR双机通信
    发表于 11-15 21:06 5次下载
    基于<b class='flag-5'>NRF24L01</b>的AVR双机<b class='flag-5'>通信</b>

    nRF24L01无线通信模块使用简介

    nRF24L01无线通信模块使用简介(STC51)nRF24L01研一课设做过一个基于nRF24L01的无线温湿度传感器,在这里把C51单片机搭配n
    发表于 11-23 17:51 49次下载
    <b class='flag-5'>nRF24L01</b>无线<b class='flag-5'>通信</b>模块使用简介

    使用nRF24L01模块进行无线射频通信

    使用nRF24L01模块进行无线射频通信
    的头像 发表于 08-01 11:18 6442次阅读
    使用<b class='flag-5'>nRF24L01</b>模块进行无线射频<b class='flag-5'>通信</b>

    NRF24L01无线通信介绍

    过串口打印到电脑上。 NRF24L01 无线模块,采用的芯片是 NRF24L01,该芯片的主要特点如下: 1. 2.4G 全球开放的 ISM 频段,免许可证使用。 2. 最高工作速率 2Mbps,高校的 GFSK 调制,抗干扰
    发表于 05-30 14:17 1次下载
    <b class='flag-5'>NRF24L01</b>无线<b class='flag-5'>通信</b>介绍

    基于nRF24L01的无线通信系统设计

    电子发烧友网站提供《基于nRF24L01的无线通信系统设计.pdf》资料免费下载
    发表于 10-26 14:42 1次下载
    基于<b class='flag-5'>nRF24L01</b>的无线<b class='flag-5'>通信</b>系统设计

    基于nRF24L01的通用无线通信模块设计案例

    电子发烧友网站提供《基于nRF24L01的通用无线通信模块设计案例.pdf》资料免费下载
    发表于 11-06 16:28 9次下载
    基于<b class='flag-5'>nRF24L01</b>的通用无线<b class='flag-5'>通信</b>模块设计案例