ZigBee課程設計(溫溼度採集控制)

轉眼間ZigBee課程也上完了,本次完成了一個課程設計,希望大家能夠互相探討,解決問題,若有錯誤的地方麻煩大家及時提醒,我將不勝感激!當然我是和兩位搭檔一起合作完成,我只負責了stm32和單片機部分,希望大家多指教~~

設計方案概述

設計方案

在大棚蔬菜中安置溫溼度傳感器與溫溼度警報顯示裝置,通過ZigBee通信技術,串口通信技術將採集到的該區域溫溼度上傳至控制系統,下發給顯示裝置。控制系統STM32F103ZET6協調器組成,接收數據信息,整理,按區域節點顯示在控制端的LCD屏,判斷併產生報警信號。顯示裝置實時顯示溫溼度,根據信號產生報警,關閉報警來提醒人們。

設計圖
在這裏插入圖片描述

資源說明

1個STM32F103ZET6開發板
2個STC89C52單片機
3個ZigBee開發板(1個協調器,2個終端節點)

通信過程中的信息格式

爲了快點完成課設,所以通信的格式特別的簡潔,也不規範,考慮的因素很少,希望大家可以自己設計

五位字符(數據信息):
第一位:節點編號(1,2)
第二位:溫度的十位
第三位:溫度的個位
第四位:溼度的十位
第五位:溼度的個位

五位字符(警報信息):
第一位:警報標誌(3代表1號節點警報,4代表2號節點警報)
第二位:固定爲0
第三位:固定爲0
第四位:固定爲0
第五位:控制開關警報

模塊介紹

顯示報警模塊

通過STC89C52單片機與採集模塊進行串口通信
功能
1.將接收到的信息在數碼管上顯示
2.通過按鍵可以切換查看溫溼度以及節點號
3.當收到報警信號時,報警(數碼管顯示全0),當接收到取消報警信號時,恢復正常顯示

採集模塊

作爲終端節點的ZigBee開發板(CC2530)
功能
1.採集溫溼度將數據發送給協調器和顯示報警模塊
2.接收協調器報警信號,將報警信號發送給顯示報警模塊

中控模塊

中控模塊由兩部分組成:
1.一塊作爲協調器的ZigBee開發板
2.STM32F103ZET6開發板

它們之間通過串口通信

協調器功能
1.組建ZigBee網絡
2.將採集模塊上傳的溫溼度數據通過串口發送給STM32F103ZET6開發板
3.接收STM32F103ZET6開發板發出的報警信號並廣播給終端節點
STM32F103ZET6開發板的功能

  1. 接收來自協調器的串口數據,並將數據信息顯示到LCD屏
  2. 判斷溫度是否超過閾值,併產生報警
  3. 產生報警後通過按鍵發送報警信號或關閉報警信號給協調器

具體實現

接下來爲大家介紹一下個模塊的部分代碼

顯示報警模塊

1. 接收串口信息:接受到信息產生中斷,在中斷服務函數中將數據存入buf數組中,由於涉及到控制信號的接收所以設置一個alterflag標誌位來控制信號數據不存入buf中,只需將第五個控制位存入變量n中

