基于stm32f103c8t6的家畜养殖监测控制系统

1、主要功能

①环境检测:监测养殖场内外的环境

②环境控制:环境变化时,启动相关设备进行调节

③养殖控制:研究家畜饮食规律,设计合理的食水投喂策略

④家畜检测:监测家畜的生理数据

2、原理图

3、主函数

#include "stm32f10x.h"  
#include "main.h"       
#include "delay.h"      
#include "usart1.h"     
#include "usart2.h"    
#include "usart3.h"     
#include "timer2.h"    
#include "timer3.h"    
#include "timer4.h"    
#include "wifi.h"	    
#include "led.h"        
#include "mqtt.h"       
#include "iic.h"        
#include "adc.h"       
#include "iwdg.h"       
#include "oled.h"
#include "key.h"
#include "dht11.h"      
#include "ds18b20.h"      

char temperature,FLOG1,FLOG2,FLOG3;  	    //定义一个不变量,保存温度值    
char humidity;          //定义一个不变量,保存湿度值
unsigned int SystemTimer = 0;   //用于全局计时的变量           单位秒
unsigned int TEHUTimer = 0;     //用于温湿度采集的计时的变量   单位秒
unsigned int ADCTimer = 0;      //用于ADC采集的计时的变量      单位秒
  short turangtemp; 
	u8 temp1;
  u8 temp2;
char *CMD1 = "switch1:1";       //开关1,开控制命令
char *CMD2 = "switch1:0";       //开关1,关控制命令
char *CMD3 = "switch2:1";       //开关2,开控制命令
char *CMD4 = "switch2:0";       //开关2,关控制命令
char *CMD5 = "switch3:1";       //开关2,开控制命令
char *CMD6 = "switch3:0";       //开关2,关控制命令
	float  adcdata[3],light_data,tuhum_data,ph_data;          //用于保存3个ADC通道的数据	
