当前位置:首页 >> 信息与通信 >>

基于nRF24L01的无线通信模块设计报告正文


1 前言
本次我们三人小组设计的是无线通信模块,根据设计要求我们选择了无线收发模块 nRF24L01、单片机 STC89C52、LCD1602 和键盘模块等作为本次设计的硬件需求。首先我 们与老师一起讨论了一些设计的相关事宜和设计思路。接下来我们一起画好了模拟电路 图,在老师的帮助下我们对电路图进行了补充和完善。完成这些基本工作后,在老师和 同学的帮助下我们买回了自己所

需的元器件。接着我们变分工完成了元器件的焊接连接 和程序的编写,然后便是模块的上电调试,设计的答辩和设计报告的完善。 我们本次之所以会选择无线通信模块的设计,是我们觉得无线通信技术是现代社会 中一门很重要的技术,我们掌握好了这门技术对以后我们的工作生活都有很大的帮助。 我们本次设计的无线通信模块虽然只是我们的一次小小的体验,但我们都知道无线通信 在我们现在所处的信息时代是多么的重要,如今我们生活的方方面面无不与无线通信息 息相关。我们所熟悉的手机、电脑、电视等等都与无线通信有着直接的联系。甚至在某 些高端领域方面无线通信技术能反映一个国家的科技水平和综合国力。我们国家的无线 通信技术虽然在世界上排在了前面的位置,但与一些发达国家相比我们任然有很大差 距,如太空中有差不多 80%的通信卫星是美国的。 当然我们本次设计的无线通信模块只是很基础的无线通信模块,我们所达到的效果 就是两个模块间能相互发送一些简单的字符和数字。

第 1 页

2 总体方案设计
本次设计我们考虑用 C 语言和汇编去实现模块的无线通信功能,但我们编写程序时 发现汇编语言较难写且可读性差,因此我们选择了用 C 语言作为本次的软件实现。要实 现无线通信功能, 我们选择了小巧轻便的无线收发模块 nRF24L01。 在单片机方面考虑到 52 系列优于 51 系列且很好购买,我们选择了 STC89C52 单片机。在液晶显示上,我们只 要求能显示一些简单的数字和字母,我们选择了 LCD1602。键盘输入方面我们选择的是 4×4 矩阵键盘。以上各模块的功能信息在后面都有更为具体的介绍。

图 2.1 无线通信模块框图

第 2 页

3 单元模块设计
3.1 nRF24L01 的简单介绍
nRF24L01 是 NORDIC 公司最近生产的一款无线通信通信芯片, 采用 FSK 调制, 内 部集成 NORDIC 自己的 Enhanced Short Burst 协议。可以实现点对点或是 1 对 6 的 无线通信。无线通信速度可以达到 2M(bps) 。NORDIC 公司提供通信模块的 GERBER 文 件, 可以直接加工生产。 嵌入式工程师或是单片机爱好者只需要为单片机系统预留 5 个 GPIO,1 个中断输入引脚,就可以很容易实现无线通信的功能,非常适合用来为 MCU 系统构建无线通信功能。 2.4GHz 全球开放 ISM 频段,最大 0dBm 发射功率,免许可证使用支持六路通道的数 据接收低工作电压:1.9V ~3.6V 低电压工作高速率:2Mbps,由于空中传输时间很短, 极大的降低了无线传输中的碰撞现象(软件设置 1Mbps 或者 2Mbps 的空中传输速率)多 频点:125 频点,满足多点通信和跳频通信需要超小型:内置 2.4GHz 天线,体积小巧, 15×29mm(包括天线)低功耗:当工作在应答模式通信时,快速的空中传输及启动时间, 极大的降低了电流消耗。低应用成本:nRF24L01 集成了所有与 RF 协议相关的高速信号 处理部分,比如:自动重发丢失数据包和自动产生应答信号等,nRF24L01 的 SPI 接口可 以利用单片机的硬件 SPI 口连接或用单片机 I/O 口进行模拟,内部有 FIFO 可以与各种 高低速微处理器接口,便于使用低成本单片机。便于开发:由于链路层完全集成在模块 上,非常便于开发。自动重发功能,自动检测和重发丢失的数据包,重发时间及自动存 储未收到应答信号的数据包自动应答功能, 在收到有效数据后, 模块自动发送应答信号, 无须另行编程载波检测—固定频率检测内置硬件 CRC 检错和点对多点通信地址控制数据 包传输错误计数器及载波检测功能可用于跳频设置可同时设置六路接收通道地址,可有 选择性的打开接收通道标准插针 Dip2.54MM 间距接口,便于嵌入式应用。

第 3 页

nRF24L01 功能框图

图 3.1nRF24L01 功能框图

Fig.1 nRF24L01 BLOCK DIAGRAM nRF24L01 的框图如 Fig.1 所示, 从单片机控制的角度来看, 我们只需要关注 Fig.1 右 面 的六个控制和数据信号,分别为 CSN、SCK、MISO、MOSI、IRQ、CE。 CSN:芯片的片选线,CSN 为低电平芯片工作。 SCK:芯片控制的时钟线(SPI 时钟) MISO:芯片控制数据线(Master input slave output) MOSI:芯片控制数据线(Master output slave input) IRQ:中断信号。无线通信过程中 MCU 主要是通过 IRQ 与 nRF24L01 进行通信。 CE: 芯片的模式控制线。 在 CSN 为低的情况下,CE 协同 nRF24L01 的 CONFIG 寄 存器共同决定 nRF24L01 的状态(参照 nRF24L01 的状态机) 。

