NRF24L01(2.4G)模块的使用——SPI时序(软件)篇

2024-06-08 18:12

本文主要是介绍NRF24L01(2.4G)模块的使用——SPI时序(软件)篇,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、SPI的简介:

        SPI 是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口Motorola首先在其MC68HCXX系列处理器上定义的

        SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上占用四根线,SCK(Serial Clock)、MOSI(Master Output Slave Input)、MISI(Master Input Slave Output)、SS(Slave Select) ,其支持总线挂载多设备(一主多从)。主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间

                                SPI接口一般使用4条线通信:

   MISO 主机输入从机输出。主机通过MOSI输入,从机通过MOSI输出。

   MOSI 主机输出从机输入。主机通过MOSI输出,从机通过MOSI输入。

   SCLK时钟线,完全由主机掌握,主要是产生时钟信号,由主设备产生。对于主机来说时钟线为输出,对于从机来说,所有时钟线为输入。

   CS从设备片选信号,由主设备控制,低电平有效。主机选择从机时,只需要将连接对应的ss线置0就可以选择此从机了。相较于IIC,这种方法更简单但会浪费更多引脚,但无需IIC一样先进行寻址(SS线置0相当于寻址了)。

二、SPI时序介绍

1. spi四种模式详解:

        在spi的模式配置中,有两个很关键的东西,即SPI_CR1的第0和1位:

模式0:CPOL = 0、CPHA = 0

        由于CPOL为0,也就是空闲状态下SCK为低电平;CPHA = 0,也就是从第一个边沿开始采样,也就是上升沿采样。下图是截取NRF24l01的读写时序图,为模式0;起始SCK为低电平,上升沿采样。下降沿移出数据为下一次采样做准备。   由于第一个上升沿就要采样数据,所以得在第一个上升沿就要把数据移出,也就是把CSN的下降沿当作时钟的一部分了。从图中可以看见,CSN下降沿时数据变化(主机输出数据最高位,将数据放于MOSI线上),然后第一个上升沿采样(主机和从机读取数据,主机读从机的最高位,从机读主机的数据最高位),第一个下降沿主机输出次高位(当然,从机也会动作,但从机不需要我们操作),再第二上升沿采样......即先有了下降沿才能有数据变换的条件

第一个时序代码如下:CSN 在选择从机时会拉低,所以这里没写,拉低SS后,主机移出数据,方便从机在下一个上升沿读。此时拉高SCK,主机读从机发来的数据,从机也会读主机发来的数据,注意,为高位先行。然后拉低SCK,主机和从机输出数据,方便下个上升沿读取数据,这样,第一个周期时序就完成了,接下来只需for循环8次就可以了,这样就完成了一次数据交换。和IIC不同的是IIC有读写函数,而SPI读写是同时进行的。

uint8_t MySPI_SW_Byte(uint8_t Byte)
{uint8_t receivebyte = 0x00;for(uint8_t i=0;i<8;i++){SPI_MOSI((BitAction)(Byte & 0x80));SPI_SCK(1);if(Read_MOSI == 1)receivebyte |= 0x80;SPI_SCK(0);}return receivebyte;
}

模式1:CPOL = 0、CPHA = 1

        由于CPOL为0,也就是空闲状态下SCK为低电平;CPHA = 1,也就是从第一个边沿开始移出数据。此时主机将数据最高位放到MOSI线上,从机将数据放到MISO上,也就是上升沿输出。第二个边沿(下降沿)移入数据,即读取数据(主机读MISO,从机读MOSI)到这里完成了一个时序周期。

模式2:CPOL = 1、CPHA = 0

        由于CPOL为0,也就是空闲状态下SCK为高电平;CPHA = 0,也就是从第一个边沿开始移入数据(注:由于空闲时为高电平,所以第一个边沿变成了下降沿)。此时读取数据(主机读MISO,从机读MOSI)。第二个边沿(上升沿)移出数据,主机将数据最高位放到MOSI线上,从机将数据放到MISO上,也就是上升沿输出。到这里完成了一个时序周期即。

模式3:CPOL = 1、CPHA = 1

          由于CPOL为1,也就是空闲状态下SCK为高电平;CPHA = 1,也就是从第一个边沿(下降沿)开始移出数据。此时主机将数据最高位放到MOSI线上,从机将数据放到MISO上,也就是下降沿输出。第二个边沿(上升沿)移入数据,即读取数据(主机读MISO,从机读MOSI)到这里完成了一个时序周期。

三、SPI的初始化

下面进行SPI的初始化:

        由于我们采用的是软件SPI,所以MOSI和SCK配置为推挽输出,而MISO是从机输出线,从机掌握主动权,所以配置为上拉输入。

void MySPI_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;//定义一个GPIO_InitTypeDef类型的结构体RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启GPIO端口时钟GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//通用推挽输出GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//引脚速率50MHZGPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//上拉输入GPIO_Init(GPIOA, &GPIO_InitStructure);SPI_SCK(0);
}

即SPI代码如下:

spi.c

#include "spi.h"void MySPI_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;//定义一个GPIO_InitTypeDef类型的结构体RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启GPIO端口时钟GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//通用推挽输出GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//引脚速率50MHZGPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//上拉输入GPIO_Init(GPIOA, &GPIO_InitStructure);SPI_SCK(0);
}uint8_t MySPI_SW_Byte(uint8_t Byte)
{uint8_t receivebyte = 0x00;for(uint8_t i=0;i<8;i++){SPI_MOSI((BitAction)(Byte & (0x80>>i)));SPI_SCK(1);if(Read_MOSI == 1)receivebyte |= (0x80>>i);SPI_SCK(0);}return receivebyte;
}

