日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

华大单片机HC32L136J8TA读取DS18B20温度(源码+时钟配置)

發布時間:2024/4/13 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 华大单片机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温度(源码+时钟配置)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。