图 3.2 nRF24L01 实物图 第 4 页

nRF24L01 的引脚级说明

图 3.3nRF24L01 的引脚级说明

说明: (1)VCC 脚接电压范围为 1.9V ~3.6V 之间,不能在这个区间之外,超过 3.6V 将 会烧毁模块。推荐电压 3.3V 左右。 (2)除电源 VCC 和接地端,其余脚都可以直接和普通的 5V 单片机 IO 口直接相连,无需 电平转换。当然对 3V 左右的单片机更加适用了。 (3)硬件上面没有 SPI 的单片机也可以控制本模块,用普通单片机 IO 口模拟 SPI 不需 要单片机真正的串口介入,只需要普通的单片机 IO 口 就可以了,当然用串口也可以了

3.2

STC89C52 的简单介绍
STC89C52是一个低电压,高性能 cmos8位单片机,片内含8k bytes 的可反复擦写的

Flash 只读程序存储器和256 bytes 的随机存取数据存储器(RAM) ,器件采用 ATMEL 公 司的高密度、非易失性存储技术生产,兼容标准 MCS-51指令系统,片内置通用8位中央 处理器和 Flash 存储单元,STC89C52单片机在电子行业中有着广泛的应用。 其主要特性功能: 1、兼容 MCS51 指令系统 次)Flash ROM; 3、32 个双向 I/O 口; 个 16 位可编程定时/计数器中断; 可编程 UART 串行通道; 断口线,3 级加密位; 2、8k 可反复擦写(大于 1000 5、3 7、2 个串行中断, 9、2 个读写中 4、256×8bit 内部 RAM;

6、时钟频率 0-24MHz;

8、2 个外部中断源,共 8 个中断源;

10、低功耗空闲和掉电模式,软件设置睡眠和唤醒功能;

11、有 PDIP、PQFP、TQFP 及 PLCC 等几种封装形式,以适应不同产品的需求。
第 5 页

STC89C52 的引脚图

图 3.4 STC89C52 的引脚图

3.3

LCD1602 的简单介绍
LCD1602 是工业字符型液晶, 能够同时显示 16×02 即 32 个字符。 (16 列 2 行) 1602

液晶也叫 1602 字符型液晶它是一种专门用来显示字母、数字、符号等的点阵型液晶模 块它有若干个 5×7 或者 5×11 等点阵字符位组成,每个点阵字符位都可以显示一个字 符。每位之间有一个点距的间隔每行之间也有间隔起到了字符间距和行间距的作用,正 因为如此所以他不能显示图形 。

图 3.5LCD1602 实物图 第 6 页

LCD1602 的引脚图

图 3.6LCD1602 的引脚图

3.4

其它的器件
当然我们本次设计还用到了一些其他的元器件,包括键盘、连接导线、排针、发光

二极管、电阻、电容等等。

3.5

各单元模块的联系
键盘输入是人机交换的接口其主要功能是设置 nRF24L01 的工作模式和实现键盘输

入字符、数字等。单片机是主控模块实现数据的储存、处理,将各模块联系起来协调各 模块的工作。LCD1602 主要功能就是显示作用,将键盘输入或接收到的信息显示出来。

第 7 页

4 软件设计
我们搭建好硬件电路并确认无误后,进行了软件设计。本次无线通信模块设计我们 选择了用 C 语言实现其功能,我们在 PC 机 Keil uVision 4 下编写调试了 C 程序并将 C 程序下载到 STC89C52 单片机里进行了运行调试。

图 5.1 软件实现的流程图

第 8 页

5 系统调试
在调试环境中我们首先检查了我们焊接的硬件电路是否有问题, 如有无短路, 有无 虚焊等。确认硬件电路完善无误后。我们再次对程序进行了检查与调试,都发现没有问 题后,我们对模块进行了上电并将程序下载进去运行调试。一开始我们发现并没有达到 预期的效果,发现键盘输入与发送的字符数字不匹配,接搜端也无法搜到相应的信号。 经过我们的仔细检查和思考后, 我们发现程序中定义的端口与硬件电路的端口没有意义 对应,程序的一些其他地方也并不是很完善,我们又对程序进行了改进,对程序的改进 过程中,有时会遇到修改程序后会出现错误,这是若去一行一行的运行调试程序就会很 麻烦和花去大量的时间。这时就要认真检查思考程序出错在哪里,几个人一起检查就加 快了效率,节约了大量时间,直到调试达到了我们所预期的效果。

5.1 主要问题及分析
开始时我们想到的是在 ISIS 里画好原理图并仿真,但在 ISIS 上面我们没有找到我 们想要的元器件,因此我们只能直接去调试硬件电路。首先我们设计好程序并确认无误 后再将程序下载到单片机里进行硬件调试,结果我们发现 LCD1602 无显示,经过仔细的 检查思考后,我们发现我们所写的程序与单片机和液晶屏的引脚并不是一一对应的,经 过对程序和硬件电路的修改后液晶屏终于有了显示。虽然液晶屏有了显示,但我们的键 盘输入,发送与接收还是存在问题。考虑到时间有限我们将原来的矩阵键盘输入改为了 较简单的单一键盘输入,这样我们解决的键盘输入问题。经过反复的调试修改后,我们 的无线通信模块终于达到的预期的效果。

5.2 调试工具
此 次 调 试 过 程 中 , 我 们 主 要 用 到 了 Keil uVision 4 、 STC-ISP.exe 、 AltiumDesigner。Keil uVision 4 是用来编写程序,并编译成 HEX 文件,以便下载到单 片机中。当有了 HEX 文件之后,要将此文件下载到单片机中,不可缺少的工具就是 STC-ISP.exe。通过它,可以对单片机内部的程序进行反复修改。AltiumDesigner 是用 来查看电路原理图,并有绘制原理图的功能,在实际调试过程中,应当将软件与硬件相 结合,所以电路图的研究不可缺少。

第 9 页

6 系统功能、指标参数
6.1 系统能实现的功能
本次我们三人小组所做的无线通信模块主要能实现两个模块间的一些简单通信,实 现两个模块间一些简单字符、数字的发送与接收。我们先对键盘输入进行一些定义,如 定义键盘输入为一些字符或数字,但我们按相应的建后就输入相应的字符或数字,输入 完成后, 我们在按发送键, 预先输入的信息便发送了出去, 接送的也会收到相应的信息。

6.2 系统指标参数测试
在系统指标参数的测试中,我们首先测试了两个无线收发模块间能传输的范围,经 过我们多次的改变两个模块的距离后,我们发现两个模块能传输的最大距离约为 10 米, 在穿透效果的测试中,我们发现两个模块间可以穿过一壁普通的墙,当两个模块间隔有 两面及两面以上的普通墙时,两个模块间就很难传输信号了。我们试图测试模块的抗电 磁干扰能力的测试是,我们发现很找到一个精确的量来描述,我们大致得出在较弱和频 率与我们用的 nRF24L01 的频率相差较大时的干扰不明显,但当电磁干扰较强很干扰波 频率接近 nRF24L01 的频率时的干扰较为强烈。

6.3 系统的指标功能及参数分析
nRF24L01 的无线速率达到 2 Mbit/s,SPI 接口速率为 0~8 Mbit/s,具自动应答机 制,极大地降低丢包率,完全满足了我们本次设计的需求。将 nRF24L01 配置成增强型 ShockBurst 模式, 使得双向链接协议执行更为简易有效。 发送方要求终端设备在接收数 据后有应答信号,以便发送方检测有无数据丢失。一旦数据丢失则通过重新发送功能将 丢失的数据恢复。单片机内部 EEPROM 应用子程序进行扇区的擦除、写入以及读出功能, 实现系统信息的读取保存。nRF24L01 在外置天线时传输距离可以到达 25m,我们本次没 有使用外置天线,传输的距离约为 10m,一切都满足我们本次设计的需求。

第 10 页

7 结论
本次智能测控应用系统设计,我们三人小组成功的的完成了无线通信模块的设计与 制作。虽然我们在模块的设计、制作、调试过程中也遇到了不少困难,但在老师和同学 的细心指导帮助之下和我们自己的努力,最终还是达到了预期的效果,完成了本次的智 能化测控应用系统设计。 我们本次所设计的无线通信模块在无线通信领域有着很大的发 展空间,nRF24L01 是一种高效率低成本的无线收发模块,125 频点,满足多点通信和跳 频通信需要超小型:内置 2.4GHz 天线,体积小巧,15x29mm(包括天线)低功耗:当工 作在应答模式通信时,快速的空中传输及启动时间,极大的降低了电流消耗。低应用成 本:nRF24L01 集成了所有与 RF 协议相关的高速信号处理部分,比如:自动重发丢失数 据包和自动产生应答信号等, nRF24L01 的 SPI 接口可以利用单片机的硬件 SPI 口连接或 用单片机 I/O 口进行模拟,内部有 FIFO 可以与各种高低速微处理器接口,便于使用低 成本单片机。便于开发:由于链路层完全集成在模块上,非常便于开发。自动重发功能, 自动检测和重发丢失的数据包, 重发时间及自动存储未收到应答信号的数据包自动应答 功能,在收到有效数据后,模块自动发送应答信号,无须另行编程载波检测—固定频 率检测内置硬件 CRC 检错和点对多点通信地址控制数据包传输错误计数器及载波检测功 能可用于跳频设置可同时设置六路接收通道地址,可有选择性的打开接收通道标准插针 Dip2.54MM 间距接口, 便于嵌入式应用。 因此基于 nRF24L01 的无线通信在当今我们的生 活中有着极大的发展空间。

第 11 页

8 总结与体会
在本次智能化测控应用系统设计中我们收获了不少。 在之前我们都是学习了书本上 的东西,而很少将其应用到实际中去,虽然之前我们也做过一些课程设计、工艺实习之 类的,但这次的课程设计更加从实。我们从选取题目,画原理图到购买元器件再到焊接 电路还有后面的调试测试工作我们都一一的亲身经历并学到了不少课本上学不到的东 西。以前我们学习课本上的知识,觉得要将其应用到实际中会是一件较为轻松的事,也 看其他人做的东西很有意义,但我们自己实际去设计制作时,才发现了要做好一个作品 是那么的不容易,自己去做时,才发现自己的种种不足,动起手来是那么的笨拙。老师 常常给我们讲动手能力对我们自动化的同学有多么种要,因此我们也都一直想着要提高 我们的动手能力,这次实习对我们来说是一次难的机会,对于我们提高自己的动手能力 有很大的帮助。我们不仅学到了怎样去改进、优化、美化电路布局,也掌握更多调试、 测试电路的方法, 也学到了不少怎样去选取合适的元器件的方法。 在以后的学习工作做, 我们要不断的提高自己的动手能力,就要不断亲身去设计、自作实际的东西,这样才不 会被时代所淘汰成为对社会有用的人。

第 12 页

9 参考文献
[1]赵亮、候国锐.单片机 C 语言编程与实例[M].北京:人民邮电出版社,2003 年 9 月 [2]海创.无线收发模块 nRF24L01 开发包资料[J].海创电子科技,2010 年 [3]张毅刚.单片机原理及应用[M].北京:高等教育出版社,2010 年 11 月 [4]康华光.电子技术基础模拟部分(第五版)[M].北京:高等教育出版社,2010 年 5 月 [5]康华光.电子技术基础数字部分(第五版)[M].北京:高等教育出版社,2010 年 11 月 [6]谢自美.电子线路设计.实验.测试[M].武汉:华中科技大学出版社,2009 年 7 月

第 13 页

10 附录
10.1 相关设计图

图 10.1 无线收发模块 PCB 图

第 14 页

图 10.2 无线收发模块电路原理总图

图 10.3 正 5V 电源模块图

第 15 页

图 10.3 复位电路模块图

图 10.4 程序下载模块接口图

第 16 页

图10.5正3V 电源模块图

图10.6单片机接口图

第 17 页

图 10.3 显示仿真图

图 10.4 无线收发模块实物图 第 18 页

10.2 相关的程序
无线收发模块发送程序 #include <reg52.h> #include <intrins.h> //****************************************IO 端口定义 sbit sbit sbit sbit sbit sbit sbit sbit sbit sbit sbit MISO=P1^5; MOSI=P1^2; SCK=P1^3; CE=P1^1; CSN=P1^0; IRQ=P1^4; lcdrs =P2^0; lcden =P2^1; key1 =P2^4;//发送数据键 key2 =P2^5;//接收数据键 key3 =P2^6;//清空键 //待发送数据 //待接受数据赋 0,以便接受数据

unsigned char num1,num2; unsigned char tx_Buf[]={0,0,0}; unsigned char rx_Buf[]={0,0}; **** #define TX_ADR_WIDTH 宽度 #define RX_ADR_WIDTH 宽度 #define TX_PLOAD_WIDTH 宽度 #define RX_PLOAD_WIDTH 宽度 unsigned char const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址 unsigned char const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01};
第 19 页

//*********************************************nRF24L01******************** 5 5 3 2 // 5 uints TX address width // 5 uints RX address width // 20 uints TX payload // 20 uints TX payload // 发送地址 // 接收地址 //发送数据 // 接受数据

//接收地址 //***************************************nRF24L01 寄存器指令 #define READ_REG #define WRITE_REG #define RD_RX_PLOAD #define WR_TX_PLOAD #define FLUSH_TX #define FLUSH_RX #define REUSE_TX_PL #define NOP #define CONFIG 方式 #define EN_AA #define EN_RXADDR #define SETUP_AW #define SETUP_RETR #define RF_CH #define RF_SETUP #define STATUS #define OBSERVE_TX #define CD #define RX_ADDR_P0 #define RX_ADDR_P1 #define RX_ADDR_P2 #define RX_ADDR_P3 #define RX_ADDR_P4 #define RX_ADDR_P5 #define TX_ADDR #define RX_PW_P0 #define RX_PW_P1 #define RX_PW_P2 #define RX_PW_P3 #define RX_PW_P4 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0x10 0x11 0x12 0x13 0x14 0x15 // 自动应答功能设置 // 可用信道设置 // 收发地址宽度设置 // 自动重发功能设置 // 工作频率设置 // 发射速率、功耗功能设置 // 状态寄存器 // 发送监测功能 // 地址检测 // 频道 0 接收数据地址 // 频道 1 接收数据地址 // 频道 2 接收数据地址 // 频道 3 接收数据地址 // 频道 4 接收数据地址 // 频道 5 接收数据地址 // 发送地址寄存器 // 接收频道 0 接收数据长度 // 接收频道 0 接收数据长度 // 接收频道 0 接收数据长度 // 接收频道 0 接收数据长度 // 接收频道 0 接收数据长度
第 20 页

0x00 0x20 0x61 0xA0 0xE1 0xE2 0xE3 0xFF 0x00

// 读寄存器指令 // 写寄存器指令 // 读取接收数据指令 // 写待发数据指令 // 冲洗发送 FIFO 指令 // 冲洗接收 FIFO 指令 // 定义重复装载数据指令 // 保留 // 配置收发状态, CRC 校验模式以及收发状态响应

//*************************************SPI(nRF24L01)寄存器地址

#define RX_PW_P5 #define FIFO_STATUS ************* // **** 函

0x16 0x17

// 接收频道 0 接收数据长度 // FIFO 栈入栈出状态寄存器设置

//************************************************************************* 数 声 明

*************************************************************************** /************************************************************************** **************/ void write_com(unsigned char com); void write_date(unsigned char date); void Delay(unsigned int s); void inerDelay_us(unsigned char n); void init_nRF24L01(void); unsigned int SPI_RW(unsigned int uuchar); unsigned char SPI_Read(unsigned char reg); void SetRX_Mode(void); void tetRX_Mode(void); unsigned int SPI_RW_Reg(unsigned char reg, unsigned char value); unsigned int SPI_Read_Buf(unsigned char reg, unsigned char *pBuf, unsigned char 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++); } //************************************************************************* **** bdata sta; sbit RX_DR //状态标志 =sta^6;
第 21 页