u8 usart_buf[6];
float adcdata2,adcdata0,adcdata1;
int adcdata11,adcdata00,adcdata22;
int main(void) 
{	
	char key_num,NUM;    //定义一个变量,保存按键扫描函数的返回值
	char data1[64],data2[64];          //缓冲区
	IWDG_Init(6,625);               //独立看门狗 时间4s
	Delay_Init();                   //延时功能初始化              
	IIC_Init();                     //初始化IIC接口
	LED_Init();	                    //LED初始化
	Adc_Init();                     //ADC初始化
	DS18B20_Init();
	Usart1_Init(9600);              //串口1功能初始化,波特率9600
	Usart3_Init(9600);
	DHT11_Init();           //初始化DHT11传感器
	KEY_Init();
	WiFi_ResetIO_Init();            //初始化WiFi的复位IO
	IoT_Parameter_Init();	        //初始化连接云IoT平台MQTT服务器的参数	
	OLED_Init();
	OLED_ColorTurn(0);//0正常显示,1 反色显示
	OLED_DisplayTurn(0);
	
	OLED_ShowChinese(0,0,18,16,1);  //16*16 空温   
	OLED_ShowChinese(16,0,19,16,1);  //16*16
	OLED_ShowChinese(32,0,20,16,1);  //16*16 空湿
	OLED_ShowChinese(48,0,21,16,1);  //16*16
	OLED_ShowChinese(64,0,22,16,1);  //16*16 光照
	OLED_ShowChinese(80,0,23,16,1);  //16*16
	OLED_ShowChinese(96,0,24,16,1);  //16*16 光照
	OLED_ShowChinese(112,0,25,16,1);  //16*16
	
	OLED_ShowChinese(0,16,0,16,1);  //16*16 空温   
	OLED_ShowChinese(16,16,1,16,1);  //16*16
	OLED_ShowChinese(0,32,2,16,1);  //16*16 空湿
	OLED_ShowChinese(16,32,3,16,1);  //16*16
	OLED_ShowChinese(64,16,4,16,1);  //16*16 光照
	OLED_ShowChinese(80,16,5,16,1);  //16*16
		
	OLED_ShowChinese(64,32,12,16,1);  //16*16 烟雾
	OLED_ShowChinese(80,32,13,16,1);  //16*16
	
	OLED_ShowChinese(0,48,26,16,1);  //16*16 人体
	OLED_ShowChinese(16,48,27,16,1);  //16*16 
	OLED_ShowChinese(48,48,30,16,1);  //16*16 
	OLED_ShowChinese(64,48,28,16,1);  //16*16 人体
	OLED_ShowChinese(80,48,29,16,1);  //16*16 
	OLED_ShowChinese(112,48,30,16,1);  //16*16

	OLED_Refresh();
		
	
	while(1)                        //主循环
	{		
		turangtemp=DS18B20_Get_Temp();
		if(turangtemp<0)
		{
		 turangtemp=-turangtemp;
		}
		temp1 = (u8)(turangtemp/10);

	  temp2 = (u8)(turangtemp%10);

		DHT11_Read_Data(&temperature,&humidity);	     //读取温湿度值		
		usart_buf[0] = 0xEF;
		usart_buf[1] = (uint8_t)(temperature);
		usart_buf[2] = (uint8_t)(humidity );
		temp1 = usart_buf[4];
		//tempdata = usart_buf[1];
		//humidata = usart_buf[2];
		sprintf(data1,"%d",usart_buf[1]);
		sprintf(data2,"%d",usart_buf[2]);
		OLED_ShowString(32,16,(u8*)data1,16,1);
		OLED_ShowString(32,32,(u8*)data2,16,1);	
		adcdata0 = (float)(Get_Adc_Average(5,20))*(3.3/4096);	//光照
    adcdata1 = (float)(Get_Adc_Average(6,20))*(3.3/4096);	
    adcdata2 = (float)(Get_Adc_Average(7,20))*(3.3/4096);			
		adcdata00=  100-adcdata0/(5-1.7)*100;//光照	
		adcdata11=  adcdata1/(5-1.7)*100;//烟雾	
		adcdata22=  adcdata2/(5-1.7)*100;//气体
		OLED_ShowNum(96,16,adcdata00,2,16,1);
		OLED_ShowNum(96,32,adcdata11,2,16,1);
		OLED_ShowNum(32,48,temp1,2,16,1);
		key_num = KEY_Scan();
		if(key_num){
				OLED_ShowChinese(96,16,14,16,1);  //16*16 人体
				OLED_ShowChinese(112,16,15,16,1);  //16*16 ;//否则就报警
			  usart_buf[3] = 1;
		}else{		
				OLED_ShowChinese(96,16,16,16,1);  //16*16 人体
			 	OLED_ShowChinese(112,16,17,16,1);  //16*16 	
			  usart_buf[3] = 0;
		}	
		OLED_ShowNum(96,0,ic,3,16,1);
		OLED_Showdecimal(32,32,usart_buf[5],2,2,16);	
		OLED_Showdecimal(96,16,usart_buf[3],2,2,16);
     NUM++;
		 if(NUM==20){
		   FLOG2=0;
			 FLOG1=0;
			 NUM=0;
		 }
		 
        if(adcdata00<=40) LED2_ON;
				else if(adcdata00>40&&FLOG2==0) LED2_OFF;
				if(temp1>=30 |usart_buf[1]>=30)LED1_ON;
		    else if(temp1<30 &&usart_buf[1]<30&&FLOG1==0)LED1_OFF;



    OLED_Refresh();
		/*--------------------------------------------------------------------*/
		/*   Connect_flag=1同服务器建立了连接,我们可以发布数据和接收推送了    */
		/*--------------------------------------------------------------------*/
		if(Connect_flag==1){     
			/*-------------------------------------------------------------*/
			/*                     处理发送缓冲区数据                      */
			/*-------------------------------------------------------------*/
			if(MQTT_TxDataOutPtr != MQTT_TxDataInPtr){                    //if成立的话,说明发送缓冲区有数据了
				//3种情况可进入if
				//第1种:0x10 连接报文
				//第2种:0x82 订阅报文,且ConnectPack_flag置位,表示连接报文成功
				//第3种:SubcribePack_flag=4,说明连接和4个订阅均成功,其他报文可发
				if((DMA_flag==0)&&((MQTT_TxDataOutPtr[2]==0x10)||((MQTT_TxDataOutPtr[2]==0x82)&&(ConnectPack_flag==1))||(SubcribePack_flag==4))){     
					u1_printf("发送数据:0x%x\r\n",MQTT_TxDataOutPtr[2]);  //串口提示信息
					MQTT_TxData(MQTT_TxDataOutPtr);                       //发送数据
					MQTT_TxDataOutPtr += TBUFF_UNIT;                      //指针下移
					if(MQTT_TxDataOutPtr==MQTT_TxDataEndPtr)              //如果指针到缓冲区尾部了
						MQTT_TxDataOutPtr = MQTT_TxDataBuf[0];            //指针归位到缓冲区开头
				} 				
			}//处理发送缓冲区数据的else if分支结尾
			/*-------------------------------------------------------------*/
			/*                     处理接收缓冲区数据                      */
			/*-------------------------------------------------------------*/
			if(MQTT_RxDataOutPtr != MQTT_RxDataInPtr){                //if成立的话,说明接收缓冲区有数据了														
				u1_printf("接收到数据:");                             //串口提示信息
				/*-----------------------------------------------------*/
				/*                    处理CONNACK报文                  */
				/*-----------------------------------------------------*/				
				//if判断,如果第一个字节是0x20,表示收到的是CONNACK报文
				//接着我们要判断第4个字节,看看CONNECT报文是否成功
				if(MQTT_RxDataOutPtr[2]==0x20){             			
				    switch(MQTT_RxDataOutPtr[5]){					
						case 0x00 : u1_printf("CONNECT报文成功\r\n");                            //串口输出信息	
								    ConnectPack_flag = 1;                                        //CONNECT报文成功
									MQTT_Subscribe(S1_TOPIC_NAME,0);	                         //发送缓冲区添加订阅topic,等级0
									break;                                                       //跳出分支case 0x00                                              
						case 0x01 : u1_printf("连接已拒绝,不支持的协议版本,准备重启\r\n");      //串口输出信息
									Connect_flag = 0;                                            //Connect_flag置零,重启连接
									break;                                                       //跳出分支case 0x01   
						case 0x02 : u1_printf("连接已拒绝,不合格的客户端标识符,准备重启\r\n"); //串口输出信息
									Connect_flag = 0;                                            //Connect_flag置零,重启连接
									break;                                                       //跳出分支case 0x02 
						case 0x03 : u1_printf("连接已拒绝,服务端不可用,准备重启\r\n");         //串口输出信息
									Connect_flag = 0;                                            //Connect_flag置零,重启连接
									break;                                                       //跳出分支case 0x03
						case 0x04 : u1_printf("连接已拒绝,无效的用户名或密码,准备重启\r\n");   //串口输出信息
									Connect_flag = 0;                                            //Connect_flag置零,重启连接						
									break;                                                       //跳出分支case 0x04
						case 0x05 : u1_printf("连接已拒绝,未授权,准备重启\r\n");               //串口输出信息
									Connect_flag = 0;                                            //Connect_flag置零,重启连接						
									break;                                                       //跳出分支case 0x05 		
						default   : u1_printf("连接已拒绝,未知状态,准备重启\r\n");             //串口输出信息 
									Connect_flag = 0;                                            //Connect_flag置零,重启连接					
									break;                                                       //跳出分支case default 								
					}				
				}
				/*-----------------------------------------------------*/
				/*                    处理SUBACK报文                   */
				/*-----------------------------------------------------*/				
				//if判断,第一个字节是0x90,表示收到的是SUBACK报文
				//接着我们要判断订阅回复,看看是不是成功
				else if(MQTT_RxDataOutPtr[2]==0x90){ 
						switch(MQTT_RxDataOutPtr[6]){					
						case 0x00 :
						case 0x01 : u1_printf("订阅成功\r\n");            //串口输出信息
							        SubcribePack_flag++;                  //SubcribePack_flag+1,表示订阅报文成功,我们一共订阅4个
									switch(SubcribePack_flag){
										case 1: MQTT_Subscribe(S2_TOPIC_NAME,0);break;	 //发送缓冲区添加订阅topic,等级0.
										case 2: MQTT_Subscribe(S3_TOPIC_NAME,0);break;	 //发送缓冲区添加订阅topic,等级0
										case 3: MQTT_Subscribe(S4_TOPIC_NAME,0);break;	 //发送缓冲区添加订阅topic,等级0
										case 4: LED1_State();                            //判断开关1的初始状态,加入缓冲区,并发布给服务器 

												TIM3_ENABLE_30S();                       //启动定时器3 30s的PING保活定时器
												TIM2_ENABLE_1S();                        //启动定时器2 1s的定时器
												break;
									}
									break;                                //跳出分支                                             
						default   : u1_printf("订阅失败,准备重启\r\n");   //串口输出信息 
									Connect_flag = 0;                     //Connect_flag置零,重启连接
									break;                                //跳出分支 								
					}					
				}
				/*-----------------------------------------------------*/
				/*                  处理PINGRESP报文                   */
				/*-----------------------------------------------------*/
				//if判断,第一个字节是0xD0,表示收到的是PINGRESP报文
				else if(MQTT_RxDataOutPtr[2]==0xD0){ 
					u1_printf("PING报文回复\r\n"); 		  //串口输出信息 
					if(Ping_flag==1){                     //如果Ping_flag=1,表示第一次发送
						 Ping_flag = 0;    				  //要清除Ping_flag标志
					}else if(Ping_flag>1){ 				  //如果Ping_flag>1,表示是多次发送了,而且是2s间隔的快速发送
						Ping_flag = 0;     				  //要清除Ping_flag标志
						TIM3_ENABLE_30S(); 				  //PING定时器重回30s的时间
					}				
				}
				/*-----------------------------------------------------*/
				/*                  处理数据推送报文                   */
				/*-----------------------------------------------------*/				
				//if判断,如果第一个字节是0x30,表示收到的是服务器发来的推送数据
				//我们要提取控制命令
				else if((MQTT_RxDataOutPtr[2]==0x30)){ 
					u1_printf("服务器等级0推送\r\n"); 		   //串口输出信息 
					MQTT_DealPushdata_Qs0(MQTT_RxDataOutPtr);  //处理等级0推送数据
				}				
				
				MQTT_RxDataOutPtr +=RBUFF_UNIT;                     //接收指针下移
				if(MQTT_RxDataOutPtr==MQTT_RxDataEndPtr)            //如果接收指针到接收缓冲区尾部了
					MQTT_RxDataOutPtr = MQTT_RxDataBuf[0];          //接收指针归位到接收缓冲区开头                        
			}
			
			/*-------------------------------------------------------------*/
			/*                     处理命令缓冲区数据                      */
			/*-------------------------------------------------------------*/
			if(MQTT_CMDOutPtr != MQTT_CMDInPtr){                             //if成立的话,说明命令缓冲区有数据了			       
				u1_printf("命令:%s\r\n",&MQTT_CMDOutPtr[2]);                 //串口输出信息
				if(!memcmp(&MQTT_CMDOutPtr[2],CMD1,strlen(CMD1))){           //判断指令,如果是CMD1,开开关1
//					if(LED1_IN_STA){                                         //如果现在IO是高电平,表示开关1是关闭状态                                 
						LED1_ON;     
            FLOG1	=1;				//开开关1
//						LED1_State();                                        //上报开关1状态
//					}			
				}else if(!memcmp(&MQTT_CMDOutPtr[2],CMD2,strlen(CMD2))){     //判断指令,如果是CMD2,关开关1
//					if(!LED1_IN_STA){                                        //如果现在IO是低电平,表示开关1是打开状态
						LED1_OFF;                                            //关开关1
					  FLOG1	=0;				//开开关1 
//						LED1_State();                                        //上报开关1状态
//				}
				}
				else if(!memcmp(&MQTT_CMDOutPtr[2],CMD3,strlen(CMD3))){     //判断指令,如果是CMD3,开开关2
//					if(LED2_IN_STA){                                         //如果现在IO是高电平,表示开关2是关闭状态                                 
					 	LED2_ON;                                             //开开关2
					  FLOG2	=1;				//开开关1
                               //上报开关2状态
//					}			
				}else if(!memcmp(&MQTT_CMDOutPtr[2],CMD4,strlen(CMD4))){     //判断指令,如果是CMD4,关开关2
	//				if(!LED2_IN_STA){                                        //如果现在IO是低电平,表示开关2是打开状态
						LED2_OFF;                                            //关开
            FLOG2	=0;				//开开关1                            //上报开关2状态
//					}
				}
				else if(!memcmp(&MQTT_CMDOutPtr[2],CMD5,strlen(CMD3))){     //判断指令,如果是CMD3,开开关2
//					if(LED2_IN_STA){                                         //如果现在IO是高电平,表示开关2是关闭状态                                 
					 	LED3_ON;                                             //开开关2
					  FLOG3	=1;				//开开关1
                               //上报开关2状态
//					}			
				}else if(!memcmp(&MQTT_CMDOutPtr[2],CMD6,strlen(CMD4))){     //判断指令,如果是CMD4,关开关2
	//				if(!LED2_IN_STA){                                        //如果现在IO是低电平,表示开关2是打开状态
						LED3_OFF;                                            //关开
            FLOG3	=0;				//开开关1                            //上报开关2状态
//					}
				}
				MQTT_CMDOutPtr += CBUFF_UNIT;                             	 //指针下移
				if(MQTT_CMDOutPtr==MQTT_CMDEndPtr)           	             //如果指针到缓冲区尾部了
					MQTT_CMDOutPtr = MQTT_CMDBuf[0];          	             //指针归位到缓冲区开头				
			}//处理命令缓冲区数据的else if分支结尾	
			
			/*-------------------------------------------------------------*/
			/*                     处理定时上传任务                        */
			/*-------------------------------------------------------------*/
			Data_State();         //定时上传各种数据的任务
			Delay_Ms(1);          //延时,必须有,里面有喂狗,不然看门狗会溢出,造成复位				
		}	
		/*--------------------------------------------------------------------*/
		/*         Connect_flag=0同服务器断开了连接,我们要连接服务器          */
		/*--------------------------------------------------------------------*/
		else{ 
			u1_printf("准备连接服务器\r\n");                  //串口输出信息
			Usart2_Init(115200);                             //串口2功能初始化,波特率115200	
			TIM_Cmd(TIM4,DISABLE);                           //关闭TIM4 
			TIM_Cmd(TIM3,DISABLE);                           //关闭TIM3  
			TIM_Cmd(TIM2,DISABLE);                           //关闭TIM2    
			WiFi_RxCounter=0;                                //WiFi接收数据量变量清零                        
			memset(WiFi_RX_BUF,0,WiFi_RXBUFF_SIZE);          //清空WiFi接收缓冲区 
			if(WiFi_Connect_IoTServer()==0){   			     //如果WiFi连接云服务器函数返回0,表示正确,进入if
				u1_printf("连接服务器成功\r\n");              //串口输出信息
				Usart2_IDELInit(115200);                     //串口2 开启DMA 和 空闲中断
				Connect_flag = 1;                            //Connect_flag置1,表示连接成功	
				SystemTimer = 0;                             //全局计时时间变量清0
				TEHUTimer = 0;                               //温湿度计时时间变量清0
				ADCTimer = 0;                                //ADC计时时间变量清0
				WiFi_RxCounter=0;                            //WiFi接收数据量变量清零                        
				memset(WiFi_RX_BUF,0,WiFi_RXBUFF_SIZE);      //清空WiFi接收缓冲区 
				MQTT_Buff_Init();                            //初始化发送接收命令缓冲区 
			}				
		}
	
	}
}

