【用18B20温度控制板介绍华大HC32F030单片机 (三)——器件原理介绍】

HC32F030系列单片机属于华大半导体公司“通用控制”产品系列的产品,便宜、小巧性能够用,备件易得性好,在国产器件风靡行业的今天,学习华大系列单片机是入门嵌入式行业的首选。

方案落实第一步:搞出电路图

下图是这次项目的电路板图纸,全部元件都在上面了,接下来笔者将分别介绍各个电路单元的功能。
原理图

两种温度传感器并存——NTC热敏电阻和18B20
NTC热敏电阻

NTC热敏电阻一种半导体材料,先了解下NTC热敏电阻的几个关键参数

项目参数
阻值(25℃)10kΩ
B值(25℃/50℃)3950K
工作温度-55℃~+125℃
最大稳态电流(25℃)440uA

NTC热敏电阻
第一,NTC热敏电阻,即 Negative Temperature Coefficient thermistor,其阻值随着温度升高而降低,还有一种PTC热敏电阻,即Positive Temperature Coefficient thermistor,正温度系数的热敏电阻,其阻值随温度升高也升高;

第二,工作温度,-55℃~+125℃,这说明了可以测量的温度范围;

第三,B值的含义,即热敏常数,它表示阻值随温度变化的速度程度,B值越大,阻值随温度升高降低得越快;B值通常是在两个温度之间通过公式得出的,表中的B值是在25℃和50℃之间得出的。理论上,有了公式,可以算出热敏电阻在不同温度时的阻值,但是这只限于在25℃和50℃之间,在其他温度范围上就不准确了,因为热敏电阻的阻值和温度对应关系不是线性关系;

第四,最大稳态电流,在25℃下不要超过440uA,因为电阻要流过电流才能得到压降,其本身也要消耗功率,但是消耗功率太大就会影响精度,这也是阻值-温度呈非线性的原因。
热敏电阻的阻值和温度对应关系不是线性关系
这里要说明的是,热敏电阻作为一种半导体元件有很多技术参数供工程师们参考,为何这里只列四个?这里要重新对一下我们这个项目对温度的需求了:

1、温度是启停智能风扇的信号,这个温度在40℃左右较为合理,因为多媒体盒的工作场所不是恶劣的室外,而是稳定的家庭室内;

2、温度属于缓慢变化的模拟量,除非在锻造、淬火这种领域外,风扇控制类的设备对温度变化速度的响应可以不做特别高要求,所以大部分型号的热敏电阻的B值都可以接受;

3、我们这个项目可以让用户设定温度值,我们可以现在暂定三个温度值:30℃、40℃、50℃,这本身足够了,并且由于只设计了一个按钮,如果设置太多温度操作起来也不方便。我们只要保证这三个温度值下的电阻值稳定就行,措施如下:

①保证工作电流低于0.4mA,避免工作电流过大其自身要消耗功率。和它串联的电阻暂定1kΩ;
保证工作电流低于0.4mA

②规范焊接,焊接时间不要超过5s;
③ADC精度选最高位,并借助用18B20的温度值作为热敏电阻的采样参考值,18B20属于集成电路,按照数据手册正确使用即可得到相对精准的温度值,正所谓“清水煮杂面,你(18B20)吃我(热敏电阻)也见”

本项目热敏电阻的型号是:SDNT2012X103F3950FTF点击链接查看数据手册。

18B20

选用18B20传感器,是小型温控项目性价比很高的方案。
从商品角度说,市场上货量大,生产厂家多,虽然型号不同,但是基本能各个厂家平替;

功能上:测温范围在-55℃到125℃之间,能应对很多测温需求,用在零下或者高于50℃的场合,用金属壳封装带引线的型号,这种市面上也好买;

使用上,18B20属于单总线器件,一根线既作为控制输入,又做数据或者信号输出,外围电路简单(仅仅需要电源端加一个退耦电容,以及数据线上增加一个上拉电阻);
不足之处,其封装除了金属壳引线形式的,还有SO-8和TO-92,没见到有更小的封装的;并且价格在2-3元,不是十分便宜;
TO-92封装的18B20
金属探头形式的18B20
因为很多厂家都生产18B20,因此,如果你是初学单片机的入门工程师,各个厂家的数据手册是了解18B20的第一手资料,有的手册事无巨细,有的干净简洁,多多浏览能从不同的角度全面掌握这个芯片。

笔者在官方手册里挑选几个值得关注的信息:

1、在-10℃~70℃范围内精确度为±0.4°C,意思是如果真实温度是25℃,芯片读出来可能是在24.6℃到25.4℃之间的数据,实际这是该芯片的误差范围;

2、温度传感器的精度最高可以到9、10、11或12位,温度分辨率分别0.5℃、0.25℃、0.125℃和0.0625℃,意思是最高可以做到0.0625℃的最小步进,但是这和上面的误差±0.4℃没有关系。芯片在上电状态下默认的精度为12位,实际使用中,我们看到小数点后1位足够了。再者,位数越高,转换一次的时间越长,设置为12位分辨率下转换时间最长400ms,在程序中注意给转换留足时间;

3、18B20的数据引脚,也就是单总线引脚,是开漏形式的,必须要保证芯片不传输数据时保持高电平,所以必须在该引脚增加一个上拉电阻

4、操作基本内容:
操作基本内容
① 因为是一根线,作为主机的I/O端口要经常变化输入或输出的状态;

② 芯片上电默认是12位分辨率,没有必要改成其他分辨率,得到的数据乘以0.0625就是温度值;

