STM32 AM2320 温湿度万年历 微信小程序显示及控制

news/2024/11/24 6:29:03/

功能描述:

使用STM32F103R8T6,红外遥控器,数码管,串口,预留ADC(4~20mA输入、0~10V输入)、485、以太网、WiFi、SD卡、USB_OTG等功能。单总线的方式采集温湿度(因整个系统时序要求,所以使用状态机采集),ST自带的RTC时钟。单片机采集到温湿度数值通过串口自制的4G模块通讯,上传数据到指定服务器,然后在微信小程序关注蓝星物联,就可以看到设备数据,我们还做了一个网站,专门管理底层设备。现在分享单片机程序和部分原理图。程序源码在一个资源里面,下载需要积分,没有积分的可以私信我。源码地址:https://download.csdn.net/download/L_e_c/14029632              

硬件设计:

1)电源及MCU部分

使用LM2596DC-DC,降压后放上一个LDO输出3.3V。预留SWD下载,纽扣电池,BOOT脚选择,红外接收头,温湿度模块,多预留一路时钟模块,防止内部RTC随温漂的误差。以及其他一些外设接口预留。

2)通讯及数据保存部分

预留485接口,232接口,USB接口,WiFi接口,以太网接口。通信接口只要做数据汇总、数据上传使用。数据保存有SD卡保存和flash保存两种,SD卡保存使用模块外接的形式,可以把采集到的数据直接保存成文件的形式。flash芯片可以保存需要的字库等等。

3)输入输出部分

预留ADC采集4~20mA及0~10V模拟信号。按键输入,不是全隔离,只是防止客户使用的时候会接错烧坏MCU引脚。继电器输出,可带12V声光报警器。

4)数码管显示部分

使用驱动芯片JXI5020级联,做到三线带多位数码管。

5)PCB展示

软件设计:

1)main.c

main函数进来,先是各种外设初始化,第一个while(1)的循环是发送消息给服务器或者上层设备注册设备用的,设备长时间不按照协议通讯的话,设备会软复位,重新注册。在第二个while(1)的循环是处理注册后的数据,包括温湿度和时间的显示,按键(红外遥控和轻触按键)设置,报警状态设置,设置定时,每1S钟发送一次实时数据到服务器,处理串口2接收到服务器发送的数据(JSON格式,使用CJSON库)。

