完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
2.4G无线通信实验
2.4G无线通信一般是通过两个设备进行通信,最高速率可达到2Mbps,抗干扰能力强。一般的可以进行1对6的通信,一般是1个接收,6个发送。 一、模块简介 本次2.4G通信使用的是NRF24L01,如图所示 CE:模式控制线。在 CSN为低的 情况下,CE 协同CONFIG 寄存器 共同决定NRF24L01 的状态(参照 NRF24L01 的状态机) CSN:SPI片选线 SCK:SPI时钟线 MOSI:SPI数据线(主机输出,从机输入) MISO:SPI数据线(主机输入,从机输出) IRQ:中断信号线。中断时变为低电平,在以下三种情况变低:Tx FIFO 发完并且收到ACK(使能ACK情况下)、Rx FIFO 收到数据、达到最大重发次数。 空闲状态SCK为0,CPOL=0;数据在时钟第一个时间边沿采集,CPHA=0; Cn:SPI命令位 Sn:STATUS寄存器位 Dn:数据位( MSB,多字节传输时,低字节在前) 其中,收发模式又有: Enhanced ShockBurstTM收发模式和ShockBurstTM收发模式,只有Enhanced ShockBurstTM收发模式支持自动ACK和自动重发。开启自动ACK,则默认选择Enhanced模式。一般的都是用的 Enhanced ShockBurstTM收发模式。 PS:在接收数据时,自动把字头和CRC校验码移去。在发送数据时,自动加上字头和CRC校验码,在发送模式下,置CE为高,至少10us,将使能发送过程。也就是发送模式时,PWR_UP由高变低时,需要有个至少10us的延时。 二、Enhanced ShockBurstTM模式介绍 Enhanced ShockBurst TM 模式:发送方要求终端设备在接收到数据后有应答信号,以便发送方检测有无数据丢失,一旦丢失则重发数据。重发数据设置在地址为 0X04 的数据重发设置寄存器 用于设置其重发次数及设置在未收到应答信号后等待重发的时间。 在接收模式下,最多可以接收6路不通的数据。每一个数据通道使用不同的地址,但是共用相同的频道。也就是说6 个不同的NRF24L01 设置为发送模式后可以与同一个设置为接收模式的NRF24L01 进行通讯,而设置为接收模式的NRF24L01可以对这6 个发射端进行识别。数据通道0 是唯一的一个可以配置为40 位自身地址的数据通道。1~5 数据通道都为8 位自身地址和32 位公用地址(由通道1设置)。所有的数据通道都可以设置为Enhanced ShockBurst 模式。 在接收端,确认收到数据后记录地址,并以此地址为目标地址发送应答信号。 在发送端,通道0被用作接收应答信号,因此通道0的接收地址要与发送地址端地址相等,以确保接收到正确的应答信号。 PS:通道0的地址不能更改,通道1-5的地址只有最后两位能进行更改。 三. 编程 1.初始化IO口 //初始化24L01的IO口 void NRF24L01_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_SetBits(GPIOC,GPIO_Pin_4); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; //上拉输入 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_SetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4); SPI1_Init(); //初始化SPI SPI_Cmd(SPI1, DISABLE); // SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //选择了串行时钟的稳态:时钟悬空低电平 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //数据捕获于第一个时钟沿 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始 SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式 SPI_Init(SPI1, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器 NRF24L01_CE=0; //使能24L01 NRF24L01_CSN=1; //SPI片选取消 } 注意:NRF24L01与W25Q64和SD卡共用SPI1,注意要分时复用!! 2.Enhanced ShockBurstTM发送流程
//启动NRF24L01发送一次数据 //txbuf:待发送数据首地址 //返回值:发送完成状况 u8 NRF24L01_TxPacket(u8 *txbuf) { u8 sta; SPI1_SetSpeed(SPI_BaudRatePrescaler_8);//spi速度为9Mhz(24L01的最大SPI时钟为10Mhz) NRF24L01_CE=0; NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//写数据到TX BUF 32个字节 NRF24L01_CE=1;//启动发送 while(NRF24L01_IRQ!=0);//等待发送完成 sta=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值 NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志 if(sta&MAX_TX)//达到最大重发次数 { NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器 return MAX_TX; } if(sta&TX_OK)//发送完成 { return TX_OK; } return 0xff;//其他原因发送失败 } 3.Enhanced ShockBurstTM发送模式初始化 1)写Tx 节点的地址 TX_ADDR 2)写Rx 节点的地址(主要是为了使能Auto Ack) RX_ADDR_P0 3)使能AUTO ACK EN_AA 4)使能PIPE 0 EN_RXADDR 5)配置自动重发次数 SETUP_RETR 6)选择通信频率 RF_CH 7)配置发射参数(低噪放大器增益、发射功率、无线速率) RF_SETUP 8)配置24L01 的基本参数以及切换工作模式 CONFIG。 //该函数初始化NRF24L01到TX模式 //设置TX地址,写TX数据宽度,设置RX自动应答的地址,填充TX发送数据,选择RF频道,波特率和LNA HCURR //PWR_UP,CRC使能 //当CE变高后,即进入RX模式,并可以接收数据了 //CE为高大于10us,则启动发送. void NRF24L01_TX_Mode(void) { NRF24L01_CE=0; NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址 NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); //使能通道0的自动应答 NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址 NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次 NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40); //设置RF通道为40 NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启 NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断 NRF24L01_CE=1;//CE为高,10us后启动发送 } 4.Enhanced ShockBurstTM接收流程
//启动NRF24L01发送一次数据 //txbuf:待发送数据首地址 //返回值:0,接收完成;其他,错误代码 u8 NRF24L01_RxPacket(u8 *rxbuf) { u8 sta; SPI1_SetSpeed(SPI_BaudRatePrescaler_8); //spi速度为9Mhz(24L01的最大SPI时钟为10Mhz) sta=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值 NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志 if(sta&RX_OK)//接收到数据 { NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据 NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器 return 0; } return 1;//没收到任何数据 } 5.Enhanced ShockBurstTM接收模式初始化 1)写Rx 节点的地址 RX_ADDR_P0 2)使能AUTO ACK EN_AA 3)使能PIPE 0 EN_RXADDR 4)选择通信频率 RF_CH 5)选择通道0 有效数据宽度 RX_PW_P0 6)配置发射参数(低噪放大器增益、发射功率、无线速率) RF_SETUP 7)配置24L01 的基本参数以及切换工作模式 CONFIG。 //该函数初始化NRF24L01到RX模式 //设置RX地址,写RX数据宽度,选择RF频道,波特率和LNA HCURR //当CE变高后,即进入RX模式,并可以接收数据了 void NRF24L01_RX_Mode(void) { NRF24L01_CE=0; NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址 NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); //使能通道0的自动应答 NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址 NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40); //设置RF通信频率 NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度 NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启 NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式 NRF24L01_CE = 1; //CE为高,进入接收模式 } 6.读函数 //读取SPI寄存器值 //reg:要读的寄存器 u8 NRF24L01_Read_Reg(u8 reg) { u8 reg_val; NRF24L01_CSN = 0; //使能SPI传输 SPI1_ReadWriteByte(reg); //发送寄存器号 reg_val=SPI1_ReadWriteByte(0XFF);//读取寄存器内容 NRF24L01_CSN = 1; //禁止SPI传输 return(reg_val); //返回状态值 } //在指定位置读出指定长度的数据 //reg:寄存器(位置) //*pBuf:数据指针 //len:数据长度 //返回值,此次读到的状态寄存器值 u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len) { u8 status,u8_ctr; NRF24L01_CSN = 0; //使能SPI传输 status=SPI1_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值 for(u8_ctr=0;u8_ctr return status; //返回读到的状态值 } 7.写函数 //SPI写寄存器 //reg:指定寄存器地址 //value:写入的值 u8 NRF24L01_Write_Reg(u8 reg,u8 value) { u8 status; NRF24L01_CSN=0; //使能SPI传输 status =SPI1_ReadWriteByte(reg);//发送寄存器号 SPI1_ReadWriteByte(value); //写入寄存器的值 NRF24L01_CSN=1; //禁止SPI传输 return(status); //返回状态值 } //在指定位置写指定长度的数据 //reg:寄存器(位置) //*pBuf:数据指针 //len:数据长度 //返回值,此次读到的状态寄存器值 u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len) { u8 status,u8_ctr; NRF24L01_CSN = 0; //使能SPI传输 status = SPI1_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值 for(u8_ctr=0; u8_ctr return status; //返回读到的状态值 } |
|
|
|
8.主函数
#include "led.h" #include "delay.h" #include "sys.h" #include "usart.h" #include "lcd.h" #include "key.h" #include "spi.h" #include "24l01.h" //ALIENTEK Mini STM32开发板范例代码24 //无线通信实验 //技术支持:www.openedv.com //广州市星翼电子科技有限公司 int main(void) { u8 key,mode; u16 t=0; u8 tmp_buf[33]; delay_init(); //延时函数初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2 uart_init(9600); //串口初始化为9600 LED_Init(); //初始化与LED连接的硬件接口 LCD_Init(); //初始化LCD KEY_Init(); //按键初始化 NRF24L01_Init(); //初始化NRF24L01 POINT_COLOR=RED;//设置字体为红色 LCD_ShowString(60,50,200,16,16,"Mini STM32"); LCD_ShowString(60,70,200,16,16,"NRF24L01 TEST"); LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK"); LCD_ShowString(60,110,200,16,16,"2014/3/12"); while(NRF24L01_Check()) //检查NRF24L01是否在位. { LCD_ShowString(60,130,200,16,16,"NRF24L01 Error"); delay_ms(200); LCD_Fill(60,130,239,130+16,WHITE); delay_ms(200); } LCD_ShowString(60,130,200,16,16,"NRF24L01 OK"); while(1)//在该部分确定进入哪个模式! { key=KEY_Scan(0); if(key==KEY0_PRES) { mode=0; break; }else if(key==KEY1_PRES) { mode=1; break; } t++; if(t==100)LCD_ShowString(10,150,230,16,16,"KEY0:RX_Mode KEY1:TX_Mode"); //闪烁显示提示信息 if(t==200) { LCD_Fill(10,150,230,150+16,WHITE); t=0; } delay_ms(5); } LCD_Fill(10,150,240,166,WHITE);//清空上面的显示 POINT_COLOR=BLUE;//设置字体为蓝色 if(mode==0)//RX模式 { LCD_ShowString(60,150,200,16,16,"NRF24L01 RX_Mode"); LCD_ShowString(60,170,200,16,16,"Received DATA:"); NRF24L01_RX_Mode(); while(1) { if(NRF24L01_RxPacket(tmp_buf)==0)//一旦接收到信息,则显示出来. { tmp_buf[32]=0;//加入字符串结束符 LCD_ShowString(0,190,239,32,16,tmp_buf); }else delay_us(100); t++; if(t==10000)//大约1s钟改变一次状态 { t=0; LED0=!LED0; } }; }else//TX模式 { LCD_ShowString(60,150,200,16,16,"NRF24L01 TX_Mode"); NRF24L01_TX_Mode(); mode=' ';//从空格键开始 while(1) { if(NRF24L01_TxPacket(tmp_buf)==TX_OK) { LCD_ShowString(60,170,239,32,16,"Sended DATA:"); LCD_ShowString(0,190,239,32,16,tmp_buf); key=mode; for(t=0;t<32;t++) { key++; if(key>('~'))key=' '; tmp_buf[t]=key; } mode++; if(mode>'~')mode=' '; tmp_buf[32]=0;//加入结束符 }else { LCD_ShowString(60,170,239,32,16,"Send Failed "); LCD_Fill(0,188,240,218,WHITE);//清空上面的显示 }; LED0=!LED0; delay_ms(1500); }; } } 总结 总的来说,2.4G无线通信的原理和其他通信原理大同小异,基本就是几大步骤:发信息,收信息,读信息,写信息。然后2.4G无线通信还加了一个模式选择,一般选择是Enhanced ShockBurstTM这个模式,这个模式可以支持自动ACK和自动重发。然后,博主的代码是对于stm32mini板的程序,1-7步骤主要是对2.4G通信的初始化,要注意的是NRF24L01与W25Q64和SD卡共用SPI1,注意要分时复用。然后8就是主函数,能实现的功能就是通过按键0和按键1,来控制是接受模式还是发送模式,然后就进行发送或者接受。如果为发送模式,发送的是32个ASCLL码,从空格开始,一直到~。对于2.4G通信博主也只是初了解,这个程序也是从别处白嫖过来的,如有错误,请指正。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1771 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1619 浏览 1 评论
1070 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
724 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1673 浏览 2 评论
1935浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
728浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
567浏览 3评论
593浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
551浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 09:37 , Processed in 0.960415 second(s), Total 78, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号