sbit sbit ***

TX_DS MAX_RT

=sta^5; =sta^4;

/************************************************************************** /*延时函数*/ void inerDelay_us(unsigned char n) { for(;n>0;n--) _nop_(); } //************************************************************************* ** /*lcd1602 写命令 //************************************************************************* **/ void write_com(unsigned char com) { lcdrs=0; P0=com; Delay(5); lcden=1; Delay(5); lcden=0; } //************************************************************************* *** /*lcd1602 初始化 //************************************************************************* ***/ void init() { lcden=0; write_com(0x38);
第 22 页

write_com(0x0c); write_com(0x06); write_com(0x01); } //************************************************************************* ** /*lcd1602 写数据 //************************************************************************* **/ void write_date(unsigned char date) { lcdrs=0; P0=date; Delay(5); lcden=1; Delay(5); lcden=0; } //************************************************************************* **** /*nRF24L01 初始化 //************************************************************************* ****/ void init_nRF24L01(void) { inerDelay_us(100); CE=0; CSN=1; SCK=0; } /************************************************************************** ****
第 23 页

// chip enable // Spi disable // Spi clock line init high

/*函数:uint SPI_RW(uint uchar) /*功能:nRF24L01 的 SPI 写时序 /************************************************************************** / unsigned int SPI_RW(unsigned int uuchar) { unsigned int bit_ctr; for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit { MOSI = (uuchar & 0x80); uuchar = (uuchar << 1); SCK = 1; uuchar |= MISO; SCK = 0; } return(uuchar); } /************************************************************************** **** /*函数:uchar SPI_Read(uchar reg) /*功能:nRF24L01 的 SPI 时序 /************************************************************************** ***/ unsigned char SPI_Read(unsigned char reg) { unsigned char reg_val; CSN = 0; SPI_RW(reg); reg_val = SPI_RW(0); CSN = 1; return(reg_val); } /**************************************************************************
第 24 页

// output 'uchar', MSB to MOSI // shift next bit into MSB.. // Set SCK high.. // capture current MISO bit // ..then set SCK low again // return read uchar

// CSN low, initialize SPI communication... // Select register to read from.. // ..then read registervalue // CSN high, terminate SPI communication // return register value

***/ /*功能:nRF24L01 读写寄存器函数 /************************************************************************** ***/ unsigned int SPI_RW_Reg(unsigned char reg, unsigned char value) { unsigned int status; CSN = 0; status = SPI_RW(reg); SPI_RW(value); CSN = 1; return(status); } /************************************************************************** ***/ /*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出 数据的个数 /************************************************************************** ***/ unsigned int SPI_Read_Buf(unsigned char reg, unsigned char *pBuf, unsigned char uchars) { unsigned int status,uchar_ctr; CSN = 0; status = SPI_RW(reg); read status uchar for(uchar_ctr=0;uchar_ctr<uchars;uchar_ctr++) pBuf[uchar_ctr] = SPI_RW(0); // // Set CSN low, init SPI tranaction // Select register to write to and // CSN low, init SPI transaction // select register // ..and write value to it.. // CSN high again // return nRF24L01 status uchar

第 25 页

CSN = 1; return(status); } /************************************************************************** **** /*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的 个数 /************************************************************************** ***/ unsigned int SPI_Write_Buf(unsigned char reg, unsigned char *pBuf, unsigned char uchars) { unsigned int status,uchar_ctr; CSN = 0; status = SPI_RW(reg); for(uchar_ctr=0; uchar_ctr<uchars; uchar_ctr++) // SPI_RW(*pBuf++); CSN = 1; return(status); } /************************************************************************** ***/ /*函数:void SetTX_Mode(void) /*功能:数据发送设置 /************************************************************************** ***/ void SetTX_Mode(void) { CE=0;
第 26 页

// return nRF24L01 status uchar

//SPI 使能

//关闭 SPI //

SPI_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); 允许 SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); 如果需要多频道可以参考 Page21 SPI_RW_Reg(WRITE_REG + RF_CH, 40); 收发必须一致 SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); // 设置接收数据长度, 本次设置为 8 字节 SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); 1MHZ,发射功率为最大值 0dB SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); 应,16 位 CRC,主发送 CE = 1; inerDelay_us(130); } /************************************************************************** ***** //*函数:void SetRX_Mode(void) /* 功 能 : 数 据 接 收 设 置 ************************************************************/ void SetRX_Mode(void) { CE=0; SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); 许 SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); 如果需要多频道可以参考 Page21 SPI_RW_Reg(WRITE_REG + RF_CH, 40); 收发必须一致
第 27 页

