STM8软件模拟SPI与NRF24L01通信

合集下载

基于nRF24L01的SPI远程通讯发射器

基于nRF24L01的SPI远程通讯发射器

基于nRF24L01的SPI远程通讯发射器摘要近年来,随着传感技术、嵌入式计算、现代网络、无线数据传输及分布式信息处理等技术的发展,能够将监测对象的数据通过无线方式发送,使得无线测量和传输技术也越来越受到人们的重视。

同时随着我国PM2.5污染问题日益凸显,以及公众环境意识的增强,对空气质量的关注也越来越多,但对其进行远距离实时监测仍是一个困难。

该设计是通过STM32单片机进行智能控制,通过PM2.5传感器检测空气质量,将检测的数值在OLED屏幕上显示、再通过nRF24L01通信系统将信息远程传输到室内的OLED屏上显示。

关键词: nRF24L01;STM32单片机;PM2.5传感器;1 设计背景及目的伴随着科技的发展及应用,使得无线测量和传输技术越来越受到人们的重视。

常用的无线数据传输技术主要有蓝牙技术、Wi-Fi技术、IrDA技术、超宽带技术等,而蓝牙技术和Wi-Fi技术功耗较高,IrDA技术传输速率较低,超宽带技术开发难度较高。

为了更好的实现无线通信的功能,增加模块的可靠性和使用寿命,本设计一种基于nRF24L01的无线通信系统,该系统具有传输速率高、成本低、功耗小、体积小、便于开发等优点,具有很高的应用价值。

2 基本设计思路本系统由nRF24L01、STM32单片机、PM2.5传感器模块和5V稳压模块组成。

由PM2.5传感器模块作为单片机主要的信号输入源,负责采集空气中PM2.5的含量,STM32单片机负责接收PM2.5传感器输出的检测信号后根据信号的状态不同进行不同处理,再将控制信号输出到nRF24L01,将实时监测到的PM2.5值传送到手机。

5V稳压模块则是在使用非USB供电时,使系统的输入电压保持在5V,是保证工作时系统的稳定性所必须的模块。

系统结构框图如图1所示。

图1 系统结构框图3 硬件设计本设计采用性价比较高的射频芯片nRF24L01为核心搭建无线通信硬件平台。

该平台采用ATmega16L作为微控制器,控制无线发送和接收;通过ATK-ESP8266串口与用户端手机相连,实现无线数据通信。

关于使用STM32硬件SPI驱动NRF24L01

关于使用STM32硬件SPI驱动NRF24L01

关于使用STM32硬件SPI驱动NRF24L01+ 今天是大年初一总算有时间做点想做很久的事了,说到NRF2401可能很多电子爱好者都有用过或是软件模拟驱动又或是用单片机自带的硬件SPI来驱动,但不管是用哪种方法来驱动我想都在调试方面耗费了不少的时间(可能那些所谓的电子工程师不会出现这种情况吧!)网上的资料确实很多,但大多数都并没有经过发贴人认真测试过,有的只是理论上可以行的通但上机测试只能说是拿回来给他修改。

本文作者也是经过无助的多少天才算是调试成功了(基于STM32硬件SPI,软件模拟的以前用51单片机已经调通了今天就不准备再拿来讲了,当然如果以后有朋友有需要也可以告诉我,我也可以重新写一篇关于51的驱动的只要有时间是没有问题的。

)因为我用的是STM32F103C8T6的系统而且是刚接触不知道别的系统和我用的这个系统有多大的差别所以我不会整个代码全贴上来就完事了,我将就着重思路配合代码写出来,这样对于刚接触单片机的朋友会有很好的作用,但是还有一点请大家要原谅,可能会存在一些说的不好的地方,毕竟我没有经过正规渠道系统地学习过电子知识,对于前辈来说存在这样那样的问题不可避免的,在此也希望大家指教!贴个图先:NRF2401+的资料大家上网查一下,我输字的速度有点不好说!下面我来说一下整个调试流程吧1.先把STM32串口一调通(因为我不知道STM32 I/O口不知可不可以像51那样并口输出数据,如果可以那就更方便啰)。

2.与NRF2401建立起通信(这个才是问题的关键);3.利用读NRF2401的一个状态寄存器(STATUS)的值并通过串口发送到PC后通过51下载软件的串口助手显示出来(如果你用液晶来调试那你太有才了,你液晶和NRF2401存在牵连可能就会给寻找不成功的原因造成困难,而且还有不少硬件工作要做)在这说一下本文只调试发送程序,致于接收只改一个程序参数就行了。

我们先来调试STM32F103C8T6的串口1吧(也就是USART1)!它是STM32F103C8T6的片上外设之一,使用它时相对来说简单了不少。

nRF24L01的工作原理

nRF24L01的工作原理

nRF24L01的工作原理nRF24L01是一款低功耗、高性能的2.4GHz无线收发器,广泛应用于无线通信领域。

它采用射频芯片和基带处理器相结合的设计,能够实现可靠的无线数据传输。

nRF24L01的工作原理主要分为发送和接收两个部分。

1. 发送部分:在发送数据之前,首先需要进行初始化设置。

nRF24L01通过SPI接口与主控芯片进行通信,主控芯片可以是单片机或者其他的微控制器。

通过SPI接口,主控芯片可以配置nRF24L01的工作频率、发射功率、通信速率等参数。

当需要发送数据时,主控芯片将数据通过SPI接口写入nRF24L01的发送缓冲区。

nRF24L01会将数据进行编码并添加校验位,然后将数据通过天线发送出去。

发送过程中,nRF24L01会不断检测接收方是否收到确认信号。

2. 接收部分:在接收数据之前,同样需要进行初始化设置。

接收端的nRF24L01和发送端的nRF24L01需要使用相同的工作频率、发射功率、通信速率等参数。

当nRF24L01接收到数据时,它会将接收到的数据进行解码,并进行校验,确保数据的完整性。

然后将数据通过SPI接口传输给主控芯片,主控芯片可以根据接收到的数据进行相应的处理。

nRF24L01的工作原理涉及到的一些关键技术包括频率合成器、调制解调器、射频功率放大器、SPI接口等。

频率合成器用于生成所需的工作频率,调制解调器用于将数字信号转换为射频信号或将射频信号转换为数字信号。

射频功率放大器用于增强信号的发送功率,确保信号可以在一定距离内传输。

nRF24L01支持多种工作模式,包括发送模式、接收模式、待机模式和电源关闭模式。

在待机模式下,nRF24L01可以通过设置自动唤醒定时器来降低功耗,延长电池寿命。

总结:nRF24L01是一款功能强大的无线收发器,通过SPI接口与主控芯片进行通信。

它能够实现可靠的无线数据传输,适用于各种无线通信应用。

了解nRF24L01的工作原理对于使用和开发无线通信系统是非常重要的。

nRF2401与SPI接口的软硬件解决方案

nRF2401与SPI接口的软硬件解决方案

nRF2401与SPI接口的软硬件解决方案NRF2401与SPI接口的软硬件解决方案摘要:由于Nordic公司2.4GHz的双向射频收发芯片NRF2401没有标准的SPI接口。

所以在实际的应用过程当中很难发挥它的高速无线传输的性能。

针对该问题,利用带SPI接口的LPC2104 ARM内核微控制器,介绍一种能实现高速无线数据传输的接口方法。

NRF2401与微处理的接口有两种方式:I/O直接连接方式和SPI 连接方式,但是两种连接的方式各有优缺点。

下面从NRF2401的时序上分析两种方法的优点及存在的问题,并介绍一种能有效地避开两种方式的缺点,同时又能发挥两种方式的优点的设计方法。

下面假设CPU 的晶振运行在 11.0592MHz.2 I/O直接连接方式的优点及存在的问题这种连接方式的优点是可以非常方便地与各种高低速CPU接口,并且传输的误码率很低。

缺点是因为CPU和NRF2401通信的方式是模拟SPI的串行移位,所以不得不耗费大量的时间来模拟SPI的时序,导致CPU与NRF2401的数据传输速度成为整个系统传输速度的瓶颈。

