NRF24L01的C51单片机讲解

合集下载

单片机原理c51

单片机原理c51

单片机原理c51C51是英特尔公司推出的一款经典的8位单片机,它以其高性能、低功耗和丰富的外设接口而被广泛应用于各种嵌入式系统中。

C51采用哈佛结构,由CPU 核心、存储器、输入输出端口和时钟等组成。

在这篇文章中,我将从C51的结构、工作原理、指令集和应用方面进行详细介绍。

首先,我们来了解C51的基本结构。

C51的核心是一个8位的中央处理器,它包含一个紧凑的指令集、寻址模式和寄存器集。

C51的存储器主要包括ROM(只读存储器)和RAM(随机存储器)。

ROM用于存储程序代码和常量数据,而RAM用于存储变量和运行时数据。

C51还有一些特殊功能寄存器(SFR),用于控制和配置外设接口。

C51的工作原理是通过时钟信号进行同步操作的。

C51的时钟可以是外部提供的,也可以是内部产生的。

时钟信号按照一定的频率进行周期性的振荡,它驱动着C51的工作节奏。

每当时钟信号发生跳变,C51就执行一条指令。

C51的指令由操作码和操作数组成,操作码表示要执行的操作,而操作数则是操作所需要的数据。

C51的指令集非常丰富,包含多种逻辑运算、算术运算、位操作和数据传输等指令。

C51支持直接寻址、间接寻址和立即寻址等多种寻址模式,可以满足各种不同的应用需求。

C51还具有很强的中断处理能力,它可以响应外部中断和定时器中断,并在中断发生时暂停当前任务,转而执行中断服务程序。

C51的应用非常广泛。

由于其高性能和低功耗的特点,C51常常被用于无线通信系统、工业控制系统、汽车电子系统、医疗设备等领域。

它可以控制各种外设接口,如LED显示、数码管显示、键盘输入、AD/DA转换、串行通信等。

此外,C51还支持多任务操作系统,使得多个任务可以同时运行,提高了系统的并行处理能力。

总之,C51是一款经典的8位单片机,它拥有强大的性能和丰富的外设接口,可以满足各种嵌入式系统的需求。

C51采用哈佛结构,通过时钟信号进行同步操作,具有丰富的指令集和多种寻址模式。

单片机c51的特点与使用

单片机c51的特点与使用

单片机c51的特点与使用单片机(Microcontroller)是一种集成了处理器核心、存储器和外设接口的微型计算机系统。

其中,C51是一种常见的单片机系列,特点突出,广泛应用于各个领域。

本文将详细介绍C51单片机的特点及其使用方法。

一、C51单片机的特点C51单片机具有以下几个特点:1. 体积小巧:C51单片机以芯片的形式存在,体积小巧、轻便灵活。

它将CPU、存储器及外设接口等功能融合在一个芯片内,实现了高集成度的设计。

2. 低功耗:C51单片机功耗较低,适用于通过电池供电或要求长时间运行的应用场景。

其低功耗特点可以延长电池寿命,提高系统的稳定性。

3. 强大的功能:C51单片机内部集成了高性能的CPU核心,具有较大的存储空间和灵活的输入输出接口。

这使得C51单片机适合用于各种复杂的应用,如智能家居控制、工业自动化等。

4. 易于学习和使用:C51单片机的编程语言较为简单,主要采用C语言或汇编语言进行开发。

相关的开发工具和调试工具也较为完善,新手可以迅速上手并进行开发。

5. 兼容性强:C51单片机具有广泛的兼容性,支持多种外设与模块的接口,可以方便地与其他设备进行通信和数据交互。

二、C51单片机的使用方法1. 硬件设计:在使用C51单片机之前,首先需要进行相应的硬件设计。

根据具体需求,选择合适的C51单片机型号,确定所需的外设接口和引脚分配。

然后,按照硬件设计原理图进行电路设计和布局。

2. 编写程序:根据具体应用需求,使用C语言或汇编语言编写相应的程序。

在编写程序时,可以利用C51单片机所提供的开发工具,如Keil C51等。

编写程序时,应注意代码的可读性和模块化设计,方便后期维护和调试。

3. 编译和下载:将编写好的程序通过编译器进行编译成机器语言。

编译成功后,将程序下载到C51单片机中。

下载方法可以通过串口下载、仿真器下载等方式进行。

4. 调试与测试:在将程序下载到C51单片机后,进行相应的调试和测试。

C51单片机的基础知识

C51单片机的基础知识
4、灵活性:系统应支持多种广播方式,如定时广播、实时广播、点播等, 以满足不同场景的需求。
5、可扩展性:系统应具备良好的扩展性,方便未来进行设备升级或扩容。
三、系统设计方案
1、硬件设备:包括服务器、网络交换机、音源设备、功放设备、扬声器等。 服务器应采用高性能、稳定的品牌服务器,以保证系统的稳定性和可靠性。网络 交换机应选择支持大带宽、低延时的产品,以保证广播信号的传输质量。音源设 备可选用数字音
首先应该从其内部结构及各部件关系入手,清楚其内部资源及怎样使用,然 后通过自己动手制作实践来加深印象,之后通过学习语言来掌握编程方法及技巧。 切记不要一开始就试图记忆太多的内容,这样只会增加你的负担,要知道“贪多 嚼不烂”。
先搞懂最基本的原理后再试着看懂其它扩展资料就会容易多了。之后要付诸 实践进行调试练习。在理解的基础上进行记忆,切勿死记硬背。
二、中断结构
C51单片机的中断系统主要包括以下几个部分:
1、中断源:C51单片机支持多个中断源,包括定时器/计数器,串行通信口, 外部中断等。每个中断源都有相应的中断标志,用于指示该中断源是否产生了中 断。
2、中断控制器:中断控制器是中断系统的核心部件,它负责管理各个中断 源的中断请求,根据优先级判断并处理。
二、系统需求分析
1、稳定性:系统应具备高度的稳定性,能够保证长时间的连续运行,避免 因设备故障或网络问题导致的广播中断。
2、可靠性:系统应具备可靠的备份机制,确保在主设备出现问题时,备份 设备能够迅速接管,保证广播的连续性。
3、易用性:系统应具备良好的用户界面,操作简单易懂,方便管理员进行 配置和管理。
五、C51与8051的区别
C51单片机是指一系列基于8051内核的单片机,各个生产厂商根据需要都会 在其基础上增加一些功能,但这与8051内核是相同的。所以很多人都习惯称其为 8051单片机。现在流行的很多开发板都是基于8051内核的。

无线模块NRF24L01基于C51单片机双向通讯C语言程序(中文详解)

无线模块NRF24L01基于C51单片机双向通讯C语言程序(中文详解)

