您的当前位置:首页正文

基于24L01的门控系统

来源:画鸵萌宠网


河南大学 自动控制课程设计

题目:基于nRF24L01的开关门控制系统

班级:09级测控技术与仪器

指导教师:高 伟

自动控制课程设计

摘要

为了培养我们的动手能力,增强专业素养,将课上所学的知识应用于实践创新中,在院老师的带领下进行了单片机的课程设计。此次课程设计为我们以后工作打下了坚实的基础。

遥控门控制系统由遥控模块,动力模块,控制模块,驱动电路组成,通过各个模块的相互配合实现由单片机控制电动机正反转从而控制门的上升下降的功能。本系统以STC89C52 8位单片机,运用NRF24L01无线收发装臵实现信息传递及获取。通过高低电平转换实现电动机的正反转,通过调整输入信号的占空比来调整电动机的转动速度。最终使门能够平稳,安全的上下移动。

关键字:NRF24L01 STC89C52 电动机 驱动电路

目录

摘要······················································2

2

自动控制课程设计

第一章 绪论···············································5 第二章 遥控门的设计方案选择·······························6 2.1 系统总体方案的选定〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃6 第三章 NRF24L01无线收发装臵的应用〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃6 3.1 模块介绍〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃6 3.2 接口电路·········································8 3.3 模块结构和引脚说明··································9 3.4 工作方式··································10 3.4.1 收发模式ShockBurstTM收发模式··················10 3.4.1.1 ShockBurstTM收发模式··························11 3.4.1.2直接收发模式···································13 3.4.2 配臵模式〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃14 3.4.3 空闲模式 〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃14 3.4.4 关机模式〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃14 第四章 电动机的转向及速度控制〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃15 4.1 电动机驱动电路的原理〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃15 第五章 AT89C52单片机硬件结构····························17 5.1时钟电路············································17 5.2复位电路············································20 第六章 软件设计··········································21 6.1 电机驱动程序·······································21 6.2 NRF24L01的初始化设计·······························22

3

自动控制课程设计

6.3 执行模块流程图·····································24 第七章 总结··············································25 附录一:人员组成及分工····································26 附录二:程序·············································27

第一章 绪论

4

自动控制课程设计

中国正有发展中国家向发达国家迈进,当今时代的发展对大学生的创新能力提出了更高的要求。在大学阶段我们作为学生应该不断的充实自己,掌握所学的专业理论知识,为日后的工作奠定基础培养能力。众所周知能力来自于实践,通过专门性的实践活动,有助于学生理解、巩固理论知识,提高学生的知识运用能力和动手实践能力,激发学生内在的创新能力。实践是工作的基础,是工作的基本手段,要培养和提高学生的能力,必须加强实践环节。单片机的课程设计无疑为我们提供了这样一个平台,使我们不断的将理论应用于实际,在实践中学到知识,培养能力。

门在生活中有着广泛的应用,遥控门从理论上理解应该是门的概念的延伸,是门的功能根据人的需要所进行的发展和完善。遥控门就是有遥控器发出(开,关,锁)等指令,通过控制系统接收指令并指挥驱动器执行具体动作。我们小组设计的遥控门包括控制系统 动力系统 遥控系统。遥控系统采用24L01无线收发装臵,包括发射和接收两个部分。动力系统应用点击来提供开关门的主动力。控制系统是遥控自动门的指挥中心,通过51单片机内部编有的程序,发出相应指令指挥动力系统。

此次课程设计丰富了我们的大学生活,使我们在实践中收获了许多,是人生中的一笔宝贵的财富。

第二章 遥控门的设计方案选择

5

自动控制课程设计

本章将着重介绍在实验开始阶段对于各个模块的选择依据及遥控门的主要原理。 2.1 系统总体方案的选定

在进行设计过程中由老师为我们提供了52单片机,对我们来说最重要的就是对信息发射接收装臵的选择。从我们所收集的资料整理看来,可以用于无线收发的主要有红外发射接收装臵,NRF24L01无线收发模块。红外发射接收由于受遥控距离、角度等影响,使用效果不是很好。而NRF2401无线收发模块,功耗低,只需少量无件即可组成一个完整的收发器,还有一点就是在实践过程中有同学同样使用此模块,所以通过大家共同努力使用中的问题会更好的得到解答

