STM32F429與CC2530 ZigBee模塊通信

本學期學了物聯網技術與應用課程,有接觸到了ZigBee模塊,期末課設就是做一個簡單的ZigBee環境數據採集,通過串口傳輸到STM32,並用esp8266 WIFI模塊上傳至雲端。這裏記錄一下STM32F429與CC2530 ZigBee模塊通信的方法。

目錄

  • ZigBee簡介
  • 串口通信簡介
  • 簡單的數據顯示

ZigBee簡介
ZigBee譯爲"紫蜂",它與藍牙相類似。是一種新興的短距離無線通信技術,用於傳感控制應用(Sensor and Control)。由IEEE 802.15工作組中提出,並由其TG4工作組制定規範。特點如下:
①低功耗。在低耗電待機模式下,2節5號乾電池可支持1個節點工作6~24個月,甚至更長。這是ZigBee的突出優勢。相比較,藍牙能工作數週、WiFi可工作數小時。
TI公司和德國的Micropelt公司共同推出新能源的ZigBee節點。該節點採用Micropelt公司的熱電發電機給TI公司的ZigBee提供電源。
②低成本。通過大幅簡化協議(不到藍牙的1/10),降低了對通信控制器的要求,按預測分析,以8051的8位微控制器測算,全功能的主節點需要32KB代碼,子功能節點少至4KB代碼,而且ZigBee免協議專利費。每塊芯片的價格大約爲2美元。
③低速率。ZigBee工作在20~250kbps的速率,分別提供250 kbps(2.4GHz)40kbps(915 MHz)和20kbps(868 MHz)的原始數據吞吐率,滿足低速率傳輸數據的應用需求。
④近距離。傳輸範圍一般介於10~100m之間,在增加發射功率後,可增加到1-3km。這指的是相鄰節點間的距離。如果通過路由和節點間通信的接力,傳輸距離將可以更遠。
⑤短時延。ZigBee的響應速度較快,一般從睡眠轉入工作狀態只需15ms,節點連接進入網絡只需30ms,進一步節省了電能。相比較,藍牙需要3~10s、WiFi 需要3 s。
⑥高容量。ZigBee可採用星狀、片狀和網狀網絡結構,由一個主節點管理若干子節點,最多一個主節點可管理254個子節點;同時主節點還可由上一層網絡節點管理,最多可組成65000 個節點的大網。
⑦高安全。ZigBee提供了三級安全模式,包括安全設定、使用訪問控制清單(Access Control List, ACL) 防止非法獲取數據以及採用高級加密標準(AES 128)的對稱密碼,以靈活確定其安全屬性。
⑧免執照頻段。使用工業科學醫療(ISM)頻段,915MHz(美國), 868MHz(歐洲), 2. 4GHz(全球) 。
在這裏插入圖片描述

串口通信簡介

串口通信是指外設和計算機間,通過數據信號線 、地線、控制線等,按位進行傳輸數據的一種通訊方式。這種通信方式使用的數據線少,在遠距離通信中可以節約通信成本,但其傳輸速度比並行傳輸低。
串口是計算機上一種非常通用的設備通信協議。大多數計算機(不包括筆記本電腦)包含兩個基於RS-232的串口。串口同時也是儀器儀表設備通用的通信協議;很多GPIB兼容的設備也帶有RS-232口。同時,串口通信協議也可以用於獲取遠程採集設備的數據。
RS-232(ANSI/EIA-232標準)是IBM-PC及其兼容機上的串行連接標準。可用於許多用途,比如連接鼠標、打印機或者Modem,同時也可以接工業儀器儀表。用於驅動和連線的改進,實際應用中RS-232的傳輸長度或者速度常常超過標準的值。RS-232只限於PC串口和設備間點對點的通信。RS-232串口通信最遠距離是50英尺。

簡單的數據顯示