#include <reg52.h>#include <intrins.h>/********************************************************** *****************************//* NRF24L01 地管脚定义,以及在本程序中地应用,VCC接3.3V 电源,可以通过5V用电压转换芯片/*得到,NC 管脚可以接可以不接,暂时没用途.本程序应用于51或者52单片机,是两个模块进行通讯/*成功地简单指示,现象是:模块1地 KEY1 对应模块1地LED1 和模块2地LED3 ,模块1地 KEY2 对应模/*块1地LED2 和模块2地LED4,发过来也对应./********************************************************** *****************************/typedef unsigned char uchar;typedef unsigned char uint;/************************************NRF24L01端口定义***********************************/sbit NC =P2^0; //没用,不接也可sbit MISO =P2^5; //数字输出(从 SPI 数据输出脚)sbit MOSI =P2^4; //数字输入(从 SPI 数据输入脚)sbit SCK =P1^7; //数字输入(SPI 时钟)sbit CE =P2^1; //数字输入(RX 或 TX 模式选择)sbit CSN =P2^2; //数字输入(SPI片选信号)sbit IRQ =P2^6; //数字输入(可屏蔽中断)/************************************按键***********************************************/sbit KEY1=P3^3;//按键S1sbit KEY2=P3^2;//按键S2/************************************数码管位选******************************************/sbit led1=P1^0; //LED0sbit led2=P1^1; //LED1sbit led3 =P1^2; //LED2sbit led4 =P1^3; //LED3sbit led5 =P1^4; //LED4/*********************************************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 20 // 20 uints TX payload 有效载荷装载货物#define RX_PLOAD_WIDTH 20 // 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); //NRF24L01 初始化uint SPI_RW(uint dat); //根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01读出一字节uchar SPI_Read(uchar reg); //从reg寄存器读一字节void SetRX_Mode(void); //数据接收配置uint SPI_RW_Reg(uchar reg, uchar value); //写数据value到reg寄存器uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars); //从reg寄存器读出bytes个字节,通常用来读取接收通道数据或接收/发送地址uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars); //把pBuf缓存中地数据写入到nRF24L01,通常用来写入发射通道数据或接收/发送地址unsigned char nRF24L01_RxPacket(unsigned char* rx_buf);//数据读取后放入rx_buf接收缓冲区中void nRF24L01_TxPacket(unsigned char * tx_buf);//发送 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; //RX_DR 为 sta 地第六位sbit TX_DS =sta^5; //TX_DS 为 sta 地第五位sbit MAX_RT =sta^4; //MAX_RT 为 sta 地第四位/********************************************************** ********************************//*延时函数/********************************************************** ********************************/void inerDelay_us(unsigned char n) //延时,us 级{for(;n>0;n--)_nop_();}/********************************************************** ******************************//*NRF24L01初始化/********************************************************** *****************************/void init_NRF24L01(void){inerDelay_us(100);CE=0; // 芯片使能CSN=1; // 禁止 SPISCK=0; // 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); // 频道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,发射功率为最大值0dB}/********************************************************** ******************************************//*函数:uint SPI_RW(uint uchar)/*功能:NRF24L01地SPI写时序-----根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01 读出一字节/********************************************************** ******************************************/uint SPI_RW(uint dat){uint i;for(i=0;i<8;i++) // 循环8次{MOSI = (dat & 0x80); // dat地最高位输出到MOSI MSB to MOSIdat = (dat << 1); // 从右向左进一位shift next bit into MSB..SCK = 1; // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据Set SCK high..dat |= MISO; //读MISO到 dat 最低位 capture current MISO bitSCK = 0; // SCK置低..then set SCK low again}return(dat); //返回读出地一字节 return read dat}/********************************************************** ******************************************/*函数:uchar SPI_Read(uchar reg)/*功能:NRF24L01地SPI时序-----------从reg寄存器读一字节/********************************************************** ******************************************/uchar SPI_Read(uchar reg){uchar reg_val;CSN = 0; //CSN置低,开始传输数据CSN low, initialize SPI communication...SPI_RW(reg); //选择寄存器 Select register to read from..reg_val = SPI_RW(0); //然后从该寄存器读数据 ..then read registervalueCSN = 1; //CSN拉高,结束数据传输CSN high, terminate SPI communicationreturn(reg_val); //返回寄存器数据 return register value}/********************************************************** ******************************************//*功能:NRF24L01读写寄存器函数/*描述:写数据value到reg寄存器/********************************************************** ******************************************/uint SPI_RW_Reg(uchar reg, uchar value){uchar status;CSN = 0; // CSN置低,开始传输数据CSN low, init SPI transactionstatus = SPI_RW(reg); // 选择寄存器,同时返回状态字select registerSPI_RW(value); // 然后写数据到该寄存器 ..and write value to it..CSN = 1; // CSN拉高,结束数据传输CSN high againreturn(status); // 返回状态寄存器 return nRF24L01 status uchar}/********************************************************** ******************************************//*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据地个数/*描述: 从reg寄存器读出bytes个字节,通常用来读取接收通道数据或接收/发送地址/********************************************************** ******************************************/uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,i;CSN = 0; //CSN置低,开始传输数据 Set CSN low, init SPI tranactionstatus = SPI_RW(reg); //选择寄存器,同时返回状态字Select register to write to and read status uchar for(i=0;i<uchars;i++)pBuf[i] = SPI_RW(0); //逐个字节从nRF24L01读出CSN = 1; //CSN拉高,结束数据传输return(status); //返回状态寄存器return nRF24L01 status uchar}/********************************************************** ***********************************************/*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据地个数/*描述:把pBuf缓存中地数据写入到nRF24L01,通常用来写入发射通道数据或接收/发送地址/********************************************************** ***********************************************/uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,i;CSN = 0; //CSN置低,开始传输数据status = SPI_RW(reg); //选择寄存器,同时返回状态字inerDelay_us(10);for(i=0; i<uchars; i++)SPI_RW(*pBuf++); //逐个字节写入nRF24L01CSN = 1; //CSN拉高,结束数据传输return(status); //返回状态寄存器}/********************************************************** ******************************************//*函数:void SetRX_Mode(void)/*功能:数据接收配置/********************************************************** ******************************************/void SetRX_Mode(void){CE=0;SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);//CRC使能,16位CRC 校验,上电,接收模式CE = 1; // 拉高CE启动接收设备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,激发数据发送}/************************************主函数*********************************************************** */void main(void){unsigned char tf =0;unsigned char TxBuf[20]={0}; // 要发送地数组unsigned char RxBuf[20]={0}; // 接收地数据数组init_NRF24L01() ; //模块初始化led1=1;led2=1;led3 =1;led4 =1; //led 灯关闭Delay(1000);while(1){if(KEY1 ==0 ) //按键 1 按下{TxBuf[1] = 1 ; //赋值tf = 1 ;led1=0; //本地led 灯闪烁led1=1;Delay(200);}if(KEY2 ==0 ) //按键 2 按下{TxBuf[2] =1 ; //赋值tf = 1 ;led2=0; //本地led 灯闪烁Delay(200);led2=1;Delay(200);}if (tf==1) //有键按下{nRF24L01_TxPacket(TxBuf); //发送数据 Transmit Tx buffer dataTxBuf[1] = 0x00; //清零TxBuf[2] = 0x00;tf=0;Delay(1000);}SetRX_Mode(); //设置成接受模式RxBuf[1] = 0x00; //接收地数组相应位清零RxBuf[2] = 0x00;Delay(1000);nRF24L01_RxPacket(RxBuf); //接收数据if(RxBuf[1]|RxBuf[2]){if( RxBuf[1]==1){led3=RxBuf[0];}if( RxBuf[2]==1){led4=RxBuf[4];}Delay(3000); //old is '1000'}RxBuf[1] = 0x00; //清零RxBuf[2] = 0x00;led3=1; //关灯led4=1;}}本程序存在地问题:反应不够灵敏,当在按键1和按键2之间切换地时候,对方地灯闪烁会有一定地延时,另外本程序没有消除按键地抖动.对部分函数地解释:uint SPI_RW(uint dat)最基本地函数,完成 GPIO模拟 SPI 地功能.将输出字节(MOSI)从 MSB 循环输出,同时将输入字节(MISO)从 LSB 循环移入.上升沿读入,下降沿输出. (从 SCK被初始化为低电平可以判断出)uchar SPI_Read(uchar reg); //从reg寄存器读一字节读取寄存器值地函数:基本思路就是通过 READ_REG命令(也就是 0x00+寄存器地址) ,把寄存器中地值读出来.对于函数来说也就是把 reg 寄存器地值读到reg_val 中去.uint SPI_RW_Reg(uchar reg, uchar value); //写数据value到reg寄存器寄存器访问函数:用来设置 24L01 地寄存器地值.基本思路就是通过 WRITE_REG命令(也就是 0x20+寄存器地址)把要设定地值写到相应地寄存器地址里面去,并读取返回值.对于函数来说也就是把 value值写到 reg 寄存器中.需要注意地是,访问 NRF24L01 之前首先要 enable 芯片(CSN=0;) ,访问完了以后再 disable芯片(CSN=1;).uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars); //从reg寄存器读出bytes个字节,通常用来//读取接收通道数据或接收/发送地址接收缓冲区访问函数:主要用来在接收时读取 FIFO 缓冲区中地值.基本思路就是通过READ_REG命令把数据从接收 FIFO(RD_RX_PLOAD)中读出并存到数组里面去.uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars); //把pBuf缓存中地数据写入到nRF24L01,通常//用来写入发发射缓冲区访问函数:主要用来把数组里地数放到发射 FIFO缓冲区中.基本思路就是通过WRITE_REG命令把数据存到发射 FIFO(WR_TX_PLOAD)中去.Tx 模式初始化过程1)写 Tx 节点地地址 TX_ADDR2)写 Rx 节点地地址(主要是为了使能 Auto Ack) RX_ADDR_P0 3)使能 AUTO ACK EN_AA4)使能 PIPE 0 EN_RXADDR5)配置自动重发次数 SETUP_RETR6)选择通信频率 RF_CH7)配置发射参数(低噪放大器增益.发射功率.无线速率) RF_SETUP 8 ) 选择通道0 有效数据宽度 Rx_Pw_P09)配置 24L01 地基本参数以及切换工作模式 CONFIG.Rx 模式初始化过程:初始化步骤 24L01 相关寄存器1)写 Rx 节点地地址 RX_ADDR_P02)使能 AUTO ACK EN_AA3)使能 PIPE 0 EN_RXADDR4)选择通信频率 RF_CH5) 选择通道0 有效数据宽度 Rx_Pw_P06)配置发射参数(低噪放大器增益.发射功率.无线速率) RF_SETUP 7)配置 24L01 地基本参数以及切换工作模式 CONFIG.。

c51单片机基础知识

c51单片机基础知识

C51单片机是一种基于C语言的微控制器,具有强大的处理能力和灵活的编程特性。

以下是一些关于C51单片机的基础知识:
硬件结构:C51单片机采用冯·诺依曼结构,由运算器、控制器、存储器、输入输出设备等组成。

存储器:C51单片机内部有一个程序存储器(Flash ROM)、一个数据存储器(RAM)和一个特殊功能寄存器(SFR)。

程序存储器用于存储程序,数据存储器用于存储变量和临时数据,特殊功能寄存器用于控制各种外设和功能。

指令系统:C51单片机的指令系统类似于C语言,包括算术指令、逻辑指令、数据传输指令、程序控制指令等。

外设:C51单片机有多种外设,如定时器/计数器、串行通信接口、中断控制器、I/O端口等。

这些外设可以通过特殊功能寄存器进行配置和控制。

开发环境:C51单片机的开发环境通常包括编译器、调试器和集成开发环境(IDE)。

编译器将C语言代码转换为单片机可执行的机器码,调试器用于在单片机上进行程序调试和仿真,IDE提供了代码编写、编译、调试和下载的一体化环境。

应用领域:C51单片机广泛应用于各种嵌入式系统,如智能仪表、家电控制、通信设备、工业自动化等领域。

总之,C51单片机是一种功能强大、易于编程的微控制器,通过学习和掌握其基础知识,可以开发出各种高效的嵌入式应用系统。

nrf24l01无线通信模块与51单片机工作原理

nrf24l01无线通信模块与51单片机工作原理

nrf24l01无线通信模块与51单片机工作原理无线通信技术在现代社会中扮演着重要的角色,其中nrf24l01无线通信模块与51单片机也成为了无线通信的重要组成部分。

本文将探讨nrf24l01无线通信模块与51单片机的工作原理,以及它们之间的配合关系。

一、nrf24l01无线通信模块nrf24l01无线通信模块是一种低功耗的2.4GHz无线收发模块,广泛应用于物联网、无线传感器网络等领域。

其工作原理基于射频通信技术,通过无线信道进行数据的传输。

nrf24l01模块由无线收发器和嵌入式射频微控制器组成,具备高速率、长距离传输和多通道选择等特性。

1. 发射端工作原理nrf24l01发射端主要由收发器、天线和控制电路组成。

当51单片机通过SPI总线与nrf24l01通信时,可将要发送的数据通过控制电路和收发器转换成射频信号,并通过天线发送出去。

发送端的工作原理可简述为以下几个步骤:a. 初始化设置:通过配置寄存器进行初始化设置,包括工作频率、数据传输速率、天线增益等参数。

b. 数据准备与发送:将待发送的数据加载到发送缓冲区中,并通过发送指令启动数据的发送。

c. 发送前导码:在发送数据之前,发射端会先发送一段前导码作为同步信号,以确保接收端正确接收数据。

d. 数据传输与重发机制:发送端将数据以数据包的形式传输,接收端在接收到数据后会进行确认应答,发送端根据应答情况决定是否进行重发。