③ 将以上步骤封装成库函数,在主程序里只调用读取数据的函数,并且读取数据的最小间隔1s,因为12位分辨率的最长转换时间是400ms

RESET 复位脉冲

//复位DS18B20
void DS18B20_Rst(void)
{

    stc_gpio_cfg_t stcGpioCfg;

    ///< 打开GPIO外设时钟门控
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);

    ///< 端口方向配置->输出(其它参数与以上(输入)配置参数一致)
    stcGpioCfg.enDir = GpioDirOut;
    ///< 端口上下拉配置->下拉
    stcGpioCfg.enPu = GpioPuDisable;
    stcGpioCfg.enPd = GpioPdEnable;

    ///关闭18B20总线端口
    Gpio_ClrIO(TEMP_PORT, TEMP_PIN);

    ///初始化18B20总线端口
    Gpio_Init(TEMP_PORT, TEMP_PIN, &stcGpioCfg);

    Gpio_ClrIO(TEMP_PORT, TEMP_PIN); //DS18B20_DQ_OUT_Clr
    delay10us(75ul);
    Gpio_SetIO(TEMP_PORT, TEMP_PIN); //DS18B20_DQ_OUT_Set
    delay10us(2ul);
}

Presence 芯片返回存在脉冲

//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
uint8_t DS18B20_Check(void)
{
    uint8_t retry = 0;

    stc_gpio_cfg_t stcGpioCfg;

    ///< 打开GPIO外设时钟门控
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
    ///< 端口方向配置->输入
    stcGpioCfg.enDir = GpioDirIn;
    ///< 端口驱动能力配置->高驱动能力
    stcGpioCfg.enDrv = GpioDrvL;
    ///< 端口上下拉配置->无
    stcGpioCfg.enPu = GpioPuDisable;
    stcGpioCfg.enPd = GpioPdDisable;
    ///< 端口开漏输出配置->开漏输出关闭
    stcGpioCfg.enOD = GpioOdDisable;
    ///< 端口输入/输出值寄存器总线控制模式配置->AHB
    stcGpioCfg.enCtrlMode = GpioAHB;
    ///初始化18B20总线端口
    Gpio_Init(TEMP_PORT, TEMP_PIN, &stcGpioCfg);


    while (Gpio_GetInputIO(TEMP_PORT, TEMP_PIN) && retry < 200)
    {
        retry++;
        delay10us(1ul);
    };
    if(retry >= 200)return 1;
    else retry = 0;
    while (!Gpio_GetInputIO(TEMP_PORT, TEMP_PIN) && retry < 240)
    {
        retry++;
        delay10us(1ul);
    };
    if(retry >= 240)return 1;
    return 0;
}

CCh 跳过ROM指令

DS18B20_Write_Byte(0xcc);

温度转换指令

DS18B20_Write_Byte(0x44);// convert
}

写一个字节到芯片

//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(uint8_t dat)
{
    uint8_t j;
    uint8_t testb;
    stc_gpio_cfg_t stcGpioCfg;

    ///< 打开GPIO外设时钟门控
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
    ///< 端口方向配置->输出(其它参数与以上(输入)配置参数一致)
    stcGpioCfg.enDir = GpioDirOut;
    ///< 端口上下拉配置->下拉
    stcGpioCfg.enPu = GpioPuDisable;
    stcGpioCfg.enPd = GpioPdEnable;
    ///关闭18B20总线端口
    Gpio_ClrIO(TEMP_PORT, TEMP_PIN);
    ///初始化18B20总线端口
    Gpio_Init(TEMP_PORT, TEMP_PIN, &stcGpioCfg);

    for (j = 1; j <= 8; j++)
    {
        testb = dat & 0x01;
        dat = dat >> 1;
        if (testb)
        {
            Gpio_ClrIO(TEMP_PORT, TEMP_PIN); //DS18B20_DQ_OUT_Clr
            delay10us(1ul);
            Gpio_SetIO(TEMP_PORT, TEMP_PIN); //DS18B20_DQ_OUT_Set
            delay10us(6ul);
        }
        else
        {
            Gpio_ClrIO(TEMP_PORT, TEMP_PIN); //DS18B20_DQ_OUT_Clr
            delay10us(6ul);
            Gpio_SetIO(TEMP_PORT, TEMP_PIN); //DS18B20_DQ_OUT_Set
            delay10us(1ul);
        }
    }
}

从芯片读取一个字节

//从DS18B20读取一个字节
//返回值:读到的数据
uint8_t DS18B20_Read_Byte(void)    // read one byte
{
    uint8_t i, j, dat;
    dat = 0;
    for (i = 1; i <= 8; i++)
    {
        j = DS18B20_Read_Bit();
        dat = (j << 7) | (dat >> 1);
    }
    return dat;
}

得到温度值


//返回值:温度值 (-550~1250)
short DS18B20_Get_Temp(void)
{
    uint8_t temp;
    uint8_t TL, TH;
    short tem;
    DS18B20_Start ();        // ds1820 start convert
    DS18B20_Rst();
    DS18B20_Check();
    DS18B20_Write_Byte(0xcc);// skip rom
    DS18B20_Write_Byte(0xbe);// convert
    TL = DS18B20_Read_Byte(); // LSB
    TH = DS18B20_Read_Byte(); // MSB
    if(TH > 7)
    {
        TH = ~TH;
        TL = ~TL;
        temp = 0; //温度为负
    } else temp = 1; //温度为正
    tem = TH; //获得高八位
    tem <<= 8;
    tem += TL; //获得底八位
    tem = (double)tem * 0.625; //转换
    if(temp)return tem; //返回温度值
    else return -tem;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值