OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 384|回复: 2

NRF905无线收发, 硬件SPI和软件SPI两种功能

[复制链接]

6

主题

67

帖子

0

精华

高级会员

Rank: 4

积分
554
金钱
554
注册时间
2016-7-29
在线时间
125 小时
发表于 2026-9-28 20:55:16 | 显示全部楼层 |阅读模式
本帖最后由 小迷哥 于 2026-9-30 15:34 编辑

最近在调NRF905, NRF24L01将遇到的一些问题总结一下
看了很多网友的资料,发现都写得不怎么清晰,将自己的测试过程梳理出来主控芯片使用:STM32F103ZET6

一:SPI功能
1)SPI有mode0, 1, 2, 3共4种模式,实测NRF905, NRF24L01只支持mode0, 其中NRF905手册明确要求用mode0;
2) 这个SPI是全双工模式,MISO和MOSI两条线上同时走数据,本质为主机的移位寄存器和从机的移位寄存器内数据单字节交换;
这里面包含以下几种情况,这个主要根据SPI从机支持的指令来:
  • 主机只写,不处理返回值
  • 主机只读,通常写入数据0xFF
  • 主机又写又读
3)使用的硬件SPI2, 读写就靠1个函数"u8 SPI2_ReadWriteByte(u8 TxData)",实现全双工读写
如果使用软件SPI方式,那么也是一样的要实现这个全双工读写,"u8 spisoft_readwrite(u8 TxData)",并且支持4种mode, 以及宏延时设置

4)这种SPI从设备,驱动大多是"指令+数据方式", 比如下

比如我们想写某个配置寄存器,地址为add=0x00, 那么就要先写指令0x00, 在写数据1字节或多字节
如果读某个配置寄存器,地址为add=0x00, 那么就要先写指令0x20|add, 紧接着从机通过MISO就会输出数据;

5) 这个NRF905和NRF24L01和其他SPI从设备,有个最大的区别就是,只要启动了1次SPI读或写,在写入第一个指令字节时,会同时输出
状态字节,就下图中的S7:0;
二:收发功能

这里面如果要写配置寄存器或者,写发送地址,写发送数据,必须要在standby/掉电模式下

1)其中比较特别的一点是:发送模式下,需要将TRX_CE拉低,触发发送,同时可以清除DR脚信号为低电平
2)DR脚,在发送模式下,如果为1表示已发送完成, 在接收模式下为1表示已收到数据
这个DR清零是通过将TRX_CE拉低方式清除;
3)这个NRF905可以工作的频率是3个段, 433Mhz, 868Mhz, 915Mhz;
4)只支持1对1通信;

三:程序设计和调试
1.程序参考原子的stm32f1标准库方式, NRF24L01实验,
使用2块开发板,通过按键选择RX或TX模式后,就会间隔1.5s发送32字节可见ASCII数据;

2.新增加的功能
1) 在上面移植了usamrt,这样可以直接读取任意配置寄存器或者指令寄存器下所有数据;
可以将1个NRF905设置为RX模式,在电脑端通过"u8 NRF905_TxPacket(u8 *txbuf)",发送任意字符数据,这里只支持ASCII字符显示,
需要显示中的,需要自己去移植;