2. 接收端工作原理nrf24l01接收端与发送端相似,主要由收发器、天线和控制电路组成。

当发送端通过射频信号将数据发送过来时,接收端的工作原理如下:a. 初始化设置:与发送端类似,接收端也需要通过配置寄存器进行初始化设置,以匹配发送端的参数。

b. 接收与解码:接收端在接收到射频信号后,对信号进行解码,并将解码后的数据加载到接收缓冲区。

c. 数据处理与应答:通过与51单片机的交互,将接收到的数据进行处理,并向发送端发送确认应答,确保数据的可靠性。

单片机C51教学课件

单片机C51教学课件
中断概念
中断是单片机处理的一种方式,当某个事件发生时,单片机可以暂 时停止当前的工作,转去处理这个事件,处理完后再回到原来的工 作。
中断源
C51单片机有多个中断源,包括定时器溢出、串行通信接收、外部 中断等。
中断处理过程
中断处理过程包括中断请求、中断响应、中断处理和中断返回四个步 骤。
定时器/计数器
总结词:利用单片机C51和温度传感 器,实现温度的实时检测和显示。
详细描述
选择合适的温度传感器,如DS18B20 ,将其连接到C51单片机的IO口。
单片机通过读取温度传感器的数据, 获取当前温度值。
将温度值通过LCD显示屏或者其他显 示设备显示出来。
可根据需要添加报警功能,当温度超 过设定阈值时,触发报警。
易于开发
C51单片机支持多种开发工具 和软件平台,如Keil、SDCC 等,方便开发者进行编程和调
试。
单片机C51的应用领域
01
02
03
工业控制
C51单片机广泛应用于工 业自动化控制系统中,如 电机控制、温度控制等。
智能仪表
C51单片机适用于各种智 能仪表,如智能温度计、 智能流量计等。
通信设备
C51单片机在通信设备领 域也有广泛应用,如无线 通信模块、GPS定位器等 。
单片机C51教学课件
目录
CONTENTS
• 单片机C51简介 • 单片机C51开发环境 • 单片机C51编程语言基础 • 单片机C51编程实践 • 单片机C51进阶知识 • 单片机C51项目实战
01
单片机C51简介
单片机C51的定义
01
单片机C51是指基于Intel 8051内 核的单片机,是一种集成微处理 器、存储器、输入输出接口于一 体的集成电路芯片。

nrf24l01无线通信模块与51单片机工作原理

nrf24l01无线通信模块与51单片机工作原理

nrf24l01无线通信模块与51单片机工作原理
nRF24L01是一款低功耗的2.4GHz无线通信模块,适用于微
控制器和嵌入式系统之间的短距离数据传输。

它可以与51单
片机进行配合使用。

nRF24L01模块包括一个射频发射芯片和一个射频接收芯片。

模块通过SPI接口与51单片机连接。

其工作原理如下:
1. 初始化:首先,51单片机通过SPI接口向nRF24L01模块发送配置命令,包括设置通信频率、通信通道、发射功率等参数。

2. 发送数据:当需要发送数据时,51单片机将待发送的数据
通过SPI接口发送给nRF24L01模块的发送芯片。

发送芯片将
数据转换为无线信号,并通过天线发射出去。

3. 接收数据:当有数据被接收时,nRF24L01模块的接收芯片
会把接收到的数据通过SPI接口传递给51单片机。

单片机再
根据需要对接收到的数据进行处理。

4. 确认和重传:发送芯片在发送数据后会等待接收芯片的确认信号。

如果收到确认信号,发送芯片会继续发送下一个数据包。

如果未收到确认信号,发送芯片会进行多次重传,以确保数据的可靠传输。

5. 通信协议:nRF24L01模块支持多种通信协议,如无线串口、SPI、I2C等。

可以根据需要选择合适的通信协议进行数据传输。

通过上述工作原理,nRF24L01模块可以实现低功耗、短距离的无线数据传输,并与51单片机进行可靠的通信。

它被广泛应用于无线遥控、传感器网络、智能家居等领域。

nrf24l01无线温度传输—51单片机

nrf24l01无线温度传输—51单片机

无线温度传输系统学校:安徽工业大学学院:电气信息学院由于最近要毕业设计了,老师让我做无线通信,然后我上网找了很多资料,决定用24L01做,经过一段时间的摸索,终于实现了24L01的无线温度传输。

以下是我的程序,可供大家参考(当中在贴吧中学到了很多关于24l01的知识)。

