IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 基于STM32F103C8T6实现用2.4G模块(NRF2401)传输室内温湿度并显示OLED -> 正文阅读

[嵌入式]基于STM32F103C8T6实现用2.4G模块(NRF2401)传输室内温湿度并显示OLED

基于STM32F103C8T6实现用2.4G模块(NRF2401)传输室内温湿度并显示OLED

对于2.4G模块上的应用,很多是将这个这个模块上的应用实现在51单片机上,我问了很多相关文章的博主,他们从最开始的程序几乎都是从51单片机上,进行开发,感谢这些赶路人,我们这些从事快速开发的爱好者做好的道路。
感谢999994博主绽放中的青春博主

好了,现在就进入主食阶段

一:对2.4G模块(NRF2401)的介绍

作为我们在开发应用的短距离传输信息的选择模块之一,作为在项目上实现互传的模块,可实现半双工和全双工,可以实现点对点或是 1 对 6 的无线通信。对于 NRF24L01 的固件编程工作主要是参照NRF24L01 的状态机。主要有以下几个状态:
Power Down Mode:掉电模式
Tx Mode:发射模式
Rx Mode:接收模式
Standby-1Mode:待机 1 模式
Standby-2 Mode:待机 2 模式

这里配上接线管脚
NRF2401管脚图示

PA1NRF- CSN
PA5-SPI1-SCKNRF -SCK
PA6-SPI1-MISONRF -MISO
PA7-SPI1-MOSINRF -MOSI
PA3NRF-IRQ
PA2NRF-CE

但是在我应用的项目上我没有使用全双工,项目设计是一个板子(STM32最小系统,以下皆是)上的一个作为主机,一个作为从机,其中主机是负责采集室内的温度,从机是为了负责接收主机主机上的数据,显示在OLED上面,同时为了让自己的项目更好的检测,我在从机上也实现了对主机数据的发送,主句实现接收。
主机上发送:

printf("\r\n 主机端 进入自应答发送模式\r\n"); 
	NRF_TX_Mode();

	txbuf[0]=temp;			
	txbuf[1]=humi;//将检测到的温度和湿度赋值给这个非空数组中,实现数据包的发送
	status = NRF_Tx_Dat(txbuf);//

		  switch(status)
		  	{
		  	  case MAX_RT:
			 	 	printf("\r\n 主机端 没接收到应答信号,发送次数超过限定值,发送失败。 \r\n");
				 break;
	
			  case ERROR:
			  	 	printf("\r\n 未知原因导致发送失败。 \r\n");
				 break;
	
			  case TX_DS:
			  		printf("\r\n 主机端 接收到 从机端 的应答信号,发送成功! \r\n");	 		
				 break;  								
		  	}			   	
	

从机上接收:

printf("\r\n 从机端 进入接收模式\r\n"); 
	NRF_RX_Mode();     //这边的是在收
	 
	/*等待接收数据*/
	status = NRF_Rx_Dat(rxbuf);

	   /*判断接收状态*/
		 if(status == RX_DR)
	{
		printf("\r\n 从机端 接收到 主机端 发送的数据 \r\n");
	  for(i=0;i<2;i++)
				{	
					if(i%2==0)
					{
						printf("\r\n 温度的数据为:%d \r\n",rxbuf[i]);
						OLED_ShowNum(45,2,rxbuf[i],3,16);//显示温度的码值
						txbuf[i] =1;
			        }
			        else
			       {
						printf("\r\n 湿度的数据为:%d \r\n",rxbuf[i]);
					    OLED_ShowNum(45,4,rxbuf[i],3,16);//显示湿度的码值
						txbuf[i] =1;
			       }									
				}		
	}   

主机上接收从机数据:

printf("\r\n 主机端 进入接收模式。 \r\n");	
		NRF_RX_Mode();
		status = NRF_Rx_Dat(rxbuf);	
			
		switch(status)
			{
			 case RX_DR:
			 	for(i=0;i<4;i++)
				{					
					printf("\r\n 主机端 接收到 从机端 发送的数据为:%d \r\n",rxbuf[i]);
					txbuf[i] =rxbuf[i];
														
				}
				  break;
			
			 case ERROR:
				  	printf("\r\n 主机端 接收出错。   \r\n");
				  break;  		
			}
		

从机上发送给主机数据:

printf("\r\n 温度的数据为:%d \r\n",rxbuf[i]);
						OLED_ShowNum(45,2,rxbuf[i],3,16);//显示温度的码值
						txbuf[i] =1;//返回发送给主机上的值为1

txbuf[i]就是发送个主机上面的数据

printf("\r\n 湿度的数据为:%d \r\n",rxbuf[i]);
					    OLED_ShowNum(45,4,rxbuf[i],3,16);//显示湿度的码值
						txbuf[i] =1;//返回发送给主机上的值为1

二.温湿度传感器简介