/********************************************************************************** 文件名  :main.c* 描述    :      * 实验平台:* 库版本  :ST3.5.0* 作者    : * 论坛    :* 版本    ?VV1.0* 时间	   :2017.6.6备注    : STM32F103_R8T6 工程模版 
**********************************************************************************/#include "Header_File.h"u8 Send_Buff1[114];
u16   Crc_Send_Num=0;
u8 Crc_Send_H=0;
u8 Crc_Send_L=0;u32 Set_MS_Num=0;#define  SW_RESET()	       NVIC_SystemReset()int processMessage(char *msg) {cJSON *jsonObj=cJSON_Parse(msg);cJSON *method;cJSON *typ;
//	cJSON *temmin;
//	cJSON *temmax;
//	cJSON *temcalibrate;
//	cJSON *tembkwd;
//	cJSON *hummin;
//	cJSON *hummax;
//	cJSON *humcalibrate;
//	cJSON *humbkwd;char *m;int x;//json字符串解析失败,直接退出if(!jsonObj){cJSON_Delete(jsonObj);return 0;}method = cJSON_GetObjectItem(jsonObj, "TYPE");m = method->valuestring;if(strncmp(m, "AUTHERROR", 9) == 0 ) //设备未注册,重新注册{cJSON_Delete(jsonObj);SW_RESET();return 1;
//        char *content = cJSON_GetObjectItem(jsonObj, "DATA")->valuestring;	
//        if(strncmp(content, "No identity", 4) == 0)
//        {
//			
//        }}if(strncmp(m, "HSOK", 4) == 0 ) //注册信息返回{char *content = cJSON_GetObjectItem(jsonObj, "DATA")->valuestring;	if(strncmp(content, "HSOK", 4) == 0){cJSON_Delete(jsonObj);return 1;}}if(strncmp(m, "DATAOK", 6) == 0 ) //{char *content = cJSON_GetObjectItem(jsonObj, "TYPE")->valuestring;	if(strncmp(content, "DATAOK", 6) == 0){Resert_Cnt_10S=0; //重启时间清零cJSON_Delete(jsonObj);return 1;}}if(strncmp(m, "CDATA", 5) == 0 ) //{typ = cJSON_GetObjectItem(jsonObj, "ctype");x=typ->valueint;
//		if(strncmp(m, "1", 1) == 0 ) if(x==1) {int ye = cJSON_GetObjectItem(jsonObj, "y")->valueint;	int mo = cJSON_GetObjectItem(jsonObj, "m")->valueint;int da = cJSON_GetObjectItem(jsonObj, "d")->valueint;	int ho = cJSON_GetObjectItem(jsonObj, "h")->valueint;	int mi = cJSON_GetObjectItem(jsonObj, "i")->valueint;	int se = cJSON_GetObjectItem(jsonObj, "s")->valueint;	RTC_Set(ye,mo,da,ho,mi,se);
//			Set_MS_Num=atoi(ye);}else if(x==2) //{double temmin = cJSON_GetObjectItem(jsonObj, "tem_min")->valuedouble;double temmax = cJSON_GetObjectItem(jsonObj, "tem_max")->valuedouble;double temcalibrate = cJSON_GetObjectItem(jsonObj, "tem_calibrate")->valuedouble;double tembkwd = cJSON_GetObjectItem(jsonObj, "tem_bkwd")->valuedouble;double hummin = cJSON_GetObjectItem(jsonObj, "hum_min")->valuedouble;	double hummax = cJSON_GetObjectItem(jsonObj, "hum_max")->valuedouble;	double humcalibrate = cJSON_GetObjectItem(jsonObj, "hum_calibrate")->valuedouble;	double humbkwd = cJSON_GetObjectItem(jsonObj, "hum_bkwd")->valuedouble;	
//			Temperature_Down=atoi(temmin);
//			Temperature_Up=atoi(temmax);Temperature_Up=(s16)(temmax*10);Temperature_Down=(s16)(temmin*10);Temperature_Temp=(s16)(temcalibrate*10);Temperature_hc=(s16)(tembkwd*10);Humidity_Up=(s16)(hummax*10);Humidity_Down=(s16)(hummin*10);Humidity_Temp=(s16)(humcalibrate*10);Humidity_hc=(s16)(humbkwd*10);}}//    if(jsonObj)cJSON_Delete(jsonObj);return 0;
}int main(void)
{	
//    char* out="{\"TYPE\":\"fengxin\",\"passwd\":123,\"y\":2020,\"m\":6,\"d\":3,\"h\":23,\"minu\":33}"; //  ,\"miao\":20u8 ack_Usart1=0;u8 cclen=0;u16 Cnt_500S=0; u16 Cnt_500Ms=0;SystemInit(); 			 	//系统时钟初始化为72M	  SYSCLK_FREQ_72MHz	TIM3_Cnt_Init(999,71);      //配置定时器3  1Ms中断一次 RTC_Init();	  				//RTC时钟初始化IO_Init(); 					//GPIO初始化Uart1_Init(115200);			//串口1初始化
//	Uart3_Init(9600);HC595_IO_Init();			//74HC595使用初始化Init_AOSONG();				//温湿度模块初始化Init_Infrared();			//红外模块初始化,开一个定时器和一个外部中断
//	Adc_Init();Key_IO();					//按键输入初始化 就是这么优秀Uart2_Init(115200);			//数据上传	
//	Interface_Changes=1;W25QXX_Init();				//W25QXX初始化FLASH_SIZE=32*1024*1024;	//FLASH 大小为xxM字节Read_Data_From_Flash();	Time_Num[8]=calendar.week%10;delay_ms(100);show_led12();while(1)	//注册设备信息,待服务器返回后退出{if(System1S==1){System1S=0;cclen=sprintf((char *)Send_Server,"{\"TYPE\":\"HS\",\"CID\":\"WJVSAIL1\"}");Usart2_Printf((uint8_t *)Send_Server,cclen);}if(USART2_RX_STA == 1){USART2_RX_STA = 0;ack_Usart1=processMessage((char*)Usart2_RxBuff);Clear_Buffer((uint8_t*)Usart2_RxBuff,strlen((char*)Usart2_RxBuff));rx_counter_Usart2 = 0;if(ack_Usart1==1)	break;}}while(1){ 		show_led12();	//数码管显示Key_use();		//按键处理Data_Change();if(Display_Complete_Flag==1){if(((Temp_001>Temperature_Up)||(Temp_001<Temperature_Down)||(Humi_001>Humidity_Up)||(Humi_001<Humidity_Down))&&(Mute_Flag==0)&&(Set_Position==0)&&(Key_Set_Position==0)){if(Temp_001>Temperature_Up)	Temperature_Up_Flag=1;if(Humi_001>Humidity_Up)	Humidity_Up_Flag=1;if(Temp_001<Temperature_Down)	Temperature_Down_Flag=1;if(Humi_001<Humidity_Down)	Humidity_Down_Flag=1;Out2=1;	}else if((Set_Position==0)&&(Key_Set_Position==0))	{if(Temp_001<=(Temperature_Up-Temperature_hc))	Temperature_Up_Flag=0;if(Temp_001>=(Temperature_Down+Temperature_hc))	Temperature_Down_Flag=0;if(Humi_001<=(Humidity_Up-Humidity_hc))			Humidity_Up_Flag=0;if(Humi_001>=(Humidity_Down+Humidity_hc))		Humidity_Down_Flag=0;if((Temperature_Up_Flag==0)&&(Temperature_Down_Flag==0)&&(Humidity_Up_Flag==0)&&(Humidity_Down_Flag==0))Out2=0;if(Mute_Flag==1)	Out2=0;}	}if((Set_Position==0)&&(Key_Set_Position==0))	{Time_Num[8]=calendar.week%10;if(Time_Num[8]==0)	Time_Num[8]=7;}if(System10Ms==1){System10Ms=0;  if(++Cnt_500Ms>=50){Cnt_500Ms=0;LED1=~LED1;if((Set_Position==0)&&(Key_Set_Position==0)){RTC_LED=~RTC_LED;}else RTC_LED=0;}}	if(System1S==1){System1S=0;Clear_Buffer((uint8_t*)Send_Server,strlen((char*)Send_Server));cclen=sprintf((char *)Send_Server,"{\"TYPE\":\"DATA\",\"Tmp\":\"%d.%01d\",\"Hum\":\"%d.%01d\"}",Temp_001/10,Temp_001%10,Humi_001/10,Humi_001%10); //,Temp_001/10,Temp_001%10,Humi_001/10,Humi_001%10Usart2_Printf((uint8_t *)Send_Server,cclen);if(++Resert_Cnt_10S>=20) //10s后没有接到来自服务器的数据进行软重启,再次注册{Resert_Cnt_10S=0;SW_RESET();}}	if(USART2_RX_STA == 1){USART2_RX_STA = 0;processMessage((char*)Usart2_RxBuff);Clear_Buffer((uint8_t*)Usart2_RxBuff,strlen((char*)Usart2_RxBuff));rx_counter_Usart2 = 0;}}
}

