完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
注意:1.本实验不是利用传统意义上的多通道实现的
一、功能方案与分析 实验内容 使用 STM32F407 开发板、NRF2401 WIFI 模块,完成以下内容:
实验功能简介:开机的时候先检测 NRF24L01 模块是否存在,在检测到 NRF24L01 模块之后,根据 KEY0 和 KEY1 的设置来决定模块的工作模式,在设定好工作模式之后,就会发送/接收数据,可以通过 KEY0 和 KEY1 完成模式切换。 所要用到的硬件资源如下:
这里 NRF24L01 也是使用的 SPI1,和 W25Q128 共用一个 SPI 接口,所以在使用的时候,他们分时复用 SPI1 。本章我们需要把 W25Q128 的片选信号置高,以防止这个器件对NRF24L01的通信造成干扰。另外, NRF_IRQ 和 RS485_RE 共用了 PG8 ,所以,他们不能同时使用,不过我们一般用不到 NRF_IRQ 这个信号,因此, RS485 和 NRF 一般也可以同时使用。 功能流程图 模块的配置 利用 USB 转 NRF24L01 上位机对模块进行配置。 其实没什么用,到时候用单片机,配置代码全在单片机中,其中还有一个很奇怪的现象,用上位机或者AT指令改完配置之后,把NRF24L01模块插入另一个转换器中,用AT指令显示配置会发现配置变成了另外一个。 二、代码实现 模块检测 u8 NRF24L01_Check(void) { u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5}; u8 i; SPI1_SetSpeed(SPI_SPEED_8); NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,buf,5); NRF24L01_Read_Buf(TX_ADDR,buf,5); for(i=0;i<5;i++)if(buf!=0XA5)break; if(i!=5)return 1; return 0; } 模块检测的原理为:在模块的寄存器上写入数据,然后再将数据读取出来,若读取的数据与原理相同,则表明,模块存在且功能正常。 按键相关 void EXTI3_IRQHandler(void) { delay_ms(10); if(KEY1==0) { delay_ms(2000); if(KEY1==0){ printf("进入发送2模式n"); mode=2; } else {printf("进入发送1模式n");mode=1;} } EXTI->PR=1<<3; } void EXTI4_IRQHandler(void) { delay_ms(10); if(KEY0==0) { delay_ms(10); if(KEY0==0) { printf("进入接收模式n"); mode=3; } } EXTI->PR=1<<4; } void EXTIX_Init(void) { KEY_Init(); Ex_NVIC_Config(GPIO_E,3,FTIR); Ex_NVIC_Config(GPIO_E,4,FTIR); MY_NVIC_Init(2,2,EXTI3_IRQn,2); MY_NVIC_Init(2,2,EXTI4_IRQn,2); } 长短按键的实现主要是依靠外部中断。利用延迟函数,判断按键前后的状态来实现 key1 的长按和短按。利用全局变量 mode 获取按键按下后得到的值,然后将 mode 传到主函数,进入相应的模式。 if(KEY_Scan(0)==1||KEY_Scan(0)==0){break;} 在主函数中的相关模式下加入如上代码,可以实现当前模式结束,判断按键,进入下一个模式,实现利用 key1 和 key0 完成模式转换操作。前提是将key.c中无键值返回改为除0和1以外的其他数。 对于 key1和 key2的切换不太好用,也许在主函数整体加个while(1)会比较好。 定时器相关 TIM3_Int_Init(10000-1,8400-1); void TIM3_IRQHandler(void) { if(TIM3->SR&0X0001) { time++; } TIM3->SR&=~(1<<0); } 利用公式可以求出现在计时器为1秒。利用while循环,time 每增大1就过去1秒,到达一定数值后利用break函数跳出循环,这样就能实现相应的功能。 发送模式1(key1短按) LCD_Fill(0,170,lcddev.width,170+16*3,WHITE); LCD_ShowString(30,150,200,16,16,"NRF24L01 TX_Mode1"); NRF24L01_TX_Mode(); while(1) { adcx=Lsens_Get_Val(); bon[0]=adcx/10; bon[1]=adcx%10; bon[2]=37; if(NRF24L01_TxPacket(tmp_buf)==TX_OK) { LCD_ShowString(30,170,239,32,16,"Sended DATA:(LSENS_VAL)"); LCD_ShowString(30,190,55,16,16,tmp_buf); LCD_DrawLine(47, 205, 56, 191); LCD_Draw_Circle(50,192,2); LCD_Draw_Circle(54,202,2); tmp_buf[0]=bon[0]+48; tmp_buf[1]=bon[1]+48; for(t=3;t<32;t++) { tmp_buf[t]=' '; } tmp_buf[31]=3; tmp_buf[32]=0; }else { LCD_Fill(0,170,lcddev.width,170+16*3,WHITE); LCD_ShowString(30,170,lcddev.width-1,32,16,"Send Failed "); }; while(1) { if(time>=1){time=0;break;} } if(KEY_Scan(0)==1||KEY_Scan(0)==0){break;} } 首先是LCD_Fill()函数进行屏幕清除,NRF24L01_TX_Mode()进入发送模式,利用 adcx 获取光照强度。将获取到的 adcx 值进行一些运算存贮在 bon[ ] 数组中,然后将 bon[ ] 数组中的值赋值给 tmp_buf[ ] 数组中,利用for循环将 tmp_buf[ ] 数组中没有数据的位置空,最后在 tmp_buf[ ] 数组中的倒数第二位加上标识符确定身份,在 tmp_buf[ ] 数组中的最后一位加入结束符。至此第一个数据包制作完成,进入while(1)语句中延迟 1 秒后继续发送数据包。 标识符是为了识别是那个单片机传的数据,所以三套单片机的程序是有一些区别的。 发送模式2(key1长按) if(NRF24L01_TxPacket(tmp_buf)==TX_OK) { LCD_ShowString(30,170,239,32,16,"Sended DATA:"); LCD_ShowString(30,190,55,16,16,tmp_buf); key=mode; key1=mode; for(t=0;t<32;t++) { tmp_buf[t]=a[key-key1]; key++; if(key>=key1+7)key=0; } mode++; tmp_buf[31]=3; tmp_buf[32]=0; for(mode=0;mode<6;mode++) { bin[0]=a[mode]; a[mode]=a[mode+1]; a[mode+1]=bin[0]; } }else { LCD_Fill(0,170,lcddev.width,170+16*3,WHITE); LCD_ShowString(30,170,lcddev.width-1,32,16,"Send Failed "); }; mode=0; while(1) { if(time>=2){time=0;break;} } if(KEY_Scan(0)==1||KEY_Scan(0)==0){break;} 发送模式 2 与发送模式 1 同理,只是将光照强度改为数组 a[7]={“IOT-BCU”} 的值。为了实现每 2 秒左移的功能,利用for语句将第一个值右移6次即等价于数组左移 1 次。然后就是相同的操作,最后在 tmp_buf[ ] 数组中的倒数第二位加上标识符确定身份,在 tmp_buf[ ] 数组中的最后一位加入结束符。至此第一个数据包制作完成,进入while(1)语句中延迟 2 秒后继续发送数据包。 这里写啰嗦了,第一次是想用另一种方法写的,结果失败了,后面又懒得改了。 接收模式(key0短按) LCD_Fill(0,170,lcddev.width,170+16*3,WHITE); LCD_ShowString(30,150,200,16,16,"NRF24L01 RX_Mode"); LCD_ShowString(30,170,200,16,16,"Received DATA:"); NRF24L01_RX_Mode(); while(1) { if(NRF24L01_RxPacket(tmp_buf)==0) { tmp_buf[32]=0; for(i=i;i<32;i++) { tmp_buf=tmp_buf[i+1]; } if(tmp_buf[0]<58&&tmp_buf[31]==1&&tmp_buf[0]!='-') { LCD_ShowString(150,170,200,16,16,"(LSENS_VAL)"); LCD_DrawLine(47, 205, 56, 191); LCD_Draw_Circle(50,192,2); LCD_Draw_Circle(54,202,2); } if(tmp_buf[0]<58&&tmp_buf[31]==2&&tmp_buf[0]!='-') { LCD_ShowString(150,170,200,16,16,"(LSENS_VAL)"); LCD_DrawLine(47, 225, 56, 211); LCD_Draw_Circle(50,212,2); LCD_Draw_Circle(54,222,2); } if(tmp_buf[0]<58&&tmp_buf[31]==3&&tmp_buf[0]!='-') { LCD_ShowString(150,170,200,16,16,"(LSENS_VAL)"); LCD_DrawLine(47, 245, 56, 231); LCD_Draw_Circle(50,232,2); LCD_Draw_Circle(54,242,2); } if(tmp_buf[31]==1)LCD_ShowString(30,190,55,16,16,tmp_buf); if(tmp_buf[31]==2)LCD_ShowString(30,210,55,16,16,tmp_buf); if(tmp_buf[31]==3)LCD_ShowString(30,230,55,16,16,tmp_buf); } else delay_us(100); t++; if(t==10000) { t=0; LED0=!LED0; } if(KEY_Scan(0)==1||KEY_Scan(0)==0){break;} } 与发送模式大同小异。清屏,进入接收模式,将 tmp_buf[ ] 数组中的 32 位数据依次显示在屏幕上,其中利用了if语句,判断数据的格式、标识符来确定输出的位置及信息。 三、实验结果与分析 实验现象: 程序刚开始运行,没有插入NRF24L01模块。会显示“NRF24L01 Error”不断闪 插入 NRF2401 模块之后。 让其中 1 号和 2 号板子进入发送模式 1,3 号板子进入接收模式。 进入模式 2。 总结 问题一:check() 函数没有问题,可是屏幕上一直显示 “NRF24L01 Error”。解决:ST-Link 与 NRF24L01 冲突,导致 NRF24L01 模块无法正常的写读。在烧录程序之后,将 ST-Link 断开再调试。 问题二:利用通道 1 和 2 实现一收多发存在一系列问题。解决:将三个模块的收发地址全部改为相同的地址。tmp_buf 的倒数第二位存入标识符再发送,在读取数据的时候,根据标识符即可判断数据来自那个模块。 问题三:光照强度存入 tmp_buf 中,最后无法显示或者显示乱码。解决:tmp_buf 存入的数据为 ASCII 码,故要在相应的位上加 48。 问题四:通信协议解决:根据相关资料,tmp_buf 的第 0 个字节系统保留,用于每次传输的数据包长度统计。这个是针对于使用了这中上位机模块如果使用的是两个 24L01 相互通信,完全不用考虑这个。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1561 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1501 浏览 1 评论
933 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
665 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1555 浏览 2 评论
1848浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
610浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
504浏览 3评论
508浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
489浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-10 16:37 , Processed in 0.607772 second(s), Total 45, Slave 40 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号