DHT11是一款价格便宜,易于使用的温度湿度测量二合一传感器。它使用单根总线与单片机进行双向的串行数据传输,信号传输距离可达20米以上。非常适用于对精度和实时性要求不高的温湿度测量场合。DHT117温湿度传感器
接口设置:

DATAPB11

这个模块也是有相应的代码格式,我这里就提几个注意事项:
1.DHT11使用单一总线通信,即DATA引脚和单片机连接的线。总线总是处于空闲状态和通信状态这个2个状态之间。
2.DHT11上电后,要等待 约 1秒 以越过不稳定状态,在此期间不能发送任何指令。
3.DHT11属于低速传感器,两次通信请求之间的间隔时间不能太短,一般来说要不能低于1秒。
4.当前DHT11通信帧的小数部分默认都是0,厂商预留给以后实现。所以一般只读取整数值部分即可。校验和定义为:前4个Byte的总和的低8位。

三.OLED显示屏

我所用的OLED屏有白色,屏的大小为0.96寸,像素点为128*64,也称之为0.96OLED屏或者12864屏。通时我选择的是4脚,运用的协议是IIC协议,

void IIC_Start(void)
{

	OLED_SCLK_Set() ;
	OLED_SDIN_Set();
	OLED_SDIN_Clr();
	OLED_SCLK_Clr();
}

理解了OLED的显示方式,汉字取模也是很有必要的,我选择列行式的取模方式,设置为C51原则:
PLC取模软件

想要更加详细的理解OLED上面的知识我推荐这位博主的博文OLED详细解剖

下面是主机项目工程中的main.c文件:

#include "stm32f10x.h"
#include "usart.h"
#include "delay.h"
#include "DTH117.h"
#include "sys.h"
#include "SPI_NRF.h"
#include <stdarg.h>
#include <string.h>
#include <stdio.h>

u8 status;	//用于判断接收/发送状态
u8 txbuf[2];	 //发送缓冲
u8 rxbuf[4];//接收缓冲
int i=0;
/*
*读取温湿度传感器DHT11的值,并用串口打印出来
*/

void clock_init(void);

u8 temp = 0,humi = 0;


/**************************************************************************
函数名:int main(void)
参数说明:无
返回值:无
函数作用:主函数
***************************************************************************/
 int main(void)
 {	
	 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	SPI_NRF_Init();
	delay_init();
    DHT11_Init();	 
    clock_init();	
    usart_init(115200);		//初始化串口
	printf("\r\n 这是一个 NRF24L01 无线传输实验 \r\n");
	printf("\r\n 这是无线传输 主机端 的反馈信息\r\n");
	printf("\r\n   正在检测NRF与MCU是否正常连接。。。\r\n");
	
	 /*检测NRF模块与MCU的连接*/
   	status = NRF_Check(); 

	/*判断连接状态*/  
   if(status == SUCCESS)	   
   		 printf("\r\n      NRF与MCU连接成功!\r\n");  
   else	  
   	     printf("\r\n  NRF与MCU连接失败,请重新检查接线。\r\n"); 
	 
	 
	 while(1)
	 {	
	DHT11_Read_Data(&temp,&humi);
	printf("\r\n 主机端 进入自应答发送模式\r\n"); 
	NRF_TX_Mode();

	txbuf[0]=temp;			
	txbuf[1]=humi;//将检测到的温度和湿度赋值给这个非空数组中,实现数据包的发送
	status = NRF_Tx_Dat(txbuf);//这里是发送
		  switch(status)		  	{
		  	  case MAX_RT:
			 	 	printf("\r\n 主机端 没接收到应答信号,发送次数超过限定值,发送失败。 \r\n");
				 break;
	
			  case ERROR:
			  	 	printf("\r\n 未知原因导致发送失败。 \r\n");
				 break;
	
			  case TX_DS:
			  		printf("\r\n 主机端 接收到 从机端 的应答信号,发送成功! \r\n");	 		
				 break;  								
		  	}			   	
	
	 	printf("\r\n 主机端 进入接收模式。 \r\n");	
		NRF_RX_Mode();
		status = NRF_Rx_Dat(rxbuf);	
			
		switch(status)
			{
			 case RX_DR:
			 	for(i=0;i<4;i++)
				{					
					printf("\r\n 主机端 接收到 从机端 发送的数据为:%d \r\n",rxbuf[i]);
					txbuf[i] =rxbuf[i];
														
				}
				  break;
			
			 case ERROR:
				  	printf("\r\n 主机端 接收出错。   \r\n");
				  break;  		
			}
		
	 } 	  
	
 } 
/**************************************************************************
函数名:void clock_init(void)
参数说明:无
返回值:无
函数作用:开启高速外部时钟,
ADCCLK设置为12MHZ,	SYSCLK设置为72Mhz,PCLK1设置为36MHZ,PKLC2设置为72mhz
***************************************************************************/
 void clock_init(void)
 {
	RCC->CR = 0x1010000;
	RCC->CFGR = 0x1DC402;
}