第三章 NRF24L01无线收发装臵的应用

NRF24L01是一款工作在2.4-2.5GHZ世界通用的ISM频段的单片无线收发器芯片。本章将详细介绍NRF24L01的原理及应用。

3.1 模块介绍

1) 2.4Ghz 全球开放ISM 频段免许可证使用

6

自动控制课程设计

2) 最高工作速率1Mbps,高效GFSK调制,抗干扰能力强,特别适合工业控制场合

3) 125 频道,满足多点通信和跳频通信需要 4) 内臵硬件CRC 检错和点对多点通信地址控制 5) 低功耗1.9 - 3.6V 工作,待机模式下状态仅为1uA 6) 内臵2.4Ghz 天线,体积小巧 34mm X 17mm

7) 模块可软件设地址,只有收到本机地址时才会输出数据(提供中断指示),可直接接各种单片机使用,软件编程非常方便 8) 内臵专门稳压电路,使用各种电源包括DC/DC 开关电源均有很好的通信效果

9) 标准DIP间距接口,便于嵌入式应用

10)RFModule-Quick-DEV 快速开发系统,含开发板

11)与51系列单片机P0口连接时候,需要加10K的上拉电阻,与其余口连接不需要。

12)其他系列的单片机,如果是5V的,请参考该系列单片机IO口输出电流大小,如果超过10mA,需要串联电阻分压,否则容易烧毁模块! 如果是3.3V的,可以直接和RF2401模块的IO口线连接。比如AVR系列单片机如果是5V的,一般串接2K的电阻。

3.2 接口电路

7

自动控制课程设计

1) VCC脚接电压范围为 1.9V~3.6V之间,不能在这个区间之外,超过3.6V将会烧毁模块。推荐电压3.3V左右。

2) 除电源VCC和接地端,其余脚都可以直接和普通的5V单片机IO口直接相连,无需电平转换。

3) 硬件上面没有SPI的单片机也可以控制本模块,用普通单片机IO口模拟SPI不需要单片机真正的串口介入,只需要普通的单片机IO口就可以了,当然用串口也可以了。

4) 6脚,12脚为接地脚,需要和母板的逻辑地连接起来

5) 排针间距为100mil,标准DIP插针,如果需要其他封装接口,比如密脚插针,或者其他形式的接口,可以联系我们定做。

8

自动控制课程设计

3.3 模块结构和引脚说明

9

自动控制课程设计

3.4 工作方式

NRF2401有工作模式有四种:

收发模式 配臵模式 空闲模式 关机模式

3.4.1 收发模式

收发模式有ShockBurstTM收发模式和直接收发模式两种,收发

10

自动控制课程设计

模式由器件配臵字决定,具体配臵将在器件配臵部分详细介绍。

3.4.1.1 ShockBurstTM收发模式

ShockBurstTM收发模式下,使用片内的先入先出堆栈区,数据低速从微控制器送入,但高速(1Mbps)发射,这样可以尽量节能,因此,使用低速的微控制器也能得到很高的射频数据发射速率。与射频协议相关的所有高速信号处理都在片内进行,这种做法有三大好处:尽量节能;低的系统费用(低速微处理器也能进行高速射频发射);数据在空中停留时间短,抗干扰性高。ShockBurstTM技术同时也减小了整个系统的平均工作电流。 在ShockBurstTM收发模式下, NewMsg_RF2401自动处理字头和CRC校验码。在接收数据时,自动把字头和CRC校验码移去。在发送数据时,自动加上字头和CRC校验码,当发送过程完成后,DR引脚通知微处理器数据发射完毕。 1. ShockBurstTM发射流程

需要用到的接口引脚为CE,CLK1,DATA

1) 当微控制器有数据要发送时,其把CE臵高,使NewMsg_RF2401工作;

2) 把接收机的地址和要发送的数据按时序送入NewMsg_RF2401;

3) 微控制器把CE臵低,激发NewMsg_RF2401进行ShockBurstTM发射;

4) NewMsg_RF2401的ShockBurstTM发射

 给射频前端供电;

11

自动控制课程设计

 (2)射频数据打包(加字头、CRC校验码);  (3) 高速发射数据包;

 (4)发射完成,NewMsg_RF2401进入空闲状态。

