3.1.3两种数据双方向的通讯方式:
如果想要数据在双方向上通讯,PRIM_RX 寄存器必须紧随芯片工作模式的变化而变化。
处理器必须保证PTX 和PRX 端的同步性。在RX_FIFO 和TX_FIFO 寄存器中可能同时存有数据。
3.1.4数据包识别和CRC校验应用于增强型ShockBurstTM模式下:
每一包数据都包括两位的PID(数据包识别)来识别接收的数据是新数据包还是重发的数据包。
PID识别可以防止接收端同一数据包多次送入MCU。
在发送方每从MCU取得一包新数据后PID值加一。
PID和CRC校验应用在接收方识别接收的数据是重发的数据包还是新数据包。
如果链接中有一些数据丢失了,则PID值与上一包数据的PID值相同。
接收方对新接收的数据包进行比较:如果一包数据拥有与上一包数据相同的PID值,nRF24L01将对两包数据的CRC值进行比较。如果CRC值也相同的话就认为后面一包是前一包的重发数据包而被舍弃。
3.1.5 数据通道:
nRF24L01 配置为接收模式时可以接收==6== 路不同地址相同频率的数据。每个数据通道拥有自己的地址并且可以通过寄存器来进行分别配置。
数据通道是通过寄存器==EN_RXADDR== 来设置的,默认状态下只有数据通道==0== 和数据通道==1== 是开启状态的。
每一个数据通道的地址是通过寄存器==RX_ADDR_Px== 来配置的。通常情况下不允许不同的数据通道设
置完全相同的地址。
数据通道==0== 有==40== 位可配置地址。数据通道==1-5== 的地址为:==32== 位共用地址+各自的地址(最低字节)。
下图所示的是数据通道==1-5== 的地址设置方法举例。所有数据通道可以设置为多达==40== 位,但是==1-5== 数据通道的最低位必须不同。
**当从一个数据通道接收到数据,并且此数据通道设置为应答方式的话,则nRF24L01 在收到数据后
产生应答信号,此应答信号的目标地址为接收通道地址**

3.2待机模式
待机模式1在保证快速启动的同时减少系统平均消耗电流。
在待机模式1下,晶振正常工作。
在待机模式2下部分时钟缓冲器处在工作模式。
当发送端TX FIFO寄存器位空并且CE为高电平时进入待机模式2。
在待机模式期间,寄存器配置字内容保持不变。
3.3掉电模式
在掉电模式下,nRF24L01各功能关闭,保持电流消耗最小。
进入掉电模式后,nRF24L01停止工作,但寄存器内容保持不变。
掉电模式由寄存器中PWR_UP位来控制。
二、SPI介绍
SPI 是英语 Serial Peripheral interface 的缩写串行外围设备接口。
SPI,是一种高速的,全双工,
同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为 PCB 的布局
上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信
协议, STM32 也有 SPI 接口。
==SPI 接口一般使用 4 条线通信:==
MISO 主设备数据输入,从设备数据输出。
MOSI 主设备数据输出,从设备数据输入。
SCLK 时钟信号,由主设备产生。
CS 从设备片选信号,由主设备控制。
SPI内部结构简明图:

SPI 总线四种工作方式 SPI 模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置,
时钟极性(CPOL)配置串行同步时钟空闲状态:
如果CPOL=0,串行同步时钟的空闲状态为低电平;
如果CPOL=1,串行同步时钟的空闲状态为高电
平。
时钟相位(CPHA)能够配置用于选择两种不同的传输协议之一进行数据传输:
如果 CPHA=0,
在串行同步时钟的第一个跳变沿(上升或下降)数据被采样;
如果 CPHA=1,在串行同步时钟
的第二个跳变沿(上升或下降)数据被采样。
==SPI 主模块和与之通信的外设备时钟相位和极性应该一致==
不同时钟相位下的总线数据传输时序如图:

三、STM32开发板控制NRF24L01
ALIENTKEMiniSTM32 开发板带有一个 2.4G 无线模块(NRF24L01 模块)通信接口,采用
8 脚插针方式与开发板连接,用两块板子,一块接收,一块发送,实现无线传输。
1.宏定义
nRF24L01 SPI指令格式