void receive(void) interrupt 4{
	if(RI==1)
	{
		 //FENG=1;
		if(i==5)	   //接收到5個後將下標置0,爲下次接受做準備
			i=0;
		RI=0;
		receiv=SBUF;   //將緩存變量SBUF中數據存入變量receiv
		if(i==0&&(receiv=='4'||receiv=='3')  //通過數據的第一位判斷是否是警報信號
			 alterflag=0;			 //警報信號標誌置爲0
		else if(alterflag)			  //如果不是警報信號而是溫溼度數據則存入buf中
			buf[i]=receiv-0x30;
		else if(i==4&&alterflag==0)	   //是警報信號將信號中第五個控制位存入變量n中
			n=receiv;
		i++;
		flag=1;	   //接收到數據標誌
	}
}

2. 數碼管顯示:根據一些標誌來判斷顯示的信息,數據顯示:第一個爲節點號,第二個爲溫溼度的十位,第三個爲溫溼度的個位。報警顯示:全部顯示0

void lcdshow()
{
	if(alterflag==0)	  //是報警信號
	{
		if(n=='1')		 //報警信號第五個控制位爲1則爲報警
		{
			buf[0]=0;		//數碼管全部顯示0
			buf[1]=0;
			buf[2]=0;
			buf[3]=0;
			buf[4]=0;
		}
		else if(n=='0')	  //報警信號第五個控制位爲0則爲取消報警
		{
			alterflag=1;
		}	
	}
	if(sign)	//根據按鍵信息來顯示溫度還是溼度  sign:1爲溫度 0爲溼度
	{
		P1=0xf1;
		P0=led_mod[buf[2]];
		delayms(5);
		P1=0xf2;
		P0=led_mod[buf[1]];
		delayms(5);
		P1=0xf4;
		P0=led_mod[buf[0]];
		delayms(5);
	}
	else
	{
		P1=0xf1;
		P0=led_mod[buf[4]];
		delayms(5);
		P1=0xf2;
		P0=led_mod[buf[3]];
		delayms(5);
		P1=0xf4;
		P0=led_mod[buf[0]];
		delayms(5);	
	}	

3. 按鍵切換顯示內容:判斷是否按下,按下改變按鍵標誌

if(KEY==0)	//按鍵是否按下
{
	delayms(10);  //消抖
	if(KEY==0)
	{
		while(KEY==0);	//當按鍵鬆開
		sign=!sign;		//改變按鍵的標誌
	}
}

採集模塊

1. 採集溫溼度將數據發送給協調器和顯示報警模塊
終端節點加入網絡後觸發SEND_DATA_EVENT事件調用下面函數。

void GenericApp_SendTheMessage( void )
{
    DHT11();   //溫度採集 
    Data[0] = 2+0x30;//用於表示自己的節點號
    Data[1] = wendu_shi+0x30;
    Data[2] = wendu_ge+0x30;
    Data[3] = shidu_shi+0x30;
    Data[4] = shidu_ge+0x30;
    AF_DataRequest( &GenericApp_DstAddr, &GenericApp_epDesc,
                       GENERICAPP_CLUSTERID,
                       6,
                       (uint8 *)&Data,
                       &GenericApp_TransID,
                       AF_DISCV_ROUTE, 
                       AF_DEFAULT_RADIUS );//發送到協調器
    HalUARTWrite(0, Data,5);//發送到顯示報警模塊  
}

其中DHT11()爲溫度採集函數,其代碼如下

void DHT11(void)   //溫溼傳感啓動
{
  P0DIR |= 0x10;
  wenshi=0;
  Delay_ms(19);  //>18MS 主機拉低18ms
  wenshi=1; 
   
  //主機延時40us
  Delay_10us();
  Delay_10us();
  Delay_10us();
  Delay_10us();  
  
  wenshi=1; 
  P0DIR &= ~0x10;//重新配置IO口方向 0001 0000
  if(!wenshi) 
  {
    ucharFLAG=2;
    //判斷從機是否80us的低電平,響應信號是否結束
    while((!wenshi)&&ucharFLAG++);
    ucharFLAG=2;
    while((wenshi)&&ucharFLAG++); 
    COM();//讀溼度的高八位
    ucharRH_data_H_temp=ucharcomdata;
    COM();//讀溼度的低八位
    ucharRH_data_L_temp=ucharcomdata;
    COM();//讀溫度的高八位
    ucharT_data_H_temp=ucharcomdata;
    COM();//讀溫度的低八位
    ucharT_data_L_temp=ucharcomdata;    
    COM();
    ucharcheckdata_temp=ucharcomdata;//校驗和
    
    //數據校驗
    wenshi=1; 
    uchartemp=(ucharT_data_H_temp+ucharT_data_L_temp+ucharRH_data_H_temp+ucharRH_data_L_temp);    
    if(uchartemp==ucharcheckdata_temp)//校驗結果正確則收集數據
    {
      ucharRH_data_H=ucharRH_data_H_temp;//收集溼度
      ucharRH_data_L=ucharRH_data_L_temp;
      
      ucharT_data_H=ucharT_data_H_temp;//收集溫度
      ucharT_data_L=ucharT_data_L_temp;
      
      ucharcheckdata=ucharcheckdata_temp;
    } 
    wendu_shi=ucharT_data_H/10; 
    wendu_ge=ucharT_data_H%10;
    shidu_shi=ucharRH_data_H/10; 
    shidu_ge=ucharRH_data_H%10;        
  } 
  else //沒用成功讀取,返回0
  {
    wendu_shi=0; 
    wendu_ge=0;    
    shidu_shi=0; 
    shidu_ge=0;  
  } 
}
void COM(void) // 溫溼寫入
{     
  uchar i;         
  for(i=0;i<8;i++)    
  {
    ucharFLAG=2;
    //如果高電平 或者uchatFLAG到達0 退出循環
    while((!wenshi)&&ucharFLAG++);
    Delay_10us();
    Delay_10us();
    Delay_10us();
    uchartemp=0;
    if(wenshi)// 如果P0_4是高電平,
      uchartemp=1;//超過30us依然爲高電平,即數據爲1;否則數據爲0
    ucharFLAG=2;
    //如果是高電平並且ucharFLAG++ 一直爲真 直到255 當做延時 
    //ucharFLAG變成0 停止執行 但是wenshi沒有變成0 說明沒有響應
    while((wenshi)&&ucharFLAG++);   //超時則跳出for循環
    if(ucharFLAG==1)
      break;    
    ucharcomdata<<=1;
    ucharcomdata|=uchartemp;  //判斷數據是0還是1
  }    
}

2. 接收協調器報警信號,將報警信號發送給顯示報警模塊
收到協調器廣播消息根據數據的第一位判斷是否爲發送給自己的,其中3表示1號節點,4表示2號節點。(其中燒另外一個節點時判斷改爲判斷"3")

void GenericApp_MessageMSGCB(afIncomingMSGPacket_t *pkt )
{
  uint8 buf[5];
  switch(pkt->clusterId)
  {
  case (GENERICAPP_CLUSTERID):
    osal_memcpy(buf,pkt -> cmd.Data,5);
     if(osal_memcmp(buf,"4",1))//只判斷第一位
     {
        HalUARTWrite(0, buf,5);//發送到顯示報警模塊
     }
  }
}

中控模塊

協調器
1. 組建ZigBee網絡
網絡組建成功點亮黃燈,收到終端節點傳來的數據後點亮藍燈。
2. 將採集模塊上傳的溫溼度數據通過串口發送給STM32F103ZET6

void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
  uint8 buf[10];
  switch ( pkt->clusterId )
  {
    case GENERICAPP_CLUSTERID: 
      uint8 endbuf[2]={0x0d,0x0a};
      HalLedSet(HAL_LED_1,HAL_LED_MODE_ON);
      osal_memcpy(&buf,pkt->cmd.Data,5);存儲終端節點的數據
      HalUARTWrite(0, buf,5);//發送給STM32F103ZET6
      HalUARTWrite(0, endbuf,2);//以換行符結尾
      break;   
  } 
}

3. 接收STM32F103ZET6發出的報警信號並廣播給終端節點
用回調函數來處理報警信號,並以廣播模式發出

GenericApp_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;//廣播模式
  GenericApp_DstAddr.endPoint =GENERICAPP_ENDPOINT;
  GenericApp_DstAddr.addr.shortAddr = 0xFFFF;//所有節點

以下爲回調函數

static void rxCB(uint8 port, uint8 event)
{
  uint8 buf[5];
  HalUARTRead(0,buf,5);//讀取STM32F103ZET6發來的報警信號
  AF_DataRequest( &GenericApp_DstAddr, &GenericApp_epDesc,
                       GENERICAPP_CLUSTERID,
                       5,
                       (uint8*)&buf,
                       &GenericApp_TransID,
                       AF_DISCV_ROUTE, 
                       AF_DEFAULT_RADIUS );//廣播給網絡下的所有節點
}

STM32F103ZET6
1.接收串口信息:在串口中斷服務函數中將收到的數據保存在串口緩存中,根據接收到信息標誌USART_RX_STA的最高位來判斷是否收到數據,然後調用DataHandle函數將緩存中的數據存入對應的變量中

u8 USART_RX_BUF[USART_REC_LEN];     //接收緩衝,最大USART_REC_LEN //(200)個字節.
//接收狀態
//bit15,	接收完成標誌
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字節數目
u16 USART_RX_STA=0;       //接收狀態標記	

DataHandle函數:

void DataHandle()
{
	char num = USART_RX_BUF[0];    //根據數據的第一位判斷是哪個節點
	if(num =='1')   //1節點
	{
		number1[0]=USART_RX_BUF[0];   //存下節點標號
		number1[1]='\0';
		temp1[0]=USART_RX_BUF[1];			//存下溫度的十位
		temp1[1]=USART_RX_BUF[2];			//存下溫度的個位
		temp1[2]='\0';
		hum1[0]=USART_RX_BUF[3];      //存下溼度的十位
		hum1[1]=USART_RX_BUF[4];      //存下溼度的個位
		hum1[2]='\0';
	}
	else if(num=='2')  //2節點
	{
		number2[0]=USART_RX_BUF[0];
		number2[1]='\0';
		temp2[0]=USART_RX_BUF[1];
		temp2[1]=USART_RX_BUF[2];
		temp2[2]='\0';
		hum2[0]=USART_RX_BUF[3];
		hum2[1]=USART_RX_BUF[4];
		hum2[2]='\0';
	}
}

2.LCD顯示:在循環裏面調用顯示函數LCD_show,根據報警標誌來顯示相應的報警信息

void LCD_show()
{
	LCD_ShowString(30,40,200,16,16,"number:");
	LCD_ShowString(120,40,200,16,16,number1);
	LCD_ShowString(30,60,200,16,16,"temp:");
	LCD_ShowString(120,60,200,16,  16,temp1);
	LCD_ShowString(30,80,200,16,16,"humidity:");
	LCD_ShowString(120,80,200,16,16,hum1);
	LCD_ShowString(30,100,200,16,16,"number:");
	LCD_ShowString(120,100,200,16,16,number2);
	LCD_ShowString(30,120,200,16,16,"temp:");
	LCD_ShowString(120,120,200,16,16,temp2);
	LCD_ShowString(30,140,200,16,16,"humidity:");
	LCD_ShowString(120,140,200,16,16,hum2);
	LCD_ShowString(30,280,200,16,16,"lowtemp:15  hightemp:19"); 
	if(ALERT1==true && ALERT2==false)    //節點1產生報警
	{
		LCD_ShowString(30,175,200,16,24,"ALERT1");
		LCD_ShowString(30,210,200,16,24,"PRESS KEY0");
	}
	else if(ALERT1==false && ALERT2==true)   //節點2產生報警
	{
		LCD_ShowString(30,175,200,16,24,"ALERT2");
		LCD_ShowString(30,210,200,16,24,"PRESS KEY0");
	}
	else if(ALERT1 && ALERT2)   //節點1,2都產生報警
	{
		LCD_ShowString(30,175,200,16,24,"ALERT");
		LCD_ShowString(30,210,200,16,24,"PRESS KEY0");
	}
}

3.判斷溫度是否超過閾值,併產生報警:根據收到數據轉化位十進制數與閾值比較,若超過閾值則將報警標誌置1,具體函數在接收到信息後進來判斷,函數爲ALERT01

void ALERT01()
{
	int temprture1 = (temp1[0]-0x30)*10+(temp1[1]-0x30);    //溫度轉化爲十進制數
	int temprture2 = (temp2[0]-0x30)*10+(temp2[1]-0x30); 
	if((temprture1<=lowtemp && temprture1>0) || temprture1>=hightemp)   //判斷節點1溫度是否超過閾值
	{
		ALERT1 = true;  //改變節點1報警標誌
	}  
	if((temprture2<=lowtemp && temprture2>0) || temprture2>=hightemp)   //判斷節點2溫度是否超過閾值
	{
		ALERT2 = true;  //改變節點2報警標誌
	}
}

4.按鍵下發報警信息:當產生報警後可以按KEY1下發報警信息給協調器,按KEY0可取消報警,下發取消報警信息
KEY1的中斷服務函數

void EXTI3_IRQHandler(void)
{
	delay_ms(10);//消抖
	if(ALERT1 || ALERT2)  //有報警
	{
		if(ALERT1)
		{
			uart_send_buff(USART1,"30001",5);  //第一位3與第五位1表示1號節點的報警信息
		}
		if(ALERT2)
		{
			uart_send_buff(USART1,"40001",5);  //第一位4與第五位1表示2號節點的報警信息
		}
		LCD_Clear(WHITE);
		EXTI_ClearITPendingBit(EXTI_Line3);  //清除LINE3上的中斷標誌位
	}
}

KEY0的中斷服務函數

void EXTI4_IRQHandler(void)
{
	delay_ms(10);//消抖
	if(ALERT1 || ALERT2)  //有報警
	{
		if(ALERT1)
		{
			ALERT1=false;   //1節點警報標誌置位false
			uart_send_buff(USART1,"30000",5);  //第一位3與第五位0表示1號節點的取消報警信息
		}
		if(ALERT2)
		{
			ALERT2=false;  ////2節點警報標誌置位false
			uart_send_buff(USART1,"40000",5);  //第一位4與第五位0表示2號節點的取消報警信息
		}
		LCD_Clear(WHITE);
		EXTI_ClearITPendingBit(EXTI_Line4);  //清除LINE4上的中斷標誌位
	}
}

5.下發報警信號函數uart_send_buff:

void uart_send_buff(USART_TypeDef* USARTx, u8 *buf,u8 len)  
{  
  u8 j=0 ;
	LED0=!LED0;  //紅燈狀態反轉
	for(j=0;j<len;j++)							//循環發送給定長度
	{
	  while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)==RESET); //循環,直到發送完畢   
		USART_SendData(USARTx,buf[j]);   //發送數據
	}
}
![在這裏插入圖片描述](https://img-blog.csdnimg.cn/2020010515275091.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQyMzk4MzQy,size_16,color_FFFFFF,t_70)

結果展示

採集模塊採集到溫溼度通過串口發給顯示報警模塊
由圖可知當前1號節點溫度數值爲:26,2號節點溫度值爲:24
在這裏插入圖片描述
當按下按鍵時,切換查看溼度
由圖可知當前1號節點溼度數值爲:17,2號節點溼度值爲:16
在這裏插入圖片描述
採集模塊將採集到的溫溼度發給協調器,協調器通過串口輸出可以看到1,2節點的溫溼度
在這裏插入圖片描述
協調器通過串口將溫溼度發給STM32控制板顯示在LCD上並且由於溫度過高發出警報
在這裏插入圖片描述
Number:1
Temp:26
Humidity:17
Number:2
Temp:24
Humidity:16

Lowtemp:15 hightemp:19

當按下按鍵1時通過串口發出警報信號給協調器
警報信號30001表示給1號節點的警報信號
在這裏插入圖片描述
警報信號40001表示給2號節點的警報信號

在這裏插入圖片描述
協調器在將警報信號廣播給採集模塊,採集模塊收到信號後通過串口將信號發個顯示報警模塊,產生報警(數碼管顯示全0)
在這裏插入圖片描述
當按下按鍵0時通過串口發出取消警報信號給協調器
警報信號30000表示給1號節點的取消警報信號
在這裏插入圖片描述
警報信號40000表示給2號節點的警報信號
在這裏插入圖片描述
協調器在將警報信號廣播給採集模塊,採集模塊收到信號後通過串口將信號發個顯示報警模塊,取消報警信號,當下次溫溼度數據來到時恢復顯示。
由圖可知當前1號節點溫度數值爲:25,2號節點溫度值爲:24
在這裏插入圖片描述

總結

這門課程也學完了,雖然沒什麼機會去實踐,去將所學的知識好好利用起來,希望自己以後能夠多加深入,研究!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章