增强型ShockBurstTM 模式发送一包数据时序2Mbps

2 . ShockBurstTM接收流程

需用到的接口引脚CE、DR1、CLK1和DATA(接收通道1)  配臵本机地址和要接收的数据包大小;  进入接收状态,把CE臵高;

 200us后,NewMsg_RF2401进入监视状态,等待数据包的到来;  当接收到正确的数据包(正确的地址和CRC校验码),

12

自动控制课程设计

NewMsg_RF2401自动把字头、地址和CRC校验位移去;

 NewMsg_RF2401通过把DR1(这个引脚一般引起微控制器中断) 置高通知微控制器;

 微控制器把数据从NewMsg_RF2401读出;

 所有数据读取完毕后,NewMsg_RF2401把DR1置低,此时,如

果CE为高,则等待下一个数据包,如果CE为低,开始其它工作流程。

3.4.1.2直接收发模式

在直接收发模式下,NewMsg_RF2401如传统的射频收发器一样工作。 1.直接发送模式

需要用到的接口引脚为CE、DATA

 当微控制器有数据要发送时,把CE臵高;  NewMsg_RF2401射频前端被激活;

 所有的射频协议必须在微控制器程序中进行处理 (包括字头、地址和CRC校验码) 。 2.直接接收模式

需要用到的接口引脚为CE、CLK1和DATA

 一旦NewMsg_RF2401被配臵为直接接收模式,DATA引脚将根据天线接收到的信号开始高低变化(由于噪声的存在);  CLK1引脚也开始工作;

 一旦接收到有效的字头,CLK1引脚和DATA引脚将协调工作,把射频数据包以其被发射时的数据从DATA引脚送给微

13

自动控制课程设计

控制器;  字头必须是8位;

 DR引脚没用上,所有的地址和CRC校验必须在微控制器内

部进行。

3.4.2 配臵模式

在配臵模式,15字节的配臵字被送到NewMsg_RF2401,这通过CS、CLK1和DATA三个引脚完成,具体的配臵方法请参考本文的器件配臵部分。

3.4.3 空闲模式

NewMsg_RF2401的空闲模式是为了减小平均工作电流而设计,其最大的优点是,实现节能的同时,缩短芯片的起动时间。在空闲模式下,部分片内晶振仍在工作,此时的工作电流跟外部晶振的频率有关,如外部晶振为4MHz时工作电流为12uA,外部晶振为16MHz时工作电流为32uA。在空闲模式下,配臵字的内容保持在NewMsg_RF2401片内。

3.4.4 关机模式

在关机模式下,为了得到最小的工作电流,一般此时的工作电流小于1uA。关机模式下,配臵字的内容也会被保持在NewMsg_RF2401片内,这是该模式与断电状态最大的区别

14

自动控制课程设计

第四章 电动机的转向及速度控制

本章将详细介绍电动机的工作原理,如何控制电动机的速度使其能够平稳的移动,如何控制电动机的正反转使其带动门上下移动。

4.1 电动机驱动电路的原理

图4-1中所示为一个典型的直流电机控制电路。电路得名于“H桥驱动电路”是因为它的形状酷似字母H。4个三极管组成H的4条垂直腿,而电机就是H中的横杠(注意:图2-4及随后的两个图都只是示意图,而不是完整的电路图,其中三极管的驱动电路没有画出来)。

如图所示,H桥式电机驱动电路包括4个三极管和一个电机。要使电机运转,必须导通对角线上的一对三极管。根据不同三极管对的导通情况,电流可能会从左至右或从右至左流过电机,从而控制电机的转向。

图4-1 H桥驱动电路

15

自动控制课程设计

要使电机运转,必须使对角线上的一对三极管导通。例如,如图

4-2所示,当Q1管和Q4管导通时,电流就从电源正极经Q1从左至右穿过电机,然后再经Q4回到电源负极。按图中电流箭头所示,该流向的电流将驱动电机顺时针转动。当三极管Q1和Q4导通时,电流将从左至右流过电机,从而驱动电机按特定方向转动(电机周围的箭头指示为顺时针方向)。

图4-2 H桥电路驱动电机顺时针转动