簡單來說,就是把ZigBee的串口和STM32的串口連接起來,這裏STM32的串口選取串口2,波特率都設置爲115200
在這裏插入圖片描述
接線如下:
STM32-----ZigBee
VCC -----> VCC
GND -----> GND
TXD -----> RXD
RXD -----> TXD

程序部分,就是通過配置串口2實現數據的採集,這裏給出一個簡單的串口2配置函數,通過該函數的配置可以在串口1輸出在ZigBee傳輸過來的數據:

//初始化IO 串口1 
//bound:波特率
void uart_init(u32 bound)
{	
	//UART 初始化設置
	UART1_Handler.Instance=USART1;					    //USART1
	UART1_Handler.Init.BaudRate=bound;				    //波特率
	UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //字長爲8位數據格式
	UART1_Handler.Init.StopBits=UART_STOPBITS_1;	    //一個停止位
	UART1_Handler.Init.Parity=UART_PARITY_NONE;		    //無奇偶校驗位
	UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //無硬件流控
	UART1_Handler.Init.Mode=UART_MODE_TX_RX;		    //收發模式
	HAL_UART_Init(&UART1_Handler);					    //HAL_UART_Init()會使能UART1
	
	//HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);//該函數會開啓接收中斷:標誌位UART_IT_RXNE,並且設置接收緩衝以及接收緩衝接收最大數據量 
}

//串口2初始化
void uart2_init(u32 baund)
{
    UART2_Handler.Instance=USART2;					    //USART2
	UART2_Handler.Init.BaudRate=baund;				    //波特率
	UART2_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //字長爲8位數據格式
	UART2_Handler.Init.StopBits=UART_STOPBITS_1;	    //一個停止位
	UART2_Handler.Init.Parity=UART_PARITY_NONE;		    //無奇偶校驗位
	UART2_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //無硬件流控
	UART2_Handler.Init.Mode=UART_MODE_TX_RX;		    //收發模式    
    HAL_UART_Init(&UART2_Handler);//HAL_UART_Init()會使能UART2
}

//UART底層初始化,時鐘使能,引腳配置,中斷配置
//此函數會被HAL_UART_Init()調用
//huart:串口句柄
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
    //GPIO端口設置
	GPIO_InitTypeDef GPIO_Initure;
	
	if(huart->Instance==USART1)//如果是串口1,進行串口1 MSP初始化
	{
		__HAL_RCC_GPIOA_CLK_ENABLE();			//使能GPIOA時鐘
		__HAL_RCC_USART1_CLK_ENABLE();			//使能USART1時鐘
	
		GPIO_Initure.Pin=GPIO_PIN_9;			//PA9
		GPIO_Initure.Mode=GPIO_MODE_AF_PP;		//複用推輓輸出
		GPIO_Initure.Pull=GPIO_PULLUP;			//上拉
		GPIO_Initure.Speed=GPIO_SPEED_FAST;		//高速
		GPIO_Initure.Alternate=GPIO_AF7_USART1;	//複用爲USART1
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA9

		GPIO_Initure.Pin=GPIO_PIN_10;			//PA10
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA10
		
#if EN_USART1_RX
		HAL_NVIC_EnableIRQ(USART1_IRQn);				//使能USART1中斷通道
		HAL_NVIC_SetPriority(USART1_IRQn,3,3);			//搶佔優先級3,子優先級3
#endif	
	}
    
    if(huart->Instance==USART2)//如果是串口2,進行串口2 MSP初始化
	{
		__HAL_RCC_GPIOA_CLK_ENABLE();			//使能GPIOA時鐘
		__HAL_RCC_USART2_CLK_ENABLE();			//使能USART3時鐘
	
		GPIO_Initure.Pin=GPIO_PIN_2;			//PA2
		GPIO_Initure.Mode=GPIO_MODE_AF_PP;		//複用推輓輸出
		GPIO_Initure.Pull=GPIO_PULLUP;			//上拉
		GPIO_Initure.Speed=GPIO_SPEED_FAST;		//高速
		GPIO_Initure.Alternate=GPIO_AF7_USART2;	//複用爲USART2
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PB10

		GPIO_Initure.Pin=GPIO_PIN_3;			//PA3
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA3
		
		__HAL_UART_ENABLE_IT(huart,UART_IT_RXNE);		//開啓接收中斷
		HAL_NVIC_EnableIRQ(USART2_IRQn);				//使能USART3中斷
		HAL_NVIC_SetPriority(USART2_IRQn,2,3);			//搶佔優先級2,子優先級3	
    }
}