发射端程序:#include <reg52.h>#include <intrins.h>//#include "api.h"#define uchar unsigned char#define TX_ADR_WIDTH 5 // 发射地址的字节个数#define TX_PLOAD_WIDTH 2 //发射字节uchar const TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x55,0x10,0x10,0x01};uchar rx_buf[TX_PLOAD_WIDTH];uchar tx_buf[TX_PLOAD_WIDTH];uchar distance_data[2];uchar flag;//标志sbit CE=P1^1; //发射高电平大于10MS 接收高电平sbit CSN=P1^2; //低电平ISP使能sbit SCK=P1^3; //下降沿sbit MOSI=P1^4; //MCU出sbit MISO=P1^5; //MCU入sbit IRQ=P1^6; //中断uchar bdata sta;sbit RX_DR =sta^6; //接收数据准备就绪sbit TX_DS =sta^5; //已发送数据sbit MAX_RT =sta^4;sbit DQ=P3^3;unsigned char time; //设置全局变量,专门用于严格延时//*********************************************NRF24L01*********************** **************//***************************************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 init_io(void){CE=0;CSN=1;SCK=0;}void delay_ms(unsigned int x){unsigned int i,j;for(i=0;i<x;i++){j=108;while(j--);}}uchar SPI_RW(uchar byte)//发送指令,接受状态,返回值为状态值{uchar bit_ctr;for(bit_ctr=0;bit_ctr<8;bit_ctr++){MOSI = (byte&0x80);byte = (byte<<1);SCK = 1;byte|=MISO;SCK=0;}return(byte);}uchar SPI_RW_Reg(uchar reg, uchar value){uchar status;CSN = 0;status = SPI_RW(reg);SPI_RW(value);CSN = 1;return(status);}uchar SPI_Read(uchar reg){uchar reg_val;CSN = 0;SPI_RW(reg); //写指令reg_val = SPI_RW(0); //读reg的内容CSN = 1;return(reg_val);}uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar bytes){uchar status,byte_ctr;CSN = 0;status = SPI_RW(reg);for(byte_ctr=0;byte_ctr<bytes;byte_ctr++)pBuf[byte_ctr] = SPI_RW(0);CSN = 1;return(status);}uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar bytes){uchar status,byte_ctr;CSN = 0;status = SPI_RW(reg);for(byte_ctr=0; byte_ctr<bytes; byte_ctr++)SPI_RW(*pBuf++);CSN = 1;return(status);}void TX_Mode(void){CE=0;SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS/*接收模块的地址*/, TX_ADR_WIDTH/*地址宽度5*/);SPI_Write_Buf(WRITE_REG + RX_ADDR_P0/*通道0 接收数据地址*/, TX_ADDRESS, TX_ADR_WIDTH);SPI_Write_Buf(WR_TX_PLOAD,/*写待发数据指令a0*/ tx_buf, TX_PLOAD_WIDTH/*20*/);SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); //数据通道0应答允许SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); //接收数据通道0允许SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a);//等待500+86us 自动重发10次SPI_RW_Reg(WRITE_REG + RF_CH,40);SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); //数据传输率1Mbps ,发射功率0dBm SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); //配置寄存器CE=1;}void checkflag(){ sta=SPI_Read(STA TUS);//读状态寄存器// if(RX_DR)// {// SPI_Read_Buf(RD_RX_PLOAD/*读取接收数据指令*/,rx_buf/*数组[20]*/,TX_PLOAD_WIDTH/*20*/);// flag=1;// }if(MAX_RT){SPI_RW_Reg(FLUSH_TX/*冲洗发送FIFO指令*/,0);}SPI_RW_Reg(WRITE_REG+STATUS,sta);//清除中断}//以下是DS18B20的操作程序//************************************************************************/ void delay1ms(){unsigned char i,j;for(i=0;i<4;i++)for(j=0;j<33;j++);}/*****************************************************函数功能:延时若干毫秒入口参数:n***************************************************/void delaynms(unsigned char n){unsigned char i;for(i=0;i<n;i++)delay1ms();}/*****************************************************函数功能:将DS18B20传感器初始化,读取应答信号出口参数:flag***************************************************/bit Init_DS18B20(void){bit flag; //储存DS18B20是否存在的标志,flag=0,表示存在;flag=1,表示不存在DQ = 1; //先将数据线拉高for(time=0;time<2;time++) //略微延时约6微秒;DQ = 0; //再将数据线从高拉低,要求保持480~960usfor(time=0;time<200;time++) //略微延时约600微秒; //以向DS18B20发出一持续480~960us的低电平复位脉冲DQ = 1; //释放数据线(将数据线拉高)for(time=0;time<10;time++); //延时约30us(释放总线后需等待15~60us让DS18B20输出存在脉冲)flag=DQ; //让单片机检测是否输出了存在脉冲(DQ=0表示存在)for(time=0;time<200;time++) //延时足够长时间,等待存在脉冲输出完毕;return (flag); //返回检测成功标志}/*****************************************************函数功能:从DS18B20读取一个字节数据出口参数:dat***************************************************/unsigned char ReadOneChar(void){unsigned char i=0;unsigned char dat; //储存读出的一个字节数据for (i=0;i<8;i++){DQ =1; // 先将数据线拉高_nop_(); //等待一个机器周期DQ = 0; //单片机从DS18B20读书据时,将数据线从高拉低即启动读时序_nop_(); //等待一个机器周期DQ = 1; //将数据线"人为"拉高,为单片机检测DS18B20的输出电平作准备for(time=0;time<2;time++); //延时约6us,使主机在15us内采样dat>>=1;if(DQ==1)dat|=0x80; //如果读到的数据是1,则将1存入datelsedat|=0x00;//如果读到的数据是0,则将0存入dat//将单片机检测到的电平信号DQ存入r[i]for(time=0;time<8;time++); //延时3us,两个读时序之间必须有大于1us的恢复期}return(dat); //返回读出的十六进制数据}/*****************************************************函数功能:向DS18B20写入一个字节数据入口参数:dat***************************************************/WriteOneChar(unsigned char dat){unsigned char i=0;for (i=0; i<8; i++){DQ =1; // 先将数据线拉高_nop_(); //等待一个机器周期DQ=0; //将数据线从高拉低时即启动写时序DQ=dat&0x01; //利用与运算取出要写的某位二进制数据,//并将其送到数据线上等待DS18B20采样for(time=0;time<10;time++);//延时约30us,DS18B20在拉低后的约15~60us期间从数据线上采样DQ=1; //释放数据线for(time=0;time<1;time++);//延时3us,两个写时序间至少需要1us的恢复期dat>>=1; //将dat中的各二进制位数据右移1位}for(time=0;time<4;time++); //稍作延时,给硬件一点反应时间}/*****************************************************函数功能:做好读温度的准备***************************************************/void ReadyReadTemp(void){Init_DS18B20(); //将DS18B20初始化WriteOneChar(0xCC); // 跳过读序号列号的操作WriteOneChar(0x44); // 启动温度转换delaynms(150); //转换一次需要延时一段时间Init_DS18B20(); //将DS18B20初始化WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0xBE); //读取温度寄存器,前两个分别是温度的低位和高位}void dwend(void){ uchar TL; //储存暂存器的温度低位uchar TH; //储存暂存器的温度高位TL=ReadOneChar(); //先读的是温度值低位TH=ReadOneChar(); //接着读的是温度值高位distance_data[0]=TH ; //测量结果的高8位distance_data[1]=TL; //放入16位的高8位}void main(void){uchar xx;init_io();while(1){ReadyReadTemp() ;dwend();checkflag();for(xx=0;xx<2;xx++){tx_buf[xx]= distance_data[xx];//发数据之前必须把要发送的数据装入它}TX_Mode(); //必须启动发送模块delay_ms(5);}}接收端程序:#include <reg52.h>#include <intrins.h>#define uchar unsigned charuchar code digit[11]={"0123456789-"}; //定义字符数组显示数字uchar code Str[]={"RICHMCU DS18B20"}; //说明显示的是温度//unsigned char code Error[]={" DS18B20 ERROR"}; //说明没有检测到DS18B20 //unsigned char code Error1[]={" PLEASE CHECK"}; //说明没有检测到DS18B20 uchar code Temp[]={"WENDU:"}; //说明显示的是温度uchar code Cent[]={"Cent"}; //温度单位uchar tm[2];uchar flg=0; //负温度标志和临时暂存变量uchar tltemp;#define TX_ADR_WIDTH 5#define TX_PLOAD_WIDTH 2uchar const TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x55,0x10,0x10,0x01};uchar rx_buf[TX_PLOAD_WIDTH];uchar tx_buf[TX_PLOAD_WIDTH];uchar flag;//标志int cout;sbit CE=P1^1; //发射高电平大于10MS 接收高电平sbit CSN=P1^2; //低电平ISP使能sbit SCK=P1^3; //下降沿sbit MOSI=P1^4; //MCU出sbit MISO=P1^5; //MCU入sbit IRQ=P1^6; //中断uchar bdata sta;sbit RX_DR =sta^6; //接收数据准备就绪sbit TX_DS =sta^5; //已发送数据sbit MAX_RT =sta^4;sbit RS=P2^0; //寄存器选择位,将RS位定义为P2.0引脚sbit RW=P2^1; //读写选择位,将RW位定义为P2.1引脚sbit E=P2^2; //使能信号位,将E位定义为P2.2引脚sbit BF=P0^7; //忙碌标志位,,将BF位定义为P0.7引脚//***************************************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 delay1ms(){unsigned char i,j;for(i=0;i<4;i++)for(j=0;j<33;j++);}/*****************************************************函数功能:延时若干毫秒入口参数:n***************************************************/void delaynms(unsigned char n){unsigned char i;for(i=0;i<n;i++)delay1ms();}bit BusyTest(void){bit result;RS=0; //根据规定,RS为低电平,RW为高电平时,可以读状态RW=1;E=1; //E=1,才允许读写_nop_(); //空操作_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间result=BF; //将忙碌标志电平赋给resultE=0; //将E恢复低电平return result;}/*****************************************************函数功能:将模式设置指令或显示地址写入液晶模块入口参数:dictate***************************************************/void WriteInstruction (unsigned char dictate){while(BusyTest()==1); //如果忙就等待RS=0; //根据规定,RS和R/W同时为低电平时,可以写入指令RW=0;E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,// 就是让E从0到1发生正跳变,所以应先置"0"_nop_();_nop_(); //空操作两个机器周期,给硬件反应时间P0=dictate; //将数据送入P0口,即写入指令或地址_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=1; //E置高电平_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令}/*****************************************************函数功能:指定字符显示的实际地址入口参数:x***************************************************/void WriteAddress(unsigned char x){WriteInstruction(x|0x80); //显示位置的确定方法规定为"80H+地址码x"}/*****************************************************函数功能:将数据(字符的标准ASCII码)写入液晶模块入口参数:y(为字符常量)***************************************************/void WriteData(unsigned char y){while(BusyTest()==1);RS=1; //RS为高电平,RW为低电平时,可以写入数据RW=0;E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,// 就是让E从0到1发生正跳变,所以应先置"0"P0=y; //将数据送入P0口,即将数据写入液晶模块_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=1; //E置高电平_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令}/*****************************************************函数功能:对LCD的显示模式进行初始化设置***************************************************/void LcdInitiate(void){delaynms(15); //延时15ms,首次写指令时应给LCD一段较长的反应时间WriteInstruction(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口delaynms(5); //延时5ms,给硬件一点反应时间WriteInstruction(0x38);delaynms(5); //延时5ms,给硬件一点反应时间WriteInstruction(0x38); //连续三次,确保初始化成功delaynms(5); //延时5ms,给硬件一点反应时间WriteInstruction(0x0c); //显示模式设置:显示开,无光标,光标不闪烁delaynms(5); //延时5ms,给硬件一点反应时间WriteInstruction(0x06); //显示模式设置:光标右移,字符不移delaynms(5); //延时5ms,给硬件一点反应时间WriteInstruction(0x01); //清屏幕指令,将以前的显示内容清除delaynms(5); //延时5ms,给硬件一点反应时间}/*****************************************************函数功能:显示说明信息***************************************************/void display_explain(void){unsigned char i;WriteAddress(0x00); //写显示地址,将在第1行第1列开始显示i = 0; //从第一个字符开始显示while(Str[i] != '\0') //只要没有写到结束标志,就继续写{WriteData(Str[i]); //将字符常量写入LCDi++; //指向下一个字符delaynms(100); //延时100ms较长时间,以看清关于显示的说明}}/*****************************************************函数功能:显示温度符号***************************************************/void display_symbol(void){unsigned char i;WriteAddress(0x40); //写显示地址,将在第2行第1列开始显示i = 0; //从第一个字符开始显示while(Temp[i] != '\0') //只要没有写到结束标志,就继续写{WriteData(Temp[i]); //将字符常量写入LCDi++; //指向下一个字符delaynms(50); //延时1ms给硬件一点反应时间}}/*****************************************************函数功能:显示温度的小数点***************************************************/void display_dot(void){WriteAddress(0x49); //写显示地址,将在第2行第10列开始显示WriteData('.'); //将小数点的字符常量写入LCDdelaynms(50); //延时1ms给硬件一点反应时间}/*****************************************************函数功能:显示温度的单位(Cent)***************************************************/void display_cent(void){unsigned char i;WriteAddress(0x4c); //写显示地址,将在第2行第13列开始显示i = 0; //从第一个字符开始显示while(Cent[i] != '\0') //只要没有写到结束标志,就继续写{WriteData(Cent[i]); //将字符常量写入LCDi++; //指向下一个字符delaynms(50); //延时1ms给硬件一点反应时间}}/*****************************************************函数功能:显示温度的整数部分入口参数:x***************************************************/void display_temp1(uchar x){uchar j,k,l; //j,k,l分别储存温度的百位、十位和个位j=x/100; //取百位k=(x%100)/10; //取十位l=x%10; //取个位WriteAddress(0x46); //写显示地址,将在第2行第7列开始显示if(flg==1) //负温度时显示“—”{WriteData(digit[10]); //将百位数字的字符常量写入LCD}else{WriteData(digit[j]); //将十位数字的字符常量写入LCD}WriteData(digit[k]); //将十位数字的字符常量写入LCDWriteData(digit[l]); //将个位数字的字符常量写入LCDdelaynms(5); //延时1ms给硬件一点反应时间}/*****************************************************函数功能:显示温度的小数数部分入口参数:x***************************************************/void display_temp2(uchar x){WriteAddress(0x4a); //写显示地址,将在第2行第11列开始显示WriteData(digit[x]); //将小数部分的第一位数字字符常量写入LCD delaynms(5); //延时1ms给硬件一点反应时间}void init_io(void){CE=0;CSN=1;SCK=0;}void delay_ms(unsigned int x){unsigned int i,j;for(i=0;i<x;i++){j=108;while(j--);}}uchar SPI_RW(uchar byte){uchar bit_ctr;for(bit_ctr=0;bit_ctr<8;bit_ctr++){MOSI = (byte&0x80);byte = (byte<<1);SCK = 1;byte|=MISO;SCK=0;}return(byte);}uchar SPI_RW_Reg(uchar reg, uchar value){uchar status;CSN = 0;status = SPI_RW(reg);SPI_RW(value);CSN = 1;return(status);}uchar SPI_Read(uchar reg){uchar reg_val;CSN = 0;SPI_RW(reg);reg_val = SPI_RW(0);CSN = 1;return(reg_val);}uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar bytes) {uchar status,byte_ctr;CSN = 0;status = SPI_RW(reg);for(byte_ctr=0;byte_ctr<bytes;byte_ctr++)pBuf[byte_ctr] = SPI_RW(0);CSN = 1;return(status);}uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar bytes) {uchar status,byte_ctr;CSN = 0;status = SPI_RW(reg);for(byte_ctr=0; byte_ctr<bytes; byte_ctr++)SPI_RW(*pBuf++);CSN = 1;return(status);}void RX_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); //数据通道0应答允许SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);//接收数据通道0允许SPI_RW_Reg(WRITE_REG + RF_CH, 40);SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH);// 接收频道0 接收数据长度设置SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); //数据传输率1Mbps ,发射功率0dBm SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); //配置寄存器CE = 1;}void checkflag(){sta=SPI_Read(STA TUS);if(RX_DR){SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);flag=1;}if(MAX_RT){SPI_RW_Reg(FLUSH_TX,0);}SPI_RW_Reg(WRITE_REG+STATUS,sta);}void yejinchu(void){LcdInitiate(); //将液晶初始化delaynms(5); //延时5ms给硬件一点反应时间display_explain();display_symbol(); //显示温度说明display_dot(); //显示温度的小数点display_cent(); //显示温度的单位}void xianshi(void){uchar TL; //储存暂存器的温度低位uchar TH; //储存暂存器的温度高位uchar TN; //储存温度的整数部分uchar TD; //储存温度的小数部分TH=tm[0] ;TL=tm[1];if((TH&0xf8)!=0x00)//判断高五位得到温度正负标志{flg=1;TL=~TL; //取反TH=~TH; //取反tltemp=TL+1; //低位加1TL=tltemp;if(tltemp>255) TH++; //如果低8位大于255,向高8位进1TN=TH*16+TL/16; //实际温度值=(TH*256+TL)/16,即:TH*16+TL/16//这样得出的是温度的整数部分,小数部分被丢弃了TD=(TL%16)*10/16; //计算温度的小数部分,将余数乘以10再除以16取整,}TN=TH*16+TL/16; //实际温度值=(TH*256+TL)/16,即:TH*16+TL/16//这样得出的是温度的整数部分,小数部分被丢弃了TD=(TL%16)*10/16; //计算温度的小数部分,将余数乘以10再除以16取整,//这样得到的是温度小数部分的第一位数字(保留1位小数)display_temp1(TN); //显示温度的整数部分display_temp2(TD); //显示温度的小数部分delaynms(5);}void main(void){uchar xx;yejinchu();init_io();RX_Mode();while(1){checkflag();if(flag){flag=0;for(xx=0;xx<2;xx++){tm[xx]=rx_buf[xx];delay_ms(1);}xianshi();}}}。