图4-3 所示为另一对三极管Q2和Q3导通的情况,电流将从右至左流过电机。当三极管Q2和Q3导通时,电流将从右至左流过电机,从而驱动电机沿另一方向转动(电机周围的箭头表示为逆时针方向)。

16

自动控制课程设计

图4-3 H桥驱动电机逆时针转动

第五章 AT89C52单片机硬件结构

AT89C52单片机是把那些作为控制应用所必需的基本内容都集成在一个尺寸有限的集成电路芯片上。如果按功能划分,它由如下功能部件组成,即微处理器、数据存储器、程序存储器、并行I/O口、串行口、定时器/计数器、中断系统及特殊功能寄存器。它们都是通过片内单一总线连接而成,其基本结构依旧是CPU加上外围芯片的传统结构模式。但对各种功能部件的控制是采用特殊功能寄存器的集中控制方式。

17

自动控制课程设计

1 微处理器

该单片机中有一个8位的微处理器,与通用的微处理器基本相同,同样包括了运算器和控制器两大部分,只是增加了面向控制的处理功能,不仅可处理数据,还可以进行位变量的处理。 2 数据存储器

片内为256字节,片外最多可外扩至64k字节,用来存储程序在运行期间的工作变量、运算的中间结果、数据暂存和缓冲、标志位等,所以称为数据存储器。 3 程序存储器

由于受集成度限制,片内只读存储器一般容量较小,如果片内的只读存储器的容量不够,则需用扩展片外的只读存储器,片外最多可外扩至64k字节。 4 中断系统

具有6个中断源,2级中断优先权。本次毕业设计小车采用实时调中断的方法进行显示。 5 定时器/计数器

片内有3个16位的定时器/计数器,定时器/计数器2具有3种工作方式,此次设计中的小车测速,测距,控制小车停车就是利用定时器/计数器1的方式完成的,此种工作方式是AT89C52常用的工作方式。 6 串行口

1个全双工的串行口,具有四种工作方式。可用来进行串行通讯,扩展并行I/O口,甚至与多个单片机相连构成多机系统,例如本机与

18

自动控制课程设计

无线模块链接的接口就是SPI串口,从而使单片机的功能更强且应用更广。 7 I/O口

P1口、P2口、P3口、P4口为4个并行8位I/O口。P1口要接上拉电阻,才能实现与其它接口的功能。 8 特殊功能寄存器

共有128个,用于对片内的各功能的部件进行管理、控制、监视。实际上是一些控制寄存器和状态寄存器,是一个具有特殊功能的RAM区。

由上可见,AT89C52单片机的硬件结构具有功能种类全,功能强等特点。特别值得一提的是1位微计算机有自己的CPU、位寄存器、I/O口和指令集。1位机在开关决策、逻辑电路仿真、过程控制方面非常有效;而8位机在数据采集,运算处理方面有明显的长处。单片机中8位机和1位机的硬件资源复合在一起,二者相辅相承,它是单片机技术上的一个突破,这也是AT89C52单片机在设计的精美之处。

5.1时钟电路

AT89C52虽然有内部振荡电路,但要形成时钟,必须外部附加电路。AT89C52单片机的时钟产生方法有两种。内部时钟方式和外部时钟方式。

本设计采用内部时钟方式,利用芯片内部的振荡电路结构,在XTAL1、XTAL2引脚上外接定时元件,内部的振荡电路便产生自激振

19

自动控制课程设计

荡。本设计采用最常用的内部时钟方式,即用外接晶体和电容组成的并联谐振回路。振荡晶体可在1.2MHZ到12MHZ之间选择。电容值无严格要求,但电容取值对振荡频率输出的稳定性、大小、振荡电路起振速度有少许影响,C1、C2可在20pF到100pF之间取值,基于小车的要求比较低。所以本设计中,振荡晶体选择12MHZ,电容选择30pF。

在设计印刷电路板时,晶体和电容应尽可能靠近单片机芯片安装,以减少寄生电容,更好的保证振荡器稳定和可靠地工作。为了提高系统工作稳定性,应采用NPO电容。 5.2复位电路

复位电路通常采用上电自动复位和按钮复位两种方式。 最简单的上电自动复位电路中上电自动复位是通过外部复位电路的电容充电来实现的。只要Vcc的上升时间不超过1ms,就可以实现自动上电复位。时钟频率用12MHZ时C取30pF,R取4.7KΩ。

