//spi与iic都是串行
//stm32内部集成spi,需要模拟iic
//spi四线(三线根通讯,一根线片选)
//mosi主发,miso从发,sck,mss片选
//miso该引脚在从模式下发送,主模式下接收
//mosi相反,即主模式下输出发送
//主机从机mosi,miso管脚相连
//nss片选,一头接在单片机端口,另一头接从机,控制从机,也就是一个端口csn=cs=nss哈哈哈哈
//nss可以输入(从给主)也可以输出(主给从),通过寄存器设置
//触摸屏,检测是spi通讯(显示不是spi,好像是iic)(spi2)
//24L01也是spi通讯(spi2)
//以太网也是spi(spi_1)
//mp3也是spi2
//spi_1与spi_2不共用时钟线,相互不影响
//spi_2挂在SPB2时钟线上,可双击检查时钟线
//SPI是全双工通信
//CSN,SPI片选
//SCK,SPI时钟线
//MOSI,SPI数据线(主发从读)
//MISO,SPI数据线(从发主读)
//CE,模式控制线,在CSN为低时,CE协同CONFIG寄存器共同决定NRF24L01的状态
//IRQ,中断信号线,中断时变为低电平,三种情况会拉低,这里略
//点对点模式或一对多模式(1收6发就是1个接收6个发送)
//单字节传输高位在前,多字节传输低位在前
//大黄蜂上csn就是cs,就是24L01片选,上电默认高电平,高电平就是24L01未被选中
//当cs拉低时就是选中它,这个端口配置推挽输出
//spi中nss片选就是片选,也是spi片选,irq是上拉输入
//spi片选与24L01片选是连在一起,刚刚打电话给刘洋也确认了
//总结一下,csn=nss=cs
#include "pbdata.h"
//spi与iic都是串行
//stm32内部集成spi,需要模拟iic
//spi四线(三线根通讯,一根线片选)
//mosi主发,miso从发,sck,mss片选
//miso该引脚在从模式下发送,主模式下接收
//mosi相反,即主模式下输出发送
//主机从机mosi,miso管脚相连
//nss片选,一头接在单片机端口,另一头接从机,控制从机,也就是一个端口csn==cs==nss哈哈哈哈
//nss可以输入(从给主)也可以输出(主给从),通过寄存器设置
//触摸屏,检测是spi通讯(显示不是spi,好像是iic)(spi2)
//24L01也是spi通讯(spi2)
//以太网也是spi(spi_1)
//mp3也是spi2
//spi_1与spi_2不共用时钟线,相互不影响
//spi_2挂在SPB2时钟线上,可双击检查时钟线
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void USART_Configuration(void);
//SPI是全双工通信
//CSN,SPI片选
//SCK,SPI时钟线
//MOSI,SPI数据线(主发从读)
//MISO,SPI数据线(从发主读)
//CE,模式控制线,在CSN为低时,CE协同CONFIG寄存器共同决定NRF24L01的状态
//IRQ,中断信号线,中断时变为低电平,三种情况会拉低,这里略
//点对点模式或一对多模式(1收6发就是1个接收6个发送)
//单字节传输高位在前,多字节传输低位在前
//大黄蜂上csn就是cs,就是24L01片选,上电默认高电平,高电平就是24L01未被选中
//当cs拉低时就是选中它,这个端口配置推挽输出
//spi中nss片选就是片选,也是spi片选,irq是上拉输入
//spi片选与24L01片选是连在一起,刚刚打电话给刘洋也确认了
//总结一下,csn==nss==cs
int fputc(int ch,FILE *f)
{
USART_SendData(USART1,(u8)ch);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
return ch;
}
int main(void)
{
RCC_Configuration(); //系统时钟初始化
GPIO_Configuration();//端口初始化
USART_Configuration();
NVIC_Configuration();
NRF24L01_Init();
SPI_Configation();
while(1)
{
NRF24L01_Demo2();
}
}
void RCC_Configuration(void)
{
SystemInit();//72m
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2 ,ENABLE);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RX
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA,&GPIO_InitStructure);
}
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void USART_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate=115200;
USART_InitStructure.USART_WordLength=USART_WordLength_8b;
USART_InitStructure.USART_StopBits=USART_StopBits_1;
USART_InitStructure.USART_Parity=USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
USART_Init(USART1,&USART_InitStructure);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
USART_Cmd(USART1,ENABLE);
USART_ClearFlag(USART1,USART_FLAG_TC);
}
#include "pbdata.h"
//以下为24L01底层硬件驱动代码文件
//很重要,必须两个地址相同
//这两个地址发送与接收40位地址(p0通道可更改 点对点),都是我们自己定义(也可以其它数值),是为了两个24L01之间通信
const u8 TX_ADDRESS[TX_ADR_WIDTH]={0xFF,0xFF,0xFF,0xFF,0xFF}; //发送地址
const u8 RX_ADDRESS[RX_ADR_WIDTH]={0xFF,0xFF,0xFF,0xFF,0xFF}; //接收地址
///根据不同的单片机更改以下3个函数//
void SPI_Configation(void)//对应改为stm32大黄蜂管脚 32自带内部SPI底层配置
{
SPI_InitTypeDef SPI_InitStructure;
/* SPI2 配置 */
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //8位
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //时钟极性 空闲状态时,SCK保持低电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //时钟相位 数据采样从第一个时钟边沿开始
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //软件产生NSS
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; //波特率控制 SYSCLK/16
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据高位在前
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC多项式寄存器初始值为7
SPI_Init(SPI2, &SPI_InitStructure);
/* 使能SPI2 */
SPI_Cmd(SPI2, ENABLE);
}
u8 SPI_SendByte(u8 byte)//对应改为stm32,如果想用spi1则直接改名字就可以了
{
/* 循环检测发送缓冲区是否是空 */
while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
/* 通过SPI2外设发出数据 */
SPI_I2S_SendData(SPI2, byte);
/* 等待接收数据,循环检查接收数据缓冲区 */
while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
/* 返回读出的数据 */
return SPI_I2S_ReceiveData(SPI2);
}
void NRF24L01_Init(void)//初始化24L01,ce推挽输出,cs也是推挽输出(上电默认为高,高电平意思是模块不工作),irq上拉输入
{
GPIO_InitTypeDef GPIO_InitStructure;
/* 配置 SPI2 引脚: SCK, MISO and MOSI(PB13, PB14, PB15) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;//这三个是spi三个端口不包括片选,因为连在了一起,很重要
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用功能(推挽)输出 SPI2
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* 配置PB0为VS1003B的片选 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//这一步禁止是因为大黄蜂开发板上mp3与其共用spi2,所以要禁止它
GPIO_SetBits(GPIOB, GPIO_Pin_0); //禁止MP3片选
/* 配置SPI2 NRF24L01+片选 */
GPIO_InitStructure.GPIO_Pin = NRF_PIN_CS;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出模式最大速度50MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //通用推挽输出模式
GPIO_Init(NRF_PORT_CS, &GPIO_InitStructure);
/* 配置NRF24L01+ 模式选择 */
GPIO_InitStructure.GPIO_Pin = NRF_PIN_CE; //NRF24L01 MODE-CE
GPIO_Init(NRF_PORT_CE, &GPIO_InitStructure);
/* 配置NRF24L01+ 中断信号产生连接到 */
GPIO_InitStructure.GPIO_Pin = NRF_PIN_IRQ; //NRF24L01 IRQ
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入模式
GPIO_Init(NRF_PORT_IRQ, &GPIO_InitStructure);
SPI_RF_CS_H;
}
//
/*********************************************/
/* 函数功能:给24L01的寄存器写值(一个字节) */
/* 入口参数:reg 要写的寄存器地址 */
/* value 给寄存器写的值 */
/* 出口参数:status 状态值 */
/*********************************************/
u8 NRF24L01_Write_Reg(u8 reg,u8 value)//写时序通讯
{
u8 status;
SPI_RF_CS_L;//片选
status = SPI_SendByte(reg);//发送寄存器地址,并读取状态值,发送寄存器地址就是发送控制命令
//然后status是读取返回的状态值
SPI_SendByte(value);//这是要发送的命令或者数据
SPI_RF_CS_H;
return status;
}
/*************************************************/
/* 函数功能:读24L01的寄存器值 (一个字节) */
/* 入口参数:reg 要读的寄存器地址 */
/* 出口参数:value 读出寄存器的值 */
/*************************************************/
u8 NRF24L01_Read_Reg(u8 reg)//读时序通讯
{
u8 value;
SPI_RF_CS_L;
SPI_SendByte(reg);//发送寄存器值(位置),并读取状态值
//应该就是寄存器位置,锁定这个寄存器
value = SPI_SendByte(NOP);//nop是空操作,就是读取值
SPI_RF_CS_H;
return value;
}
/*********************************************/
/* 函数功能:读24L01的寄存器值(多个字节) */
/* 入口参数:reg 寄存器地址 */
/* *pBuf 读出寄存器值的存放数组 */
/* len 数组字节长度 */
/* 出口参数:status 状态值 */
/*********************************************/
u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len)//len是长度,几就是几个字节
{
u8 status,i;
SPI_RF_CS_L;
status=SPI_SendByte(reg);//发送寄存器地址,并读取状态值
for(i=0;i<len;i++)
pBuf[i]=SPI_SendByte(0XFF);//读出数据,0xff==nop,就是空操作
SPI_RF_CS_H;
return status; //返回读到的状态值
}
/**********************************************/
/* 函数功能:给24L01的寄存器写值(多个字节) */
/* 入口参数:reg 要写的寄存器地址 */
/* *pBuf 值的存放数组 */
/* len 数组字节长度 */
/**********************************************/
u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len)
{
u8 status,i;
SPI_RF_CS_L;
status = SPI_SendByte(reg);//发送寄存器值(位置),并读取状态值
for(i=0; i<len; i++)
SPI_SendByte(*pBuf++); //写入数据
SPI_RF_CS_H;
return status; //返回读到的状态值
}
/*********************************************/
/* 函数功能:24L01接收数据 */
/* 入口参数:rxbuf 接收数据数组 */
/* 返回值: 0 成功收到数据 */
/* 1 没有收到数据 */
/*********************************************/
u8 NRF24L01_RxPacket(u8 *rxbuf)//注意接收数据 不等于 读取寄存器值
{
u8 state;
state=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值
NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中断标志
if(state&RX_OK)//接收到数据
{
NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据,注意参数是指针类型
NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
return 0;
}
return 1;//没收到任何数据
}
/**********************************************/
/* 函数功能:设置24L01为发送模式 */
/* 入口参数:txbuf 发送数据数组 */
/* 返回值; 0x10 达到最大重发次数,发送失败*/
/* 0x20 成功发送完成 */
/* 0xff 发送失败 */
/**********************************************/
u8 NRF24L01_TxPacket(u8 *txbuf)
{
u8 state;
SPI_RF_CE_L;//CE拉低,使能24L01配置
NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//写数据到TX BUF 32个字节
SPI_RF_CE_H;//CE置高,使能发送
while (SPI_RF_IRQ!=0);//等待发送完成
state=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值
NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中断标志
NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器
if(state&MAX_TX)//达到最大重发次数
{
NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器
return MAX_TX;
}
if(state&TX_OK)//发送完成
{
return TX_OK;
}
return 0xff;//发送失败
}
//以下三个函数需要重点理解
/********************************************/
/* 函数功能:检测24L01是否存在 */
/* 返回值; 0 存在 */
/* 1 不存在 */
/********************************************/
u8 NRF24L01_Check(void)
{
u8 check_in_buf[5]={0x11,0x22,0x33,0x44,0x55};
u8 check_out_buf[5]={0x00};
//tx_addr是发送地址,发送check_in_buf 数组数据到tx_addr寄存器地址里,NRF_WRITE_REG是写寄存器地址
NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR, check_in_buf, 5);
NRF24L01_Read_Buf(NRF_READ_REG+TX_ADDR, check_out_buf, 5);//然后再读出此寄存器中数组数据
if( (check_out_buf[0] == 0x11)&&\
(check_out_buf[1] == 0x22)&&\
(check_out_buf[2] == 0x33)&&\
(check_out_buf[3] == 0x44)&&\
(check_out_buf[4] == 0x55))return 0;//如果返回0说明24L01是正常的模块,实现检测功能
else return 1;
}
/*********************************************/
/* 函数功能:设置24L01为接收模式 */
/*********************************************/
void NRF24L01_RX_Mode(void)
{
SPI_RF_CE_L;//CE拉低,使能24L01配置
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0, (u8*)RX_ADDRESS, RX_ADR_WIDTH);//写RX接收地址
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); //开启通道0自动应答
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);//通道0接收允许
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,0); //设置RF工作通道频率 ,2.4G不变
NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);//设置TX发射参数,0db增益,2Mbps,低噪声增益开启
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式
NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
SPI_RF_CE_H;//CE置高,进入接收模式
}
/*********************************************/
/* 函数功能:设置24L01为发送模式 */
/*********************************************/
void NRF24L01_TX_Mode(void)
{
SPI_RF_CE_L;//CE拉低,使能24L01配置
NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); //使能通道0的自动应答
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址
//发送需要设置时间间隔,接收不需要
NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,0); //设置RF通道为0,也是2.4G
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启 2Mbps
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,发送模式,开启所有中断
SPI_RF_CE_H;//CE置高,10us后启动发送
}
void NRF24L01_RT_Mode(void)
{
SPI_RF_CE_L;
NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度
NRF24L01_Write_Reg(FLUSH_RX,0xff); //清除RX FIFO寄存器
//下面的两个地址就是const u8 TX_ADDRESS[TX_ADR_WIDTH]={0xFF,0xFF,0xFF,0xFF,0xFF}; //发送地址
//const u8 RX_ADDRESS[RX_ADR_WIDTH]={0xFF,0xFF,0xFF,0xFF,0xFF}; //接收地址
NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); //使能通道0的自动应答
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址
NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,0); //设置RF通道为2.400GHz 频率=2.4+0GHz
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0F); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0f); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
SPI_RF_CE_H;
}
#ifndef _RF24L01_H
#define _RF24L01_H
///根据不同的单片机更改以下引脚定义//
#include "stm32f10x.h"
//修改以下24L01端口,也就是cs片选端口,ce模式选择端口,irq终端端口
#define NRF_PIN_CS GPIO_Pin_12//这个片选端也就是spi片选端 默认上电拉高
#define NRF_PORT_CS GPIOB
#define NRF_PIN_CE GPIO_Pin_1
#define NRF_PORT_CE GPIOB
#define NRF_PIN_IRQ GPIO_Pin_0
#define NRF_PORT_IRQ GPIOA
#define SPI_RF_CS_L GPIO_ResetBits(NRF_PORT_CS, NRF_PIN_CS)
#define SPI_RF_CS_H GPIO_SetBits(NRF_PORT_CS, NRF_PIN_CS)
#define SPI_RF_CE_L GPIO_ResetBits(NRF_PORT_CE, NRF_PIN_CE)
#define SPI_RF_CE_H GPIO_SetBits(NRF_PORT_CE, NRF_PIN_CE)
#define SPI_RF_IRQ GPIO_ReadInputDataBit(NRF_PORT_IRQ, NRF_PIN_IRQ)
//
/********** 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 //空操作,可以用来读状态寄存器
/********** NRF24L01寄存器地址 *************/
#define CONFIG 0x00 //配置寄存器地址
#define EN_AA 0x01 //使能自动应答功能
#define EN_RXADDR 0x02 //接收地址允许
#define SETUP_AW 0x03 //设置地址宽度(所有数据通道)
#define SETUP_RETR 0x04 //建立自动重发
#define RF_CH 0x05 //RF通道
#define RF_SETUP 0x06 //RF寄存器
#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有效数据宽度(1~32字节)
#define RX_PW_P1 0x12 // 接收数据通道1有效数据宽度(1~32字节)
#define RX_PW_P2 0x13 // 接收数据通道2有效数据宽度(1~32字节)
#define RX_PW_P3 0x14 // 接收数据通道3有效数据宽度(1~32字节)
#define RX_PW_P4 0x15 // 接收数据通道4有效数据宽度(1~32字节)
#define RX_PW_P5 0x16 // 接收数据通道5有效数据宽度(1~32字节)
#define FIFO_STATUS 0x17 // FIFO状态寄存器
/*————————————————————————————————————————————————————————————————————*/
/****** STATUS寄存器bit位定义 *******/
#define MAX_TX 0x10 //达到最大发送次数中断
#define TX_OK 0x20 //TX发送完成中断
#define RX_OK 0x40 //接收到数据中断
/*——————————————————————————————————————————————————*/
/********* 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字节有效数据宽度
/*———————————————————————————————————————————————————————*/
extern void NRF24L01_Init(void);
extern u8 NRF24L01_Write_Reg(u8 reg,u8 value);
extern u8 NRF24L01_Read_Reg(u8 reg);
extern u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len);
extern u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len);
extern u8 NRF24L01_Check(void);
extern void NRF24L01_RX_Mode(void);
extern void NRF24L01_TX_Mode(void);
extern void NRF24L01_RT_Mode(void);
extern u8 NRF24L01_RxPacket(u8 *rxbuf);
extern u8 NRF24L01_TxPacket(u8 *txbuf);
extern void SPI_Configation(void);
extern u8 SPI_SendByte(u8 byte);
#endif
#include "pbdata.h"
//如果想实现两块单片机通信,最好,demo1,和demo2配合使用
#define uart_max 32
u8 rece_buf[uart_max];//定义数组///接收是接收数组中的数据,发送也是发送里面的数据
u8 uart_count=0;
//模块通过串口助手中的无线模块配置将无线模块配置好,然后通过波特率为115200发给模块数据
//usb转无线模块插上不用管,一个助手发送,一个助手接收
//这个函数是模块24L01,模块波特率不等于串口打印波特率,这个也就是模块接收数据,然后串口打印告诉电脑我已接收
//也许你会问,谁发送给模块信息呢?就是通过串口助手(usb转接口)发给模块(一个助手发送一个助手显示串口打印)
void NRF24L01_Demo1(void)//接收函数
{
u8 i=0;
NRF24L01_RX_Mode();//设置24L01为接收模式
while(1)
{
if(SPI_RF_IRQ==0)//IRQ为0说明进入中断,这个irq是24L01内部寄存器,为0时说明接收数据了,还有两种main解释有
{
//参数是指针,数组名刚好是指针,至于为啥这样就接收与寄存器内部,不深究
//差不多明白了,下面一步过后就将接受的数据传到了rece_buf中,因为此函数形参是指针,正好recebuf就是数组名,就是指针
if(NRF24L01_RxPacket(rece_buf)==0)//为0说明正常接收数据,这个是说明接收到数据,上面只是说明开始接受了,这个说明接收成功且完成
{
if(rece_buf[0]<uart_max)//首先判定小于32个字节(因为无线接收最大就32位字节)
{
for(i=0;i<rece_buf[0];i++)//注意首先发送rece_buf[1]数据,这是自己定义的报文格式
{
USART_SendData(USART1,rece_buf[i+1]);//发送数组中的数据,不是很理解,反正
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//这是串口打印显示在助手
}
}
}
}
}
}
//也就是将大黄蜂开发板上的24L01设置为发送模式,上面的是接收,usb转接口发,它接
//这是定义好的数据发给模块
void NRF24L01_Demo2(void)//发送函数
{
u8 i=0;
NRF24L01_TX_Mode();//设置24L01为发送模式
while(1)
{
rece_buf[0]=0x04;//表示发送四个字节有效数据
for(i=1;i<5;i++)//这里是事先存储数组为1234,rece_buf[0]=0x04
{
rece_buf[i]=i;
}
SPI_RF_CE_L;
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e);//配置工作发送模式
SPI_RF_CE_H;//CE拉高
//下面形参也是指针,也就是说执行这一步,发送数组中的数据
NRF24L01_TxPacket(rece_buf);//发送数据,rece_buf就是
SPI_RF_CE_L;
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0f);//配置工作接收模式
SPI_RF_CE_H;
delay_ms(1000);
}
}
//这个函数作用是,单片机通过串口接收数据时,再通过无线模块发送这个数据
void NRF24L01_Demo3(void)//发送及接收函数
{
u8 i=0;
NRF24L01_RT_Mode();//接收发射双模式
while(1)
{
//串口接收 无线模块发送
if(uart_count>0)
{
delay_ms(20);//串口接收数组也需要时间,所以要时间
rece_buf[0]=uart_count;
uart_count=0;
SPI_RF_CE_L;
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e);
SPI_RF_CE_H;
NRF24L01_TxPacket(rece_buf);
SPI_RF_CE_L;
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0f);
SPI_RF_CE_H;
}
//无线模块收到数据转发串口
if(SPI_RF_IRQ==0)
{
if(NRF24L01_RxPacket(rece_buf)==0)
{
if(rece_buf[0]<uart_max)
{
for(i=0;i<rece_buf[0];i++)
{
USART_SendData(USART1,rece_buf[i+1]);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
}
}
}
}
}
}
//作用是将串口接受的数据传到rece_buf数组里
void UART1_Recv_Byte(u8 byte)//这个函数,放在了串口中断里,就是下面注释的函数
{
if(uart_count<uart_max)
{
rece_buf[++uart_count]=byte;
}
else
{
uart_count=0;
}
}
//void USART1_IRQHandler(void)
//{
// if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)
// {
// //USART_SendData(USART1,USART_ReceiveData(USART1));
// //while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
// UART1_Recv_Byte(USART_ReceiveData(USART1));
// }
//
//}
/************************ 论坛地址 www.zxkjmcu.com ******************************/
#ifndef _NRF24L01_DEMO_H //宏定义,定义文件名称
#define _NRF24L01_DEMO_H
/*---------------------------头文件引用--------------------------------------*/
#include "stm32f10x.h"
void NRF24L01_Demo1(void);
void NRF24L01_Demo2(void);
void NRF24L01_Demo3(void);
void UART1_Recv_Byte(u8 byte);
#endif //定义文件名称结束
/************************ 论坛地址 www.zxkjmcu.com ******************************/