// // //

频道 0 自动

ACK 应答

允许接收地址只有频道 0, 设置信道工作为 2.4GHZ,

// 设置发射速率为 // IRQ 收发完成中断响

// // //

频道 0 自动

ACK 应答允

允许接收地址只有频道 0, 设置信道工作为 2.4GHZ,

SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本 次设置为 8 字节 SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); 发射功率为最大值 0dB SPI_RW_Reg(WRITE_REG + CONFIG, 0x0F); CE=1; } /************************************************************************** ****/ /*函数: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; payload from RX_FIFO buffer revale =1; } SPI_RW_Reg(WRITE_REG+STATUS,sta); 都置高为 1,通过写 1 来清楚中断标志 return revale; } /************************************************************************** **** /*函数:void nRF24L01_TxPacket(unsigned char * tx_buf) /*功能:发送 tx_buf 中数据 /************************************************************************** ***/
第 28 页

//设置发射速率为 1MHZ,

// 读取状态寄存其来判断数据接收状况 // 判断是否接收到数据 //SPI 使能 read receive

SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// //读取数据完成标志

// 接收到数据后 RX_DR,TX_DS,MAX_PT

void nRF24L01_TxPacket(unsigned char * tx_buf) { CE=0; SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载 接收端地址 SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); 载数据 CE=1; } //************************************主函数 void main(void) { void init(); init_nRF24L01(); while(1) { if( key1==0 ) { void init(); init_nRF24L01(); SetTX_Mode(); nRF24L01_TxPacket(tx_Buf); write_com(0x80); for(num1=0;num1<TX_PLOAD_WIDTH;num1++) { write_date(tx_Buf[num1]); Delay(1); } } if( key2==0) { void init(); init_nRF24L01();
第 29 页