由nRF24L01的SPI指令格式和寄存器地址进行相关操作和寄存器地址的宏定义
相关操作和地址宏定义:
//NRF24L01寄存器操作命令
#define NRF_READ_REG 0x00 //读配置寄存器,低5位为寄存器地址
#define NRF_WRITE_REG 0x20 //写配置寄存器,低5位为寄存器地址
#define RD_RX_PLOAD 0x61 //读RX有效数据,1~32字节
#define WR_TX_PLOAD 0xA0 //写TX有效数据,1~32字节
#define FLUSH_TX 0xE1 //清除TX FIFO寄存器.发射模式下用
#define FLUSH_RX 0xE2 //清除RX FIFO寄存器.接收模式下用
#define REUSE_TX_PL 0xE3 //重新使用上一包数据,CE为高,数据包被不断发送.
#define NOP 0xFF //空操作,可以用来读状态寄存器
//SPI(NRF24L01)寄存器地址
#define CONFIG 0x00 //配置寄存器地址;bit0:1接收模式,0发射模式;bit1:电选择;bit2:CRC模式;bit3:CRC使能;
//bit4:中断MAX_RT(达到最大重发次数中断)使能;bit5:中断TX_DS使能;bit6:中断RX_DR使能
#define EN_AA 0x01 //使能自动应答功能 bit0~5,对应通道0~5
#define EN_RXADDR 0x02 //接收地址允许,bit0~5,对应通道0~5
#define SETUP_AW 0x03 //设置地址宽度(所有数据通道):bit1,0:00,3字节;01,4字节;02,5字节;
#define SETUP_RETR 0x04 //建立自动重发;bit3:0,自动重发计数器;bit7:4,自动重发延时 250*x+86us
#define RF_CH 0x05 //RF通道,bit6:0,工作通道频率;
#define RF_SETUP 0x06 //RF寄存器;bit3:传输速率(0:1Mbps,1:2Mbps);bit2:1,发射功率;bit0:低噪声放大器增益
#define STATUS 0x07 //状态寄存器;bit0:TX FIFO满标志;bit3:1,接收数据通道号(最大:6);bit4,达到最多次重发
//bit5:数据发送完成中断;bit6:接收数据中断;
#define MAX_TX 0x10 //达到最大发送次数中断
#define TX_OK 0x20 //TX发送完成中断
#define RX_OK 0x40 //接收到数据中断
#define OBSERVE_TX 0x08 //发送检测寄存器,bit7:4,数据包丢失计数器;bit3:0,重发计数器
#define CD 0x09 //载波检测寄存器,bit0,载波检测;
#define RX_ADDR_P0 0x0A //数据通道0接收地址,最大长度5个字节,低字节在前
#define RX_ADDR_P1 0x0B //数据通道1接收地址,最大长度5个字节,低字节在前
#define RX_ADDR_P2 0x0C //数据通道2接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;
#define RX_ADDR_P3 0x0D //数据通道3接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;
#define RX_ADDR_P4 0x0E //数据通道4接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;
#define RX_ADDR_P5 0x0F //数据通道5接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;
#define TX_ADDR 0x10 //发送地址(低字节在前),ShockBurstTM模式下,RX_ADDR_P0与此地址相等
#define RX_PW_P0 0x11 //接收数据通道0有效数据宽度(1~32字节),设置为0则非法
#define RX_PW_P1 0x12 //接收数据通道1有效数据宽度(1~32字节),设置为0则非法
#define RX_PW_P2 0x13 //接收数据通道2有效数据宽度(1~32字节),设置为0则非法
#define RX_PW_P3 0x14 //接收数据通道3有效数据宽度(1~32字节),设置为0则非法
#define RX_PW_P4 0x15 //接收数据通道4有效数据宽度(1~32字节),设置为0则非法
#define RX_PW_P5 0x16 //接收数据通道5有效数据宽度(1~32字节),设置为0则非法
#define NRF_FIFO_STATUS 0x17 //FIFO状态寄存器;bit0,RX FIFO寄存器空标志;bit1,RX FIFO满标志;bit2,3,保留
//bit4,TX FIFO空标志;bit5,TX FIFO满标志;bit6,1,循环发送上一数据包.0,不循环;
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//24L01操作线
#define NRF24L01_CE PAout(4) //24L01片选信号
#define NRF24L01_CSN PCout(4) //SPI片选信号
#define NRF24L01_IRQ PAin(1) //IRQ主机数据输入
//24L01发送接收数据宽度定义
#define TX_ADR_WIDTH 5 //5字节的地址宽度
#define RX_ADR_WIDTH 5 //5字节的地址宽度
#define TX_PLOAD_WIDTH 32 //32字节的用户数据宽度
#define RX_PLOAD_WIDTH 32 //32字节的用户数据宽度
2.初始化
NRF24L01的SPI通信时序:

从图中可以看出, SCK 空
闲的时候是低电平的,而数据在 SCK 的上升沿被读写。所以,我们需要设置 SPI 的 CPOL 和 CPHA均为 0,来满足 NRF24L01 对 SPI 操作的要求。
NRF24L01使用STM32的SPI1,和W25Q64以及SD卡共用一个SPI接口,所以在使用的时候,他们分时复用SPI1,需要把SD卡和W25Q64的片选信号置高,以防这两个器件对NRF24L01的通信造成干扰。
NRF24L01的SPI接口是标准的SPI接口,其最大的数据传输率为10Mbps。
STM32的SPI与nRF2401初始化代码:
SPI_InitTypeDef SPI_InitStructure; //全局变量SPI结构体
void NRF24L01_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_SPI1, ENABLE );
// 使能GPIOA,GPIOC,SPI1时钟
//PA5.SPI1_SCK; PA6.SPI_MISO; PA7.SPI_MOSI
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);//初始化SPI1的GPIO口
//PA2.CE W25Q4片选信号; PA3.CE SD卡片选信号; PA4.CE 24L01片选信号
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//PC4.CSN SPI片选信号
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_SetBits(GPIOC,GPIO_Pin_4);
//PA1.IRQ IRQ主机数据输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; //上拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//PA1(中断信号引脚)置高,中断时变为低电平
//PA2(W25Q4片选信号)与PA3(SD卡片选信号)置高,以防这两个器件对NRF24L01造成干扰
//PA4(24L01片选信号)置高
GPIO_SetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //选择了串行时钟的稳态:时钟悬空低电平
//即(CPOL=0)
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //数据捕获于第一个时钟沿
//即(CPHA=0)
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; //定义波特率预分频的值:波特率预分频值为8
//spi速度为9Mhz(24L01的最大SPI时钟为10Mhz)
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
SPI_Init(SPI1, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
SPI_Cmd(SPI1,ENABLE);//使能SPI1
//CE低电平 待机模式
NRF24L01_CE=0; //使能24L01
//CSN为低电平芯片工作
NRF24L01_CSN=1; //SPI片选取消
}
3.1.3两种数据双方向的通讯方式:
如果想要数据在双方向上通讯,PRIM_RX 寄存器必须紧随芯片工作模式的变化而变化。
处理器必须保证PTX 和PRX 端的同步性。在RX_FIFO 和TX_FIFO 寄存器中可能同时存有数据。
3.1.4数据包识别和CRC校验应用于增强型ShockBurstTM模式下:
每一包数据都包括两位的PID(数据包识别)来识别接收的数据是新数据包还是重发的数据包。
PID识别可以防止接收端同一数据包多次送入MCU。
在发送方每从MCU取得一包新数据后PID值加一。
PID和CRC校验应用在接收方识别接收的数据是重发的数据包还是新数据包。
如果链接中有一些数据丢失了,则PID值与上一包数据的PID值相同。
接收方对新接收的数据包进行比较:如果一包数据拥有与上一包数据相同的PID值,nRF24L01将对两包数据的CRC值进行比较。如果CRC值也相同的话就认为后面一包是前一包的重发数据包而被舍弃。
3.1.5 数据通道:
nRF24L01 配置为接收模式时可以接收==6== 路不同地址相同频率的数据。每个数据通道拥有自己的地址并且可以通过寄存器来进行分别配置。
数据通道是通过寄存器==EN_RXADDR== 来设置的,默认状态下只有数据通道==0== 和数据通道==1== 是开启状态的。
每一个数据通道的地址是通过寄存器==RX_ADDR_Px== 来配置的。通常情况下不允许不同的数据通道设
置完全相同的地址。
数据通道==0== 有==40== 位可配置地址。数据通道==1-5== 的地址为:==32== 位共用地址+各自的地址(最低字节)。
下图所示的是数据通道==1-5== 的地址设置方法举例。所有数据通道可以设置为多达==40== 位,但是==1-5== 数据通道的最低位必须不同。
**当从一个数据通道接收到数据,并且此数据通道设置为应答方式的话,则nRF24L01 在收到数据后
产生应答信号,此应答信号的目标地址为接收通道地址**