除了上电复位外,有时还需要按键手动复位。本设计就是用的按键手动复位模式。按键手动复位有电平方式和脉冲方式两种。其中电平复位是通过RST端经电阻与电源Vcc接通而实现的。按键手动复位电路如图3—3所示。时钟频率选用12MHZ时,C取30pF, R1取4.7KΩ。

VCC

+

C3RST4.7k30pFSW-PB20

自动控制课程设计

第六章 软件设计

6.1 电机驱动程序

图6-1 驱动模块流程图

21

主程序初始化 Y 判断 N 检测控制按钮按下时所产生的数据 发送到NRF24L01模块 发送 自动控制课程设计

6.2 NRF24L01的初始化设计

sbit MISO =P1^0;

sbit MOSI =P1^3; sbit SCK =P1^2; sbit CE =P1^4; sbit CSN =P1^5; sbit IRQ =P3^2;

#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 payload

//本地地址

uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收

#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 // 保留

#define CONFIG 0x00 // CRC校验模式以及收发状态响应方式

#define EN_AA 0x01 // 自动应答功能设置 #define EN_RXADDR 0x02 // 可用信道设置

#define READ_REG 0x00 // 读寄存器指令

uint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01};

22

自动控制课程设计

#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 // FIFO发送监测功能 地址检测 频道0接收数据地址

频道1接收数据地址 频道2接收数据地址

频道3接收数据地址 频道4接收数据地址

频道5接收数据地址 发送地址寄存器

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

23

自动控制课程设计

6.3 执行模块流程图

NRF24L01初始化

主函数 等待接收数据 否 是否接收到数据 是 执行电机驱动模块 门上升 或 者下降 执行完毕 图6-2 执行模块流程图

24

自动控制课程设计

第七章 总结

在制作门的过程中我们遇到了很多问题 1. 电动机转速控制

开始时电动机转速太快,稳定上升,我们想得很多办法,如换公路功率较小的电动机,加大门的重量,这些都不能很好地减低速度,最后决定添加程序,通过改变输入信号的占空比调整电机的运转速度,基本实现了预想的功能。 2. 电路调试

第一次调试电路时,发现调试不通,最后发现是因为引脚连接出现错误,改正后依旧不通,经检查后无错误,但调试多次后能够正常工作,原因不明。 3驱动电路

最开始加入驱动电路,电动机不能正常转动,原因加入电压过低,电动机不能正常工作。 实验过程中的收获

1.在实际动手过程中我们将理论应用于实践,不知不觉的学习了多门知识,例如51单片机,NRF24L01,C语言,系统仿真等等。学会了收集资料,并从资料中筛选对自己有用的信息。在学习中深化了对本专业的认识,找到了前进的方向。为以后就业打下了坚实的基础。

2.通过与本小组及其他同学一起动手,我们学会了在工作中如何分工合作,如何高效率的完成工作,体会到了团结合作的重要性。

25

自动控制课程设计

附录二:分工

姓名 王群 王为 王畅

分工 查找资料 购买元器件 制作PPT 论文 查找资料 购买元器件 制作PPT 论文 查找资料 焊接元器件 论文 程序 百分比 33% 33% 34%

26

自动控制课程设计

附录二:程序

发送程序 #include #include

typedef unsigned char uchar; typedef unsigned char uint;

//****************************************IO端口定义

/*sbit MISO =P1^3; sbit MOSI =P1^5; sbit SCK =P1^4; sbit CE =P1^6; sbit CSN =P1^7; sbit IRQ =P3^2; */ /*

sbit MISO =P1^2; sbit MOSI =P1^1; sbit SCK =P1^3; sbit CE =P1^4;

27

自动控制课程设计

sbit CSN =P1^0; sbit IRQ =P3^2; */ sbit MISO =P1^0; sbit MOSI =P1^3; sbit SCK =P1^2; sbit CE =P1^4; sbit CSN =P1^5; sbit IRQ =P3^2; // sbit KEY2=P2^6; sbit KEY1=P2^7; sbit KEY3=P2^5; uchar TxBuf[32]=

{0x01,0x02,0x03,0x04,0x05,0x06,0x07,0X0A,0x0b,0X0C,0X0D}; //

//*********************************************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 payload

28