基于51单片机与nRF24L01无线门禁控制系统设计

基于51单片机与nRF24L01无线门禁控制系统设计

基于51单片机与nRF24L01无线门禁控制系统设计1. 本文概述本文旨在探讨基于51单片机与nRF24L01无线门禁控制系统的设计。

随着科技的快速发展和智能化趋势的加强,门禁控制系统作为保障场所安全的重要手段,其设计与实现变得尤为重要。

传统的门禁系统多采用有线连接方式,布线复杂、成本较高且灵活性不足。

本文提出了一种基于51单片机与nRF24L01无线模块的门禁控制系统设计,旨在实现门禁系统的无线化、智能化和便捷化。

本文将首先介绍51单片机和nRF24L01无线模块的基本原理和特点,为后续的设计工作提供理论基础。

随后,将详细阐述系统的硬件设计,包括无线模块的选型、电路设计以及门禁控制器的实现等。

在此基础上,本文将进一步探讨软件设计的关键问题,包括无线通信协议的制定、门禁控制算法的实现以及用户界面的设计等。

通过本文的研究,旨在设计并实现一个稳定可靠、易于扩展的无线门禁控制系统,为各类场所提供高效便捷的门禁管理解决方案。

同时,本文的研究结果将为相关领域的研究人员提供有益的参考和借鉴,推动无线门禁控制技术的进一步发展。

2. 系统设计原理51单片机,作为一种经典的微控制器,其核心是基于Intel的8051架构。

它具备基本的输入输出控制能力,定时器计数器,中断系统以及一定的内存管理功能。

在本系统中,51单片机扮演着中央处理单元(CPU)的角色,负责接收传感器数据,处理输入信号,并根据预设的逻辑控制输出设备,如无线通信模块和门禁机构。

nRF24L01是一款高性能的无线传输模块,基于Nordic Semiconductor的 NRF24L01 芯片。

它工作在4GHz的ISM频段,支持点对点、点对多点的通信模式。

nRF24L01模块具有自动应答和自动重发功能,确保数据传输的可靠性。

在本系统中,nRF24L01用于无线传输门禁控制信号,包括身份验证数据和控制指令。

系统设计将51单片机和nRF24L01无线模块整合,形成一个高效、可靠的无线门禁控制系统。

单片机C51课件

单片机C51课件

单片机C51课件一、引言单片机作为现代电子技术领域的重要组成部分,在众多领域都有着广泛的应用。

C51 作为一种常用的单片机编程语言,对于初学者来说,掌握其基础知识和编程技巧至关重要。

本课件将系统地介绍单片机C51 的相关内容,帮助您逐步建立起对单片机编程的认识和理解。

二、单片机概述(一)单片机的定义与特点单片机是一种将中央处理器(CPU)、存储器、输入输出接口等集成在一块芯片上的微型计算机。

它具有体积小、成本低、可靠性高、易于开发等特点,广泛应用于工业控制、智能仪器仪表、家用电器等领域。

(二)单片机的发展历程从早期的 4 位、8 位单片机,到如今的 16 位、32 位单片机,其性能不断提升,功能也越来越强大。

三、C51 编程语言基础(一)C51 程序的结构一个完整的 C51 程序通常包括预处理指令、全局变量声明、函数声明和定义等部分。

其基本结构如下:```cinclude <reg51h> //包含头文件void main()//主函数{//程序主体}void function_name()//自定义函数{//函数体}```(二)数据类型C51 支持多种数据类型,如整型(int)、字符型(char)、浮点型(float)等。

不同的数据类型在存储空间和取值范围上有所不同。

(三)运算符与表达式包括算术运算符(+、、、/、%)、关系运算符(>、<、==、!=)、逻辑运算符(&&、||、!)等。

(四)控制语句1、顺序结构:程序按照语句的先后顺序依次执行。

2、选择结构:通过 ifelse 语句、switch 语句实现程序的分支选择。

3、循环结构:for 循环、while 循环、dowhile 循环用于重复执行一段代码。

四、单片机的硬件资源(一)中央处理器(CPU)负责执行程序指令和进行数据运算。

(二)存储器包括程序存储器(ROM)和数据存储器(RAM)。

(三)输入输出接口如并行 I/O 口(P0 P3)、串行通信接口等。

nrf24l01无线通信模块与51单片机工作原理 -回复

nrf24l01无线通信模块与51单片机工作原理 -回复

nrf24l01无线通信模块与51单片机工作原理-回复nRF24L01无线通信模块与51单片机工作原理引言:随着物联网的快速发展,无线通信技术在各个领域中的应用越来越广泛。

而在无线通信领域中,nRF24L01无线通信模块和51单片机成为了常见的组合。

本文将详细介绍nRF24L01和51单片机的工作原理及其之间的通信过程。

第一部分:nRF24L01无线通信模块的工作原理nRF24L01是一款低功耗的单片机无线通信模块,广泛应用于无线传感器网络、智能家居等领域。

其工作原理可以分为硬件和软件两个方面。

硬件方面,nRF24L01模块由射频前端及基带部分两个主要部分组成。

射频前端部分包括射频收发器和RF增益模块,用于接收和发送射频信号。

基带部分包含SPI接口、调制解调器和数据缓存区,用于控制数据的传输及处理。

软件方面,nRF24L01模块的工作需要通过使用专用的库函数进行驱动。

这些库函数可以在编程环境中调用,以实现nRF24L01模块的相应功能。

软件通过SPI接口与模块进行通信,并通过设置寄存器、发送命令和接收状态等方式控制模块的工作。

第二部分:51单片机的工作原理51单片机,全称为AT89C51,是一种典型的8051架构的单片机。

在无线通信系统中,51单片机通常作为主控芯片,通过与nRF24L01模块进行交互,实现与其他设备的无线通信。

51单片机的工作原理主要包括四个方面:时钟与计时、IO口控制、中断系统和串行通信。

时钟与计时:51单片机内部由一个双字节的定时器/计数器组成,用于提供计时和延时功能。

通过设置计时器的时钟源和分频系数,可以实现不同频率和精度的计时与延时。

IO口控制:51单片机的IO口主要用于与其他设备进行数据交互。

通过设置相应的寄存器,可以控制IO口的输入输出、上拉电阻和工作模式等。

中断系统:51单片机内部集成了中断控制器,可以通过设置中断优先级和中断源等参数,实现对不同事件的响应。

在无线通信系统中,可以通过中断来处理接收数据、发送完成等事件。

基于51单片机与nRF24L01无线门禁控制系统设计

基于51单片机与nRF24L01无线门禁控制系统设计

Vo l _ 2 7 No .1
F e b . 2 0 1 3
d o i : 1 0 . 3 9 6 9 / j . i s s n . 1 6 7 3— 4 8 0 7 . 2 0 1 3 . 0 1 . 0 1 5
基于 5 1单 片机 与 n R F 2 4 L 0 1无 线 门禁 控 制 系统 设 计
环 境 下 的 多种 小 型 场 所 .
关键 词 : 5 1 单片机 ; n R F 2 4 k 0 1 ; 发送端 ; 接收端 ; 控制信号 中图分类号 : T P 3 9 1 . 4 文献标志码 :A 文章编号 :1 6 7 3— 4 8 0 7 ( 2 0 1 3 ) 叭 一 0 0 6 4— 0 6
De s i g n o f wi r e l e s s d o o r g u ar d c o nt r o l s y s t e m ba s e d o n 5 1 M CU a nd n 啦 4L01
Z h a n g Yo n g h o n g ,Ca o J i a n,W a n g L i h u a
t r o l s i g n a l s a n d c o n t r o l s t h e d o o r — g ua r d s y s t e m. Th e r e s u l t o f ma n y d i f f e r e n t e n v i r o n me n t g r o u p i n g t e s t s s h o ws t ha t t h e s y s t e m i s o f l o w c o s t ,g o o d r e a l — t i me p e r f o r ma n c e,hi g h s e c u r i t y,g o o d s e la a b i l i t y a nd i s s ui t a b l e or f a