4、上位机

相关推荐

  1. 基于STM32F103C8T6小四轴无人机悬停代码

    2024-05-04 22:08:01       42 阅读
  2. 基于stm32f103c8t6连接阿里云上传信息

    2024-05-04 22:08:01       57 阅读
  3. 基于STM32F103C8T6单片机1秒定时器设计与应用

    2024-05-04 22:08:01       56 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-04 22:08:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-04 22:08:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-05-04 22:08:01       82 阅读
  4. Python语言-面向对象

    2024-05-04 22:08:01       91 阅读

热门阅读

  1. 大模型+低代码平台

    2024-05-04 22:08:01       33 阅读
  2. 2024年目标检测数据集大合集所有下载地址汇总

    2024-05-04 22:08:01       169 阅读
  3. SpringBoot camunda

    2024-05-04 22:08:01       30 阅读
  4. 算法:状态压缩dp

    2024-05-04 22:08:01       112 阅读
  5. 什么是CI/CD流水线

    2024-05-04 22:08:01       28 阅读
  6. windows ubuntu:sed,awk,grep篇:5.sed 附加命令

    2024-05-04 22:08:01       28 阅读
  7. GitHacker:Git源码泄漏检测工具可恢复整个Git Repo

    2024-05-04 22:08:01       33 阅读
  8. 由混淆依赖所引起的RCE

    2024-05-04 22:08:01       33 阅读
  9. 深入探索Elasticsearch中的QueryBuilders

    2024-05-04 22:08:01       37 阅读