2)Infrared.c

红外接收模块处理文件。在主函数里面只需要直接访问InfraredCode变量就可以知道是否有按键按下。开启一个定时器和一个外部中断,检测接收头(HS0038B)是否收到遥控器的信号,并按照固定的格式给信号做一个处理。识别对应的按钮按下对应的码值,做一个赋值,供主函数读取使用。

#include "infrared.h"
//#include "Timer2_Cnt.h"u8 timercnt_up=0;
u8 timercnt_down=0;
u8 Infraredbuf[4];
u8 InfraredCode=0;
// 红外遥控器 编码格式
// START + 8Bit厂商编码 + 8Bit反码 + 8Bit数据 + 8Bit反码// START L=9.00ms   H=4.500ms  引导码
// BIT0  L=0.56ms   H=0.565ms  数据0
// BIT1  L=0.56ms   H=1.690ms  数据1
// PRESS L=9.00ms   H=2.250ms  重复码u8 irdata[33];
u8 irok;   
u16  irtime;
static u8 ir_flag;     //是否开始处理标志位void TIM2_Cnt_Init(u16 arr,u16 psc)	 // TIM2_Cnt_Init(999,71);  1ms中断一次   
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);         //①时钟TIM2使能 //定时器TIM2初始化 TIM_TimeBaseStructure.TIM_Period = arr;                      //设置自动重装载寄存器周期的值   TIM_TimeBaseStructure.TIM_Prescaler =psc;                    //设置时钟频率除数的预分频值 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;      //设置时钟分割 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);              //②初始化TIM2   TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE );                    //③允许更新中断   //中断优先级NVIC设置 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;              //TIM2中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;    //抢占优先级1级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;           //从优先级0级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;              //IRQ 通道被使能 NVIC_Init(&NVIC_InitStructure);                              //④初始化NVIC寄存器 TIM_Cmd(TIM2, ENABLE);                                       //⑤使能TIM2 
}	//定时器2中断服务程序 
void TIM2_IRQHandler(void)      //TIM2中断 
{ if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)               //检查TIM2更新中断发生与否   { TIM_ClearITPendingBit(TIM2, TIM_IT_Update);             	 //清除TIM2更新中断标志   irtime++; 			//用于计数2个下降沿之间的时间,0.1ms进一次定时器中断if(irtime>=1000)	//irtime>=1000说明按键已经松开有1000*0.1ms=100ms了,故可以使能红外接收功能{ir_flag=1;		//使能红外接收功能}
//		if(INIR) timercnt_up++;	
//		else 	 timercnt_down++;
//	    System1Ms=1;
//		if(++i>=10)
//		{
//			i=0;
//			System10Ms=1;
//		}} 
}void EXTIX_Init(void)
{EXTI_InitTypeDef EXTI_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//外部中断,需要使能AFIO时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能PORTA,PORTC时钟GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);//关闭jtag,使能SWD,可以用SWD模式调试GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_4;//PC5GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOC5//GPIOC.1 中断线以及中断初始化配置GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource4);EXTI_InitStructure.EXTI_Line=EXTI_Line4;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);	 	//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;			//使能按键所在的外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//抢占优先级2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;					//子优先级1NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								//使能外部中断通道NVIC_Init(&NVIC_InitStructure);  	  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器}void EXTI4_IRQHandler(void)
{static u8  RecvCnt;          //接收红外信号处理u8 a,b,c,d,i,e,f,tmp;u32 RecvData = 0;u16  VS1838_KEY_VALUE;if(EXTI_GetITStatus(EXTI_Line4)!=RESET){EXTI_ClearITPendingBit(EXTI_Line4);  //清除EXTI0线路挂起位if(ir_flag==0){irtime=0;                           //清零计数器return;}	else if(ir_flag==1){if((irtime>IR_START) && (irtime<(IR_START + DataTolerance_IR)))	//接收到引导码 9ms+4.5ms{RecvCnt=0;}irdata[RecvCnt]=irtime;	//存储每个电平的持续时间,用于以后判断是0还是1irtime=0;		//清零irtime变量RecvCnt++;		//数组下标自增1if(RecvCnt>=33){irok=1;		//接收完33个红外数据RecvCnt=0;	//数组下标清零ir_flag=0;	//失能红外接收功能VS1838_KEY_VALUE=0;for(i=1;i<33;i++){if((irdata[i] > IR_BIT1) && (irdata[i] < (IR_BIT1 + DataTolerance_IR))){   		// BIT1RecvData <<= 1;RecvData  |= 1;}else if((irdata[i] > IR_BIT0) && (irdata[i] < (IR_BIT0 + DataTolerance_IR))){ 	// BIT0RecvData <<= 1;}}a=(RecvData>>24)&0xFF;b=(RecvData>>16)&0xFF;c=(RecvData>>8)&0xFF;d= RecvData&0xFF;e=~b;f=~d;if((a==e)&&(c==f)){VS1838_KEY_VALUE=(a<<8)|c;}switch(VS1838_KEY_VALUE){case 0x0098:InfraredCode=Infrared_0;break;	// 按键 0case 0x00A2:InfraredCode=Infrared_1;break;	// 按键 1case 0x0062:InfraredCode=Infrared_2;break;	// 按键 2case 0x00E2:InfraredCode=Infrared_3;break;	// 按键 3case 0x0022:InfraredCode=Infrared_4;break;	// 按键 4case 0x0002:InfraredCode=Infrared_5;break;	// 按键 5case 0x00C2:InfraredCode=Infrared_6;break;	// 按键 6case 0x00E0:InfraredCode=Infrared_7;break;	// 按键 7case 0x00A8:InfraredCode=Infrared_8;break;	// 按键 8case 0x0090:InfraredCode=Infrared_9;break;	// 按键 9case 0x0068:InfraredCode=Infrared_Xing;break;	// 按键 *case 0x00B0:InfraredCode=Infrared_Jing;break;	// 按键 #case 0x0010:InfraredCode=Infrared_Left;break;	// 按键 <case 0x005A:InfraredCode=Infrared_Right;break;	// 按键 >case 0x0018:InfraredCode=Infrared_Up;break;	// 按键 ^case 0x004A:InfraredCode=Infrared_Down;break;	// 按键 vcase 0x0038:InfraredCode=Infrared_OK;break;	// 按键 OKdefault: tmp=0;break;	// NO_KEY	}}}		//		irok=0;	}
}/* 红外解码,返回按键键值 */
void HS0038B_DeCode(void)
{
//	u8 a,b,c,d,i,tmp;
//	u32 RecvData = 0;
//	u16  VS1838_KEY_VALUE;
//	
//	if(irok){
//		irok=0;
//		VS1838_KEY_VALUE=0;//		for(i=1;i<33;i++){
//			if((irdata[i] > IR_BIT1) && (irdata[i] < (IR_BIT1 + DataTolerance_IR))){   		// BIT1
//		        RecvData <<= 1;
//		        RecvData  |= 1;
//		    }else if((irdata[i] > IR_BIT0) && (irdata[i] < (IR_BIT0 + DataTolerance_IR))){ 	// BIT0
//		        RecvData <<= 1;
//		    }
//		}//		a=(RecvData>>24)&0xFF;
//		b=(RecvData>>16)&0xFF;
//		c=(RecvData>>8)&0xFF;
//		d= RecvData&0xFF;
//		if((a==~b)&&(c==~d))
//			VS1838_KEY_VALUE=(a<<8)|c;
//	
//		switch(VS1838_KEY_VALUE){
//			case 0x0098:InfraredCode=Infrared_0;break;	// 按键 0
//			case 0x00A2:InfraredCode=Infrared_1;break;	// 按键 1
//			case 0x0062:InfraredCode=Infrared_2;break;	// 按键 2
//			case 0x00E2:InfraredCode=Infrared_3;break;	// 按键 3
//			case 0x0022:InfraredCode=Infrared_4;break;	// 按键 4
//			case 0x0002:InfraredCode=Infrared_5;break;	// 按键 5
//			case 0x00C2:InfraredCode=Infrared_6;break;	// 按键 6
//			case 0x00E0:InfraredCode=Infrared_7;break;	// 按键 7
//			case 0x00A8:InfraredCode=Infrared_8;break;	// 按键 8
//			case 0x0090:InfraredCode=Infrared_9;break;	// 按键 9
//			case 0x0068:InfraredCode=Infrared_Xing;break;	// 按键 *
//			case 0x00B0:InfraredCode=Infrared_Jing;break;	// 按键 #
//			case 0x0010:InfraredCode=Infrared_Left;break;	// 按键 <
//			case 0x005A:InfraredCode=Infrared_Right;break;	// 按键 >
//			case 0x0018:InfraredCode=Infrared_Up;break;	// 按键 ^
//			case 0x004A:InfraredCode=Infrared_Down;break;	// 按键 v
//			case 0x0038:InfraredCode=Infrared_OK;break;	// 按键 OK
//			default: tmp=0;break;	// NO_KEY	
//		}return tmp;
//	}							   
//	return 0;	
}void Init_Infrared(void)
{TIM2_Cnt_Init(99,71);       //100usEXTIX_Init();}

3)其他

具体使用到的可以看下面的工程的目录,下面有源码分享的链接。

协议及调试效果

1)硬件实物图

