生活随笔
收集整理的這篇文章主要介紹了
华大单片机HC32L136J8TA读取DS18B20温度(源码+时钟配置)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
-
免費的C語言和linuxPDF文檔:傳送門
-
?有一點C語言基礎和華大單片機開發經驗,應該就能看得懂就不多介紹了,有疑問可以留言,看到就回了;
-
關于協議具體解析:傳送門@不脫發的程序猿
-
注(2021-05-21) :如果有時候數據采集不準確,可能和定時器中斷有關,中斷會打亂時序;
-
因此再讀取溫度的時候關閉中斷,讀取完成后開啟中斷(CMx關開全局中斷網上有例程,自己找一下就好了);
#include "ds18b20.h"uint8_t DS18B20_Init(void)
{stc_gpio_config_t pstcGpioCfg;DDL_ZERO_STRUCT(pstcGpioCfg);Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);pstcGpioCfg.enDir = GpioDirOut;pstcGpioCfg.enDrv = GpioDrvH; //< 端口驅動能力配置->高驅動能力pstcGpioCfg.enPuPd = GpioNoPuPd; //無上下拉pstcGpioCfg.enOD = GpioOdDisable; //< 端口開漏輸出配置->開漏輸出關閉pstcGpioCfg.enCtrlMode = GpioFastIO; //< 端口輸入/輸出值寄存器總線控制模式配置->AHBGpio_Init(DS18B20DQ_PORT, DS18B20DQ_PIN, &pstcGpioCfg); //初始化引腳Gpio_WriteOutputIO(DS18B20DQ_PORT, DS18B20DQ_PIN,TRUE); ///< 默認置高電平
}
static void DS18B20_IO_OUT(void)
{stc_gpio_config_t pstcGpioCfg;DDL_ZERO_STRUCT(pstcGpioCfg);pstcGpioCfg.enDir = GpioDirOut;pstcGpioCfg.enDrv = GpioDrvH; //< 端口驅動能力配置->高驅動能力pstcGpioCfg.enPuPd = GpioNoPuPd; //無上下拉pstcGpioCfg.enOD = GpioOdDisable; //< 端口開漏輸出配置->開漏輸出關閉pstcGpioCfg.enCtrlMode = GpioFastIO; //< 端口輸入/輸出值寄存器總線控制模式配置->AHBGpio_Init(DS18B20DQ_PORT, DS18B20DQ_PIN, &pstcGpioCfg); //< 初始化引腳Gpio_WriteOutputIO(DS18B20DQ_PORT, DS18B20DQ_PIN,FALSE);//< 默認置高電平
}
static void DS18B20_IO_IN(void)
{stc_gpio_config_t pstcGpioCfg;DDL_ZERO_STRUCT(pstcGpioCfg);pstcGpioCfg.enDir = GpioDirIn;pstcGpioCfg.enDrv = GpioDrvL;pstcGpioCfg.enPuPd = GpioNoPuPd;pstcGpioCfg.enOD = GpioOdDisable;pstcGpioCfg.enCtrlMode = GpioFastIO;Gpio_Init(DS18B20DQ_PORT, DS18B20DQ_PIN, &pstcGpioCfg);
}
//復位DS18B20
static void DS18B20_Rst(void)
{DS18B20_IO_OUT(); ///< 配置端口輸出Gpio_WriteOutputIO(DS18B20DQ_PORT, DS18B20DQ_PIN,FALSE);///< 拉低DQ__delay_us__(DELAY_700US); ///< 拉低700usGpio_WriteOutputIO(DS18B20DQ_PORT, DS18B20DQ_PIN,TRUE); ///< 拉高DQ__delay_us__(DELAY_15US); ///< 拉高15us
}//等待DS18B20的回應
//返回1:未檢測到DS18B20的存在
//返回0:存在
static uint8_t DS18B20_Check(void)
{uint8_t retry = 0;DS18B20_IO_IN(); ///< 配置端口輸入while ((Gpio_GetInputIO(DS18B20DQ_PORT, DS18B20DQ_PIN) == 1) && (retry < 100)) ///< 最多200us{retry++;__delay_us__(DELAY_2US); ///< 每次等待2us}if (retry >= 200){return 1;}else{retry = 0;}while ((Gpio_GetInputIO(DS18B20DQ_PORT, DS18B20DQ_PIN) == 0) && (retry < 120)) ///< 最多240us{retry++;__delay_us__(DELAY_2US); ///< 每次等待2us}if (retry >= 120){return 1;}return 0;
}
//寫一個字節到DS18B20
//dat:要寫入的字節
static void DS18B20_Write_Byte(uint8_t dat)
{uint8_t j;uint8_t testb;DS18B20_IO_OUT(); ///< 配置端口輸出for (j = 1; j <= 8; j++){testb = dat & 0x01;dat = dat >> 1;if (testb) ///< 寫入1{Gpio_WriteOutputIO(DS18B20DQ_PORT, DS18B20DQ_PIN,FALSE);__delay_us__(DELAY_2US); ///< 拉低2usGpio_WriteOutputIO(DS18B20DQ_PORT, DS18B20DQ_PIN,TRUE);__delay_us__(DELAY_60US); ///< 拉高64us}else ///< 寫入0{Gpio_WriteOutputIO(DS18B20DQ_PORT, DS18B20DQ_PIN,FALSE);__delay_us__(DELAY_60US); ///< 拉低64usGpio_WriteOutputIO(DS18B20DQ_PORT, DS18B20DQ_PIN,TRUE);__delay_us__(DELAY_2US); ///< 拉高2us}}
}
//從DS18B20讀取一個位
//返回值:1/0
static uint8_t DS18B20_Read_Bit(void)
{uint8_t data;DS18B20_IO_OUT(); ///< 配置端口輸出Gpio_WriteOutputIO(DS18B20DQ_PORT, DS18B20DQ_PIN,FALSE);__delay_us__(DELAY_2US); ///< 等待2usGpio_WriteOutputIO(DS18B20DQ_PORT, DS18B20DQ_PIN,TRUE);DS18B20_IO_IN(); ///< 配置端口輸入__delay_us__(DELAY_12US); ///< 等待12usif (Gpio_GetInputIO(DS18B20DQ_PORT, DS18B20DQ_PIN) == 1){data = 1;}else{data = 0;}__delay_us__(DELAY_52US); ///< 等待52usreturn data;
}//從DS18B20讀取一個字節
//返回值:讀到的數據
static uint8_t DS18B20_Read_Byte(void)
{uint8_t i = 0, j = 0, dat = 0;uint8_t num1, num2;for (i = 1; i <= 8; i++) ///< 一次讀取一個字節,8位{j = DS18B20_Read_Bit();num1 = j << 7;num2 = dat >> 1;dat = num1 | num2;}return dat;
}// TL = DS18B20_Read_Byte(); ///< 讀取LSB,低八位數據
// TH = DS18B20_Read_Byte(); ///< 讀取MSB,高八位數據
//開始溫度轉換
static uint8_t DS18B20_Start(void)
{DS18B20_Rst();if (!DS18B20_Check()){DS18B20_Write_Byte(0xCC); ///< skip romDS18B20_Write_Byte(0x44); ///< convertreturn 0;}else{return 1;}
}//讀出溫度
static float DS18B20_Read_Templet(void)
{uint8_t TL = 0, TH = 0;uint16_t tem = 0;float temp = 0;uint8_t temp_flag = 0;//讀取溫度DS18B20_Write_Byte(0xCC); ///< skip romDS18B20_Write_Byte(0xBE); ///< convert TL = DS18B20_Read_Byte(); ///< 讀取LSB,低八位數據TH = DS18B20_Read_Byte(); ///< 讀取MSB,高八位數據if (TH > 7) ///< 溫度為負{TH = ~TH;TL = ~TL;temp_flag = 0;}else ///< 溫度為正{temp_flag = 1;}tem = TH;tem <<= 8;tem += TL;temp = (float)tem / 16.0; ///< 轉換數據if (temp_flag){return temp;}return -temp;
}float DS18B20_Get_Templet(void)
{float fget_temp;uint8_t check_flag;check_flag = DS18B20_Start(); //1if(!check_flag){DS18B20_Rst(); //2DS18B20_Check(); //3fget_temp = DS18B20_Read_Templet(); //4PRINTF_B20("DS18B20_Get_temp = %f", fget_temp);return fget_temp;}PRINTF_B20("DS18B20_Get_temp fail");return 1;
}
#ifndef __DS18B20__
#define __DS18B20__
#include "global.h"
#define DS18B20DQ_PORT GpioPortB
#define DS18B20DQ_PIN GpioPin8extern uint8_t DS18B20_Init(void); //初始化管腳
extern float DS18B20_Get_Templet(void); //獲取溫度
#endif
//華大單片機時鐘不準,最好做驗證
//延時函數要準確,避免數據不準確
//如果有邏輯分析儀 可以自己做測試
//沒有的話,我把我的內部時鐘配置源碼放在下面了,用我的時鐘配置應該沒問題
#define DELAY_700US 3694
#define DELAY_200US 1050
#define DELAY_150US 789
#define DELAY_60US 310
#define DELAY_52US 267
#define DELAY_15US 71
#define DELAY_12US 55
#define DELAY_2US 1void __delay_us__(const uint32_t ucus)
{register uint32_t ucustemp = ucus;while(ucustemp--){__NOP();}
}
#define DEBUG_18B20 1
#if DEBUG_18B20
#define PRINTF_B20(format, ...) printf(format "\r\n", ##__VA_ARGS__ )
#else
#define PRINTF_B20(format, ...)
#endif
//時鐘切換內部時鐘48MHZ
void SYSTEMCLKSWITCH(void)
{stc_sysctrl_pll_config_t stcPLLCfg;stc_sysctrl_clk_config_t stcCfg;DDL_ZERO_STRUCT(stcPLLCfg);DDL_ZERO_STRUCT(stcCfg);Flash_WaitCycle(FlashWaitCycle1); //< 當前時鐘源HCLK大于24M:此處設置FLASH 讀等待周期為1 cycle(前面已經配置,此處無需重復配置)/*< 切換時鐘前配置PLL相關參數*/Sysctrl_SetRCHTrim(SysctrlRchFreq4MHz); //PLL使用RCH24MHz作為時鐘源,因此需要先設置RCH,之前已經設置 Sysctrl_ClkSourceEnable(SysctrlClkRCH, TRUE); //RCH使能,因RCH使能未關閉,此處可以不重復操作stcPLLCfg.enInFreq = SysctrlPllInFreq4_6MHz; //RCH 24MHzstcPLLCfg.enOutFreq = SysctrlPllOutFreq36_48MHz; //PLL 輸出48MHzstcPLLCfg.enPllClkSrc = SysctrlPllRch; //輸入時鐘源選擇RCHstcPLLCfg.enPllMul = SysctrlPllMul12; //4MHz x 12 = 48MHzSysctrl_SetPLLFreq(&stcPLLCfg);///< 選擇PLL作為HCLK時鐘源;stcCfg.enClkSrc = SysctrlClkPLL;stcCfg.enHClkDiv = SysctrlHclkDiv1;stcCfg.enPClkDiv = SysctrlPclkDiv1;Sysctrl_ClkInit(&stcCfg);Sysctrl_SetPLLStableTime(SysctrlPllStableCycle16384);Sysctrl_ClkSourceEnable(SysctrlClkPLL, TRUE);Sysctrl_SysClkSwitch(SysctrlClkPLL); //< 時鐘切換 Sysctrl_ClkSourceEnable(SysctrlClkXTH, FALSE); //< 根據需要選擇是否關閉原時鐘(此處關閉XTH)}
總結
以上是生活随笔為你收集整理的华大单片机HC32L136J8TA读取DS18B20温度(源码+时钟配置)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。