//串口1中斷服務程序
void USART1_IRQHandler(void)                	
{ 
	u8 Res;
#if SYSTEM_SUPPORT_OS	 	//使用OS
	OSIntEnter();    
#endif
	if((__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_RXNE)!=RESET))  //接收中斷(接收到的數據必須是0x0d 0x0a結尾)
	{
        HAL_UART_Receive(&UART1_Handler,&Res,1,1000); 
		if((USART_RX_STA&0x8000)==0)//接收未完成
		{
			if(USART_RX_STA&0x4000)//接收到了0x0d
			{
				if(Res!=0x0a)USART_RX_STA=0;//接收錯誤,重新開始
				else USART_RX_STA|=0x8000;	//接收完成了 
			}
			else //還沒收到0X0D
			{	
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
				{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收數據錯誤,重新開始接收	  
				}		 
			}
		}   		 
	}
	HAL_UART_IRQHandler(&UART1_Handler);	
#if SYSTEM_SUPPORT_OS	 	//使用OS
	OSIntExit();  											 
#endif
} 

void USART2_IRQHandler(void)
{
	u8 Res;
	if((__HAL_UART_GET_FLAG(&UART2_Handler,UART_FLAG_RXNE)!=RESET))  //接收中斷(接收到的數據必須是0x0d 0x0a結尾)
	{
        HAL_UART_Receive(&UART2_Handler,&Res,1,1000); 
		if((USART2_RX_STA&0x8000)==0)//接收未完成
		{
			if(USART2_RX_STA&0x4000)//接收到了0x0d
			{
				if(Res!=0x0a)USART2_RX_STA=0;//接收錯誤,重新開始
				else USART2_RX_STA|=0x8000;	//接收完成了 
			}
			else //還沒收到0X0D
			{	
				if(Res==0x0d)USART2_RX_STA|=0x4000;
				else
				{
					USART2_RX_BUF[USART2_RX_STA&0X3FFF]=Res ;
					USART2_RX_STA++;
					if(USART2_RX_STA>(USART2_MAX_RECV_LEN-1))USART2_RX_STA=0;//接收數據錯誤,重新開始接收	  
				}		 
			}
		}   		 
	}
	HAL_UART_IRQHandler(&UART2_Handler);			 											 
}

main.c中的輸出如下:

int main(void)
{    
    u8 reclen=0;
    HAL_Init();                     //初始化HAL庫    
    Stm32_Clock_Init(360,25,2,8);   //設置時鐘,180Mhz
    delay_init(180);
    uart_init(115200);
    uart2_init(115200);
	
	printf("Welcome to use!\r\n");
    
	while(1)
	{      
		reclen=USART2_RX_STA&0X7FFF;	//得到數據長度
		USART2_RX_BUF[reclen]=0;	 	//加入結束符

		printf("%s\r\n",USART2_RX_BUF);//USART2接ZigBeeTXD和RXD
 		USART2_RX_STA=0;
        delay_ms(1000);
	}
}

ZigBee部分的代碼是一個裸機代碼,隨便寫的:

/**************************************/
/*           WeBee團隊                */
/*         Zigbee學習例程             */
/*例程名稱:溫溼度傳感器DHT11         */
/*建立時間:2012/10/2                 */
/*描述:將採集到的環境信息通過串口打印到
        串口調試助手。
**************************************/
#include <ioCC2530.h>
#include <string.h>
#include "UART.H" 
#include "DHT11.H" 

