stm32f103用NRF24L01无法实时接收数据
发送:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "NRF24L01.h"
#include "My_ADC.h"
int main(void)
{
uint8_t Buf[32]={0};
NRF24L01_Init();
AD_Init();
while (1)
{
uint8_t Speed= (uint8_t)(AD_Value[1]>>4);
Speed = AD_Value[1];
Buf[0] = Speed;
NRF24L01_SendBuf(Buf);
}
}
接收:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "Timer.h"
#include "PWM.h"
#include "NRF24L01.h"
#include "OLED.h"
int main(void)
{
uint8_t Buf[32] = {0};
uint8_t Mode = 0;
Timer_Init(); //定时器初始化
PWM_Init();
NRF24L01_Init();
OLED_Init();
while (1)
{
uint16_t Speed;
OLED_ShowHexNum(1,1,Buf[0],4);
Delay_ms(10);
if (NRF24L01_Get_Value_Flag() == 0)
{
NRF24L01_GetRxBuf(Buf);
}
Speed = Buf[0]/128;
PWM_SetCompare1(Speed);
PWM_SetCompare2(Speed);
PWM_SetCompare3(Speed);
PWM_SetCompare4(Speed);
}
}
NRF24L01.c
#include "NRF24L01.h"
#include "NRF24L01_define.h"
#include "stm32f10x.h" // Device header
#include "Delay.h"
/***************************************************************************
主要函数使用说明:
NRF24L01_Pin_Init() 引脚初始化, 无参数,无返回值,一般不调用,初始化直接调用NRF24L01_Init()即可
*---------------------------------------------------------------------------*
NRF24L01_Write_Reg(uint8_t Reg, uint8_t Value) 写NRF24L01寄存器
参数:Reg, 寄存器地址
Value:要写入的数据
返回值:状态值
*---------------------------------------------------------------------------*
NRF24L01_Read_Reg(uint8_t Reg) 读NRF24L01寄存器
参数:Reg:寄存器地址
返回值:状态值
*---------------------------------------------------------------------------*
NRF24L01_Read_Buf(uint8_t Reg, uint8_t *Buf, uint8_t Len) 一次读NRF24L01寄存器多个字节
参数:Reg:寄存器地址;*Buf:寄存器字节读出后存储的数组;Len:要读出的字节个数
返回值:状态值
*---------------------------------------------------------------------------*
NRF24L01_Write_Buf(uint8_t Reg, uint8_t *Buf, uint8_t Len) 一次写NRF24L01寄存器多个字节
参数:Reg:寄存器地址;*Buf:寄存器写入字节的存放数组;Len:要读出的字节个数
返回值:状态值
*---------------------------------------------------------------------------*
NRF24L01_GetRxBuf(uint8_t *Buf) 读出接收到的数据,为多个字节
参数:*Buf多个字节存放的数组
返回值:状态值
*---------------------------------------------------------------------------*
NRF24L01_SendTxBuf(uint8_t *Buf) 发送多个字节
参数:*Buf要发送的字节存放的数组
返回值:状态值
*---------------------------------------------------------------------------*
NRF24L01_Check(void) 检验NRF24L01是否存在
返回值:1:不存在,0:存在
*---------------------------------------------------------------------------*
NRF24L01_Init() NRF24L01初始化,包含检验NRF24L01是否存在、收发配置初始化,初始化直接调用该函数即可
*---------------------------------------------------------------------------*
NRF24L01_RT_Init(void) NRF24L01收发配置初始化
*---------------------------------------------------------------------------*
NRF24L01_SendBuf(uint8_t *Buf) NRF24L01发送多个字节数据
参数:要发送字节存放的数组
*---------------------------------------------------------------------------*
uint8_t NRF24L01_Get_Value_Flag() 获取中断标志,一旦接收到数据,返回0
返回值:0:接收到数据;1:未接收到数据
************************************************************/
#define TX_ADR_WIDTH 5 //5字节地址宽度
#define RX_ADR_WIDTH 5 //5字节地址宽度
#define TX_PLOAD_WIDTH 32 //32字节有效数据宽度
#define RX_PLOAD_WIDTH 32 //32字节有效数据宽度
const uint8_t TX_ADDRESS[TX_ADR_WIDTH]={0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
const uint8_t RX_ADDRESS[RX_ADR_WIDTH]={0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
void W_SS(uint8_t BitValue)
{
GPIO_WriteBit(CSN_Port, CSN_Pin, (BitAction)BitValue);
}
void W_CE(uint8_t BitValue)
{
GPIO_WriteBit(CE_Port, CE_Pin, (BitAction)BitValue);
}
void W_SCK(uint8_t BitValue)
{
GPIO_WriteBit(SCK_Port, SCK_Pin, (BitAction)BitValue);
}
void W_MOSI(uint8_t BitValue)
{
GPIO_WriteBit(MOSI_Port, MOSI_Pin,(BitAction)BitValue);
}
uint8_t R_MISO(void)
{
return GPIO_ReadInputDataBit(MISO_Port, MISO_Pin);
}
uint8_t R_IRQ(void)
{
return GPIO_ReadInputDataBit(IRQ_Port, IRQ_Pin);
}
void NRF24L01_Pin_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = CSN_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(CSN_Port, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = SCK_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(SCK_Port, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = MOSI_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(MOSI_Port, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = CE_Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(CE_Port, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = MISO_Pin;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(MISO_Port, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = IRQ_Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(IRQ_Port, &GPIO_InitStructure);
}
uint8_t SPI_SwapByte(uint8_t Byte)
{
uint8_t i;
for(i = 0; i < 8; i ++)
{
if((uint8_t)(Byte & 0x80) == 0x80)
{
W_MOSI(1);
}
else
{
W_MOSI(0);
}
Byte = (Byte << 1);
W_SCK(1);
Byte |= R_MISO();
W_SCK(0);
}
return Byte;
}
uint8_t NRF24L01_Write_Reg(uint8_t Reg, uint8_t Value)
{
uint8_t Status;
W_SS(0);
Status = SPI_SwapByte(Reg);
SPI_SwapByte(Value);
W_SS(1);
return Status;
}
uint8_t NRF24L01_Read_Reg(uint8_t Reg)
{
uint8_t Value;
W_SS(0);
SPI_SwapByte(Reg);
Value = SPI_SwapByte(NOP);
W_SS(1);
return Value;
}
uint8_t NRF24L01_Read_Buf(uint8_t Reg, uint8_t *Buf, uint8_t Len)
{
uint8_t Status, i;
W_SS(0);
Status =SPI_SwapByte(Reg);
for(i = 0; i < Len; i ++)
{
Buf[i] = SPI_SwapByte(NOP);
}
W_SS(1);
return Status;
}
uint8_t NRF24L01_Write_Buf(uint8_t Reg, uint8_t *Buf, uint8_t Len)
{
uint8_t Status, i;
W_SS(0);
Status = SPI_SwapByte(Reg);
for(i = 0; i < Len; i ++)
{
SPI_SwapByte(*Buf ++);
}
W_SS(1);
return Status;
}
uint8_t NRF24L01_GetRxBuf(uint8_t *Buf)
{
uint8_t State;
State = NRF24L01_Read_Reg(STATUS);
NRF24L01_Write_Reg(nRF_WRITE_REG + STATUS, State);
if(State & RX_OK)
{
W_CE(1);
NRF24L01_Read_Buf(RD_RX_PLOAD, Buf, RX_PLOAD_WIDTH);
NRF24L01_Write_Reg(FLUSH_RX, NOP);
W_CE(1);
Delay_us(150);
return 0;
}
return 1;
}
uint8_t NRF24L01_SendTxBuf(uint8_t *Buf)
{
uint8_t State;
W_CE(0);
NRF24L01_Write_Buf(WR_TX_PLOAD, Buf, TX_PLOAD_WIDTH);
W_CE(1);
while(R_IRQ() == 1);
State = NRF24L01_Read_Reg(STATUS);
NRF24L01_Write_Reg(nRF_WRITE_REG + STATUS, State);
if(State&MAX_TX)
{
NRF24L01_Write_Reg(FLUSH_TX, NOP);
return MAX_TX;
}
if(State & TX_OK)
{
return TX_OK;
}
return NOP;
}
uint8_t NRF24L01_Check(void)
{
uint8_t check_in_buf[5] = {0x11 ,0x22, 0x33, 0x44, 0x55};
uint8_t check_out_buf[5] = {0x00};
W_SCK(0);
W_SS(1);
W_CE(0);
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;
}
else
{
return 1;
}
}
void NRF24L01_RT_Init(void)
{
W_CE(0);
NRF24L01_Write_Reg(nRF_WRITE_REG+RX_PW_P0, RX_PLOAD_WIDTH);
NRF24L01_Write_Reg(FLUSH_RX, NOP);
NRF24L01_Write_Buf(nRF_WRITE_REG + TX_ADDR, (uint8_t*)TX_ADDRESS, TX_ADR_WIDTH);
NRF24L01_Write_Buf(nRF_WRITE_REG + RX_ADDR_P0, (uint8_t*)RX_ADDRESS, RX_ADR_WIDTH);
NRF24L01_Write_Reg(nRF_WRITE_REG + EN_AA, 0x01);
NRF24L01_Write_Reg(nRF_WRITE_REG + EN_RXADDR, 0x01);
NRF24L01_Write_Reg(nRF_WRITE_REG + SETUP_RETR, 0x1A);
NRF24L01_Write_Reg(nRF_WRITE_REG + RF_CH, 0);
NRF24L01_Write_Reg(nRF_WRITE_REG + RF_SETUP, 0x0F);
NRF24L01_Write_Reg(nRF_WRITE_REG + CONFIG, 0x0F);
W_CE(1);
}
void NRF24L01_Init()
{
NRF24L01_Pin_Init();
while(NRF24L01_Check());
NRF24L01_RT_Init();
}
void NRF24L01_SendBuf(uint8_t *Buf)
{
W_CE(0);
NRF24L01_Write_Reg(nRF_WRITE_REG + CONFIG, 0x0E);
W_CE(1);
Delay_us(15);
NRF24L01_SendTxBuf(Buf);
W_CE(0);
NRF24L01_Write_Reg(nRF_WRITE_REG + CONFIG, 0x0F);
W_CE(1);
}
uint8_t NRF24L01_Get_Value_Flag()
{
return R_IRQ();
}
NRF24L01.h
#ifndef __NRF24L01_H
#define __NRF24L01_H
#include "stm32f10x.h" // Device header
uint8_t SPI_SwapByte(uint8_t byte);
uint8_t NRF24L01_Write_Reg(uint8_t reg,uint8_t value);
uint8_t NRF24L01_Read_Reg(uint8_t reg);
uint8_t NRF24L01_Read_Buf(uint8_t reg,uint8_t *pBuf, uint8_t len);
uint8_t NRF24L01_Write_Buf(uint8_t reg, uint8_t *pBuf, uint8_t len);
uint8_t NRF24L01_GetRxBuf(uint8_t *rxbuf);
uint8_t NRF24L01_SendTxBuf(uint8_t *txbuf);
uint8_t NRF24L01_Check(void);
void NRF24L01_RT_Init(void);
void NRF24L01_Init(void);
void NRF24L01_SendBuf(uint8_t *Buf);
void NRF24L01_Pin_Init(void);
uint8_t NRF24L01_Get_Value_Flag();
#endif
NRF24L01_define.h
#ifndef __nRF24L01_H
#define __nRF24L01_H
/********** NRF24L01引脚定义 ***********/
#define IRQ_Port GPIOA
#define CE_Port GPIOA
#define MISO_Port GPIOA
#define MOSI_Port GPIOA
#define SCK_Port GPIOA
#define CSN_Port GPIOA
#define IRQ_Pin GPIO_Pin_11
#define CE_Pin GPIO_Pin_15
#define MOSI_Pin GPIO_Pin_7
#define MISO_Pin GPIO_Pin_6
#define SCK_Pin GPIO_Pin_5
#define CSN_Pin GPIO_Pin_4
/********** NRF24L01寄存器操作命令 ***********/
#define nRF_READ_REG 0x00
#define nRF_WRITE_REG 0x20
#define RD_RX_PLOAD 0x61
#define WR_TX_PLOAD 0xA0
#define FLUSH_TX 0xE1
#define FLUSH_RX 0xE2
#define REUSE_TX_PL 0xE3
#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
#define RF_SETUP 0x06
#define STATUS 0x07
#define OBSERVE_TX 0x08
#define CD 0x09
#define RX_ADDR_P0 0x0A
#define RX_ADDR_P1 0x0B
#define RX_ADDR_P2 0x0C
#define RX_ADDR_P3 0x0D
#define RX_ADDR_P4 0x0E
#define RX_ADDR_P5 0x0F
#define TX_ADDR 0x10
#define RX_PW_P0 0x11
#define RX_PW_P1 0x12
#define RX_PW_P2 0x13
#define RX_PW_P3 0x14
#define RX_PW_P4 0x15
#define RX_PW_P5 0x16
#define FIFO_STATUS 0x17
/****** STATUS寄存器bit位定义 *******/
#define MAX_TX 0x10 //达到最大发送次数中断
#define TX_OK 0x20 //TX发送完成中断
#define RX_OK 0x40 //接收到数据中断
#endif
ADC.c
#include "stm32f10x.h" // Device header
uint32_t AD_Value[4]; //定义用于存放AD转换结果的全局数组
/**
* 函 数:AD初始化
* 参 数:无
* 返 回 值:无
*/
void AD_Init(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //开启ADC1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //开启DMA1的时钟
/*设置ADC时钟*/
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //选择时钟6分频,ADCCLK = 72MHz / 6 = 12MHz
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA0、PA1、PA2和PA3引脚初始化为模拟输入
/*规则组通道配置*/
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); //规则组序列1的位置,配置为通道0
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5); //规则组序列2的位置,配置为通道1
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5); //规则组序列3的位置,配置为通道2
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5); //规则组序列4的位置,配置为通道3
/*ADC初始化*/
ADC_InitTypeDef ADC_InitStructure; //定义结构体变量
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //模式,选择独立模式,即单独使用ADC1
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //数据对齐,选择右对齐
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //外部触发,使用软件触发,不需要外部触发
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //连续转换,使能,每转换一次规则组序列后立刻开始下一次转换
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //扫描模式,使能,扫描规则组的序列,扫描数量由ADC_NbrOfChannel确定
ADC_InitStructure.ADC_NbrOfChannel = 4; //通道数,为4,扫描规则组的前4个通道
ADC_Init(ADC1, &ADC_InitStructure); //将结构体变量交给ADC_Init,配置ADC1
/*DMA初始化*/
DMA_InitTypeDef DMA_InitStructure; //定义结构体变量
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; //外设基地址,给定形参AddrA
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设数据宽度,选择半字,对应16为的ADC数据寄存器
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址自增,选择失能,始终以ADC数据寄存器为源
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)AD_Value; //存储器基地址,给定存放AD转换结果的全局数组AD_Value
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //存储器数据宽度,选择半字,与源数据宽度对应
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //存储器地址自增,选择使能,每次转运后,数组移到下一个位置
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //数据传输方向,选择由外设到存储器,ADC数据寄存器转到数组
DMA_InitStructure.DMA_BufferSize = 4; //转运的数据大小(转运次数),与ADC通道数一致
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //模式,选择循环模式,与ADC的连续转换一致
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //存储器到存储器,选择失能,数据由ADC外设触发转运到存储器
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //优先级,选择中等
DMA_Init(DMA1_Channel1, &DMA_InitStructure); //将结构体变量交给DMA_Init,配置DMA1的通道1
/*DMA和ADC使能*/
DMA_Cmd(DMA1_Channel1, ENABLE); //DMA1的通道1使能
ADC_DMACmd(ADC1, ENABLE); //ADC1触发DMA1的信号使能
ADC_Cmd(ADC1, ENABLE); //ADC1使能
/*ADC校准*/
ADC_ResetCalibration(ADC1); //固定流程,内部有电路会自动执行校准
while (ADC_GetResetCalibrationStatus(ADC1) == SET);
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1) == SET);
/*ADC触发*/
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //软件触发ADC开始工作,由于ADC处于连续转换模式,故触发一次后ADC就可以一直连续不断地工作
}
ADC.h
#ifndef __AD_H
#define __AD_H
extern uint32_t AD_Value[4];
void AD_Init(void);
#endif