基于NRF24L01的校园智能路灯初步粗略设计方案Word文件下载.docx
《基于NRF24L01的校园智能路灯初步粗略设计方案Word文件下载.docx》由会员分享,可在线阅读,更多相关《基于NRF24L01的校园智能路灯初步粗略设计方案Word文件下载.docx(21页珍藏版)》请在冰豆网上搜索。
8.IRQ7.MISO
6.MOSI5.SCK
4.CSN3.CE
2.VCC1.GND
具体说明:
3.CE芯片的模式控制线。
在CSN为低的情况下,CE协同NRF24L01的CONFIG寄存器共同决定NRF24L01的状态(参照NRF24L01的状态机)。
4.CSN为芯片的片选线CSN为低电平芯片工作
5.SCK为芯片控制的时钟线(SPI时钟)
6.MOSI为芯片控制数据线(Masteroutputslaveinput)主输出从输入
7.MISO芯片控制数据线(Masterinputslaveoutput)主输入从输出
8.IRQ中断信号引脚。
中断时变为低电平,即NRF24L01内部发生中断时IRQ引脚从高电平变为低电平。
引脚会在以下三种情况变低:
TxFIFO发完并且收到ACK(使能ACK情况下)、RxFIFO收到数据、达到最大重发次数。
中断:
nRF24L01的中断引脚(IRQ)为低电平触发,当状态寄存器中TX_DS(数据发送完成中断位)、RX_DR(接收数据中断位)或MAX_RT(达到最多次重发中断位)为高时触发中断。
当MCU给中断源写‘1’时,中断引脚被禁止。
可屏蔽中断可以被IRQ中断屏蔽。
通过设置可屏蔽中断位为高,则中断响应被禁止。
默认状态下所有的中断源是被禁止的。
系统结构框图如下所示
五.设计原理
NRF24L01工作原理
发射数据时,首先将nRF24L01配置为发射模式:
接着把接收节点地址TX_ADDR和有效数据TX_PLD按照时序由SPI口写入nRF24L01缓存区,TX_PLD必须在CSN为低时连续写入,而TX_ADDR在发射时写入一次即可,然后CE置为高电平并保持至少10μs,延迟130μs后发射数据;
若自动应答开启,那么nRF24L01在发射数据后立即进入接收模式,接收应答信号(自动应答接收地址应该与接收节点地址TX_ADDR一致)。
如果收到应答,则认为此次通信成功,TX_DS置高,同时TX_PLD从TX
FIFO中清除;
若未收到应答,则自动重新发射该数据(自动重发已开启),若重发次数(ARC)达到上限,MAX_RT置高,TX
FIFO中数据保留以便在次重发;
MAX_RT或TX_DS置高时,使IRQ变低,产生中断,通知MCU。
最后发射成功时,若CE为低则nRF24L01进入空闲模式1;
若发送堆栈中有数据且CE为高,则进入下一次发射;
若发送堆栈中无数据且CE为高,则进入空闲模式2。
接收数据时,首先将nRF24L01配置为接收模式,接着延迟130μs进入接收状态等待数据的到来。
当接收方检测到有效的地址和CRC时,就将数据包存储在RX
FIFO中,同时中断标志位RX_DR置高,IRQ变低,产生中断,通知MCU去取数据。
若此时自动应答开启,接收方则同时进入发射状态回传应答信号。
最后接收成功时,若CE变低,则nRF24L01进入空闲模式1。
在写寄存器之前一定要进入待机模式或掉电模式。
如下图,给出SPI操作及时序图:
图2.4SPI读操作
SPI口为同步串行通信接口,最大传输速率为10Mb/s,传输时先传送低位字节,再传送高位字节。
但针对单个字节而言,要先送高位再送低位。
与SPI相关的指令共有8个,使用时这些控制指令由nRF24L01的MOSI输入。
相应的状态和数据信息是从MISO输出给MCU。
nRF24L0l所有的配置字都由配置寄存器定义,这些配置寄存器可通过SPI口访问。
nRF24L01的配置寄存器共有25个,常用的配置寄存器如表2所示。
表2:
常用配置寄存器
地址(H)
寄存器名称
功能
00
CONFIG
设置24L01工作模式
01
EN_AA
设置接收通道及自动应答
02
EN_RXADDR
使能接收通道地址
03
SETUP_AW
设置地址宽度
04
SETUP_RETR
设置自动重发数据时间和次数
07
STATUS
状态寄存器,用来判定工作状态
0A~0F
RX_ADDR_P0~P5
设置接收通道地址
10
TX_ADDR
设置接收接点地址
11~16
RX_PW_P0~P5
设置接收通道的有效数据宽度
六.硬件电路图
(1).NRF24L01原理图
(2).光敏电阻模块原理图
(3).硬件电路连接图
七.程序源码及分析
(1).主机程序
主机程序主要实现
当三个从机中在时间触发的情况下进行AD采集带电压并且返回给主机,主机进行错误判断
一号路灯出现问题时候,主机会通过串口向PC段发送数据,主机端监视助手会进行判断,对应的相应的灯会出现亮灭以及闪烁状态。
以达到提醒维修人员及时检查维修路灯。
程序部分如下所示
//错误检测
NRF_RX_Mode();
printf("
Receivemode\r\n"
);
if(NRF_Rx_Dat(rxbuf)==RX_DR)
;
else
{
接收失败\r\n"
}
//第一个路灯出现问题
if(rxbuf[0]==JC1[0]&
&
rxbuf[1]==JC1[1]&
rxbuf[2]==JC1[2])
bz1=1;
USART_SendData(USART1,0x01);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
delay_ms(10);
出错请检查路灯\r\n"
memcpy(rxbuf,"
"
12);
%d\r\n"
rxbuf[0]);
rxbuf[1]);
rxbuf[2]);
//第二个路灯出现问题
elseif(rxbuf[0]==JC2[0]&
rxbuf[1]==JC2[1]&
rxbuf[2]==JC2[2])
bz2=1;
USART_SendData(USART1,0x02);
//第三个路灯出现问题
elseif(rxbuf[0]==JC3[0]&
rxbuf[1]==JC3[1]&
rxbuf[2]==JC3[2])
bz3=1;
USART_SendData(USART1,0x03);
//路灯一和路灯二出现问题
elseif(bz1&
bz2==1)
USART_SendData(USART1,0x04);
bz1=0;
bz2=0;
//路灯二和路灯三出现问题
elseif(bz2&
bz3==1)
USART_SendData(USART1,0x05);
bz3=0;
//路灯一和路灯三出现问题
USART_SendData(USART1,0x06);
//路灯一.路灯二.路灯三出现问题
bz2&
USART_SendData(USART1,0x07);
if(rxbuf[0]==JN1[0]&
rxbuf[1]==JN1[1]&
rxbuf[2]==JN1[2])
key1=1;
if(rxbuf[0]==JN2[0]&
rxbuf[1]==JN2[1]&
rxbuf[2]==JN2[2])
key2=1;
if(rxbuf[0]==JN3[0]&
rxbuf[1]==JN3[1]&
rxbuf[2]==JN3[2])
key3=1;
if(key1&
key2&
key3==1)
USART_SendData(USART1,0x08);
key1=0;
key2=0;
key3=0;
GPIO_SetBits(GPIOB,GPIO_Pin_5);
delay_ms(1000);
/*
*函数名:
SPI_NRF_Init
*描述:
SPI的I/O配置
*输入:
无
*输出:
*调用:
外部调用
*/
voidSPI_NRF_Init(void)
SPI_InitTypeDefSPI_InitStructure;
GPIO_InitTypeDefGPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);
//使能PB,G端口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
//PORTB时钟使能
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
//SPI2时钟使能
/*配置SPI_NRF_SPI的SCK,MISO,MOSI引脚*/
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
//复用功能
GPIO_Init(GPIOB,&
GPIO_InitStructure);
/*配置SPI_NRF_SPI的CE引脚和SPI_NRF_SPI的CSN引脚:
NSS*/
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7|GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(GPIOG,&
/*配置SPI_NRF_SPI的IRQ引脚*/
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
//上拉输入
/*这是自定义的宏,用于拉高csn引脚,NRF进入空闲状态*/
NRF_CSN_HIGH();
SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;
//双线全双工
SPI_InitStructure.SPI_Mode=SPI_Mode_Master;
//主模式
SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b;
//数据大小8位
SPI_InitStructure.SPI_CPOL=SPI_CPOL_Low;
//时钟极性,空闲时为低
SPI_InitStructure.SPI_CPHA=SPI_CPHA_1Edge;
//第1个边沿有效,上升沿为采样时刻
SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;
//NSS信号由软件产生
SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_8;
//8分频,9MHz
SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB;
//高位在前
SPI_InitStructure.SPI_CRCPolynomial=7;
SPI_Init(SPI2,&
SPI_InitStructure);
/*EnableSPI1*/
SPI_Cmd(SPI2,ENABLE);
NRF_RX_Mode
配置并进入接收模式
无
voidNRF_RX_Mode(void)
NRF_CE_LOW();
SPI_NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH);
//写RX节点地址
SPI_NRF_WriteReg(NRF_WRITE_REG+EN_AA,0x01);
//使能通道0的自动应答
SPI_NRF_WriteReg(NRF_WRITE_REG+EN_RXADDR,0x01);
//使能通道0的接收地址
SPI_NRF_WriteReg(NRF_WRITE_REG+RF_CH,CHANAL);
//设置RF通信频率
SPI_NRF_WriteReg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);
//选择通道0的有效数据宽度
SPI_NRF_WriteReg(NRF_WRITE_REG+RF_SETUP,0x0f);
//设置TX发射参数,0db增益,2Mbps,低噪声增益开启
SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG,0x0f);
//配置基本工作模式的参数;
PWR_UP,EN_CRC,16BIT_CRC,接收模式
/*CE拉高,进入接收模式*/
NRF_CE_HIGH();
}
NRF_TX_Mode
配置发送模式
voidNRF_TX_Mode(void)
{
SPI_NRF_WriteBuf(NRF_WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH);
//写TX节点地址SPI_NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH);
//设置TX节点地址,主要为了使能ACK
//使能通道0的接收地址
SPI_NRF_WriteReg(NRF_WRITE_REG+SETUP_RETR,0x1a);
//设置自动重发间隔时间:
500us+86us;
最大自动重发次数:
10次
//设置RF通道为CHANAL
SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG,0x0e);
PWR_UP,EN_CRC,16BIT_CRC,发射模式,开启所有中断
/*CE拉高,进入发送模式*/
delay_ms(20);
//CE要拉高一段时间才进入发送模式
此处主要设置ADC的初始化,负责电压采集初始
voidADC_Configuration(void)
ADC_InitTypeDefADC_InitStructure;
ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode=DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel=1;
ADC_Init(ADC1,&
ADC_InitStructure);
ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_239Cycles5);
ADC_Cmd(ADC1,ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
(2).从机一程序源码
从机一程序即为路灯一控制程序
主要实现功能是:
通过RTC时钟的触发和光敏电阻模块同时触发来触发不同时间的路灯的工作状态。
当通过AD电压检测,检测到路灯处于断路状态时,会触发射频模块向主机发送错误报警数据,及时在主机PC端显示‘
程序如下所示
adcx=Lsens_Get_Val();
adcx);
//持续轮询自动检测控制通过光敏电阻
//高峰期开启普通模式
//并且向主机返回数据4,5,6
if(adcx<
56&
calendar.hour==18&
calendar.min==0&
calendar.sec==0)
//普通模式
GPIO_ResetBits(GPIOF,GPIO_Pin_11);
GPIO_ResetBits(GPIOF,GPIO_Pin_12);
GPIO_ResetBits(GPIOF,GPIO_Pin_13);
ad=JC11_Get_Val();
ad12=JC12_Get_Val();
ad13=JC13_Get_Val();
mix11=3.3/4095*ad;
mix12=3.3/4095*ad12;
mix13=3.3/4095*ad13;
delay_ms(600);
ad=%f\r\n"
3.3/4095*ad);
//实际电压值
3.3/4095*ad12);
3.3/4095*ad13);
/