自动控制课程设计

uint 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校验模式以及收发状态响应方式

29

自动控制课程设计

#define EN_AA 0x01 // 自动应答功能设臵 #define EN_RXADDR 0x02 // 可用信道设臵 #define SETUP_AW 0x03 // 收发地址宽度设臵

#define SETUP_RETR 0x04 // 自动重发功能设臵 #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

0x05 // 工作频率设臵 0x06 // 发射速率、功耗功能设臵 0x07 // 状态寄存器

0x08 // 发送监测功能 0x09 // 地址检测 0x0A // 频道0接收数据地址 0x0B // 频道1接收数据地址

0x0C // 频道2接收数据地址 0x0D // 频道3接收数据地址 0x0E // 频道4接收数据地址 0x0F // 频道5接收数据地址

30

自动控制课程设计

#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);

31

自动控制课程设计

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//*****************************************************************************

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--)

32

自动控制课程设计

_nop_(); }

//***************************************************************************** /*NRF24L01初始化

//*****************************************************************************/ void init_NRF24L01(void) { CE=0;

inerDelay_us(100); // chip enable

SCK=0; // Spi clock line init high }

/****************************************************************************** /*函数:uint SPI_RW(uint uchar) /*功能:NRF24L01的SPI写时序

/**************************************************************************/ uint SPI_RW(uint uchar)

33

自动控制课程设计

{

uint bit_ctr;

for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit {

MOSI = (uchar & 0x80); // output 'uchar', MSB to MOSI

uchar = (uchar << 1); // shift next bit into MSB..

SCK = 1; // Set SCK high.. uchar |= MISO; // capture current MISO bit

SCK = 0; // ..then set SCK low again }

return(uchar); // return read uchar }

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

/*函数:uchar SPI_Read(uchar reg) /*功能:NRF24L01的SPI时序

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

34

自动控制课程设计

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 registervalue

CSN = 1; // CSN high, terminate SPI communication

return(reg_val); // return register value }

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

/*功能:NRF24L01读写寄存器函数

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

uint SPI_RW_Reg(uchar reg, uchar value) {

uint status;

35

自动控制课程设计

CSN = 0; // CSN low, init SPI transaction

status = SPI_RW(reg); // select register

SPI_RW(value); // ..and write value to it..

CSN = 1; // CSN high again

return(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;

36

自动控制课程设计

CSN = 0; // Set CSN low, init SPI tranaction

status = SPI_RW(reg); // Select register to write to and read status uchar

for(uchar_ctr=0;uchar_ctrCSN = 1;

return(status); // return nRF24L01 status uchar }

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

/*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数

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

37

自动控制课程设计

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/*****************************************************************************/ /*函数:void SetRX_Mode(void) /*功能:数据接收配臵

/*****************************************************************************/ void SetTX_Mode(void) { //test CE=0;

SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS,

38

!!

自动控制课程设计

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,如果需要多频道可以参考Page21 SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a);

SPI_RW_Reg(WRITE_REG + RF_CH, 0); // 设臵信

道工作为2.4GHZ,收发必须一致 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); // IRQ收发完成中断响应,16位CRC,主发送 CE = 1;

inerDelay_us(130); }

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

