DS18B20是常用的溫度傳感器。CC2530 采集DS18B20 可以實現溫度采集系統等等。
模塊鏈接:https://item.taobao.com/item.htm?id=541308617329
代碼使用Zstack 的sample 工程作為基本框架。
主要實現內容:一個節點采集DS18B20並發送到另一個節點,並在節點連接的LCD上顯示溫度信息。
節點數量:2個(可擴展)
數據傳輸: 終端節點到協調器節點
顯示方式:LCD(可擴展串口顯示)
A: 終端節點采集DS18B20 主要代碼分析:
直接在應用層初始化函數中添加如下代碼
// Received whenever the device changes state in the network case ZDO_STATE_CHANGE: SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status); if ( (SampleApp_NwkState == DEV_ZB_COORD) || (SampleApp_NwkState == DEV_ROUTER) || (SampleApp_NwkState == DEV_END_DEVICE) ) { initial_lcd(); clear_screen(); HalLcdWriteString( "DS18B20 Test ", HAL_LCD_LINE_1 ); // full_display(); // Start sending the periodic message in a regular interval. if(SampleApp_NwkState != DEV_ZB_COORD) { osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT, SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT ); } } else { // Device is no longer in the network } break;
當設備啟動成功后會初始化液晶,並在液晶上顯示“DS18B20”,然后根據設備類型,當設備不是協調器(路由器和終端節點都可以采集數據)定時觸發事件SAMPLEAPP_SEND_PERIODIC_MSG_EVT。
// Send a message out - This event is generated by a timer // (setup in SampleApp_Init()). if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT ) { // Send the periodic message SampleApp_SendPeriodicMessage(); // Setup to send message again in normal period (+ a little jitter) osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT, (SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) ); // return unprocessed events return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT); }
SAMPLEAPP_SEND_PERIODIC_MSG_EVT 事件的處理函數,我們可以看到調用了函數SampleApp_SendPeriodicMessage(),這個函數主要是采集DS18B20,並將數據發送到協調器節點。 然后再次調用定時器觸發SAMPLEAPP_SEND_PERIODIC_MSG_EVT 事件,形成周期性不停的采集發送-采集發送。
/********************************************************************* * @fn SampleApp_SendPeriodicMessage * * @brief Send the periodic message. * * @param none * * @return none */ void SampleApp_SendPeriodicMessage( void ) { uint8 SensorBuf[2]; SensorBuf[0]=Read_Temperature()/10+0x30; SensorBuf[1]=Read_Temperature()%10+0x30; HalLcdWriteString( SensorBuf, HAL_LCD_LINE_2 ); //HalUARTWrite(0,&SensorBuf[1],i); // HalUARTWrite(SERIAL_APP_PORT,&SensorBuf[0],i); if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_FLASH_CLUSTERID, 2, &SensorBuf[0], &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ) { //Successfully requested to be sent } else { // Error occurred in request to send. } }
在這個函數中使用了Read_tempeature() 讀取溫度信息,具體DS18B20 處理函數和C51 的一樣,主要要注意時序。 上面就是采集節點部分主要代碼。
B 匯集節點,匯集遠程節點數據
上面的代碼分析到有終端節點發來的數據,我們回顧上面的代碼
if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_FLASH_CLUSTERID, 2, &SensorBuf[0], &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ) { //Successfully requested to be sent } else { // Error occurred in request to send. }
對應的cluster 是 SAMPLEAPP_FLASH_CLUSTERID,那么我們看協調器采集節點的處理函數
/********************************************************************* * @fn SampleApp_MessageMSGCB * * @brief Data message processor callback. This function processes * any incoming data - probably from other devices. So, based * on cluster ID, perform the intended action. * * @param none * * @return none */ void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ) { uint16 flashTime; uint8 buffer[2]; switch ( pkt->clusterId ) { case SAMPLEAPP_PERIODIC_CLUSTERID: break; case SAMPLEAPP_FLASH_CLUSTERID: flashTime = BUILD_UINT16(pkt->cmd.Data[1], pkt->cmd.Data[2] ); HalLedBlink( HAL_LED_4, 4, 50, (flashTime / 4) ); buffer[0]=pkt->cmd.Data[0]; buffer[1]=pkt->cmd.Data[1]; HalLcdWriteString( buffer, HAL_LCD_LINE_2 ); break; } }
由下面的代碼在顯示屏的第二行顯示溫度信息(第一行顯示DS18B20 Test,初始化與終端節點使用相同的代碼)
buffer[0]=pkt->cmd.Data[0]; buffer[1]=pkt->cmd.Data[1]; HalLcdWriteString( buffer, HAL_LCD_LINE_2 );