2)支持软件SPI模式,这个参考了电阻式XPT2046触摸屏程序的驱动部分;
  1. #include "spi_soft.h"

  2. //////////////////////////////////////////////////////////////////////////////////         
  3. //作者:Planets
  4. //创建日期:2026/9/24
  5. //版本:V0.0.0                                                                  
  6. //功能:
  7. //1.软件模式SPI方式,支持模式0/1/2/3;
  8. //2.通信速率通过延时时间调整;
  9. //3.使用任意IO口,方便在没有硬件SPI时,也能正常控制,像51这种都是使用模拟时序方式;
  10. //4.包括读/写单字节,读/写多字节;
  11. //////////////////////////////////////////////////////////////////////////////////         
  12. //修改记录
  13. /*
  14. 2026/9/24 V0.0.1 by Planets

  15. */
  16. //////////////////////////////////////////////////////////////////////////////////

  17. //变量声明
  18. MYSPI_Mode_TypeDef my_spi_mode={0,0};//SPI模式0
  19. //MYSPI_Mode_TypeDef my_spi_mode={0,1};//SPI模式1
  20. //MYSPI_Mode_TypeDef my_spi_mode={1,0};//SPI模式2
  21. //MYSPI_Mode_TypeDef my_spi_mode={1,1};//SPI模式3

  22. //功能:模拟IO口初始化
  23. //#define MYSPI_SCK       PBout(13)
  24. //#define MYSPI_MISO      PBin(14)
  25. //#define MYSPI_MOSI      PBout(15)
  26. void spisoft_Init(void)
  27. {
  28.     GPIO_InitTypeDef  GPIO_InitStructure;

  29.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

  30.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_15;                                 
  31.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  
  32.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;               
  33.     GPIO_Init(GPIOB, &GPIO_InitStructure);                                         

  34.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;                                 
  35.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;                                 
  36.     GPIO_Init(GPIOB, &GPIO_InitStructure);        

  37.     if(my_spi_mode.CPOL) {MYSPI_SCK_H();}//空闲电平设置
  38.     else {MYSPI_SCK_L();}

  39.     MYSPI_MOSI_H();
  40. }

  41. //功能:全双工读写1字节,MSB先行,SPI模式判断
  42. //TxData:要写入的数据
  43. //返回:读出的数据
  44. u8 spisoft_readwrite(u8 TxData)
  45. {
  46.     u8 i, rx=0;

  47.     for(i=0;i<8;i++)
  48.     {
  49.         //MOSI往总线上送数据
  50.         if(TxData&0x80) {MYSPI_MOSI_H();}
  51.         else {MYSPI_MOSI_L();}

  52.         TxData<<=1;
  53.         MYSPI_DLAY(DLAY_TIME);

  54.         if(my_spi_mode.CPHA==0)/* CPHA=0:第一个时钟沿采样 */
  55.         {
  56.             if(my_spi_mode.CPOL==0)//SPImode0
  57.             {
  58.                 MYSPI_SCK_H();//上升沿采样
  59.                 MYSPI_DLAY(DLAY_TIME);
  60.                 rx<<=1;
  61.                 if(MYSPI_MISO_READ()) rx|=0x01;
  62.                 MYSPI_SCK_L();
  63.                 MYSPI_DLAY(DLAY_TIME);
  64.             }else//SPImode1
  65.             {
  66.                 MYSPI_SCK_L();//下降沿采样
  67.                 MYSPI_DLAY(DLAY_TIME);
  68.                 rx<<=1;
  69.                 if(MYSPI_MISO_READ()) rx|=0x01;
  70.                 MYSPI_SCK_H();
  71.                 MYSPI_DLAY(DLAY_TIME);
  72.             }
  73.         }else/* CPHA=1:第二个时钟沿采样 */
  74.         {
  75.             if(my_spi_mode.CPOL==0)//SPImode2
  76.             {
  77.                 MYSPI_SCK_H();//上升沿采样
  78.                 MYSPI_DLAY(DLAY_TIME);
  79.                 MYSPI_SCK_L();
  80.                 MYSPI_DLAY(DLAY_TIME);
  81.                 rx<<=1;
  82.                 if(MYSPI_MISO_READ()) rx|=0x01;
  83.             }else//SPImode3
  84.             {
  85.                 MYSPI_SCK_L();//下降沿采样
  86.                 MYSPI_DLAY(DLAY_TIME);
  87.                 MYSPI_SCK_H();
  88.                 MYSPI_DLAY(DLAY_TIME);
  89.                 rx<<=1;
  90.                 if(MYSPI_MISO_READ()) rx|=0x01;
  91.             }
  92.         }
  93.     }
  94.     return rx;
  95. }
复制代码

3)使用的模块,在下面这家买的
这里面引脚使用情况如下
//CSN-----PC0, SPI使能  
//TX_EN---PC1, 1发送,0接收
//TRX_CE--PC2, 使能发射或接收
//PWR_UP--PC3, 芯片上电
//CD------PC4, 载波检测,不用
//AM------PC5, 地址匹配,不用
//DR------PC6, 接收或发射数据完成

//SCK-----PB13
//MISO-----PB14
//MOSI-----PB15
总共需要:8个引脚, 其中SPI控制4个, 模块控制4个
通过DR电平为1时,判断发送/接收完成,

ScreenShot_2026-09-28_203432_138.png
ScreenShot_2026-09-28_201332_729.png
ScreenShot_2026-09-28_201050_211.png
微信图片_2026-09-28_200623_549.png

实验33 NRF905实验V0.0.1主机.rar

391.63 KB, 下载次数: 1

Planets, no limit!
回复

使用道具 举报

6

主题

67

帖子

0

精华

高级会员

Rank: 4

积分
554
金钱
554
注册时间
2016-7-29
在线时间
125 小时
 楼主| 发表于 2026-9-28 21:03:26 | 显示全部楼层
cool, 给自己打个call
Planets, no limit!
回复 支持 反对

使用道具 举报

6

主题

67

帖子

0

精华

高级会员

Rank: 4

积分
554
金钱
554
注册时间
2016-7-29
在线时间
125 小时
 楼主| 发表于 2026-9-28 22:18:51 | 显示全部楼层
cool, 感谢留言
Planets, no limit!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /1 下一条

正点原子公众号

如发现本坛存在违规或侵权内容, 请点击这里发送邮件举报 (或致电020-38271790)。请提供侵权说明和联系方式。我们将及时审核依法处理,感谢配合。

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2026-10-9 00:18

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表