NRF24L01无线串口开发板程序详解

NRF24L01无线串口开发板程序详解

1.源程序开发环境建立1.1程序编译软件编译软件用keil C51,打开安装文件,一路点击下一步即可完成。

1.2程序下载软件使用STC ISP下载软件。

2.源程序文件整体结构工程中,只有一个main.c文件,所有程序都写在这个文件里面。

Reg51.h是包含的头文件。

是不是非常简单!3.源程序执行流程无线数据处理程序:串口数据处理程序:4.串口配置函数void serial_open(void){SCON = 0X50;AUXR |= 0X04;TL2 = 0Xc0; // 9600TH2 = 0Xfd;AUXR|=0X10;}此串口配置函数,利用单片机内部的定时器2作为波特率发生器。

共用到4个寄存器:SCON AUXR TL2 TH2SM0和SM1的位决定串口工作的4种方式:程序中,SCON=0X50,即SM0=0 SM1=1,即串口工作在“方式1”;REN=1,允许串口接收数据。

TL2和TH2是定时器2的高位和低位寄存器。

程序中,首先AUXR|=0X40,最后AUXR|=0X10。

即首先把T2x12置1,然后把T2R置1。

即首先把定时器2设置为1T模式,然后把定时器打开。

5.串口发送数据函数void senddata(uchar data_buf){SBUF = data_buf;while(!TI);TI = 0;}用到了寄存器SBUF和寄存器SCON中的TI位。

SBUF寄存器是串口收发数据缓存寄存器,放到这个寄存器中的数据,会通过串口发送出去,接收到的串口数据,也会放到这个寄存器中。

也就是串口接收和发送都是使用这个寄存器。

程序中,SBUF=data_buf,就是把data_buf给了SBUF,单片机自动把SBUF里面的数据发送到串口。

TI是串口发送数据完成标志位,当串口发送完一个数据,此位置1,置位后,需要通过软件清0。

所以通过while(!TI),来检测TI位,达到检测串口是否发送完数据的目的。

C51单片机的结构及原理

C51单片机的结构及原理

编程实例:LED闪烁
LED=0xFF; //LED全亮 delay(1000); //延时
编程实例:LED闪烁
} } ```
编程实例:按键控制LED
目的
通过按键控制LED的亮灭。
实现方法
使用单片机的IO口检测按键状态,根据按键状态控制LED的亮灭。
编程实例:按键控制LED
代码示例 ```c
sbit KEY = P2^0; //定义按键接口
首先检查电源是否正常,确保电源电压稳定 且符合单片机的工作电压范围。其次检查复 位电路是否正常,复位电路中的电容和电阻 值是否正确,以及复位引脚是否连接正确。 最后检查晶振电路是否正常,晶振是否起振, 以及晶振引脚是否连接正确。
程序无法烧录问题排查
总结词
单片机无法正常接收和存储程序,可能是由于编程器与单片机连接不良、编程器驱动程 序未安装、单片机选型不正确等引起的。
感谢您的观看
中断系统
中断系统是C51单片机中用于 实现实时处理和多任务管理的
功能模块。
中断系统能够响应外部事件 或者异常情况,并中断当前 执行的程序,转而执行相应
的中断服务程序。
中断系统包括中断控制器和多 个可编程中断源,可以通过软
件配置和控制。
03 C51单片机工作原理
指令系统与寻址方式
指令系统
C51单片机采用精简指令集结构,包 含一系列基本指令,如算术运算、逻 辑运算、数据传输等。
数据传输方式
01
内部数据传输
C51单片机内部寄存器之间进行 数据传输,通过直接读写寄存器 实现。
02
03
外部数据传输
数据格式
C51单片机与外部设备或存储器 进行数据传输,通过串行或并行 通信接口实现。

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

C51单片机基础知识

C51单片机基础知识

C51单片机基础知识单片机是指一种在单个芯片上集成了微处理器、存储器和其他外围设备的计算机系统。

C51单片机是一种常用的单片机系列,由英特尔公司推出。

它具有广泛的应用领域,比如嵌入式系统、自动控制和电子产品等。

本文将介绍C51单片机的基础知识,包括架构、指令集、I/O口、中断等方面内容。

1. 架构C51单片机的架构采用哈佛结构,即程序存储器和数据存储器分离。

程序存储器用于存储程序指令,数据存储器则用于存储数据和变量。

C51单片机的典型架构包括存储器、中央处理器、时钟和I/O接口等组成部分。

2. 指令集C51单片机的指令集采用专用指令,能够高效地执行各种任务。

指令集包括数据传送指令、算术运算指令、逻辑运算指令、控制指令等。

通过合理利用指令集,可以实现各种功能。

3. I/O口C51单片机包含多个可编程I/O口,用于与其他外部设备进行数据交互。

每个I/O口可配置为输入或输出模式。

通过编程设置,可以实现单片机与外部设备的数据输入和输出。

4. 中断C51单片机支持中断功能,能够在特定条件下中断当前的程序执行,响应其他优先级更高的任务。

中断可以提高系统的实时性和响应能力。

C51单片机包含多个中断源,可以通过编程设置中断优先级和中断向量表等。

5. 定时器/计数器C51单片机内置了多个定时器/计数器,用于生成定时和计数功能。

定时器可以用于精确控制时间间隔,计数器可以用于计数外部事件的次数。

通过编程设置,可以灵活地利用定时器和计数器实现各种应用需求。

6. 串口通信C51单片机支持串口通信,可以与其他设备进行数据的收发。

通过串口通信,可以实现单片机与计算机的数据交换,或者与其他外部设备的连接。

7. 软件开发针对C51单片机的软件开发,常用的编程语言为C语言和汇编语言。

C语言具有高级抽象特性,能够更容易地实现复杂的功能。

汇编语言则更加底层,可以直接操作硬件资源。

总结C51单片机是一种常用的单片机系列,具有广泛的应用领域。

NRF24L01单片机的应用和程序

NRF24L01单片机的应用和程序

3.1.4 电源电路单片机STC89C51芯片的第40脚为正电源引脚VCC,外接+5V电压。

第20脚为接地引脚GND。

本设计里与PC连接的单片机采用USB供电,同时nRF24L01芯片采用3.3V电压供电。

电路设计如图3-4。

图3-4 电源电路3.3 NRF24L01无线模块3.3.1 NRF24L01芯片概述NRF24L01 是一款工作在2.4~2.5GHz 世界通用ISM 频段的单片无线收发器芯片。

无线收发器包括:频率发生器、增强型SchockBurstTM 模式控制器、功率放大器、晶体振荡器、调制器、解调器、输出功率。

频道选择和协议的设置可以通过SPI 接口进行设置。

极低的电流消耗,当工作在发射模式下发射功率为-6dBm 时电流消耗为9.0mA,接收模式时为12.3mA 。

掉电模式和待机模式下电流消耗更低。

NRF24L01主要特性如下[12][13]:(1)真正的GFSK 单收发芯片(2)内置链路层(3)增强型ShockBurstTM(4)自动应答及自动重发功能(5)地址及CRC 检验功能(6)数据传输率1 或2Mbps(7)SPI 接口数据速率0~8Mbps(8)125个可选工作频道(9)很短的频道切换时间可用于跳频(10)极低的晶振要求60ppm(11)工作电压1.9~3.6V3.3.2芯片结构NRF24L01内置地址解码器、先入先出堆栈区、解调处理器、时钟处理器、GFSK 滤波器、低噪声放大器、频率合成器、功率放大器等功能模块。

需要很少的外围元件,因此使用起来非常方便。

QFN24引脚封装,外形尺寸只有5×5mm。

NRF24L01的功能模块[14]如图3-6所示。

图3-6 NRF24L01的芯片结构3.3.3引脚功能及描述NRF24L01的封装及引脚排列如图3-7所示。

各引脚功能如下:图3-7 NRF24L01的封装及引脚排各引脚功能说明如表3-1所示。

表3-1 各引脚功能引脚名称引脚功能描述1 CE 数字输入RX 或TX 模式选择2 CSN 数字输入SPI 片选信号3 SCK 数字输入SPI 时钟4 MOSI 数字输入从SPI 数据输入脚5 MISO 数字输出从SPI 数据输出脚6 IRQ 数字输出可屏蔽中断脚7 VDD 电源电源+3V8 VSS 电源接地0V9 XC2 模拟输出晶体震荡器2 脚10 XC1 模拟输入晶体震荡器1 脚/外部时钟输入脚11 VDD_PA 电源输出给RF 的功率放大器提供的+1.8V电源12 ANT1 天线天线接口113 ANT2 天线天线接口214 VSS 电源接地0V15 VDD 电源电源+3V16 IREF 模拟输入参考电流17 VSS 电源接地0V18 VDD 电源电源+3V19 DVDD 电源输出去耦电路电源正极端20 VSS 电源接地0V3.3.4 NRF24L01模块原理图NRF24L01单端匹配网络:晶振,偏置电阻,去耦电容。

单片机c51原理及应用

单片机c51原理及应用

单片机c51原理及应用单片机C51是一种常见的8位微控制器,它采用哈佛架构,由英特尔公司推出。

C51广泛应用于各种嵌入式系统中,具有体积小、功耗低、可编程性强等特点,因此在工业控制、通信、家电、汽车电子等领域有广泛的应用。

单片机C51的原理是基于哈佛架构的,即指令和数据存储在不同的存储体中。

具体来说,C51中的指令存储器称为代码存储器,用于存储程序的指令;数据存储器则用于存储程序中的数据、变量等。

C51一般包含一个中央处理器、存储器、I/O接口和定时器/计数器等功能模块。

C51的应用非常广泛,下面分别介绍其在工业控制、通信、家电和汽车电子领域的应用。

1. 工业控制:C51可用于工业自动化控制系统中。

通过与传感器、执行器等外部设备的连接,C51能够实时监测工业过程的状态,并根据需求来控制执行器的动作。

例如,在自动化流水线上,C51可根据传感器检测到的物料情况来控制传送带的速度和方向。

2. 通信:C51可以用于通信系统中。

通过串口通信模块,C51可以与其他设备进行数据交换。