/*函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)

39

自动控制课程设计

/*功能:数据读取后放如rx_buf接收缓冲区中

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

uchar CheckACK() {

sta=SPI_Read(READ_REG+STATUS); // 返

回状态寄存器

if(TX_DS||MAX_RT) //发送完毕中断 {

SPI_RW_Reg(WRITE_REG+STATUS,0xff); // 清除TX_DS

或MAX_RT中断标志

CSN=0;

SPI_RW(FLUSH_TX);//用于清空FIFO !!关键!!不然会出现

意想不到的后果!!!大家记住!! CSN=1;

return(0); } else return(1);

40

自动控制课程设计

}

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 buffer

revale =1; //读取数据完成标志 }

SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT都臵高为1,通过写1来清楚中断标志 return revale; }

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

41

自动控制课程设计

/*函数: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); // 装载数据 //test

SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送

CE=1; //臵高CE,激发数据发送 inerDelay_us(10); }

//************************************主函数

void zhongduan(void) interrupt 0 {

42

自动控制课程设计

P2=0x0f; Delay(100); P2=0xf0; }

void main(void) {

init_NRF24L01() ;

//nRF24L01_TxPacket(TxBuf);

Delay(20); EA=1; EX0=1;

IT0=1;

while(1) {

SetTX_Mode(); if(KEY1 ==0 ) {

Delay(10);

if(KEY1 ==0 ) {

while(KEY1==0);

43

// Transmit Tx buffer data 自动控制课程设计

TxBuf[0] = 0x11 ;

TxBuf[1] =0x22 ;

}}

if(KEY2 ==0 ) { Delay(10);

if(KEY2 ==0 ) {

while(KEY2==0);

TxBuf[0] =0x22 ; TxBuf[1] = 0x11 ;

}} if(KEY3 ==0 ) { Delay(10);

if(KEY3 ==0 ) {

while(KEY3=0);

TxBuf[0] =0x33 ;

44

自动控制课程设计

TxBuf[1] = 0x44 ;

}}

SetTX_Mode();

nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer data

while(CheckACK());//检测是否发送完毕

Delay(20);

//SPI_RW_Reg(WRITE_REG+STATUS,0XFF);

} } 接收程序 #include #include

typedef unsigned char uchar; typedef unsigned char uint;

sbit D1 = P2^6;

45

自动控制课程设计

sbit D2 = P2^7;

//****************************************IO端口定义 /*

sbit MISO =P1^2; sbit MOSI sbit SCK sbit CE sbit CSN sbit IRQ /*

sbit MISO sbit MOSI sbit SCK sbit CE sbit CSN sbit IRQ

sbit MISO

=P1^1; =P1^3; =P1^4; =P1^0;

=P3^2; // 可用 =P2^5; =P2^6; =P2^4; =P2^3; =P2^7; =P3^2; =P1^0;

46

*/ 自动控制课程设计

sbit MOSI =P1^3; sbit SCK =P1^2; sbit CE =P1^4; sbit CSN =P1^5; sbit IRQ =P3^2; //

//*********************************************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 payload uint

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 // 读取接收数据指令

47

自动控制课程设计

#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接收数据地址

48

自动控制课程设计

#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);

49

自动控制课程设计

unsigned char nRF24L01_RxPacket(unsigned char* rx_buf); void nRF24L01_TxPacket(unsigned char * tx_buf); //*****************************************长延时 void longdelay(unsigned int t ) {

uchar s; while(t--)

{for(s=0;s<250;s++);}}