// 装

//置高 CE,激发数据发送

SetRX_Mode(); nRF24L01_RxPacket(rx_Buf); write_com(0x80+0x40); for(num2=0;num2<RX_PLOAD_WIDTH;num2++) { write_date(rx_Buf[num2]); Delay(5); } } if( key3==0 ) { void init(); init_nRF24L01(); } } }
无线收发模块接收程序 #include <reg52.h>

#include <intrins.h> //****************************************IO 端口定义 sbit sbit sbit sbit sbit sbit sbit sbit sbit sbit sbit MISO=P1^5; MOSI=P1^2; SCK=P1^3; CE=P1^1; CSN=P1^0; IRQ=P1^4; lcdrs =P2^0; lcden =P2^1; key1 =P2^4;//发送数据键 key2 =P2^5;//接收数据键 key3 =P2^6;//清空键

unsigned char num1,num2;
第 30 页

unsigned char tx_Buf[]={0,0}; unsigned char rx_Buf[]={0,0,0}; **** #define TX_ADR_WIDTH 宽度 #define RX_ADR_WIDTH 宽度 #define TX_PLOAD_WIDTH 宽度 #define RX_PLOAD_WIDTH 宽度 2 3 5 5

//待发送数据 //待接受数据赋 0,以便接受数据

//*********************************************nRF24L01******************** // 5 uints TX address width // 5 uints RX address width // 20 uints TX payload // 20 uints TX payload // 发送地址 //接收地址 // 发送数据 // 接受数据