3.2待机模式
待机模式1在保证快速启动的同时减少系统平均消耗电流。
在待机模式1下,晶振正常工作。
在待机模式2下部分时钟缓冲器处在工作模式。
当发送端TX FIFO寄存器位空并且CE为高电平时进入待机模式2。
在待机模式期间,寄存器配置字内容保持不变。
3.3掉电模式
在掉电模式下,nRF24L01各功能关闭,保持电流消耗最小。
进入掉电模式后,nRF24L01停止工作,但寄存器内容保持不变。
掉电模式由寄存器中PWR_UP位来控制。
二、SPI介绍
SPI 是英语 Serial Peripheral interface 的缩写串行外围设备接口。
SPI,是一种高速的,全双工,
同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为 PCB 的布局
上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信
协议, STM32 也有 SPI 接口。
==SPI 接口一般使用 4 条线通信:==
MISO 主设备数据输入,从设备数据输出。
MOSI 主设备数据输出,从设备数据输入。
SCLK 时钟信号,由主设备产生。
CS 从设备片选信号,由主设备控制。
SPI内部结构简明图:

SPI 总线四种工作方式 SPI 模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置,
时钟极性(CPOL)配置串行同步时钟空闲状态:
如果CPOL=0,串行同步时钟的空闲状态为低电平;
如果CPOL=1,串行同步时钟的空闲状态为高电
平。
时钟相位(CPHA)能够配置用于选择两种不同的传输协议之一进行数据传输:
如果 CPHA=0,
在串行同步时钟的第一个跳变沿(上升或下降)数据被采样;
如果 CPHA=1,在串行同步时钟
的第二个跳变沿(上升或下降)数据被采样。
==SPI 主模块和与之通信的外设备时钟相位和极性应该一致==
不同时钟相位下的总线数据传输时序如图:

三、STM32开发板控制NRF24L01
ALIENTKEMiniSTM32 开发板带有一个 2.4G 无线模块(NRF24L01 模块)通信接口,采用
8 脚插针方式与开发板连接,用两块板子,一块接收,一块发送,实现无线传输。
1.宏定义
nRF24L01 SPI指令格式

由nRF24L01的SPI指令格式和寄存器地址进行相关操作和寄存器地址的宏定义
相关操作和地址宏定义:
//NRF24L01寄存器操作命令
#define NRF_READ_REG 0x00 //读配置寄存器,低5位为寄存器地址
#define NRF_WRITE_REG 0x20 //写配置寄存器,低5位为寄存器地址
#define RD_RX_PLOAD 0x61 //读RX有效数据,1~32字节
#define WR_TX_PLOAD 0xA0 //写TX有效数据,1~32字节
#define FLUSH_TX 0xE1 //清除TX FIFO寄存器.发射模式下用
#define FLUSH_RX 0xE2 //清除RX FIFO寄存器.接收模式下用
#define REUSE_TX_PL 0xE3 //重新使用上一包数据,CE为高,数据包被不断发送.
#define NOP 0xFF //空操作,可以用来读状态寄存器
//SPI(NRF24L01)寄存器地址
#define CONFIG 0x00 //配置寄存器地址;bit0:1接收模式,0发射模式;bit1:电选择;bit2:CRC模式;bit3:CRC使能;
//bit4:中断MAX_RT(达到最大重发次数中断)使能;bit5:中断TX_DS使能;bit6:中断RX_DR使能
#define EN_AA 0x01 //使能自动应答功能 bit0~5,对应通道0~5
#define EN_RXADDR 0x02 //接收地址允许,bit0~5,对应通道0~5
#define SETUP_AW 0x03 //设置地址宽度(所有数据通道):bit1,0:00,3字节;01,4字节;02,5字节;
#define SETUP_RETR 0x04 //建立自动重发;bit3:0,自动重发计数器;bit7:4,自动重发延时 250*x+86us
#define RF_CH 0x05 //RF通道,bit6:0,工作通道频率;
#define RF_SETUP 0x06 //RF寄存器;bit3:传输速率(0:1Mbps,1:2Mbps);bit2:1,发射功率;bit0:低噪声放大器增益
#define STATUS 0x07 //状态寄存器;bit0:TX FIFO满标志;bit3:1,接收数据通道号(最大:6);bit4,达到最多次重发
//bit5:数据发送完成中断;bit6:接收数据中断;
#define MAX_TX 0x10 //达到最大发送次数中断
#define TX_OK 0x20 //TX发送完成中断
#define RX_OK 0x40 //接收到数据中断
#define OBSERVE_TX 0x08 //发送检测寄存器,bit7:4,数据包丢失计数器;bit3:0,重发计数器
#define CD 0x09 //载波检测寄存器,bit0,载波检测;
#define RX_ADDR_P0 0x0A //数据通道0接收地址,最大长度5个字节,低字节在前
#define RX_ADDR_P1 0x0B //数据通道1接收地址,最大长度5个字节,低字节在前
#define RX_ADDR_P2 0x0C //数据通道2接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;
#define RX_ADDR_P3 0x0D //数据通道3接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;
#define RX_ADDR_P4 0x0E //数据通道4接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;
#define RX_ADDR_P5 0x0F //数据通道5接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;
#define TX_ADDR 0x10 //发送地址(低字节在前),ShockBurstTM模式下,RX_ADDR_P0与此地址相等
#define RX_PW_P0 0x11 //接收数据通道0有效数据宽度(1~32字节),设置为0则非法
#define RX_PW_P1 0x12 //接收数据通道1有效数据宽度(1~32字节),设置为0则非法
#define RX_PW_P2 0x13 //接收数据通道2有效数据宽度(1~32字节),设置为0则非法
#define RX_PW_P3 0x14 //接收数据通道3有效数据宽度(1~32字节),设置为0则非法
#define RX_PW_P4 0x15 //接收数据通道4有效数据宽度(1~32字节),设置为0则非法
#define RX_PW_P5 0x16 //接收数据通道5有效数据宽度(1~32字节),设置为0则非法
#define NRF_FIFO_STATUS 0x17 //FIFO状态寄存器;bit0,RX FIFO寄存器空标志;bit1,RX FIFO满标志;bit2,3,保留
//bit4,TX FIFO空标志;bit5,TX FIFO满标志;bit6,1,循环发送上一数据包.0,不循环;
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//24L01操作线
#define NRF24L01_CE PAout(4) //24L01片选信号
#define NRF24L01_CSN PCout(4) //SPI片选信号
#define NRF24L01_IRQ PAin(1) //IRQ主机数据输入
//24L01发送接收数据宽度定义
#define TX_ADR_WIDTH 5 //5字节的地址宽度
#define RX_ADR_WIDTH 5 //5字节的地址宽度
#define TX_PLOAD_WIDTH 32 //32字节的用户数据宽度
#define RX_PLOAD_WIDTH 32 //32字节的用户数据宽度
2.初始化
NRF24L01的SPI通信时序:

从图中可以看出, SCK 空
闲的时候是低电平的,而数据在 SCK 的上升沿被读写。所以,我们需要设置 SPI 的 CPOL 和 CPHA均为 0,来满足 NRF24L01 对 SPI 操作的要求。
NRF24L01使用STM32的SPI1,和W25Q64以及SD卡共用一个SPI接口,所以在使用的时候,他们分时复用SPI1,需要把SD卡和W25Q64的片选信号置高,以防这两个器件对NRF24L01的通信造成干扰。
NRF24L01的SPI接口是标准的SPI接口,其最大的数据传输率为10Mbps。
STM32的SPI与nRF2401初始化代码:
SPI_InitTypeDef SPI_InitStructure; //全局变量SPI结构体
void NRF24L01_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_SPI1, ENABLE );
// 使能GPIOA,GPIOC,SPI1时钟
//PA5.SPI1_SCK; PA6.SPI_MISO; PA7.SPI_MOSI
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);//初始化SPI1的GPIO口
//PA2.CE W25Q4片选信号; PA3.CE SD卡片选信号; PA4.CE 24L01片选信号
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//PC4.CSN SPI片选信号
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_SetBits(GPIOC,GPIO_Pin_4);
//PA1.IRQ IRQ主机数据输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; //上拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//PA1(中断信号引脚)置高,中断时变为低电平
//PA2(W25Q4片选信号)与PA3(SD卡片选信号)置高,以防这两个器件对NRF24L01造成干扰
//PA4(24L01片选信号)置高
GPIO_SetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //选择了串行时钟的稳态:时钟悬空低电平
//即(CPOL=0)
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //数据捕获于第一个时钟沿
//即(CPHA=0)
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; //定义波特率预分频的值:波特率预分频值为8
//spi速度为9Mhz(24L01的最大SPI时钟为10Mhz)
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
SPI_Init(SPI1, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
SPI_Cmd(SPI1,ENABLE);//使能SPI1
//CE低电平 待机模式
NRF24L01_CE=0; //使能24L01
//CSN为低电平芯片工作
NRF24L01_CSN=1; //SPI片选取消
}
举报