例如,C51可以实现与计算机的通信,将采集到的数据发送给计算机进行处理;也可以实现与无线通信模块的通信,用于无线数据传输。

3. 家电:C51可以应用于各种家电产品中,如电视、空调、洗衣机等。

通过与传感器和控制器的连接,C51可以实现家电的自动控制和智能化。

例如,C51可以根据温度传感器采集到的数据自动调整空调的工作模式和温度设置,以达到更加舒适的室内环境。

4. 汽车电子:C51也广泛应用于汽车电子领域。

通过与汽车各种传感器和执行器的连接,C51可以实现对汽车的电子控制。

例如,C51可以与车速传感器和制动控制器连接,实现车辆的智能制动系统;也可以与发动机控制器连接,实现发动机的自动控制和故障检测。

除了上述应用领域,C51还可以应用于医疗设备、农业自动化、安防系统等多个领域。

总之,单片机C51由于其体积小、功耗低、可编程性强等特点,在各个领域都有广泛的应用前景。

NRF24L01的C51单片机讲解

NRF24L01的C51单片机讲解

NRF24L01的C51单片机讲解#include#include/************************************************************** ********* ****************//* NRF24L01 的管脚定义,以及在本程序中的应用,VCC接3.3V 电源,可以通过5V用电压转换芯片/*得到,NC 管脚可以接可以不接,暂时没用途。

本程序应用于51或者52单片机,是两个模块进行通讯/*成功的简单指示,现象是:模块1的 KEY1 对应模块1的LED1 和模块2的LED3 ,模块1的 KEY2 对应模/*块1的LED2 和模块2的LED4,发过来也对应。

/************************************************************** ********* ****************/typedef unsigned char uchar;typedef unsigned char uint;/************************************NRF24L01端口定义***********************************/=P1^3;sbit MOSI =P1^2;sbit SCK =P1^1;sbit CSN =P1^0;sbit IRQ =P3^2; //数字输入(可屏蔽中断)/************************************按键***********************************************/sbit KEY1=P2^7;//按键S1sbit KEY2=P2^2;//按键S2/************************************数码管位选******************************************/sbit led1=P1^0; //LED0sbit led2=P1^1; //LED1sbit led3 =P1^2; //LED2sbit led4 =P1^3; //LED3sbit led5 =P1^4; //LED4/*********************************************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 20 // 20 uints TX payload#define RX_PLOAD_WIDTH 20 // 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 // 读取接收数据指令读RX 有效数据#define WR_TX_PLOAD 0xA0 // 写待发数据指令写TX 有效数据#define FLUSH_TX 0xE1 // 冲洗发送 FIFO指令//清除TX FIFO 寄存器应用于发射模式下#define FLUSH_RX 0xE2 // 冲洗接收 FIFO指令//清除RX FIFO 寄存器应用于接收模式下#define REUSE_TX_PL 0xE3 // 定义重复装载数据指令//重新使用上一包有效数据#define NOP 0xFF // 保留/*************************************SPI(nRF24L01)寄存器地址***********************/#define CONFIG 0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式#define EN_AA 0x01 // 自动应答功能设置//使能自动应答功能//此功能禁止后可与nRF2401 通讯#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接收数据地址数据通道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栈入栈出状态寄存器设置//FIFO 状态寄存器/*************************************函数声明****************************************/void Delay(unsigned int s); //大延时void inerDelay_us(unsigned char n); //小延时void init_NRF24L01(void); //NRF24L01 初始化uint SPI_RW(uint dat); //根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01读出一字节uchar SPI_Read(uchar reg); //从reg寄存器读一字节void SetRX_Mode(void); //数据接收配置uint SPI_RW_Reg(uchar reg, uchar value); //写数据value到reg 寄存器uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars); //从reg寄存器读出bytes个字节,通常用来//读取接收通道数据或接收/发送地址uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars); //把pBuf缓存中的数据写入到nRF24L01,通常用来写入发//射通道数据或接收/发送地址unsigned char nRF24L01_RxPacket(unsigned char* rx_buf); //数据读取后放入rx_buf接收缓冲区中void nRF24L01_TxPacket(unsigned char * tx_buf); //发送tx_buf中数据/*****************************************长延时*****************************************/void Delay(unsigned int s){unsigned int i;for(i=0; i<="" p="">for(i=0; i<="" p="">}/************************************************************** ********* *******************/uint bdata sta; //状态标志sbit RX_DR =sta^6; //RX_DR 为 sta 的第六位sbit TX_DS =sta^5; //TX_DS 为 sta 的第五位sbit MAX_RT =sta^4; //MAX_RT 为 sta 的第四位/************************************************************** ********* *******************//*延时函数/************************************************************** ********* *******************/void inerDelay_us(unsigned char n) //延时,us 级{for(;n>0;n--)_nop_();}/************************************************************** ********* *****************//*NRF24L01初始化/************************************************************** ********* ****************/void init_NRF24L01(void){inerDelay_us(100);CE=0; // 芯片使能CSN=1; // 禁止 SPISCK=0; // 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); // 频道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,发射功率为最大值0dB}/************************************************************** ********* *****************************//*函数:uint SPI_RW(uint uchar)/*功能:NRF24L01的SPI写时序-----根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01 读出一字节/****************************要读/写的是最低字节的高位*************************************************************** ********* /uint SPI_ReadWrite(uint dat){uint i;for(i=0;i<8;i++) // 循环8次{MOSI = (dat & 0x80); // dat的最高位输出到MOSI MSB to MOSIdat = (dat << 1); // 从右向左进一位 shift next bit into MSB..SCK = 1; // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据 Set SCK high..dat |= MISO; //读MISO到 dat 最低位 capture current MISO bitSCK = 0; // SCK置低 ..then set SCK low again}return(dat); //返回读出的一字节 return read dat}/************************************************************** ********* *****************************/*函数:uchar SPI_Read_byte(uchar reg)/*功能:NRF24L01的SPI时序-----------从reg寄存器读一字节/************************************************************** ********* *****************************/uchar SPI_Read (uchar reg){uchar reg_val;CSN = 0; //CSN置低,开始传输数据CSN low, initialize SPI communication...SPI_RW(reg); //选择寄存器 Select register to read from..reg_val = SPI_RW(0); //然后从该寄存器读数据//#define READ_REG 0x00 // 读寄存器指令CSN = 1; //CSN拉高,结束数据传return(reg_val); //返回寄存器数据 return register value }/************************************************************** ********* *****************************//* uint SPI_Write_byte(uchar reg, uchar value)/*功能:NRF24L01读写寄存器函数/*描述:写数据value到reg寄存器/*********************************************************************** *****************************/uint SPI_RW_Reg(uchar reg, uchar value){uchar status;CSN = 0; // CSN置低,开始传输数据CSN low, init SPI transactionstatus = SPI_RW(reg); // 选择寄存器,同时返回状态字select register SPI_RW(value); // 然后写数据到该寄存器 ..and write value to it..CSN = 1; // CSN拉高,结束数据传输 CSN high againreturn(status); // 返回状态寄存器return nRF24L01 status uchar}/************************************************************** ********* *****************************//*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数/*描述: 从reg寄存器读出bytes个字节,通常用来读取接收通道数据或接收/发送地址/************************************************************** ********* *****************************/uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,i;CSN = 0; //CSN置低,开始传输数据Set CSN low, init SPI tranactionstatus = SPI_RW(reg); //选择寄存器,同时返回状态字Select register to write to and read status ucharfor(i=0;i<uchars;i++)< bdsfid="285" p=""></uchars;i++)<> pBuf[i] = SPI_RW(0); //逐个字节从nRF24L01读出CSN = 1; //CSN拉高,结束数据传输return(status); //返回状态寄存器 return nRF24L01 status uchar }/************************************************************** ********* **********************************/*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数/*描述:把pBuf缓存中的数据写入到nRF24L01,通常用来写入发射通道数据或接收/发送地址/************************************************************** ********* **********************************/uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,i;CSN = 0; //CSN置低,开始传输数据status = SPI_RW(reg); //选择寄存器,同时返回状态字inerDelay_us(10);for(i=0; i<="" p="">SPI_RW(*pBuf++); //逐个字节写入nRF24L01CSN = 1; //CSN拉高,结束数据传输return(status); //返回状态寄存器}/************************************************************** ********* *****************************//*函数:void SetRX_Mode(void)/*功能:数据接收配置/************************************************************** ********* *****************************/void SetRX_Mode(void){CE=0;//待机模式SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);//CRC使能,16位CRC校验,上电,接收模式CE = 1; // 拉高CE启动接收设备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); // 读取状态寄存其来判断数据接收状况//#define STATUS 0x07 // 状态寄存器if(RX_DR) // 判断是否接收到数据{ ////RX_DR 为 sta 的第六位当接收到有效数据后置一CE = 0; //SPI使能SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO buffer//#define RD_RX_PLOAD 0x61 // 读取接收数据指令///////////////////////////#define TX_PLOAD_WIDTH 20revale =1; //读取数据完成标志SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT 都置高为1,通过写1来清楚中断标志#define WRITE_REG 0x20// 写寄存器指令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); // 装载接收端地址 //#define RX_ADDR_P0 0x0A // 频道0接收数据地址数据通道0 接收地址// uint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址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 main(void)unsigned char tf =0;unsigned char TxBuf[20]={0}; // 要发送的数组unsigned char RxBuf[20]={0}; // 接收的数据数组init_NRF24L01() ; //模块初始化led1=1;led2=1;led3 =1;led4 =1; //led 灯关闭Delay(1000);while(1){if(KEY1 ==0 ) //按键 1 按下{TxBuf[1] = 1 ; //赋值tf = 1 ;led1=0; //本地led 灯闪烁Delay(200);led1=1;Delay(200);}if(KEY2 ==0 ) //按键 2 按下{TxBuf[2] =1 ; //赋值tf = 1 ;led2=0; //本地led 灯闪烁Delay(200);led2=1;Delay(200);}if (tf==1) //有键按下{nRF24L01_TxPacket(TxBuf); //发送数据Transmit Tx bufferdataTxBuf[1] = 0x00; //清零TxBuf[2] = 0x00;tf=0;Delay(1000);}SetRX_Mode(); //设置成接受模式RxBuf[1] = 0x00; //接收的数组相应位清零RxBuf[2] = 0x00;Delay(1000);nRF24L01_RxPacket(RxBuf); //接收数据if(RxBuf[1]|RxBuf[2]){if( RxBuf[1]==1){led3=RxBuf[0];}if( RxBuf[2]==1){led4=RxBuf[4];}Delay(3000); //old is '1000'}RxBuf[1] = 0x00; //清零RxBuf[2] = 0x00;led3=1; //关灯led4=1;}}本程序存在的问题:反应不够灵敏,当在按键1和按键2之间切换的时候,对方的灯闪烁会有一定的延时,另外本程序没有消除按键的抖动。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