unsigned char const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址 unsigned char const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址 //***************************************nRF24L01 寄存器指令 #define READ_REG #define WRITE_REG #define RD_RX_PLOAD #define WR_TX_PLOAD #define FLUSH_TX #define FLUSH_RX #define REUSE_TX_PL #define NOP #define CONFIG 方式
//*****************************************长延时 void Delay(unsigned int s) {#define EN_AA

0x00 0x20 0x61 0xA0 0xE1 0xE2 0xE3 0xFF 0x00

// 读寄存器指令 // 写寄存器指令 // 读取接收数据指令 // 写待发数据指令 // 冲洗发送 FIFO 指令 // 冲洗接收 FIFO 指令 // 定义重复装载数据指令 // 保留 // 配置收发状态, CRC 校验模式以及收发状态响应

//*************************************SPI(nRF24L01)寄存器地址

0x01 0x02 0x03 0x04

// 自动应答功能设置 // 可用信道设置 // 收发地址宽度设置 // 自动重发功能设置
第 31 页

#define EN_RXADDR #define SETUP_AW #define SETUP_RETR

#define RF_CH #define RF_SETUP #define STATUS #define OBSERVE_TX #define CD #define RX_ADDR_P0 #define RX_ADDR_P1 #define RX_ADDR_P2 #define RX_ADDR_P3 #define RX_ADDR_P4 #define RX_ADDR_P5 #define TX_ADDR #define RX_PW_P0 #define RX_PW_P1 #define RX_PW_P2 #define RX_PW_P3 #define RX_PW_P4 #define RX_PW_P5 #define FIFO_STATUS ************* // **** 函

0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17

// 工作频率设置 // 发射速率、功耗功能设置 // 状态寄存器 // 发送监测功能 // 地址检测 // 频道 0 接收数据地址 // 频道 1 接收数据地址 // 频道 2 接收数据地址 // 频道 3 接收数据地址 // 频道 4 接收数据地址 // 频道 5 接收数据地址 // 发送地址寄存器 // 接收频道 0 接收数据长度 // 接收频道 0 接收数据长度 // 接收频道 0 接收数据长度 // 接收频道 0 接收数据长度 // 接收频道 0 接收数据长度 // 接收频道 0 接收数据长度 // FIFO 栈入栈出状态寄存器设置