通过图1的时序图分析导致传输速度下降的原因。

图1 NRF2401以ShoekBurst方式发送的时序图通过时序图(图1)可以发现当希望以Shock-Burst方式发送一个数据包的时候,需要经过下面几个阶段:(1)边沿之间的延时T d,最短时间是50 ns。

(2)从CE引脚出现高电平到可以开始传输数据的延时T ce2data,最短时间是5 us。

(3)数据传输过程中的数据建立时间Ts,最短时间为500 ns。

保持时间Th,最短时间为500 ns。

(4)由Stand-by模式到ShockBurst发射的延时Tsby2txSB,最短时间为195us。

(5)NRF2401真正发射刚才写入FIFO中的数据包的时问Toa。

NRF2401的数据发送方式是按照数据包的方式发送的。

每发射一个数据包都要经过上述的5个阶段。

基于模拟SPI的nrf24l01点对点通信说明

基于模拟SPI的nrf24l01点对点通信说明

基于模拟SPI的nrf24l01点对点通信说明基于模拟SPI的nrf24l01点对点通信通过阅读nrf24l01的中文手册大致了解其通信方式为SPI通信,上网查询SPI通信相关知识。

通过参考手册例程和网上例程完成程序的编写。

模拟SPI:使用单片机的IO口,利用函数来模拟SPI通信。