spi.h

#ifndef __SPI_H
#define __SPI_H#include "stm32f10x.h"                  // Device header
#include "sys.h"#define SPI_MOSI(x)  GPIOA->BSRR = GPIO_Pin_7<<(16*(!x))
#define SPI_SCK(x)   GPIOA->BSRR = GPIO_Pin_5<<(16*(!x))
#define Read_MOSI    PAin(7) 		//输入MOSIvoid MySPI_Init(void);
uint8_t MySPI_SW_Byte(uint8_t Byte);#endif

下一章将讲如何使用2.4G模块。 

这篇关于NRF24L01(2.4G)模块的使用——SPI时序(软件)篇的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1042933

相关文章

C语言中联合体union的使用

本文编辑整理自: http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=179471 一、前言 “联合体”(union)与“结构体”(struct)有一些相似之处。但两者有本质上的不同。在结构体中,各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和。而在“联合”中,各成员共享一段内存空间, 一个联合变量

Tolua使用笔记(上)

目录   1.准备工作 2.运行例子 01.HelloWorld:在C#中,创建和销毁Lua虚拟机 和 简单调用。 02.ScriptsFromFile:在C#中,对一个lua文件的执行调用 03.CallLuaFunction:在C#中,对lua函数的操作 04.AccessingLuaVariables:在C#中,对lua变量的操作 05.LuaCoroutine:在Lua中,

Vim使用基础篇

本文内容大部分来自 vimtutor,自带的教程的总结。在终端输入vimtutor 即可进入教程。 先总结一下,然后再分别介绍正常模式,插入模式,和可视模式三种模式下的命令。 目录 看完以后的汇总 1.正常模式(Normal模式) 1.移动光标 2.删除 3.【:】输入符 4.撤销 5.替换 6.重复命令【. ; ,】 7.复制粘贴 8.缩进 2.插入模式 INSERT

Lipowerline5.0 雷达电力应用软件下载使用

1.配网数据处理分析 针对配网线路点云数据,优化了分类算法,支持杆塔、导线、交跨线、建筑物、地面点和其他线路的自动分类;一键生成危险点报告和交跨报告;还能生成点云数据采集航线和自主巡检航线。 获取软件安装包联系邮箱:2895356150@qq.com,资源源于网络,本介绍用于学习使用,如有侵权请您联系删除! 2.新增快速版,简洁易上手 支持快速版和专业版切换使用,快速版界面简洁,保留主

如何免费的去使用connectedpapers?

免费使用connectedpapers 1. 打开谷歌浏览器2. 按住ctrl+shift+N,进入无痕模式3. 不需要登录(也就是访客模式)4. 两次用完,关闭无痕模式(继续重复步骤 2 - 4) 1. 打开谷歌浏览器 2. 按住ctrl+shift+N,进入无痕模式 输入网址:https://www.connectedpapers.com/ 3. 不需要登录(也就是

22.手绘Spring DI运行时序图

1.依赖注入发生的时间 当Spring loC容器完成了 Bean定义资源的定位、载入和解析注册以后,loC容器中已经管理类Bean 定义的相关数据,但是此时loC容器还没有对所管理的Bean进行依赖注入,依赖注入在以下两种情况 发生: 、用户第一次调用getBean()方法时,loC容器触发依赖注入。 、当用户在配置文件中将<bean>元素配置了 lazy-init二false属性,即让

21.手绘Spring IOC运行时序图

1.再谈IOC与 DI IOC(lnversion of Control)控制反转:所谓控制反转,就是把原先我们代码里面需要实现的对象创 建、依赖的代码,反转给容器来帮忙实现。那么必然的我们需要创建一个容器,同时需要一种描述来让 容器知道需要创建的对象与对象的关系。这个描述最具体表现就是我们所看到的配置文件。 DI(Dependency Injection)依赖注入:就是指对象是被动接受依赖类

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测 目录 时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测基本介绍程序设计参考资料 基本介绍 MATLAB实现LSTM时间序列未来多步预测-递归预测。LSTM是一种含有LSTM区块(blocks)或其他的一种类神经网络,文献或其他资料中LSTM区块可能被描述成智能网络单元,因为

Toolbar+DrawerLayout使用详情结合网络各大神

最近也想搞下toolbar+drawerlayout的使用。结合网络上各大神的杰作,我把大部分的内容效果都完成了遍。现在记录下各个功能效果的实现以及一些细节注意点。 这图弹出两个菜单内容都是仿QQ界面的选项。左边一个是drawerlayout的弹窗。右边是toolbar的popup弹窗。 开始实现步骤详情: 1.创建toolbar布局跟drawerlayout布局 <?xml vers

iptables(7)扩展模块state

简介         前面文章我们已经介绍了一些扩展模块,如iprange、string、time、connlimit、limit,还有扩展匹配条件如--tcp-flags、icmp。这篇文章我们介绍state扩展模块  state          在 iptables 的上下文中,--state 选项并不是直接关联于一个扩展模块,而是与 iptables 的 state 匹配机制相关,特