18B20单线传感器操作方法
/**************************************************************************//*** @file DS18B20.c
* @versionV1.00
* $Date: 19/06/17 3:56p $
* @brief DS18B20 Driver
*
*****************************************************************************/
#include "mini51series.h"
/*---------------------------------------------------------------------------*/
/* Macro definition */
/*---------------------------------------------------------------------------*/
#defineDQ P52 //DQ Pin
#defineCMD_SKIP_ROM 0xCC
#defineCMD_CONVERT_T 0x44
#defineCMD_READ_SCRATCHPAD 0xBE
/*---------------------------------------------------------------------------*/
/* Functions */
/*---------------------------------------------------------------------------*/
static void DS18B20_Reset(void);
static void DS18B20_WriteByte(uint8_t u8dat);
static uint8_t DS18B20_ReadByte(void);
/**
* @briefRead temperature from DS18B20
* @paramNone
* @returni16temp: temperature
*/
int16_t DS18B20_ReadTemperature(void)
{
uint8_tu8tempH, u8tempL;
int16_ti16temp;
DS18B20_Reset();
DS18B20_WriteByte(CMD_SKIP_ROM);
DS18B20_WriteByte(CMD_CONVERT_T);
while (!DQ); //Waiting for conversion to complete
DS18B20_Reset();
DS18B20_WriteByte(CMD_SKIP_ROM);
DS18B20_WriteByte(CMD_READ_SCRATCHPAD);
u8tempL = DS18B20_ReadByte(); //Read temperature low byte
u8tempH = DS18B20_ReadByte(); //Read temperature high byte
i16temp = (u8tempH << 8) | u8tempL;
return (i16temp);
}
/**
* @briefReset the DS18B20 and check if the device is present
* @paramNone
* @return None
*/
static void DS18B20_Reset(void)
{
uint8_t i;
i = 1;
while (i)
{
DQ = 0; //Send a low level reset signal
CLK_SysTickDelay(480); //Delay at least 480us
DQ = 1; //Release data line
CLK_SysTickDelay(60); //Waiting for 60us
i = DQ; //Detect the presence of pulses
CLK_SysTickDelay(420); //Waiting for the device to release the data line
}
}
/**
* @briefRead 1 byte data from DS18B20
* @paramNone
* @return u8dat: Read data
*/
static uint8_t DS18B20_ReadByte(void)
{
uint8_t i;
uint8_t u8dat = 0;
for (i = 0; i < 8; i++)
{
u8dat >>= 1;
DQ = 0; //Start time slice
CLK_SysTickDelay(1); //Delay waiting
DQ = 1; //Ready to receive
CLK_SysTickDelay(1); //Reception delay
if (DQ) u8dat |= 0x80; //Read data
CLK_SysTickDelay(60); //Waiting for the end of time
}
return u8dat;
}
/**
* @briefWrite 1 byte of data to the DS18B20
* @paramu8dat Write data
* @return None
*/
static void DS18B20_WriteByte(uint8_t u8dat)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
DQ = 0; //Start time slice
CLK_SysTickDelay(1); //Delay waiting
if (u8dat & 0x01) DQ = 1; //Send data
CLK_SysTickDelay(60); //Waiting for the end of time
DQ = 1; //Restore data line
CLK_SysTickDelay(1); //Recovery delay
u8dat >>= 1;
}
}
/**************************************************************************//**
* @file main.c
* @versionV1.00
* $Date: 19/06/17 3:56p $
* @brief MINI51 DS18B20 Driver Sample Code
*
* @note
* Copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
*
*****************************************************************************/
#include <stdio.h>
#include "mini51series.h"
int16_t DS18B20_ReadTemperature(void);
void SYS_Init(void)
{
/* Unlock protected registers */
SYS_UnlockReg();
/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock */
/*---------------------------------------------------------------------------------------------------------*/
/* Enable external 12MHz XTAL, internal 22.1184MHz */
CLK->PWRCON |= CLK_PWRCON_XTL12M | CLK_PWRCON_IRC22M_EN_Msk;
/* Waiting for clock ready */
CLK_WaitClockReady(CLK_CLKSTATUS_XTL_STB_Msk | CLK_CLKSTATUS_IRC22M_STB_Msk);
/* Switch HCLK clock source to XTL */
CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_XTAL, CLK_CLKDIV_HCLK(1));
/* STCLK to XTL STCLK to XTL */
CLK_SetSysTickClockSrc(CLK_CLKSEL0_STCLK_S_XTAL);
/* Enable IP clock */
CLK_EnableModuleClock(UART_MODULE);
/* Select IP clock source */
CLK_SetModuleClock(UART_MODULE, CLK_CLKSEL1_UART_S_XTAL, CLK_CLKDIV_UART(1));
/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function */
/*---------------------------------------------------------------------------------------------------------*/
/* Set P0 multi-function pins for UART RXD and TXD */
SYS->P0_MFP &= ~(SYS_MFP_P01_Msk | SYS_MFP_P00_Msk);
SYS->P0_MFP |= (SYS_MFP_P01_RXD | SYS_MFP_P00_TXD);
/* To update the variable SystemCoreClock */
SystemCoreClockUpdate();
/* Lock protected registers */
SYS_LockReg();
}
void UART_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init UART */
/*---------------------------------------------------------------------------------------------------------*/
/* Reset IP */
SYS_ResetModule(SYS_IPRSTC2_UART_RST_Msk);
/* Configure UART and set UART Baudrate */
UART_Open(UART, 115200);
}
/*---------------------------------------------------------------------------------------------------------*/
/* MAIN function */
/*---------------------------------------------------------------------------------------------------------*/
int main(void)
{
float t;
/* Init System, IP clock and multi-function I/O */
SYS_Init(); //In the end of SYS_Init() will issue SYS_LockReg() to lock protected register. If user want to write protected register, please issue SYS_UnlockReg() to unlock protected register.
/* Init UART for printf */
UART_Init();
printf("\n\nCPU @ %dHz\n", SystemCoreClock);
printf("+-------------------------------------+ \n");
printf("| DS18B20 Sample Code | \n");
printf("+-------------------------------------+ \n");
/* Configure P5.2 as Quasi mode*/
GPIO_SetMode(P5, BIT2, GPIO_PMD_QUASI);
while (1)
{
t = DS18B20_ReadTemperature() * 0.0625;
printf("\n%f\n", t);
CLK_SysTickDelay(1000000);//delay 1 sec
}
}
18B20是非常经典的温度传感器了用的是iic总线通讯 关于这个传感器的代码示例太多了调试起来的难点还是在波形的精准上 看代码应该是 使用的普通的引脚模拟的是吗 为什么有时候在正常运行的时候会受到错误码呢 zljiu 发表于 2023-3-3 10:37
为什么有时候在正常运行的时候会受到错误码呢
估计可能有干扰信号了 然后还能恢复正常吗 gwsan 发表于 2023-3-3 10:56
估计可能有干扰信号了 然后还能恢复正常吗
这个说不好这得看是什么原因导致总线上返回错误码的 体积小,硬件开销低,抗干扰能力强,精度高,这个接线方式还有很多种 代码看着就那么多,调试起来也没多容易 使用的什么引脚模拟的 可以通过单线协议进行通信。 使用Arduino开发板和DS18B20温度传感器 在使用DS18B20单线传感器时,还需要实现CRC校验以确保数据完整性和准确性。 初始化:将单线总线拉高,并保持至少480微秒,然后将总线拉低,持续60-240微秒,意味着开始一个操作。
发送指令:在总线上发送指令(例如读取温度)。
接收响应:释放总线,并等待从DS18B20返回的响应信号。如果DS18B20准备好了,则它会拉低总线15-60微秒作为响应信号。
读取数据:依次读取每个字节的数据,共计9个字节。第一个字节是温度数据的最低位,第二个字节是温度数据的次低位,第三个字节是温度数据的次高位,第四个字节是温度数据的最高位。
计算温度值:使用读取到的4个字节的数据计算出温度值。
完成操作:拉低总线至少1微秒,表示完成操作。 单总线对时间的精度要求比较高 这个用的很多的。 调试过程还是有好多经验的 单总线对时间要求很严格
页:
[1]