//************************************************************************* 数 声 明

*************************************************************************** /************************************************************************** **************/ void write_com(unsigned char com); void write_date(unsigned char date); void Delay(unsigned int s); void inerDelay_us(unsigned char n); void init_nRF24L01(void); unsigned int SPI_RW(unsigned int uuchar); unsigned char SPI_Read(unsigned char reg); void SetRX_Mode(void);
第 32 页

void tetRX_Mode(void); unsigned int SPI_RW_Reg(unsigned char reg, unsigned char value); unsigned int SPI_Read_Buf(unsigned char reg, unsigned char *pBuf, unsigned char uchars); unsigned char nRF24L01_RxPacket(unsigned char *rx_buf); void nRF24L01_TxPacket(unsigned char *tx_buf); unsigned int i; for(i=0; i<s; i++); for(i=0; i<s; i++); } //************************************************************************* **** bdata sta; sbit sbit sbit *** /*延时函数*/ void inerDelay_us(unsigned char n) { for(;n>0;n--) _nop_(); } //************************************************************************* ** /*lcd1602 写命令 //************************************************************************* **/ void write_com(unsigned char com) { lcdrs=0; P0=com;
第 33 页

//状态标志 =sta^6; =sta^5; =sta^4;

RX_DR TX_DS MAX_RT

/**************************************************************************

Delay(5); lcden=1; Delay(5); lcden=0; } //************************************************************************* *** /*lcd1602 初始化 //************************************************************************* ***/ void init() { lcden=0; write_com(0x38); write_com(0x0c); write_com(0x06); write_com(0x01); } //************************************************************************* ** /*lcd1602 写数据 //************************************************************************* **/ void write_date(unsigned char date) { lcdrs=0; P0=date; Delay(5); lcden=1; Delay(5); lcden=0; }
第 34 页

//************************************************************************* **** /*nRF24L01 初始化 //************************************************************************* ****/ void init_nRF24L01(void) { inerDelay_us(100); CE=0; CSN=1; SCK=0; } /************************************************************************** **** /*函数:uint SPI_RW(uint uchar) /*功能:nRF24L01 的 SPI 写时序 /************************************************************************** / unsigned int SPI_RW(unsigned int uuchar) { unsigned int bit_ctr; for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit { MOSI = (uuchar & 0x80); uuchar = (uuchar << 1); SCK = 1; uuchar |= MISO; SCK = 0; } return(uuchar); } /************************************************************************** ****
第 35 页

// chip enable // Spi disable // Spi clock line init high

// output 'uchar', MSB to MOSI // shift next bit into MSB.. // Set SCK high.. // capture current MISO bit // ..then set SCK low again // return read uchar

/*函数:uchar SPI_Read(uchar reg) /*功能:nRF24L01 的 SPI 时序 /************************************************************************** ***/ unsigned char SPI_Read(unsigned char reg) { unsigned char reg_val; CSN = 0; SPI_RW(reg); reg_val = SPI_RW(0); CSN = 1; return(reg_val); } /************************************************************************** ***/ /*功能:nRF24L01 读写寄存器函数 /************************************************************************** ***/ unsigned int SPI_RW_Reg(unsigned char reg, unsigned char value) { unsigned int status; CSN = 0; status = SPI_RW(reg); SPI_RW(value); CSN = 1; return(status); } /************************************************************************** ***/ /*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出
第 36 页

// CSN low, initialize SPI communication... // Select register to read from.. // ..then read registervalue // CSN high, terminate SPI communication // return register value

// CSN low, init SPI transaction // select register // ..and write value to it.. // CSN high again // return nRF24L01 status uchar

数据的个数 /************************************************************************** ***/ unsigned int SPI_Read_Buf(unsigned char reg, unsigned char *pBuf, unsigned char uchars) { unsigned int status,uchar_ctr; CSN = 0; status = SPI_RW(reg); read status uchar for(uchar_ctr=0;uchar_ctr<uchars;uchar_ctr++) pBuf[uchar_ctr] = SPI_RW(0); CSN = 1; return(status); } /************************************************************************** **** /*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的 个数 /************************************************************************** ***/ unsigned int SPI_Write_Buf(unsigned char reg, unsigned char *pBuf, unsigned char uchars) { unsigned int status,uchar_ctr; CSN = 0; status = SPI_RW(reg);
第 37 页

// Set CSN low, init SPI tranaction // Select register to write to and

//

// return nRF24L01 status uchar

//SPI 使能

for(uchar_ctr=0; uchar_ctr<uchars; uchar_ctr++) // SPI_RW(*pBuf++); CSN = 1; return(status); } /************************************************************************** ***/ /*函数:void SetTX_Mode(void) /*功能:数据发送设置 /************************************************************************** ***/ void SetTX_Mode(void) { CE=0; SPI_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); 允许 SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); 如果需要多频道可以参考 Page21 SPI_RW_Reg(WRITE_REG + RF_CH, 40); 收发必须一致 SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); // 设置接收数据长度, 本次设置为 8 字节 SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); 1MHZ,发射功率为最大值 0dB SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); 应,16 位 CRC,主发送 CE = 1; inerDelay_us(130); }
第 38 页

//关闭 SPI //

// 写

// // //

频道 0 自动

ACK 应答

允许接收地址只有频道 0, 设置信道工作为 2.4GHZ,

// 设置发射速率为 // IRQ 收发完成中断响

/************************************************************************** ***** //*函数:void SetRX_Mode(void) /* 功 能 : 数 据 接 收 设 置 ************************************************************/ void SetRX_Mode(void) { CE=0; SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); 许 SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); 如果需要多频道可以参考 Page21 SPI_RW_Reg(WRITE_REG + RF_CH, 40); 收发必须一致 SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本 次设置为 8 字节 SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); 发射功率为最大值 0dB SPI_RW_Reg(WRITE_REG + CONFIG, 0x0F); CE=1; } /************************************************************************** ****/ /*函数: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) {
第 39 页

// // //

频道 0 自动

ACK 应答允

允许接收地址只有频道 0, 设置信道工作为 2.4GHZ,

//设置发射速率为 1MHZ,

// 读取状态寄存其来判断数据接收状况 // 判断是否接收到数据

CE = 0; payload from RX_FIFO buffer revale =1; }

//SPI 使能 read receive

SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// //读取数据完成标志

SPI_RW_Reg(WRITE_REG+STATUS,sta); 都置高为 1,通过写 1 来清楚中断标志 return revale; }

// 接收到数据后 RX_DR,TX_DS,MAX_PT

/************************************************************************** **** /*函数:void nRF24L01_TxPacket(unsigned char * tx_buf) /*功能:发送 tx_buf 中数据 /************************************************************************** ***/ void nRF24L01_TxPacket(unsigned char * tx_buf) { CE=0; SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载 接收端地址 SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); 载数据 CE=1; } //************************************主函数 void main(void) { void init(); init_nRF24L01(); while(1) { if( key1==0 ) {
第 40 页

