做門戶網站賺錢嗎深圳營銷策劃公司十強
目錄
一、教程簡介
二、驅動理論講解
三、CubeMX生成底層代碼
四、Keil5編寫代碼
五、實驗結果
一、教程簡介
????????本教程面向初學者,只介紹DS18B20的常用功能,但也能滿足大部分的運用需求。跟著本教程操作,可在10分鐘內解決DS18b20通信難題。
二、驅動理論講解
????????DS18b20支持多傳感器共用一個引腳,但本教程只教使用一個溫濕度傳感器。使用DS18b20可分為下面兩個步驟進行
(一)初始化:
????????1、將引腳初始化為推挽輸出、上拉。
????????2、發(fā)送復位脈沖:引腳輸出大于480us的低電平復位信號(建議600us),延時600us之后,需將引腳拉高并延時15us。
????????3、檢測存在脈沖:將引腳設置為上拉輸入,并檢測低電平到來的時間,若超過100us還沒檢測到低電平,則初始化失敗。檢測到低電平后開始計算時間,若低超過240us還沒檢測到高電平,則初始化失敗。
(二)獲取溫度:
????????1、配置單DS18b20模式:重復初始化操作后發(fā)送命令:0xCC
????????2、發(fā)送溫度轉換命令:發(fā)送0x44
????????3、配置單DS18b20模式:重復初始化操作后發(fā)送命令:0xCC
????????4、發(fā)送讀取命令:發(fā)送0xBE
????????5、接收兩個字節(jié)的溫度數(shù)據
三、CubeMX生成底層代碼
1、芯片選擇:這里選用STM32F103C8t6
?2、配置Debug模式
3、 配置外部高速時鐘
4、 配置時鐘速率
5、 配置DS18b20引腳
6、配置串口
7、輸出工程文件
四、Keil5編寫代碼
1、ds18b20.c 代碼
/* 包含頭文件 ----------------------------------------------------------------*/
#include "ds18b20.h"/*** 函數(shù)功能: DS18B20 初始化函數(shù)* 返 回 值: 1為初始化失敗,0為初始化成功*/
uint8_t DS18B20_Init(void)
{DS18B20_Mode_Out_PP(); //推挽輸出模式DS18B20_Dout_HIGH(); //輸出高電平DS18B20_Rst(); //輸出復位脈沖return DS18B20_Presence (); //返回響應情況
}/*** 函數(shù)功能: 使DS18B20-DATA引腳變?yōu)樯侠斎肽J?/
static void DS18B20_Mode_IPU(void)
{GPIO_InitTypeDef GPIO_InitStruct;/* 串口外設功能GPIO配置 */GPIO_InitStruct.Pin = DS18b20_Pin;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_PULLUP;HAL_GPIO_Init(DS18b20_GPIO_Port, &GPIO_InitStruct);}/*** 函數(shù)功能: 使DS18B20-DATA引腳變?yōu)橥仆燧敵瞿J?/
static void DS18B20_Mode_Out_PP(void)
{GPIO_InitTypeDef GPIO_InitStruct;/* 串口外設功能GPIO配置 */GPIO_InitStruct.Pin = DS18b20_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(DS18b20_GPIO_Port, &GPIO_InitStruct);
}/*** 函數(shù)功能: 主機給從機發(fā)送復位脈沖*/
static void DS18B20_Rst(void)
{DS18B20_Mode_Out_PP(); /* 主機設置為推挽輸出 */DS18B20_Dout_LOW(); /* 主機輸出低電平 */DS18B20_Delay(750); /* 主機至少產生480us的低電平復位信號 */DS18B20_Dout_HIGH(); /* 主機在產生復位信號后,需將總線拉高 */DS18B20_Delay(15); /* 從機接收到主機的復位信號后,會在15~60us后給主機發(fā)一個存在脈沖 */
}/*** 函數(shù)功能: 檢測從機給主機返回的存在脈沖* 返 回 值: 0:成功,1:失敗*/static uint8_t DS18B20_Presence(void)
{uint8_t pulse_time = 0;/* 主機設置為上拉輸入 */DS18B20_Mode_IPU();/* 等待存在脈沖的到來,存在脈沖為一個60~240us的低電平信號 * 如果存在脈沖沒有來則做超時處理,從機接收到主機的復位信號后,會在15~60us后給主機發(fā)一個存在脈沖*/while( DS18B20_Data_IN() && pulse_time<100 ){pulse_time++;DS18B20_Delay(1);} /* 經過100us后,存在脈沖都還沒有到來*/if( pulse_time >=100 )return 1;elsepulse_time = 0;/* 存在脈沖到來,且存在的時間不能超過240us */while( !DS18B20_Data_IN() && pulse_time<240 ){pulse_time++;DS18B20_Delay(1);} if( pulse_time >=240 )return 1;elsereturn 0;
}/*** 函數(shù)功能: 從DS18B20讀取一個bit* 返 回 值: 讀取到的數(shù)據*/
static uint8_t DS18B20_ReadBit(void)
{uint8_t dat;/* 讀0和讀1的時間至少要大于60us */ DS18B20_Mode_Out_PP();/* 讀時間的起始:必須由主機產生 >1us <15us 的低電平信號 */DS18B20_Dout_LOW();DS18B20_Delay(10);/* 設置成輸入,釋放總線,由外部上拉電阻將總線拉高 */DS18B20_Mode_IPU();//Delay_us(2);if( DS18B20_Data_IN() == SET )dat = 1;elsedat = 0;/* 這個延時參數(shù)請參考時序圖 */DS18B20_Delay(45);return dat;
}/*** 函數(shù)功能: 從DS18B20讀一個字節(jié),低位先行* 返 回 值: 讀到的數(shù)據*/
static uint8_t DS18B20_ReadByte(void)
{uint8_t i, j, dat = 0; for(i=0; i<8; i++) {j = DS18B20_ReadBit(); dat = (dat) | (j<<i);}return dat;
}/*** 函數(shù)功能: 寫一個字節(jié)到DS18B20,低位先行* 輸入參數(shù): dat:待寫入數(shù)據*/
static void DS18B20_WriteByte(uint8_t dat)
{uint8_t i, testb;DS18B20_Mode_Out_PP();for( i=0; i<8; i++ ){testb = dat&0x01;dat = dat>>1; /* 寫0和寫1的時間至少要大于60us */if (testb){ DS18B20_Dout_LOW();/* 1us < 這個延時 < 15us */DS18B20_Delay(8);DS18B20_Dout_HIGH();DS18B20_Delay(58);} else{ DS18B20_Dout_LOW();/* 60us < Tx 0 < 120us */DS18B20_Delay(70);DS18B20_Dout_HIGH(); /* 1us < Trec(恢復時間) < 無窮大*/DS18B20_Delay(2);}}
}/*** 函數(shù)功能: 跳過匹配 DS18B20 ROM*/
static void DS18B20_SkipRom ( void )
{DS18B20_Rst(); DS18B20_Presence(); DS18B20_WriteByte(0XCC); /* 跳過 ROM */
}/*** 函數(shù)功能: 獲取 DS18B20 溫度值 * 返 回 值: 浮點型溫度值*/
float DS18B20_GetTemp_SkipRom ( void )
{uint8_t tpmsb, tplsb;short s_tem;float f_tem;DS18B20_SkipRom ();DS18B20_WriteByte(0X44); /* 開始轉換 */DS18B20_SkipRom ();DS18B20_WriteByte(0XBE); /* 讀溫度值 */tplsb = DS18B20_ReadByte(); tpmsb = DS18B20_ReadByte(); s_tem = tpmsb<<8;s_tem = s_tem | tplsb;if( s_tem < 0 ) /* 負溫度 */f_tem = (~s_tem+1) * 0.0625; elsef_tem = s_tem * 0.0625;return f_tem;
}/*** 微妙延時函數(shù)* 全系列通用,只需要將宏定義CPU_FREQUENCY_MHZ根據時鐘主頻修改即可。* 系統(tǒng)滴答定時器是HAL庫初始化的,且必須有HAL庫初始化。*/
#define CPU_FREQUENCY_MHZ (int)(HAL_RCC_GetHCLKFreq()/1000000) // 自動獲取STM32時鐘主頻
void DS18B20_Delay(__IO uint32_t delay)
{int last, curr, val;int temp;while (delay != 0){temp = delay > 900 ? 900 : delay;last = SysTick->VAL;curr = last - CPU_FREQUENCY_MHZ * temp;if (curr >= 0){do{val = SysTick->VAL;}while ((val < last) && (val >= curr));}else{curr += CPU_FREQUENCY_MHZ * 1000;do{val = SysTick->VAL;}while ((val <= last) || (val > curr));}delay -= temp;}
}
2、ds18b20.h 代碼
#ifndef __DS18B20_H
#define __DS18B20_H/* 包含頭文件 ----------------------------------------------------------------*/
#include "main.h"/* 引腳操作函數(shù)宏定義 --------------------------------------------------------*/
#define DS18B20_Dout_LOW() HAL_GPIO_WritePin(DS18b20_GPIO_Port,DS18b20_Pin,GPIO_PIN_RESET)
#define DS18B20_Dout_HIGH() HAL_GPIO_WritePin(DS18b20_GPIO_Port,DS18b20_Pin,GPIO_PIN_SET)
#define DS18B20_Data_IN() HAL_GPIO_ReadPin(DS18b20_GPIO_Port,DS18b20_Pin)/* 函數(shù)聲明 ------------------------------------------------------------------*/
void DS18B20_Rst(void);
void DS18B20_SkipRom(void);
void DS18B20_Mode_IPU(void);
void DS18B20_Mode_Out_PP(void);
void DS18B20_WriteByte(uint8_t dat);
void DS18B20_Delay(__IO uint32_t delay);
float DS18B20_GetTemp_SkipRom(void);
uint8_t DS18B20_Init(void);
uint8_t DS18B20_ReadBit(void);
uint8_t DS18B20_Presence(void);
uint8_t DS18B20_ReadByte(void);#endif
3、main.c 參考調用代碼
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "ds18b20.h"
#include "stdio.h"
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
char Tx_Buf[30] = {0};
float Temp = 0;
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* USER CODE END 0 *//*** @brief The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */while(DS18B20_Init()){HAL_UART_Transmit(&huart1,(uint8_t*)"DS18b20初始化失敗\r\n",19,100);HAL_Delay(1000);}HAL_UART_Transmit(&huart1,(uint8_t*)"DS18b20初始化成功\r\n",19,100);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){Temp = DS18B20_GetTemp_SkipRom();sprintf(Tx_Buf,"溫度:%0.3f \r\n",Temp);HAL_UART_Transmit(&huart1,(uint8_t*)Tx_Buf,15,100);HAL_Delay(1000);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}
五、實驗結果
? ? ? ? 通過本驅動使用DS18b20測量出來的環(huán)境溫度,與米家溫濕度計測量的結果僅僅相差0.012攝氏度,測量精度非??捎^。
?六、特別說明
- 同學們在操作的過程中遇到的問題可在評論區(qū)留言,我看到后會第一時間回復。
- 想看其他傳感器的教程也可在評論區(qū)留言,我會按照大家的需求來修改教程內容。
- 若您覺得本教程對您有所幫助,請點贊、收藏,這是我持續(xù)更新的最大動力,感謝您!