2)微信小程序检测界面

3)演示视频

感兴趣的朋友可以关注一下抖音账号,分享了一些做的东西的视频在上面,不是太多

总结

博客就只是分享了原理图和部分程序,一些注释也不全。有需要的可以下载源码。底层的设备都是做好和服务器直接对接的,要是连接服务器的话可以直接使用。或者加上中转设备,有WiFi,以太网或者4G。协议也是有的,因最近比较忙,等我回苏之后贴出来。谢谢阅览。


http://www.ppmy.cn/news/139332.html

相关文章

STM32单片机软件模拟I2C读取AM2320温湿度传感器数据

STM32单片机使用软件模拟IIC读取AM2320温湿度传感器的数据并显示在0.96寸OLED屏上。 我用的单片机是STM32F103C8T6&#xff0c;程序用的是ST标准库写的。 STM32使用硬件I2C读取SHTC3温湿度传感器&#xff1a;https://blog.zeruns.tech/archives/692.html STM32单片机读取AHT1…

bzoj2320: 最多重复子串

2320: 最多重复子串 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 246 Solved: 66[Submit][Status][Discuss] Description 一个字符串P的重复数定义为最大的整数R&#xff0c;使得P可以分为R段连续且相同的子串。比方说&#xff0c;“ababab”的重复数为3&#xff0c;“a…