核心函数及个人的理解:uchar SPI_RW(uchar byte){uchar bit_ctr;for(bit_ctr=0;bit_ctr<8;bit_ctr++) // 循环8次{MOSI = (byte & 0x80); // byte的最高位输出到MOSI,取最高位发送byte = (byte << 1); // 左移一位SCK = 1; // 拉高SCK,24L01从MOSI中读入一位数据,同时从MISO输出一位数据byte |= MISO; // 读MISO的最低位SCK = 0; // SCK置低}return(byte); // 返回读出的数据(从机的答复)}个人对该函数的理解:①函数功能:发送一个八位数据(由高位向低位,一位一位的发送)并接受从从机返回的数据,函数最后的返回是接受的数据。

②通过MOSI = (byte & 0x80); 的与运算实现先发高位。

特别需要注意的是MOSI MISO 两个都是一位传输的③发送一位数据后,数据左移右侧补0,接受到的一位数据与原先的数据进行或运算,将接受的数据放到最后一位而不影响原数据中尚未发送位上的数据。

如此八个循环后就实现了数据的发送和接受。

SPI_RW()函数理解后,程序中的其他函数都是实现nrf24l01的寄存器的配置,需参见数据手册进行理解(PS中文手册中有一些有错误,必要时可参见英文手册)。

具体的注释在我上发的程序中有详细的注释,请参见该程序。

基于模拟SPI的nrf24l01点对点通信,是nrf24l01 入门的应用,下一步工作我将继续研究基于硬件SPI的nrf24l01点对点通信,以及nrf24l01的点对多通信。

STM8应用于NRF24L01

STM8应用于NRF24L01

编译环境 IAR发送端/* Includes ------------------------------------------------------------------*/ #include "stm8s.h"#define uint unsigned int#define uchar unsigned char#define CE_1 GPIO_WriteHigh(GPIOD, GPIO_PIN_3)#define CE_0 GPIO_WriteLow(GPIOD, GPIO_PIN_3)//SPI时钟端#define SCK_1 GPIO_WriteHigh(GPIOD, GPIO_PIN_2)#define SCK_0 GPIO_WriteLow(GPIOD, GPIO_PIN_2)//SPI主机输出从机输出端#define MISO GPIO_ReadInputPin(GPIOD,GPIO_PIN_0)//SPI主机输出从机输入端#define MOSI_1 GPIO_WriteHigh(GPIOD, GPIO_PIN_7)#define MOSI_0 GPIO_WriteLow(GPIOD, GPIO_PIN_7)//SPI片选端//就是SS#define CSN_1 GPIO_WriteHigh(GPIOD, GPIO_PIN_4)#define CSN_0 GPIO_WriteLow(GPIOD, GPIO_PIN_4)#define TX_ADDR_WITDH 5//发送地址宽度设置为5个字节#define RX_ADDR_WITDH 5#define TX_DATA_WITDH 8#define RX_DATA_WITDH 8/******************************************************************// nRF24L01指令格式:*******************************************************************/#define R_REGISTER 0x00 // 读寄存器#define W_REGISTER 0x20 // 写寄存器#define R_RX_PLOAD 0x61 // 读RX FIFO有效数据,1-32字节,当读数据完成后,数据被清除,应用于接收模式#define W_TX_PLOAD 0xA0 // 写TX FIFO有效数据,1-32字节,写操作从字节0开始,应用于发射模式#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_RX_ADDR 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 // 数据通道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有效数据宽度设置寄存器#define RX_PW_P1 0x12 // 数据通道1有效数据宽度设置寄存器#define RX_PW_P2 0x13 // 数据通道2有效数据宽度设置寄存器#define RX_PW_P3 0x14 // 数据通道3有效数据宽度设置寄存器#define RX_PW_P4 0x15 // 数据通道4有效数据宽度设置寄存器#define RX_PW_P5 0x16 // 数据通道5有效数据宽度设置寄存器#define FIFO_STATUS 0x17 // FIFO状态寄存器//******************************************************************* **************uchar sta; // 状态变量#define RX_DR (sta & 0x40) // 接收成功中断标志#define TX_DS (sta & 0x20) // 发射成功中断标志#define MAX_RT (sta & 0x10) // 重发溢出中断标志uchar TX_Addr[]={0x34,0x43,0x10,0x10,0x01};uchar TX_Buffer[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x00};uchar RX_Buffer[RX_DATA_WITDH];void _delay_us(uint x){uint i,j;for (j=0;j<x;j++)for (i=0;i<12;i++);}void _delay_ms(uint x){uint i,j;for (j=0;j<x;j++)for (i=0;i<120;i++);}/*nRF24L01初始化*/void nRF24L01_Init(void){CE_0;//待机模式ⅠCSN_1;SCK_0;//IRQ=1;}/*SPI时序函数*/uchar SPI_RW(uchar byte){uchar i;for(i=0;i<8;i++)//一字节8位循环8次写入{if(byte&0x80)//如果数据最高位是1//当访问多字节寄存器时首先要读/写的是最低字节的高位?MOSI_1;//向NRF24L01写1else //否则写0MOSI_0;byte<<=1;//低一位移到最高位SCK_1;//SCK拉高,写入一位数据,同时读取一位数据if(MISO)byte|=0x01;SCK_0;//SCK拉低}return byte;//返回读取一字节}/*SPI写寄存器一字节函数*//*reg:寄存器地址*//*value:一字节(值)*/uchar SPI_W_Reg(uchar reg,uchar value){uchar status;//返回状态CSN_0;//SPI片选status=SPI_RW(reg);//写入寄存器地址,同时读取状态SPI_RW(value);//写入一字节CSN_1;//return status;//返回状态}/*SPI*/uchar SPI_R_byte(uchar reg){uchar reg_value;CSN_0;//SPI片选SPI_RW(reg);//写入地址reg_value=SPI_RW(0);//读取寄存器的值CSN_1;return reg_value;//返回读取的值}/*SPI读取RXFIFO寄存器数据*//*reg:寄存器地址*//**Dat_Buffer:用来存读取的数据*//*DLen:数据长度*/uchar SPI_R_DBuffer(uchar reg,uchar *Dat_Buffer,uchar Dlen) {uchar status,i;CSN_0;//SPI片选status=SPI_RW(reg);//写入寄存器地址,同时状态for(i=0;i<Dlen;i++){Dat_Buffer[i]=SPI_RW(0);//存储数据}CSN_1;return status;}/*SPI向TXFIFO寄存器写入数据*//*reg:写入寄存器地址*//*TX_Dat_Buffer:存放需要发送的数据*//*Dlen:数据长度*/uchar SPI_W_DBuffer(uchar reg,uchar *TX_Dat_Buffer,uchar Dlen) {uchar status,i;CSN_0;//SPI片选,启动时序status=SPI_RW(reg);for(i=0;i<Dlen;i++){SPI_RW(TX_Dat_Buffer[i]);//发送数据}CSN_1;return status;}/*设置发送模式*/void nRF24L01_Set_TX_Mode(uchar *TX_Data){CE_0;//待机(写寄存器之前一定要进入待机模式或掉电模式)SPI_W_DBuffer(W_REGISTER+TX_ADDR,TX_Addr,TX_ADDR_WITDH);/*写寄存器指令+接收节点地址+地址宽度*/SPI_W_DBuffer(W_REGISTER+RX_ADDR_P0,TX_Addr,TX_ADDR_WITDH);/*为了接收设备应答信号,接收通道0地址与发送地址相同*/SPI_W_DBuffer(W_TX_PLOAD,TX_Data,TX_DATA_WITDH);/*写有效数据地址+有效数据+有效数据宽度*/SPI_W_Reg(W_REGISTER+EN_AA,0x01);/*接收通道0自动应答*/SPI_W_Reg(W_REGISTER+EN_RX_ADDR,0x01);/*使能接收通道0*/SPI_W_Reg(W_REGISTER+SETUP_RETR,0x0a);/*自动重发延时250US+86US,重发10次*/SPI_W_Reg(W_REGISTER+RF_CH,0);/*(2400+40)MHZ选择射频通道0X40*/SPI_W_Reg(W_REGISTER+RF_SETUP,0x07);/*1Mbps速率,发射功率:0DBM,低噪声放大器增益*/SPI_W_Reg(W_REGISTER+CONFIG,0x0e);/*发送模式,上电,16位CRC校验,CRC使能*/CE_1;//启动发射_delay_ms(5);/*CE高电平持续时间最少10US以上*/}uchar Check_Rec(void){uchar status;sta=SPI_R_byte(R_REGISTER+STATUS);if(RX_DR){CE_0;SPI_R_DBuffer(R_RX_PLOAD,RX_Buffer,RX_DATA_WITDH);status=1;}SPI_W_Reg(W_REGISTER+STATUS,0xff);return status;}/*检测应答信号*/uchar Check_Ack(void){sta=SPI_R_byte(R_REGISTER+STATUS);/*读取寄存状态*/if(TX_DS||MAX_RT)/*如果TX_DS或MAX_RT为1,则清除中断和清除TX_FIFO 寄存器的值*/{SPI_W_Reg(W_REGISTER+STATUS,0xff);CSN_0;SPI_RW(FLUSH_TX);CSN_1;return 0;}elsereturn 1;}int main(void){/* Infinite loop *//*设置内部时钟16M为主时钟*/CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);GPIO_Init(GPIOC, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_FAST); GPIO_Init(GPIOD, GPIO_PIN_0, GPIO_MODE_IN_PU_NO_IT); GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_OUT_PP_HIGH_FAST); GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_FAST); GPIO_Init(GPIOD, GPIO_PIN_7, GPIO_MODE_OUT_PP_HIGH_FAST); GPIO_Init(GPIOD, GPIO_PIN_4, GPIO_MODE_OUT_PP_HIGH_FAST);nRF24L01_Init();/*!<Set High speed internal clock */while (1){/* 添加你的代码 */nRF24L01_Set_TX_Mode(&TX_Buffer[1]);while(Check_Ack());GPIO_WriteReverse(GPIOC, GPIO_PIN_3);_delay_ms(1000);}}#ifdef USE_FULL_ASSERT/*** @brief Reports the name of the source file and the source line number* where the assert_param error has occurred.* @param file: pointer to the source file name* @param line: assert_param error line source number* @retval : None*/void assert_failed(u8* file, u32 line){/* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* Infinite loop */while (1){}}#endif/******************* (C) COPYRIGHT 风驰iCreate嵌入式开发工作室 *****END OF FILE****/接收端/* Includes ------------------------------------------------------------------*/#include "stm8s.h"/* Private defines -----------------------------------------------------------*//* Private function prototypes -----------------------------------------------*//* Private functions ---------------------------------------------------------*/#define uint unsigned int#define uchar unsigned char#define TX_ADDR_WITDH 5//发送地址宽度设置为5个字节#define RX_ADDR_WITDH 5#define TX_DATA_WITDH 8#define RX_DATA_WITDH 8#define CE_1 GPIO_WriteHigh(GPIOD, GPIO_PIN_3)#define CE_0 GPIO_WriteLow(GPIOD, GPIO_PIN_3)//SPI时钟端#define SCK_1 GPIO_WriteHigh(GPIOD, GPIO_PIN_2)#define SCK_0 GPIO_WriteLow(GPIOD, GPIO_PIN_2)//SPI主机输出从机输出端#define MISO GPIO_ReadInputPin(GPIOD,GPIO_PIN_0)//SPI主机输出从机输入端#define MOSI_1 GPIO_WriteHigh(GPIOD, GPIO_PIN_7)#define MOSI_0 GPIO_WriteLow(GPIOD, GPIO_PIN_7)//SPI片选端//就是SS#define CSN_1 GPIO_WriteHigh(GPIOD, GPIO_PIN_4)#define CSN_0 GPIO_WriteLow(GPIOD, GPIO_PIN_4)/******************************************************************// nRF24L01指令格式:*******************************************************************/#define R_REGISTER 0x00 // 读寄存器#define W_REGISTER 0x20 // 写寄存器#define R_RX_PLOAD 0x61 // 读RX FIFO有效数据,1-32字节,当读数据完成后,数据被清除,应用于接收模式#define W_TX_PLOAD 0xA0 // 写TX FIFO有效数据,1-32字节,写操作从字节0开始,应用于发射模式#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_RX_ADDR 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 // 数据通道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有效数据宽度设置寄存器#define RX_PW_P1 0x12 // 数据通道1有效数据宽度设置寄存器#define RX_PW_P2 0x13 // 数据通道2有效数据宽度设置寄存器#define RX_PW_P3 0x14 // 数据通道3有效数据宽度设置寄存器#define RX_PW_P4 0x15 // 数据通道4有效数据宽度设置寄存器#define RX_PW_P5 0x16 // 数据通道5有效数据宽度设置寄存器#define FIFO_STATUS 0x17 // FIFO状态寄存器//******************************************************************* **************uchar sta; // 状态变量#define RX_DR (sta & 0x40) // 接收成功中断标志#define TX_DS (sta & 0x20) // 发射成功中断标志#define MAX_RT (sta & 0x10) // 重发溢出中断标志uchar TX_Addr[]={0x34,0x43,0x10,0x10,0x01};uchar TX_Buffer[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; uchar RX_Buffer[RX_DATA_WITDH];void _delay_us(uint x){uint i,j;for (j=0;j<x;j++)for (i=0;i<12;i++);}void _delay_ms(uint x){uint i,j;for (j=0;j<x;j++)for (i=0;i<120;i++);}void nRF24L01_Init(void){_delay_us(2000);CE_0;CSN_1;SCK_0;//IRQ=1;}uchar SPI_RW(uchar byte){uchar i;for(i=0;i<8;i++){if(byte&0x80)MOSI_1;elseMOSI_0;byte<<=1;SCK_1;if(MISO)byte|=0x01;SCK_0;}return byte;}uchar SPI_W_Reg(uchar reg,uchar value) {uchar status;CSN_0;status=SPI_RW(reg);SPI_RW(value);CSN_1;return status;}uchar SPI_R_byte(uchar reg)uchar status;CSN_0;SPI_RW(reg);status=SPI_RW(0);CSN_1;return status;}uchar SPI_R_DBuffer(uchar reg,uchar *Dat_Buffer,uchar Dlen) {uchar reg_value,i;CSN_0;reg_value=SPI_RW(reg);for(i=0;i<Dlen;i++){Dat_Buffer[i]=SPI_RW(0);}CSN_1;return reg_value;}uchar SPI_W_DBuffer(uchar reg,uchar *TX_Dat_Buffer,uchar Dlen) {uchar reg_value,i;CSN_0;reg_value=SPI_RW(reg);for(i=0;i<Dlen;i++){SPI_RW(TX_Dat_Buffer[i]);}CSN_1;return reg_value;}void nRF24L01_Set_RX_Mode(void){CE_0;//待机SPI_W_DBuffer(W_REGISTER+TX_ADDR,TX_Addr,TX_ADDR_WITDH);SPI_W_DBuffer(W_REGISTER+RX_ADDR_P0,TX_Addr,TX_ADDR_WITDH);SPI_W_Reg(W_REGISTER+EN_AA,0x01);//auot ackSPI_W_Reg(W_REGISTER+EN_RX_ADDR,0x01);SPI_W_Reg(W_REGISTER+SETUP_RETR,0x0a);SPI_W_Reg(W_REGISTER+RX_PW_P0,RX_DATA_WITDH);SPI_W_Reg(W_REGISTER+RF_CH,0);SPI_W_Reg(W_REGISTER+RF_SETUP,0x07);//0db,lnaSPI_W_Reg(W_REGISTER+CONFIG,0x0f);CE_1;// LNA_RX=1;// LNA_TX=0;_delay_ms(5);}uchar nRF24L01_RX_Data(void){// uchar i,status;sta=SPI_R_byte(R_REGISTER+STATUS);if(RX_DR){CE_0;SPI_R_DBuffer(R_RX_PLOAD,RX_Buffer,RX_DATA_WITDH);// P3=RX_Buffer[0];SPI_W_Reg(W_REGISTER+STATUS,0xff);CSN_0;SPI_RW(FLUSH_RX);CSN_1;// LNA_RX=0;// LNA_TX=1;return 1;}elsereturn 0;}void main(void){/* Infinite loop *//*设置内部时钟16M为主时钟*/CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);GPIO_Init(GPIOC, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_FAST);GPIO_Init(GPIOC, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_FAST);GPIO_Init(GPIOD, GPIO_PIN_0, GPIO_MODE_IN_PU_NO_IT);GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_OUT_PP_HIGH_FAST);GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_FAST);GPIO_Init(GPIOD, GPIO_PIN_7, GPIO_MODE_OUT_PP_HIGH_FAST);GPIO_Init(GPIOD, GPIO_PIN_4, GPIO_MODE_OUT_PP_HIGH_FAST); nRF24L01_Init();/*!<Set High speed internal clock */while (1){//uchar i;/* 添加你的代码 */nRF24L01_Set_RX_Mode();//Delay(120);if(nRF24L01_RX_Data()){GPIO_WriteReverse(GPIOC, GPIO_PIN_3);_delay_ms(100);}}}#ifdef USE_FULL_ASSERT/*** @brief Reports the name of the source file and the source line number* where the assert_param error has occurred.* @param file: pointer to the source file name* @param line: assert_param error line source number* @retval : None*/void assert_failed(u8* file, u32 line){/* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* Infinite loop */while (1){}#endif/******************* (C) COPYRIGHT 风驰iCreate嵌入式开发工作室 *****END OF FILE****/。

如何让SPI nRF24L01无线在两个单片机里实现通信

如何让SPI nRF24L01无线在两个单片机里实现通信
65 LED6=1;
66 delay_ms(300}
69 }
2401.h
1 #ifndef __NRF24L01_H__
2 #define __NRF24L01_H__
3 #include
4 #define uchar unsigned char
5 #define uint unsigned int
45 delay_ms(5);//消抖动
46 if(KEY8==0)
47 {
48 while(!KEY8);
49 TX_Mode(); //发送模式
50 nRF24L01_TxPacket(Tx_Buf1); //发送命令数据
51 LED6=0;
52 delay_ms(300);
53 LED6=1;
6
7 sbit CE =P1
18 {
19 unsigned int i;
20 while(x--)
21 for(i=125;i》0;i--);
22 }
23 void main()
24 {
25 uchar Tx_Buf1[]={1};//发送的信息1
26 uchar Rx_Buf[32]; //接收到的数据暂存器,最多32字节数据
39 {
40 RX_Mode();//接收模式
41 while(!nRF24L01_RxPacket(Rx_Buf))//等待接收数据,返回1则接收到数据,在等待接收数据期间,可以随时变成发送模式
42 {
43 if(KEY8==0)//按了按键8则变成发送模式,发送对应数据,发送完后变成接收模式
44 {
如何让SPI nRF24L01无线在两个单片机里实现通信

无线通信24L01操作总结

无线通信24L01操作总结

24L01操作总结初始化一个芯片,如果用一个IO口来模拟协议,那么片选CS = 1;CE = 1; SCK = 0;(时钟线闲时是低电平还是高电平,这个也有讲究,特别是SPI)。

初始化时,先不使能芯片,所以片选拉高,并且使能端也拉高。

初始化函数截图:SPI_Write_Buf函数说明:先传递写操作指令+发送寄存器的地址+用户指定的发送地址+数据个数。

先传递写操作指令+接收寄存器的地址+用户指定的接收地址+数据个数。

SPI_RW_Reg函数说明:主要设置频道,例如接收频道,芯片工作频率,接收的数据宽度,发送速率的频率,以及发射功率等。

24L01常见的指令主函数:SetTX_Mode函数:主要是清除相应的中断位,然后选择校验CRC模式,有8位模式,还有16位模式,并且设置为发送,并设置芯片上电。

nRF24L01_TxPacket函数:主要是设置接收端通道0接收地址,接收地址是TX_ADDRESS。

第二步就开始写入发送命令,并且传递发送数据tx_buff数组的首地址。

发送的数据宽度是20个字节.第三步操作设置寄存器,为什么是0x0e呢,这个需要参照设置寄存器的内容来讨论,设置寄存器的内容如下:从最低位为0可以知道,选择为发射模式。

最后发送了数据,从主函数可以得知,又调用了这个函数。

SPI_RW_Reg(WRITE_REG+STATUS,0XFF);接收模式的主函数如下:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)函数说明重点是写了一个接收的指令,这个必须有。

巧妙就是接收到数据就返回1,否则返回0;并且sta这个变量读出状态寄存器的内容,然后在接收完数据后,又清理状态寄出器对应的位,这个效果是,读数据保存数据和清除状态寄出器的相应位都互不影响。

从接收的主函数可以知道,程序比较简单。

SPI控制nRF24L01程序参考

SPI控制nRF24L01程序参考

#include <reg52.h>#include <intrins.h>typedef unsigned char uchar;typedef unsigned char uint;//****************************************IO端口定义***************************************sbit CSN =P2^0; //SPI 片选使能,低电平使能sbit MOSI =P2^1; //SPI串行输入sbit IRQ =P2^2; //中断.低电平使能sbit MISO =P2^3; //SPI串行输出sbit SCK =P2^4; //SPI时钟sbit CE =P2^5; //芯片使能,高电平使能//***********************************数码管0-9编码******************************************* uchar seg[10]={0xC0,0xCF,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};//0~~9段码uchar TxBuf[32]={ /*0x01,0x02,0x03,0x4,0x05,0x06,0x07,0x08,0x09,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x30,0x31,0x32,*/0x00}; ////************************************按键**********************************************sbit KEY1=P3^6;sbit KEY2=P3^7;//***********************************数码管位选************************************************** sbit led1=P2^1;sbit led0=P2^0;sbit led2=P2^2;sbit led3=P2^3;//*********************************************NRF24L01*************************************#define TX_ADR_WIDTH 5 // 5 uints TX address width#define RX_ADR_WIDTH 5 // 5 uints RX address width#define TX_PLOAD_WIDTH 32 // 20 uints TX payload#define RX_PLOAD_WIDTH 32 // 20 uints TX payloaduint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址//***************************************NRF24L01寄存器指令*******************************************************#define READ_REG 0x00 // 读寄存器指令#define WRITE_REG 0x20 // 写寄存器指令#define RD_RX_PLOAD 0x61 // 读取接收数据指令#define WR_TX_PLOAD 0xA0 // 写待发数据指令#define FLUSH_TX 0xE1 // 冲洗发送FIFO指令#define FLUSH_RX 0xE2 // 冲洗接收FIFO指令#define REUSE_TX_PL 0xE3 // 定义重复装载数据指令#define NOP 0xFF // 保留//*************************************SPI(nRF24L01)寄存器地址****************************************************#define CONFIG 0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式#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 // 频道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接收数据长度#define RX_PW_P1 0x12 // 接收频道0接收数据长度#define RX_PW_P2 0x13 // 接收频道0接收数据长度#define RX_PW_P3 0x14 // 接收频道0接收数据长度#define RX_PW_P4 0x15 // 接收频道0接收数据长度#define RX_PW_P5 0x16 // 接收频道0接收数据长度#define FIFO_STATUS 0x17 // FIFO栈入栈出状态寄存器设置//**************************************************************************************void Delay(unsigned int s);void inerDelay_us(unsigned char n);void init_NRF24L01(void);uint SPI_RW(uint uchar);uchar SPI_Read(uchar reg);void SetRX_Mode(void);uint SPI_RW_Reg(uchar reg, uchar value);uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars);uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars);unsigned char nRF24L01_RxPacket(unsigned char* rx_buf);void nRF24L01_TxPacket(unsigned char * tx_buf);//*****************************************长延时*****************************************void Delay(unsigned int s){unsigned int i;for(i=0; i<s; i++);for(i=0; i<s; i++);}//******************************************************************************************uint bdata sta; //状态标志sbit RX_DR =sta^6;sbit TX_DS =sta^5;sbit MAX_RT =sta^4;/******************************************************************************************/*延时函数/******************************************************************************************/void inerDelay_us(unsigned char n){for(;n>0;n--)_nop_();}//****************************************************************************************/*NRF24L01初始化//***************************************************************************************/void init_NRF24L01(void){inerDelay_us(100);CE=0; // chip enableCSN=1; // Spi disableSCK=0; // Spi clock line init highSPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写本地地址SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 频道0自动ACK应答允许SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 允许接收地址只有频道0,如果需要多频道可以参考Page21SPI_RW_Reg(WRITE_REG + RF_CH, 0); // 设置信道工作为2.4GHZ,收发必须一致SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); //设置发射速率为1MHZ,发射功率为最大值0dBSPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送}/**************************************************************************************************** /*函数:uint SPI_RW(uint uchar)/*功能:NRF24L01的SPI写时序/****************************************************************************************************/ uint SPI_RW(uint uchar){uint bit_ctr;for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit{MOSI = (uchar & 0x80); // output 'uchar', MSB to MOSIuchar = (uchar << 1); // shift next bit into MSB..SCK = 1; // Set SCK high..uchar |= MISO; // capture current MISO bitSCK = 0; // ..then set SCK low again}return(uchar); // return read uchar}/**************************************************************************************************** /*函数:uchar SPI_Read(uchar reg)/*功能:NRF24L01的SPI时序/****************************************************************************************************/ uchar SPI_Read(uchar reg){uchar reg_val;CSN = 0; // CSN low, initialize SPI communication...SPI_RW(reg); // Select register to read from..reg_val = SPI_RW(0); // ..then read registervalueCSN = 1; // CSN high, terminate SPI communicationreturn(reg_val); // return register value}/****************************************************************************************************/ /*功能:NRF24L01读写寄存器函数/****************************************************************************************************/ uint SPI_RW_Reg(uchar reg, uchar value){uint status;CSN = 0; // CSN low, init SPI transactionstatus = SPI_RW(reg); // select registerSPI_RW(value); // ..and write value to it..CSN = 1; // CSN high againreturn(status); // return nRF24L01 status uchar}/****************************************************************************************************/ /*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数/****************************************************************************************************/ uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,uchar_ctr;CSN = 0; // Set CSN low, init SPI tranactionstatus = SPI_RW(reg); // Select register to write to and read status ucharfor(uchar_ctr=0;uchar_ctr<uchars;uchar_ctr++)pBuf[uchar_ctr] = SPI_RW(0); //CSN = 1;return(status); // return nRF24L01 status uchar}/**************************************************************************************************** *****/*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数/**************************************************************************************************** *****/uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,uchar_ctr;CSN = 0; //SPI使能status = SPI_RW(reg);for(uchar_ctr=0; uchar_ctr<uchars; uchar_ctr++) //SPI_RW(*pBuf++);CSN = 1; //关闭SPIreturn(status); //}/****************************************************************************************************/ /*函数:void SetRX_Mode(void)/*功能:数据接收配置/****************************************************************************************************/ void SetRX_Mode(void){CE=0;SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收发完成中断响应,16位CRC ,主接收CE = 1;inerDelay_us(130);}/**************************************************************************************************** **//*函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)/*功能:数据读取后放如rx_buf接收缓冲区中/**************************************************************************************************** **/unsigned char nRF24L01_RxPacket(unsigned char* rx_buf){unsigned char revale=0;sta=SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状况if(RX_DR) // 判断是否接收到数据{CE = 0; //SPI使能SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO bufferrevale =1; //读取数据完成标志}SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志return revale;}/**************************************************************************************************** *******/*函数:void nRF24L01_TxPacket(unsigned char * tx_buf)/*功能:发送tx_buf中数据/**************************************************************************************************** ******/void nRF24L01_TxPacket(unsigned char * tx_buf){CE=0; //StandBy I模式SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载接收端地址SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 装载数据// SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送CE=1; //置高CE,激发数据发送inerDelay_us(10);}/**************************************************************************************************** *******/*函数:init_uart(void)/*功能:初始化串口;波特率4800bps/**************************************************************************************************** ******/void init_uart(void){SCON = 0x50;TMOD = 0x20;TH1 = 0xFA;TL1 = 0xFA;PCON = 0x00;TR1 = 1;}//************************************通过串口将接收到数据发送给PC端**************************************void R_S_Byte(uchar R_Byte){SBUF = R_Byte;while( TI == 0 ); //查询法TI = 0;}//************************************工作指示灯************************************** void power_on(void){P0 = 0xfd;Delay(6000);P0 = 0xff;Delay(6000);}//************************************主函数************************************************************void main(void){uchar i;uchar temp =0;init_uart();init_NRF24L01();nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer dataDelay(6000);//CE = 1;while(1){power_on();nRF24L01_TxPacket(TxBuf);SPI_RW_Reg(WRITE_REG+STATUS,0XFF);Delay(100);//Delay(6000);TxBuf[31] = TxBuf[31] + 1;}}。

NRF24L01详细教程

NRF24L01详细教程

先来看接口电路,使用的IO 口不是唯一的哦,可随意定义接口,当然是在使用IO 口模拟SPI 且IRQ 中断引脚不使用的使用查询方法判断接收状态的情况下了。

作为初探我们就是用简单的IO 模拟SPI 的方法了,中断使用查询的方式。

那么该教程讲解的接口与单片机的连接如下:首先您需要了解NRF24L01,请参阅“NRF24L01 芯片中文资料”或者“NRF24L01 芯片英文资料”。

我们的教程是以一个简单的小项目为大家展示NRF24L01 的使用方法与乐趣。

我们所写教程均是以这种方式的呢,让您在学习的时候明白它能做什么,使您学起来不至于枯燥无味。

作为简易的教程,我们只需要知道它是怎么使用的就够了,我们本教程的目的是用NRF24L01 发送数据和接收数据,且接收方会对比发送的数据与接收的数据,若完全相同则控制LED 闪烁一次,并且把接收到的数据通过串口发送到PC 端,通过串口工具查看接收到的数据。

具体的要求如下:1、具备发送和接收的能力。

2、发送32 个字节的数据,接收方接收到正确数据之后给予提示,通过LED 闪烁灯形式。

3、把接收到的数据传送到PC 进行查看。

4、发送端每隔大约1.5 秒发送一次数据,永久循环。

以上是程序的要求,若您想自行设计出硬件接口,您也是可以添加一条呢:使用DIY 方式设计NRF24L01 的接口板,且包含含单片机平台,使用PCB 方式或者万用板方式均可。

如果您想让自己学的很扎实,那么推荐您自行做出接口板子呢。

当然若您的能力不足,那么我们不推荐自行做板呢,因为这样会增加您学习的难度,反而起到了反效果呢。

我们知道NRF24L01 的供电电压是1.9V~3.6V 不能超过这个范围,低了不工作,高了可能烧毁NRF24L01 芯片。

我们常用的STC89C52 的单片机的供电电压是5V,我们不能直接给24L01 这个模块供电,我们需要使用AMS1117-3.3V 稳压芯片把5V 转成3.3V 的电压为24L01 模块供电。

nRF24L01单片机通信的总结--看了就会用了 - 51单片机 - 单片机论坛 - 手机版

nRF24L01单片机通信的总结--看了就会用了 - 51单片机 - 单片机论坛 - 手机版

nRF24L01单片机通信的总结--看了就会用了- 51单片机-单片机论坛- 手机版1周时间,我从一个没用过STC单片机,不知道什么叫SPI接口的“文盲”,把nRF24L01的整个通信过程弄到完全没有bug.。

兴奋之余来小屁一下。

给那些正在奋斗着这个牛逼的芯片的小牛们小炫一下。

希望有所帮助。

屁话少说。

正题:基本的东西我理解了,那就是:1.用5根线的SPI 接口向2401发送数据或指令。

2.芯片在每次上电的时候都需要进行一番配置。

这些配置数据,就是所谓的指令了。

3.配置完成后知道芯片处在哪个模式。

并且知道它将要转向哪个模式。

4.通讯协议。

5.观察现象。

好了,小牛们一定急切想知道自己的程序问题出在哪里了,再小白一点的一定想急切的知道如何配置才能让它工作。

更小白一点的一定想知道这个芯片的各个模式之间是怎么联系的。

又是如何进行相互转化的。

别急,一个一个说。

要说什么最重要,你们不会想到其实是4.通讯协议。

为什么呢,你们又知道在这里的通讯协议是作什么用的呢。

举个简单的例子,我刚开始设计的时候,一心想让一个作为发送模块,每隔一秒发送一次数据,而另一个则作为接收模块,不间断的检测收到数据没有。

这就是一个简单的通讯协议,它是我们的目标。

是我们的方向。

当然真正的通讯协议绝对不会这么简单的几句话。

它告诉你,你理想中的模块应该充当什么角色。

是接收?是发送?还是接收完了马上发送。

作为开发阶段,当然是越简单的协议,正确性就越容易验证,废话不说,那就按我说的“通讯协议”来设计吧。

先说发送模式吧。

要到发送模式,要经历几个变化。

第1,上电,上电完了芯片其实还是在powerDown模式,因为芯片为了省电,它需要通过软件来控制开机或关机。

powerDown模式就是所谓的待机模式了。

这个模式理所当然是最省电的。

它除了省电以外还能干吗呢?配置!对最重要的配置。

就是可以通过SPI口向它发送数据,它是可以接收到的,并且可以正确写入到指定的寄存器中的。

nrf24l01发送接收一体程序(以调通-解决了接收端只能接收一次的问题)

nrf24l01发送接收一体程序(以调通-解决了接收端只能接收一次的问题)
函数:init_ZD()
描述:
中断初始化程序
/**************************************************/
void init_ZD(void)
{
IT0=0;//低电平触发
EA=1;
EX0=1;//中断允许
}
/**************************************************
return(status); //返回状态寄存器
}
/**************************************************
函数:RX_Mode()
描述:
这个函数设置nRF24L01为接收模式,等待接收发送设备的数据包
/**************************************************/
sbit LED=P2^1; //LED报警器输出端
sbit SDA=P2^4; //语音模块数据控制端
sbit ONN=P2^3;//语音芯片电源控制端口
sbit FM =P2^5;//蜂鸣器
/**************************************************
函数:delayus()
{
CE = 0;
SPI_Write_Buf(WR_TX_PLOAD, BUF, TX_PLOAD_WIDTH); //写数据包到TX FIFO
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0E); // CRC使能,16位CRC校验,上电
CE = 1;
delayms(1);
}

浅谈基于NRF24L01无线SPI通信协议的理解及VC

浅谈基于NRF24L01无线SPI通信协议的理解及VC

浅谈基于NRF24L01无线SPI通信协议的理解及
VC++6.0的模拟
#include<stdio.h>
#define uchar unsigned char //类型定义
uchar ch=0x63,mosi; //ch为待传输数据
uchar MISO,MOSI; //SPI通信MISO和MOSI的两根线,由于仿真,没有设置SCK
void main()
{ int i;
for(i=0;i<8;i++) //满足一个字节,即8个二进制位后,运算结束
{ MOSI=(ch&0x80); //MOSI与0x80即1000 0000作与运算
MOSI=(MOSI!=0); //如果MOSI为1000 0000 则不等于0为真为1 否则为0,因为单片机引脚只有0 1两种状态
ch=(ch<<1); //将ch左移,最右边用0补齐
MISO=MOSI; //将MOSI传输到NRF24L01,NRF24L01并将MOSI得到的0或1输入到单片机
printf("%d",MISO); //输出MISO 检查
ch|=MISO; //将MISO 与ch作或运算,相当于将ch左移后,将最左边挤出的数值转移到最右边
}
实验结果如下图。

nRF24L01无线通信模块使用手册12要点

nRF24L01无线通信模块使用手册12要点

nRF24L01无线通信模块使用手册一、模块简介该射频模块集成了NORDIC公司生产的无线射频芯片nRF24L01:1.支持2.4GHz的全球开放ISM频段,最大发射功率为0dBm2.2Mbps,传输速率高3.功耗低,等待模式时电流消耗仅22uA4.多频点(125个),满足多点通信及跳频通信需求5.在空旷场地,有效通信距离:25m(外置天线)、10m(PCB天线)6.工作原理简介:发射数据时,首先将nRF24L01配置为发射模式,接着把地址TX_ADDR和数据TX_PLD 按照时序由SPI口写入nRF24L01缓存区,TX_PLD必须在CSN为低时连续写入,而TX_ADDR在发射时写入一次即可,然后CE置为高电平并保持至少10μs,延迟130μs后发射数据;若自动应答开启,那么nRF24L01在发射数据后立即进入接收模式,接收应答信号。

如果收到应答,则认为此次通信成功,TX_DS置高,同时TX_PLD从发送堆栈中清除;若未收到应答,则自动重新发射该数据(自动重发已开启),若重发次数(ARC_CNT)达到上限,MAX_RT置高,TX_PLD不会被清除;MAX_RT或TX_DS置高时,使IRQ变低,以便通知MCU。

最后发射成功时,若CE为低,则nRF24L01进入待机模式1;若发送堆栈中有数据且CE为高,则进入下一次发射;若发送堆栈中无数据且CE为高,则进入待机模式2。

接收数据时,首先将nRF24L01配置为接收模式,接着延迟130μs进入接收状态等待数据的到来。

当接收方检测到有效的地址和CRC时,就将数据包存储在接收堆栈中,同时中断标志位RX_DR置高,IRQ变低,以便通知MCU去取数据。

若此时自动应答开启,接收方则同时进入发射状态回传应答信号。

最后接收成功时,若CE变低,则nRF24L01进入空闲模式1。

三、模块引脚说明四、模块与AT89S52单片机接口电路注:上图为示意连接,可根据自己实际需求进行更改;使用AT89S52MCU模块时,请将Nrf24L01通讯模块每个端口(MOSI、SCK、CSN和CE)接4.7K的排阻上拉到VCC增强其驱动能力(如下图:)。

nrf24l01模块与单片机通信方式

nrf24l01模块与单片机通信方式

nrf24l01模块与单片机通信方式一、nRF24L01模块与单片机的通信方式1.基于SPI通信协议的数据交换nRF24L01模块与单片机基于SPI通信协议进行数据交换。

SPI是一种同步串行通信协议,它通过四个信号线进行通信:MOSI、MISO、SCK和CSN。

在这四个信号线中,MOSI用于发送数据,MISO用于接收数据,SCK用于同步时钟信号,而CSN用于片选信号。

这种通信方式具有传输速度快、数据稳定性高、抗干扰能力强等优点。

2.控制引脚与SPI通信引脚的配置nRF24L01模块的控制引脚包括CE、CSN、IRQ,这些引脚可用于控制模块的开启、关闭以及接收中断等功能。

SPI通信引脚包括MOSI、MISO、SCK,这些引脚可用于实现与单片机之间的数据传输。

值得注意的是,这些引脚可以直接接普通的IO口,而不必特意选择SPI外设对应的引脚。

二、nRF24L01模块的应用场景1. 一对多通信当有两个以上的nRF无线模块且代码中未设置SPI片选信号时,可以实现一对多通信(即一个发多个收到该信息)。

这种通信方式在需要多个接收方的情况下非常实用,可以有效提高通信效率,降低系统成本。

2.多种通信模式的选择nRF24L01模块支持多种通信模式,如广播模式、多路复用模式等。

用户可以根据实际需求选择合适的通信模式,以满足不同场景下的应用要求。

3.远程控制与监测nRF24L01模块可应用于远程控制与监测领域,如智能家居、工业自动化、智能交通等。

通过无线通信,可以实现远程控制设备的开关、调节参数以及实时监测设备状态等功能。

4.数据传输与存储nRF24L01模块还可应用于数据传输与存储领域,如物联网、传感器网络等。

在这些场景下,nRF24L01模块可以实现传感器数据的实时采集、传输和存储,为用户提供便捷的数据处理方案。

nRF24L01模块与单片机的通信方式在实际应用中具有广泛的应用价值,可以为各类工程项目提供可靠的无线通信解决方案。

nRF24L01无线通信模块使用手册12要点

nRF24L01无线通信模块使用手册12要点

nRF24L01无线通信模块使用手册12要点nRF24L01是一种常用的无线通信模块,广泛应用于无线遥控、智能家居、物联网等领域。

本文主要介绍nRF24L01无线通信模块的使用手册12要点。

1. 硬件连接将nRF24L01模块插入Arduino板的SPI接口上,然后将CE、CSN、SCK、MOSI、MISO分别连接到Arduino板的Digital口上。

2. 初始化模块在使用nRF24L01模块之前,必须对其进行初始化,在初始化代码中需要指定通信频率、发射功率、数据通道等等。

3. 设置通信频率nRF24L01可以在2.4GHz频段内进行无线通信,可以通过设置通信频率来避免干扰。

通信频率的设置需要与对方设备的频率相匹配。

4. 设置发射功率nRF24L01具有多个发射功率级别,选择发射功率级别需要权衡通信距离和电池寿命。

5. 设置数据通道nRF24L01具有多个数据通道,可以在多个设备之间相互独立传输数据。

6. 选择传输模式nRF24L01可以选择多种不同的传输模式,包括单向、双向、广播等。

7. 发送数据使用nRF24L01发送数据时,需要将数据写入到缓冲区中,并指定接收方的地址。

8. 接收数据使用nRF24L01接收数据时,需要将接收方的地址写到接收方地址寄存器中,然后从缓冲区中读取数据。

9. 检查模块状态使用nRF24L01时需要进行状态检查,可以检查发送、接收、空闲、数据发送完成等等状态。

10. 错误处理在进行nRF24L01通信时,可能会发生各种各样的错误,需要进行错误处理。

11. 调试技巧在进行nRF24L01调试时,可以使用串口进行调试,输出各种调试信息。

12. 应用注意事项在进行nRF24L01的应用时,需要注意如下事项:避免干扰、选择合适的电源、防止数据丢失等等。

以上为nRF24L01无线通信模块使用手册12要点,希望对大家有所帮助。

NRF24L01 SPI 通讯示例程序(无线串口)

NRF24L01  SPI 通讯示例程序(无线串口)

//*pBuf:数据指针
//len:数据长度
//返回值,此次读到的状态寄存器值
u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len)
{
u8 status,u8_ctr;
NRF24L01_CSN = 0;
//使能 SPI 传输
status = SPI2_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值
=================================================================== 以下是 2401.c 文件 .h 文件在后面 =================================================================== #include "24l01.h" #include "delay.h" #include "spi.h"
//使能 SPI 传输
SPI2_ReadWriteByte(reg); //发送寄存器号
reg_val=SPI2_ReadWriteByte(0XFF);//读取寄存器内容
NRF24L01_CSN = 1;
//禁止 SPI 传输
return(reg_val);
//返回状态值
}
//在指定位置读出指定长度的数据
NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WI DTH);//写 RX 节点地址
NRF24L01_Write_Reg(WRITE_REG+EN_AA,0x01); //使能通道 0 的自动应答 NRF24L01_Write_Reg(WRITE_REG+EN_RXADDR,0x01);// 使 能 通 道 0 的 接 收 地 址

nRF24L01无线通信实验1

nRF24L01无线通信实验1

#include <STC12C5A60S2.h>unsigned char nrf_addr[]={0x23,0x34,0x23,0x23,0x01};//本机地址unsigned char nrf_txaddr[]={0x23,0x34,0x23,0x23,0x02};//发送地址sbit nrfce=P0^0;sbit nrfcsn=P0^1;sbit nrfsck=P0^2;sbit nrfmosi=P0^3;sbit nrfmiso=P0^4;sbit nrfirq=P0^5; //nrf24L01控制端void delay(int n){int i,j;for(i=0;i<n;i++)for(j=0;j<1000;j++);}unsigned char spiwr(unsigned char date) //spi写一字节数据{int i;unsigned char temp;temp=date;for(i=0;i<8;i++){temp<<=1;if(CY==1) nrfmosi=1;else nrfmosi=0;nrfsck=1;if(nrfmiso==1) temp|=0x01;nrfsck=0;}return temp;}void nrfwr(unsigned char com,unsigned char addr)//写一则指令{unsigned char date;nrfcsn=0; //启动spi串口date=0x20; //写寄存器指令spiwr(date|addr);spiwr(com);nrfcsn=1; //执行指令}unsigned char nrfrd(unsigned char addr)//从addr寄存器地址处读出数据{unsigned char date;nrfcsn=0;date=0x00; //读寄存器指令spiwr(date|addr);date=spiwr(0xff);nrfcsn=1;return date;}void nrfaddr(unsigned char addr,unsigned char *BUF) //配置nrf地址{unsigned char com;int i;nrfcsn=0;com=0x20; //写地址指令spiwr(com|addr);for(i=0;i<5;i++) spiwr(BUF[4-i]); //从最低字节开始发送nrfcsn=1;}void nrf_send_init() //无线电模块的发射初始化{delay(1);nrfce=0; //芯片使能信号nrfcsn=1; // spi初始化nrfsck=0;nrfaddr(0x0a,nrf_addr); //设置本机地址nrfaddr(0x10,nrf_txaddr);//设置发送地址nrfwr(0x00,0x07); //清除中断nrfwr(0x01,0x02); //设置通道0,1允许接收nrfwr(0x3f,0x01); //设置所有自动应答功能开nrfwr(0x01,0x11); //设置通道0有效接收数据宽度为1字节nrfwr(0x01,0x12); //设置通道1有效接收数据宽度为1字节nrfwr(0x03,0x06);//设置发送速率为1MHz,发射功率为0db}void nrf_wrsend(unsigned char date)//写入要发送的数据{unsigned char com;nrfcsn=0; //启动spi串口com=0xa0; //写寄存器指令spiwr(com);spiwr(date);nrfcsn=1; //执行指令}void nrfsend(unsigned char date)//nrf发送一字节数据{unsigned char com;// com=0x0a;// nrfwr(com,0x00); //配置CONFIG寄存器,使之进入发射模式// delay(2); //上电延时nrfce=0;delay(1);nrf_wrsend(date);com=0x0a;nrfwr(com,0x00); //配置CONFIG寄存器,使之进入发射模式delay(2);nrfce=1;while(nrfirq==1); //等待发送com=0x00;nrfwr(com,0x07); //清除中断delay(1); //进入待机模式1}void main(){delay(10000);nrf_send_init();nrfsend('*');while(1);}。

nRF24L01的工作原理

nRF24L01的工作原理

nRF24L01的工作原理引言概述:nRF24L01是一种低功耗、高性能的2.4GHz无线收发器,广泛应用于无线通信领域。

本文将详细介绍nRF24L01的工作原理,包括射频通信、调制解调、数据包传输、频道选择和功耗控制等方面。

一、射频通信1.1 发射端工作原理nRF24L01的发射端通过内置的射频发射器将数据转换为无线信号进行传输。

工作时,发射端将待发送的数据通过SPI接口发送给nRF24L01,然后nRF24L01将数据进行编码和调制处理,并将其转换为射频信号发送出去。

1.2 接收端工作原理nRF24L01的接收端通过内置的射频接收器接收从发射端发送过来的无线信号,并将其转换为可供处理的数据。

接收端将接收到的信号进行解调和解码处理,然后通过SPI接口将数据发送给主控制器进行进一步处理。

1.3 射频通信特点nRF24L01采用2.4GHz的ISM频段进行通信,具有抗干扰能力强、传输距离远、传输速率高等特点。

同时,nRF24L01支持多频道选择,可以实现多设备同时工作而互不干扰。

二、调制解调2.1 调制原理nRF24L01采用GFSK调制方式,即高斯频移键控调制。

在调制过程中,nRF24L01将数字信号转换为模拟信号,并通过改变信号的频率来表示不同的数据。

2.2 解调原理nRF24L01的接收端通过解调将接收到的模拟信号转换为数字信号,以便后续处理。

解调过程中,nRF24L01通过检测信号的频率变化来还原原始的数字信号。

2.3 调制解调性能nRF24L01的调制解调性能优良,能够实现高效的数据传输。

其采用的GFSK 调制方式具有抗干扰能力强、传输速率高等优点,能够在复杂的无线环境中稳定传输数据。

三、数据包传输3.1 数据包格式nRF24L01的数据包由多个字节组成,包括数据长度、地址、校验和等信息。

数据包格式的设计使得nRF24L01能够实现可靠的数据传输和错误检测。

3.2 传输协议nRF24L01支持多种传输协议,包括主从模式、广播模式和自动应答模式等。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
_Bool MOSI_PIN @PC_ODR:6;
_Bool MISO_PIN @PC_IDR:7;
_Bool IRQ_PIN @PD_IDR:3; //为低表示:1已接收到数据,数据移完时自动变为高,2发送完变低,3从发送次数超过设定值
_Bool CSN_PIN @PA_ODR:3; //为低时激活SPI发送数据(芯片的片选线,CSN为低电平芯片工作),此时可设置24L01
PA_CR2 = 0b00000000;
PA_ODR = 0b00001000;
PB_DDR = 0b00100000;
PB_CR1 = 0b11111111;
PB_CR2 = 0b00000000;
PB_ODR = 0b00100000;
PC_DDR = 0b01100000;
{
u16 j;
for(j=0;j<i;++j)
{ while(!f_250us)
{
IWDG_KR=0Xaa; //清除看门狗
}
f_250us=0;
}
}
////////////////////////////////////////////////
TIM2_CCR2H = 0X00; //决定PWM的占空比/utycycle control register: CCR是16BIT
//Configure CPU clock prescaler
CLK_CKDIVR |= 0x00; //CPUDIV[2:0]=000: fCPU=fMASTER/[1.2.4.8.16.32.64.128]
//决定指令速度,不影响定时器
}
//////////////////////////////////
#define FIFO_STATUS 0x17 // 'FIFO Status Register' register address
//nRF24L01 SPI Command constant 写命令时要CSN_PIN要为低
#define READ_REG 0x00 //read command to register
#define RX_ADDR_P4 0x0e // 'RX address pipe4' register address
#define RX_ADDR_P5 0x0f // 'RX address pipe5' register address
#define TX_ADDR 0x10 // 'TX address' register address
#define EN_RXADDR 0x02 // 'Enabled RXaddresses' register address
#define SETUP_AW 0x03 // 'Setup address width' register address
#define SETUP_RETR 0x04 // 'Setup Auto. Retrans' register address
#define WRITE_REG 0x20 //write command to register
#define R_RX_PAYLOAD 0x61 //RX payload register address
#define W_TX_PAYLOAD 0xa0 //TX payload register address
// COMPILER: STM8 Cosmic C Compiler
// DATE: 2010-9-12 16:41
//=========================================
#include "STM8S103F.h" //Registers and memory
#define OBSERVE_TX 0x08 // 'Observe TX' register address
#define CD 0x09 // 'Carrier Detect' register address
#define RX_ADDR_P0 0x0A // 'RX address pipe0' register address
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned int
#define countof(a) (sizeof(a)/sizeof(*(a)))//带参数的定义
#define BufferSize (countof(Tx_Buffer)-1)//减掉一个空字符
void CLK_Init(void)
{
//Configure HSI prescaler
CLK_CKDIVR &= ~0x10; //HSIDIV[4:3]=00 [系统分频1.2.4.8],上电默认值8分频
//8mhz=16ห้องสมุดไป่ตู้hz/系统2分频
u8 TX_BUF[PAYLOAD_WIDTH]={0,1,2,3};
/////////////////////////////////////////////
//
/////////////////////////////////////////////
delay_time(u16 i)
PC_CR1 = 0B11111111;
PC_CR2 = 0b00000000;
PC_ODR = 0b00000000;
PD_DDR = 0b00010000;
PD_CR1 = 0b11111111;
PD_CR2 = 0b00000000; //
#define RX_ADDR_P1 0x0b // 'RXaddress pipe1' register address
#define RX_ADDR_P2 0x0c // 'RXaddress pipe2' register address
#define RX_ADDR_P3 0x0d // 'RX address pipe3' register address
PD_ODR = 0b00000000;
CE_PIN=0; // chip enable
CSN_PIN=1; // Spi disable
SCK_PIN =0;
}
//////////////////////////////////
//
//////////////////////////////////
#define RX_PW_P0 0x11 // 'RX payload width, pipe0' register address
#define RX_PW_P1 0x12 // 'RX payload width, pipe1' register address
#define RX_PW_P2 0x13 // 'RX payload width, pipe2' register address
TIM2_CCE_PINR1 |= 0x30; //CC polarity low,enable PWM output
TIM2_ARRH = 0x00; //自动从装载寄存器/定时初值,
TIM2_ARRL = 0xff; //先装高字节
//========================================
// PROJECT: 24L01发送实验(软件模拟SPI)
// AUTHOR: MENGJICHENG
// MODULE: main.c
//
//////////////////////////////////
void TIM_Init(void)
{
/* //TIM2 CC2 control LED Brightness
TIM2_CCMR2 |= 0x70; //Output mode PWM2.
u8 Tx_Buffer[] ="123456789";//"STM8Sxxx SPI Firmware Library Example: communication with a microSD card";
//-----------------------------------
_Bool f_250us=0;
#define FLUSH_TX 0xe1 //flush TX register command
#define FLUSH_RX 0xe2 //flush RX register command
#define REUSE_TX_PL 0xE3 //reuse TX payload register command
#define RX_PW_P3 0x14 // 'RX payload width, pipe3' register address
#define RX_PW_P4 0x15 // 'RX payload width, pipe4' register address
#define RX_PW_P5 0x16 // 'RX payload width, pipe5' register address
相关文档
最新文档