// 装

//置高 CE,激发数据发送

void init(); init_nRF24L01(); SetTX_Mode(); nRF24L01_TxPacket(tx_Buf); write_com(0x80); for(num1=0;num1<TX_PLOAD_WIDTH;num1++) { write_date(tx_Buf[num1]); Delay(1); } } if( key2==0) { void init(); init_nRF24L01(); SetRX_Mode(); nRF24L01_RxPacket(rx_Buf); write_com(0x80+0x40); for(num2=0;num2<RX_PLOAD_WIDTH;num2++) { write_date(rx_Buf[num2]); Delay(5); } } if( key3==0 ) { void init(); init_nRF24L01(); } } }

第 41 页


相关文章:
基于nRF24L01模块的无线通信系统设计_图文
基于nRF24L01模块的无线通信系统设计_信息与通信_工程科技_专业资料 暂无评价|0人阅读|0次下载基于nRF24L01模块的无线通信系统设计_信息与通信_工程科技_专业资料。...
nRF24L01无线通信系统设计_图文
设计学院: 专业: 姓名: 学号: 指导老师: 电子信息学院 电子信息工程 1 摘要本文介绍了一套基于 STM32 微处理器,结合 nRF24L01 无线通信模块的无 线数据传输...
基于nRF2401开发2.4GHz无线模块
基于nRF2401模块,使用AT89C2051为主控的2.4G无线方案设计 基于《2.4G 无线传输》...P3.6) 12)直接驱动 LED 的输出端口 6 5 4 3 2 1 7 9 nRF24L01 U 2...
毕业论文-基于无线传输模块的网络通信系统设计
毕业论文-基于无线传输模块的网络通信系统设计_信息与通信_工程科技_专业资料。电子...掌握 了 nRF24L01 的无线传输原理, 并且对其进行了深入的研究, 得到 N 个...
基于NRF24L04无线收发设计报告
基于NRF24L04无线收发设计报告_信息与通信_工程科技_专业资料。无线收发,将接收...单片机对 NRF24L01 无线模块以及 DS18B20 进行初始化之后, DS18B20 读取温度...
NRF24L01 无线通信模块使用方法
NRF24L01 无线通信模块使用方法_信息与通信_工程科技_专业资料。NRF24L01 无线通信模块使用方法 1. 模块初始化。初始状态时,LED、CE、SCK 引脚均拉低,CSN 拉高...
基于NRF24L01的无线通信系统
滨江学院 课程论文题 目 基于 NRF24L01 的无线通信系统设计 专 业__ 通信...PTR6000 就是以nRF24I/)l为核心的无线收发模块,它可以通过软件设定地址,同时...
nRF24L01无线通信模块
nRF24L01无线通信模块_信息与通信_工程科技_专业资料。nRF24L01 无线通信模块 模块与 AT89S52 单片机接口电路 发送程序流程图: 开始 读状态寄存器 接收到数据? 否...
无线通信模块
无线通信模块工作原理图如下所示: 在无线通信模块中,我们将采用一种基于 NRF24L01 的无线数据传输系统,该系统具 有工作稳定可靠,传输速率较高,体积小,成本低,...
基于NRF24L01的无线数据传输系统设计_图文
基于NRF24L01的无线数据传输系统设计_信息与通信_工程科技_专业资料。典型的无线数据传输模块设计 中北大学电子与计算机科学技术学院 毕业设计开题报告学 生姓名: 学...
更多相关标签:
nrf24l01模块使用教程 | nrf24l01无线模块 | nrf24l01模块 | nrf24l01模块中文资料 | nrf24l01模块引脚图 | nrf24l01无线模块引脚 | nrf24l01双向通信 | nrf24l01无线模块程序 |