#define AIR P2_0    //定義煙霧接口
#define HUO P1_1   //定義火焰接口
#define uint unsigned int
#define uchar unsigned char

void Yanwu_init();
void huoyan_init();
uchar AirScan();
uchar AirScan2();
void Delayms(uint);

void Delayms(uint xms)  
{
 uint i,j;
 for(i=xms;i>0;i--)
   for(j=587;j>0;j--);
}

void Yanwu_init()
{
      P2SEL &= ~0X01;     
      P2DIR &= ~0X01;     
      P2INP &=  ~0x01;  
}
void huoyan_init()
{
      P1SEL &= ~0X01;    
      P1DIR &= ~0X01;    
      P1INP &=  ~0x01;  
}

uchar AirScan(void)
{
  if(AIR==0)
  {
      Delayms(10);
      if(AIR==0)
      {
      
        return 1;   
      }
  }
  return 0;           
}

uchar AirScan2(void)
{
  if(HUO==0)
  {
      Delayms(10);
      if(HUO==0)
      {
      
        return 1;   // ?T?ì?í
      }
  }
  return 0;           //óD?ì?í
}

/***************************
          主函數
***************************/
void main(void)
{
        Yanwu_init();
        huoyan_init();
        Delay_ms(1000);//讓設備穩定
        InitUart();    //串口初始化
	while(1)
	{          
         DHT11();       //獲取溫溼度
         P0DIR |= 0x40; //IO口需要重新配置 
         
         /******溫溼度的ASC碼轉換*******/
         temp[0]=wendu_shi+0x30;
         temp[1]=wendu_ge+0x30;
         humidity[0]=shidu_shi+0x30;
         humidity[1]=shidu_ge+0x30;
         
         /*******信息通過串口打印********/
     
         Uart_Send_String(biaoshifu,6);
         Uart_Send_String(douhao,1);
         
         Uart_Send_String(temp,2);
         Uart_Send_String(douhao,1);
         Uart_Send_String(temp1,1);
         Uart_Send_String(douhao,1);
         
         Uart_Send_String(humidity,2);
         Uart_Send_String(douhao,1);
         Uart_Send_String(humidity1,1);
         Uart_Send_String(douhao,1);
	 
         if(AirScan())
         {
           Uart_Send_String(truenumber,1);
           Uart_Send_String(douhao,1);
           Uart_Send_String(youyanwu,1);
           Uart_Send_String(douhao,1);
         }
         else
         {
           Uart_Send_String(falsenumber,1);
           Uart_Send_String(douhao,1);
           Uart_Send_String(youyanwu,1);
           Uart_Send_String(douhao,1);
         } 
         
         if(AirScan2())
         {
           Uart_Send_String(truenumber,1);
           Uart_Send_String(douhao,1);
           Uart_Send_String(youhuoyan,1);
           Uart_Send_String(douhao,1);
         }
         else
         {
           Uart_Send_String(falsenumber,1);
           Uart_Send_String(douhao,1);
           Uart_Send_String(youhuoyan,1);
           Uart_Send_String(douhao,1);
         }
         Uart_Send_String("\r\n",2);        
         Delay_ms(2000);
    }         
}

Uart_Send_String裏面的數組數據定義如下:

uchar biaoshifu[6]="$ZIGBE";
uchar temp[2]={0,0}; 
uchar temp1[1]="T";//temp
uchar humidity[2]={0,0};
uchar humidity1[1]="H";//humidity
uchar youyanwu[1]="W";//youyanwu
uchar meiyanwu[1]="U";//meiyanwu
uchar youhuoyan[1]="Y";//youhuoyan
uchar meihuoyan[1]="N";//meihuoyan
uchar douhao[1]=",";//douhao
uchar truenumber[1]="1";
uchar falsenumber[1]="0";

在電腦串口助手可以看到輸出從ZigBee獲取到的數據:
在這裏插入圖片描述

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