这里从机项目的main.c文件:

#include "stm32f10x.h"
#include "usart.h"
#include "delay.h"
#include "oled.h"
#include "sys.h"
#include "SPI_NRF.h"
#include <stdarg.h>
#include <string.h>
#include <stdio.h>

u8 status;	//用于判断接收/发送状态
u8 txbuf[4];	 //发送缓冲
u8 rxbuf[4];//接收缓冲
u8 i;
/*
*读取温湿度传感器DHT11的值,并用串口打印出来
*/

void clock_init(void);
/**************************************************************************
函数名:int main(void)
参数说明:无
返回值:无
函数作用:主函数
***************************************************************************/
 int main(void)
 {	
	 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	SPI_NRF_Init();
	delay_init();
    OLED_Init();	 
    clock_init();	
    usart_init(115200);		//初始化串口
	 OLED_Clear();
	OLED_Display_On();
	OLED_ShowCHinese(40,0,0);
	OLED_ShowCHinese(60,0,1);
	OLED_ShowCHinese(80,0,2);
	OLED_ShowCHinese(100,0,3);
		 //
		 //显示各个参数的中文
    OLED_ShowCHinese(0,2,4);
	OLED_ShowCHinese(18,2,5);	 
	OLED_ShowString(35,2, ":",16);//显示温度中文
	
	OLED_ShowCHinese(0,4,6);
	OLED_ShowCHinese(18,4,7);	 
	OLED_ShowString(35,4, ":",16);//显示温度中文	
	printf("\r\n 这是一个 NRF24L01 无线传输实验 \r\n");
	printf("\r\n 这是无线传输 主机端 的反馈信息\r\n");
	printf("\r\n   正在检测NRF与MCU是否正常连接。。。\r\n");
	
	 /*检测NRF模块与MCU的连接*/
   	status = NRF_Check(); 

	/*判断连接状态*/  
   if(status == SUCCESS)	   
   		 printf("\r\n      NRF与MCU连接成功!\r\n");  
   else	  
   	     printf("\r\n  正在检测NRF与MCU是否正常连接。。。\r\n"); 
	 
	 
	 while(1)
	 {	
		 
	printf("\r\n 从机端 进入接收模式\r\n"); 
	NRF_RX_Mode();     //这边的是在收
	 
	/*等待接收数据*/
	status = NRF_Rx_Dat(rxbuf);

	   /*判断接收状态*/
		 if(status == RX_DR)
	{
		printf("\r\n 从机端 接收到 主机端 发送的数据 \r\n");
	  for(i=0;i<2;i++)
				{	
					if(i%2==0)
					{
						printf("\r\n 温度的数据为:%d \r\n",rxbuf[i]);
						OLED_ShowNum(45,2,rxbuf[i],3,16);//显示温度的码值
						txbuf[i] =1;//返回发送给主机上的值为1
			        }
			        else
			       {
						printf("\r\n 湿度的数据为:%d \r\n",rxbuf[i]);
					    OLED_ShowNum(45,4,rxbuf[i],3,16);//显示湿度的码值
						txbuf[i] =1;//返回发送给主机上的值为1
			       }					
					
				}	
	}   
	 
		printf("\r\n 从机端 进入自应答发送模式"); 
	  	NRF_TX_Mode();
		
		/*不断重发,直至发送成功*/	  
	 do
	   { 	  
		status = NRF_Tx_Dat(txbuf);
		   
		}while(status == MAX_RT);
	} 

}
/**************************************************************************
函数名:void clock_init(void)
参数说明:无
返回值:无
函数作用:开启高速外部时钟,
ADCCLK设置为12MHZ,	SYSCLK设置为72Mhz,PCLK1设置为36MHZ,PKLC2设置为72mhz
***************************************************************************/
 void clock_init(void)
 {
	RCC->CR = 0x1010000;
	RCC->CFGR = 0x1DC402;
}

成果展示:
双板接线图
串口打印
室内检测

项目总结:
总项目实现最大的难点是网上找到了相应的NRF2401的传输格式,只是这个格式并不能实现对你想要的数据的传输,所以这个实现的核心代码还是自己一遍又一遍根据模块实现的逻辑不断完善的,同时在数据传输的过程,OLED的格式我也是将实现数据的传输,让其在室温显示下更加的稳定,同时这个传输有个小小的瑕疵就是,设置了一个阈值,传输的阈值一到就会切换到主机变从机,从机变主机的状态,钻了全双工的空子(假的(????))

未来可期
资料打包可用51黑子网
同时也可在本CSDN上下载:资料下载

备注:1. 本文章是个人总结,如有不足之处欢迎指正;
2.文章资料格式是网上找的也是从上面两个博主的,但是核心代码是自己写的,文章资料如有侵权,请联系我。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-08-10 13:34:55  更:2021-08-10 13:37:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/13 19:38:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码