OX 【HRBUST - 2320】

题目链接 HRBUST 2320 Kim喜欢玩井字棋。但是他从来都没有赢过&#xff1a;&#xff09;Kim非常好奇井字棋是否有一个必胜的策略。 给定一个局面&#xff0c;以及下一步该谁走&#xff08;o或x&#xff09;&#xff0c;请判断在双方都足够聪明的情况下&#xff08;双方一直采用…

Stm32F103 Hal库硬件iic 访问AM2320温湿度传感器

Stm32F103 Hal库硬件iic 访问AM2320温湿度传感器 管脚配置 PB6 PB7 之前用库函数&#xff0c;一直读不到&#xff0c;换hal库后正常了&#xff0c;因为要在android板上调试&#xff0c;但是板卡没来&#xff0c;只好用stm32 先调试下。 很简单&#xff0c;先初始化i2C1 i2c.c …

洛谷 2320

解题思路&#xff1a; 首先所有的钱袋都可以看成一个取或不取的情况。那么这些钱袋取或不取就可以看作0或1&#xff0c;也就是说&#xff0c;要使用一些数字表示一个范围里的所有数&#xff0c;同时这又很二进制&#xff08;取或不取&#xff09;。所以我们就把钱袋里钱的数量定…

AM2320 温湿度计 单总线读取数据

温湿度计 用单总线方式读取数据 AM2320支持IIC通信和单总线通信&#xff0c;这里只用单总线&#xff1a; 使用单总线时的接线方式时&#xff0c;只需接第二引脚SDA&#xff0c;SCL接地就行。 通信时序图&#xff1a; 由时序可见通信非常简单&#xff0c;关键点要把握好每个时序…

ESP8266-Arduino编程实例-AM2320温度湿度传感器驱动

AM2320温度湿度传感器驱动 1、AM2320介绍 温湿度复合传感器 AM2320数字温湿度传感器是一个经过校准的数字信号输出。 采用特殊的温湿度采集技术,确保产品具有极高的可靠性和优异的长期稳定性。 传感器由一个电容式湿度元件和一个集成的高精度温度测量装置组成,并与一个高性…