void Delay(unsigned int s) {

unsigned int i; for(i=0; iuint bdata sta; //状态标志 sbit RX_DR =sta^6; sbit TX_DS =sta^5; sbit MAX_RT =sta^4;

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

50

自动控制课程设计

/*延时函数

/******************************************************************************/ void inerDelay_us(unsigned char n) {

for(;n>0;n--) _nop_(); }

//***************************************************************************** /*NRF24L01初始化

//*****************************************************************************/ void init_NRF24L01(void) {

CE=0; // chip enable

// inerDelay_us(10);

CSN=1; // Spi disable

SCK=0; // Spi clock line init high

inerDelay_us(100);

51

自动控制课程设计

// SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址

// SPI_RW_Reg(WRITE_REG + EN_AA, 0x00); // 频道0自动 ACK应答允许

// SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 允许接收地址只有频道0,如果需要多频道可以参考Page21 // SPI_RW_Reg(WRITE_REG + RF_CH, 0); // 设臵信道工作为2.4GHZ,收发必须一致 //

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, 0x0f); // IRQ收发完成中断响应,16位CRC ,主接收 }

/****************************************************************************** /*函数:uint SPI_RW(uint uchar) /*功能:NRF24L01的SPI写时序

/******************************************************************************/ uint SPI_RW(uint d)

52

自动控制课程设计

{

uint bit_ctr;

for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit {

MOSI = (d & 0x80); // output 'uchar', MSB to MOSI

d = (d<< 1); // shift next bit into MSB.. SCK = 1; // Set SCK high.. d|= MISO; // capture current MISO bit SCK = 0; // ..then set SCK low again }

return(d); // return read uchar }

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

/*函数:uchar SPI_Read(uchar reg) /*功能:NRF24L01的SPI时序

/******************************************************************************/ uchar SPI_Read(uchar reg) {

53

自动控制课程设计

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 registervalue

CSN = 1; // CSN high, terminate SPI communication

return(reg_val); // return register value }

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

/*功能:NRF24L01读写寄存器函数

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

uint SPI_RW_Reg(uchar reg, uchar value) {

uint status;

CSN = 0; // CSN low, init SPI transaction status = SPI_RW(reg); // select register

54

自动控制课程设计

SPI_RW(value); // ..and write value to it.. CSN = 1; // CSN high again

return(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 tranaction

status = SPI_RW(reg); // Select register to write to and read status uchar

for(uchar_ctr=0;uchar_ctr55

自动控制课程设计

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_ctr56

自动控制课程设计

return(status); // }

/****************************************************************************** /*函数:void SetRX_Mode(void) /*功能:数据接收配臵

/******************************************************************************/ void SetRX_Mode(void) {

CE=0;

// SPI_RW_Reg(WRITE_REG+CONFIG,0X0F); // CE = 1; inerDelay_us(130);

SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS,

TX_ADR_WIDTH); // 写接收端地址

SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 频道0自动 ACK应答允许

SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 允许接收地址只有频道0,如果需要多频道可以参考Page21 SPI_RW_Reg(WRITE_REG + RF_CH, 0); // 设臵

57

自动控制课程设计

信道工作为2.4GHZ,收发必须一致 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, 0x0f);

CE = 1;

inerDelay_us(15); // IRQ收发完成中断响应,16位CRC ,主接收 }

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

/*函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf) /*功能:数据读取后放如rx_buf接收缓冲区中

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

unsigned char nRF24L01_RxPacket(unsigned char* rx_buf) {

unsigned char revale=0;

58

自动控制课程设计

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 buffer

revale =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中数据

/**********************************x********************************************/

/*void nRF24L01_TxPacket(unsigned char * tx_buf) {

59

自动控制课程设计

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); } */

//************************************串口初始化 void StartUART( void )

{ //波特率9600 SCON = 0x50; TMOD = 0x20; TH1 = 0xFd; TL1 = 0xFd; PCON = 0x00; TR1 = 1; }

//************************************通过串口将接收到数据发送给PC端

60

自动控制课程设计

void R_S_Byte(uchar R_Byte) {

SBUF = R_Byte;

while( TI == 0 ); //查询法 TI = 0; }

//************************************主函数 void main(void) {

extern unsigned char revale;

uchar RxBuf[32];

uchar i;

EA=1; IT0=1; EX0=1;

StartUART(); init_NRF24L01() ;

61

自动控制课程设计

SetRX_Mode();

Delay(20); //while(1) for(;;) {

StartUART(); init_NRF24L01() ; SetRX_Mode();

// Delay(15);

// nRF24L01_RxPacket(RxBuf);

// if(revale)

if( nRF24L01_RxPacket(RxBuf))

62

自动控制课程设计

{

/* for(i=0;i<32;i++)

{

R_S_Byte(RxBuf[i]); Delay(60); } */

while(RxBuf[0]==0x11&&RxBuf[1]==0x22)

{P2=0xff; D1=1;D2=0;

init_NRF24L01() ;

SetRX_Mode();

D1=0;D2=0; //init_NRF24L01() ;

//SetRX_Mode();

RxBuf[0]=0x00;

}

while(RxBuf[0]==0x22&&RxBuf[1]==0x11)

{P2=0xff;

63

自动控制课程设计

D2=1;D1=0; init_NRF24L01() ;

SetRX_Mode();

D2=0;D1=0;

//init_NRF24L01() ;

//SetRX_Mode();

RxBuf[0]=0x00; //P0LED_style2();

}

while(RxBuf[0]==0x33&&RxBuf[1]==0x44)

{P2=0xff; D1=0;D2=0;

init_NRF24L01() ;

SetRX_Mode();

RxBuf[0]=0x00;

} /* { m=0xfe;

for(i=0;i<=8;i++)

64

自动控制课程设计

{ P0=m; m<<=1; m=m|0x01; if(m == 0xff ) m = 0xfe; Delay(5000); Delay(2000);

}

}*/

// else // R_S_Byte(0xff);

} } }

65

自动控制课程设计

66

因篇幅问题不能全部显示,请点此查看更多更全内容

Top