#include <reg52.h>#include <intrins.h>/*********************************************************************** ****************//* NRF24L01 的管脚定义,以及在本程序中的应用,VCC接3.3V电源,可以通过5V用电压转换芯片/*得到,NC 管脚可以接可以不接,暂时没用途。

本程序应用于51或者52单片机,是两个模块进行通讯/*成功的简单指示,现象是:模块1的 KEY1 对应模块1的LED1 和模块2的LED3 ,模块1的 KEY2 对应模/*块1的LED2 和模块2的LED4,发过来也对应。

/*********************************************************************** ****************/typedef unsigned char uchar;typedef unsigned char uint;/************************************NRF24L01端口定义***********************************/=P1^3;sbit MOSI =P1^2;sbit SCK =P1^1;sbit CSN =P1^0;sbit IRQ =P3^2; //数字输入(可屏蔽中断)/************************************按键***********************************************/sbit KEY1=P2^7;//按键S1sbit KEY2=P2^2;//按键S2/************************************数码管位选******************************************/sbit led1=P1^0; //LED0sbit led2=P1^1; //LED1sbit led3 =P1^2; //LED2sbit led4 =P1^3; //LED3sbit led5 =P1^4; //LED4/*********************************************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 20 // 20 uints TX payload#define RX_PLOAD_WIDTH 20 // 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 // 读取接收数据指令读RX 有效数据#define WR_TX_PLOAD 0xA0 // 写待发数据指令写TX 有效数据#define FLUSH_TX 0xE1 // 冲洗发送 FIFO指令//清除TX FIFO 寄存器应用于发射模式下#define FLUSH_RX 0xE2 // 冲洗接收 FIFO指令//清除RX FIFO 寄存器应用于接收模式下#define REUSE_TX_PL 0xE3 // 定义重复装载数据指令//重新使用上一包有效数据#define NOP 0xFF // 保留/*************************************SPI(nRF24L01)寄存器地址***********************/#define CONFIG 0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式#define EN_AA 0x01 // 自动应答功能设置//使能自动应答功能//此功能禁止后可与nRF2401 通讯#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接收数据地址数据通道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栈入栈出状态寄存器设置//FIFO 状态寄存器/*************************************函数声明****************************************/void Delay(unsigned int s); //大延时void inerDelay_us(unsigned char n); //小延时void init_NRF24L01(void); //NRF24L01 初始化uint SPI_RW(uint dat); //根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01读出一字节uchar SPI_Read(uchar reg); //从reg寄存器读一字节void SetRX_Mode(void); //数据接收配置uint SPI_RW_Reg(uchar reg, uchar value); //写数据value到reg 寄存器uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars); //从reg寄存器读出bytes个字节,通常用来//读取接收通道数据或接收/发送地址uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars); //把pBuf缓存中的数据写入到nRF24L01,通常用来写入发//射通道数据或接收/发送地址unsigned char nRF24L01_RxPacket(unsigned char* rx_buf); //数据读取后放入rx_buf接收缓冲区中void nRF24L01_TxPacket(unsigned char * tx_buf); //发送 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; //RX_DR 为 sta 的第六位sbit TX_DS =sta^5; //TX_DS 为 sta 的第五位sbit MAX_RT =sta^4; //MAX_RT 为 sta 的第四位/*********************************************************************** *******************//*延时函数/*********************************************************************** *******************/void inerDelay_us(unsigned char n) //延时,us 级{for(;n>0;n--)_nop_();}/*********************************************************************** *****************//*NRF24L01初始化/*********************************************************************** ****************/void init_NRF24L01(void){inerDelay_us(100);CE=0; // 芯片使能CSN=1; // 禁止 SPISCK=0; // 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); // 频道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,发射功率为最大值0dB}/*********************************************************************** *****************************//*函数:uint SPI_RW(uint uchar)/*功能:NRF24L01的SPI写时序-----根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01 读出一字节/****************************要读/写的是最低字节的高位************************************************************************ /uint SPI_ReadWrite(uint dat){uint i;for(i=0;i<8;i++) // 循环8次{MOSI = (dat & 0x80); // dat的最高位输出到MOSI MSB to MOSIdat = (dat << 1); // 从右向左进一位 shift next bit into MSB..SCK = 1; // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据 Set SCK high..dat |= MISO; //读MISO到 dat 最低位 capture current MISO bitSCK = 0; // SCK置低 ..then set SCK low again}return(dat); //返回读出的一字节 return read dat}/*********************************************************************** *****************************/*函数:uchar SPI_Read_byte(uchar reg)/*功能:NRF24L01的SPI时序-----------从reg寄存器读一字节/*********************************************************************** *****************************/uchar SPI_Read (uchar reg){uchar reg_val;CSN = 0; //CSN置低,开始传输数据 CSN low, initialize SPI communication...SPI_RW(reg); //选择寄存器 Select register to read from..reg_val = SPI_RW(0); //然后从该寄存器读数据//#define READ_REG 0x00 // 读寄存器指令CSN = 1; //CSN拉高,结束数据传return(reg_val); //返回寄存器数据 return register value }/*********************************************************************** *****************************//* uint SPI_Write_byte(uchar reg, uchar value)/*功能:NRF24L01读写寄存器函数/*描述:写数据value到reg寄存器/*********************************************************************** *****************************/uint SPI_RW_Reg(uchar reg, uchar value){uchar status;CSN = 0; // CSN置低,开始传输数据 CSN low, init SPI transactionstatus = SPI_RW(reg); // 选择寄存器,同时返回状态字 select register SPI_RW(value); // 然后写数据到该寄存器 ..and write value to it..CSN = 1; // CSN拉高,结束数据传输 CSN high againreturn(status); // 返回状态寄存器 return nRF24L01 status uchar}/*********************************************************************** *****************************//*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数/*描述: 从reg寄存器读出bytes个字节,通常用来读取接收通道数据或接收/发送地址/*********************************************************************** *****************************/uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,i;CSN = 0; //CSN置低,开始传输数据 Set CSN low, init SPI tranactionstatus = SPI_RW(reg); //选择寄存器,同时返回状态字 Select register to write to and read status ucharfor(i=0;i<uchars;i++)pBuf[i] = SPI_RW(0); //逐个字节从nRF24L01读出CSN = 1; //CSN拉高,结束数据传输return(status); //返回状态寄存器 return nRF24L01 status uchar}/*********************************************************************** **********************************/*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数/*描述:把pBuf缓存中的数据写入到nRF24L01,通常用来写入发射通道数据或接收/发送地址/*********************************************************************** **********************************/uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,i;CSN = 0; //CSN置低,开始传输数据status = SPI_RW(reg); //选择寄存器,同时返回状态字inerDelay_us(10);for(i=0; i<uchars; i++)SPI_RW(*pBuf++); //逐个字节写入nRF24L01CSN = 1; //CSN拉高,结束数据传输return(status); //返回状态寄存器}/*********************************************************************** *****************************//*函数:void SetRX_Mode(void)/*功能:数据接收配置/*********************************************************************** *****************************/void SetRX_Mode(void){CE=0;//待机模式SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);//CRC使能,16位CRC校验,上电,接收模式CE = 1; // 拉高CE启动接收设备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); // 读取状态寄存其来判断数据接收状况//#define STATUS 0x07 // 状态寄存器if(RX_DR) // 判断是否接收到数据{ ////RX_DR 为 sta 的第六位当接收到有效数据后置一CE = 0; //SPI使能SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO buffer//#define RD_RX_PLOAD 0x61 // 读取接收数据指令///////////////////////////#define TX_PLOAD_WIDTH 20revale =1; //读取数据完成标志}SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT 都置高为1,通过写1来清楚中断标志 #define WRITE_REG 0x20// 写寄存器指令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); // 装载接收端地址 //#define RX_ADDR_P0 0x0A // 频道0接收数据地址数据通道0 接收地址// uint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址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 main(void){unsigned char tf =0;unsigned char TxBuf[20]={0}; // 要发送的数组unsigned char RxBuf[20]={0}; // 接收的数据数组init_NRF24L01() ; //模块初始化led1=1;led2=1;led3 =1;led4 =1; //led 灯关闭Delay(1000);while(1){if(KEY1 ==0 ) //按键 1 按下{TxBuf[1] = 1 ; //赋值tf = 1 ;led1=0; //本地led 灯闪烁Delay(200);led1=1;Delay(200);}if(KEY2 ==0 ) //按键 2 按下{TxBuf[2] =1 ; //赋值tf = 1 ;led2=0; //本地led 灯闪烁Delay(200);led2=1;Delay(200);}if (tf==1) //有键按下{nRF24L01_TxPacket(TxBuf); //发送数据 Transmit Tx buffer dataTxBuf[1] = 0x00; //清零TxBuf[2] = 0x00;tf=0;Delay(1000);}SetRX_Mode(); //设置成接受模式RxBuf[1] = 0x00; //接收的数组相应位清零RxBuf[2] = 0x00;Delay(1000);nRF24L01_RxPacket(RxBuf); //接收数据if(RxBuf[1]|RxBuf[2]){if( RxBuf[1]==1){led3=RxBuf[0];}if( RxBuf[2]==1){led4=RxBuf[4];}Delay(3000); //old is '1000'}RxBuf[1] = 0x00; //清零RxBuf[2] = 0x00;led3=1; //关灯led4=1;}}本程序存在的问题:反应不够灵敏,当在按键1和按键2之间切换的时候,对方的灯闪烁会有一定的延时,另外本程序没有消除按键的抖动。

相关文档
最新文档