这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 企业专区 » TI » 【玩转TIMSPM0】课程3-ADC采样和DS18B20温度报警器

共3条 1/1 1 跳转至

【玩转TIMSPM0】课程3-ADC采样和DS18B20温度报警器

工程师
2024-05-08 11:18:01     打赏

本课程的主要目的是学习MSPM0L1306的ADC应用和DS18B20温度传感器单线协议。

本次学习实现按键报警,ADC-NTC温度采集,DS18B20温度传感器单线通讯以及温度显示及环境温差异常报警。

一、硬件学习

1、按键。

S1按键:PA18默认外部下拉,检测高电平有效,配置IO时需要内部下拉或悬空。课程1中有介绍,参考:

https://forum.eepw.com.cn/thread/381478/1

2、蜂鸣器。

本次使用蜂鸣器为低电平触发方式,IO使用PA6口,配置IO时需要内部上拉或悬空,硬件原理如下:

image.png image.png

3、ADC热敏电阻。

由开发板原理图可以看出,NTC温度传感器接至了ADC通道9(PA15),如下:

image.png

NTC使用型号为TI的TMP6161DECT,其为正温度系数热敏电阻。详细规格可在TI官网中找到,链接如下:

https://www.ti.com/cn/lit/ds/symlink/tmp61.pdf?ts=1715132253294&ref_url=https%253A%252F%252Fitem.szlcsc.com%252F3075722.html

使用热敏电阻,自然离不开其温度-电阻值数据表,通过规格书可直接找到其设计工具表。

image.png

image.png

点击Thermistor Design Tool (zip)下载,得到两个Excel表:

image.png

开发板热敏电阻接法为电压基准方式,固查看电压基准的Excel文档即可。(电流基准方式可自行学习)

image.png

文档中直接给出了温度/电阻值对应关系表。本次学习使用1℃档位的电阻值分压关系,通过ADC采样的AD值查表,得到对应NTC温度值。

原理图中,NTC接法:3.3V供电,电阻10K/NTC(10K)。

得出ADC电压关系为:Uadc = 3.3*RT/(10000+RT);

转换为ADC(12bit)采样AD值为:AD = Uadc*4096/3.3 = 4096*RT/(10000+RT)。

由此ADC采样获得AD值,通过AD/RT和RT/℃的对应关系,可通过查表方式得到AD值对应温度。温度/AD表和查询函数如下:

image.png

4、数码管显示器。

在课程2中,已对数码管显示器做了详细介绍,参考:

https://forum.eepw.com.cn/thread/381492/1

由于本次课程中使用了S1按键(PA18)和ADC通道9(PA15),固在课程2的基础上调整一下显示器接口:PA21-->DIO,PA16-->SCLK,PA17-->RCLK。

5、DS18B20温度传感器

本次使用通信IO为PA11,由于开发板缺少了3V3,固将SW2接口飞线至了3V3,SW1跳线帽接至PA11。

DS18B20为单线通信方式,原理很简单,具体可参考大神作品:

https://forum.eepw.com.cn/thread/381543/1

image.png

6、总体接线图。

image.png

1715131544897.png

二、软件配置

1、按键。

image.png

2、蜂鸣器。

image.png

3、ADC通道9。

image.png

image.png

image.png

4、数码管显示器。

image.png

依次修改:DAT-->PA21,CLK-->PA16,RCK-->PA17。

5、DS18B20温度传感器。

image.png

6、配置好sysconfig后,编译更新代码。

image.png

三、代码实现

1、基础代码:按键、蜂鸣器、HC595配置和相关参数。

#define Key1Tmp     DL_GPIO_readPins(USER_KEYS_PORT, USER_KEYS_KEY1_PIN)    //KEY1
#define BEEP_ON     DL_GPIO_clearPins(BEEP_PORT, BEEP_PIN6_PIN);            //Beep ON
#define BEEP_OFF    DL_GPIO_setPins(BEEP_PORT, BEEP_PIN6_PIN);              //Beep OFF
#define HC595_DAT_H DL_GPIO_setPins(HC595_PORT, HC595_DAT_PIN)              //HC595 data
#define HC595_DAT_L DL_GPIO_clearPins(HC595_PORT, HC595_DAT_PIN)
#define HC595_CLK_H DL_GPIO_setPins(HC595_PORT, HC595_CLK_PIN)              //HC595 sclk
#define HC595_CLK_L DL_GPIO_clearPins(HC595_PORT, HC595_CLK_PIN)
#define HC595_RCK_H DL_GPIO_setPins(HC595_PORT, HC595_RCK_PIN)              //HC595 rclk
#define HC595_RCK_L DL_GPIO_clearPins(HC595_PORT, HC595_RCK_PIN)
volatile uint8_t Disp_DX[] = { 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90,   //0 1 2 3 4 5 6 7 8 9
                               0x88, 0xA0, 0x83, 0xC6, 0xA7, 0xA1, 0x86, 0x8E, 0x8C, 0xFF,   //A a b C c d E F P NC
                               0xBF, 0x7F, 0x9C, 0xA3, 0xC7, 0x89, 0xAB, 0xC1 };             //- . ^o^ o L H n U
volatile uint16_t KeyBounce=0;
//volatile uint16_t TmpVal3=0;
volatile bool gCheckADC;
volatile uint16_t gAdcResultVolts=0, gAdcNtcTempC=0, gDs18b20TempC=0, cycle=0;

2、NTC热敏电阻查表函数。

//NTC Temperature: Divider resistance:10k/RT(TMP6131DECT), Vref:3.3V, -20~+100℃
volatile uint16_t NTC_AD[121] = { 1750, 1757, 1763, 1770, 1776, 1783, 1789, 1796, 1803, 1809,
                                  1816, 1822, 1829, 1835, 1842, 1849, 1855, 1862, 1868, 1875,
                                  1881, 1888, 1894, 1901, 1908, 1914, 1921, 1927, 1934, 1940,
                                  1947, 1953, 1960, 1966, 1973, 1979, 1986, 1992, 1999, 2005,
                                  2012, 2018, 2024, 2031, 2037, 2044, 2050, 2057, 2063, 2069,
                                  2076, 2082, 2088, 2095, 2101, 2108, 2114, 2120, 2126, 2133,
                                  2139, 2145, 2152, 2158, 2164, 2170, 2177, 2183, 2189, 2195,
                                  2201, 2207, 2214, 2220, 2226, 2232, 2238, 2244, 2250, 2256,
                                  2262, 2268, 2275, 2281, 2287, 2293, 2299, 2304, 2310, 2316,
                                  2322, 2328, 2334, 2340, 2346, 2352, 2358, 2363, 2369, 2375,
                                  2381, 2387, 2392, 2398, 2404, 2410, 2415, 2421, 2427, 2432,
                                  2438, 2444, 2449, 2455, 2460, 2466, 2472, 2477, 2483, 2488,
                                  2494 };
//NTC temperature AD value Search
int16_t NTC_AD_Search(uint16_t TempAD)
{
    uint8_t start = 0;
    uint8_t end = 120;
    uint8_t mid = 0;
    int16_t temp = 0;
    uint16_t tmp;

    while(start <= end)
    {
        mid = (start+end)/2;

        if((TempAD >= NTC_AD[mid]) && (TempAD <= NTC_AD[mid+1]))
        {
            tmp = (TempAD - NTC_AD[mid]) << 1;
            if(tmp >= (NTC_AD[mid+1] - NTC_AD[mid]))
                mid = mid+1;
            break;
        }
        else if((TempAD < NTC_AD[mid]) && (TempAD >= NTC_AD[mid-1]))
        {
            tmp = (NTC_AD[mid] - TempAD) << 1;
            if(tmp > (NTC_AD[mid] - NTC_AD[mid-1]))
                mid = mid-1;
            break;
        }

        if(TempAD < NTC_AD[mid])
            end = mid-1;
        else if(TempAD > NTC_AD[mid])
            start = mid+1;
    }
    temp = mid-20;
    return temp;
}

3、ADC中断回调和温度读取转换。

void ADC12_0_INST_IRQHandler(void)
{
    switch (DL_ADC12_getPendingInterrupt(ADC12_0_INST))
    {
        case DL_ADC12_IIDX_MEM0_RESULT_LOADED:
            gCheckADC = true;
        break;

        default:
        break;
    }
}
void ReadNtcTemprature(void)
{
    while (false == gCheckADC)
    {
        __WFE();
    }
    gAdcResultVolts = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_0);
    gAdcNtcTempC = NTC_AD_Search(gAdcResultVolts);
    gCheckADC = false;
}

4、HC595显示函数。

//HC595 write 8bit
void HC595_WriteData(uint8_t data)
{
    uint8_t i;
    for(i=0; i<8; i++)
    {
        if((data & 0x80) > 0)
        {
            HC595_DAT_H;
        }else
        {
            HC595_DAT_L;
        }
        data <<= 1;
        HC595_CLK_L;
        delay_cycles(8);
        HC595_CLK_H;
        delay_cycles(8);
    }
}
//HC595 display enable
void Display_Out(void)
{
    HC595_RCK_L;
    delay_cycles(8);
    HC595_RCK_H;
    delay_cycles(8);
}
//HC595 write break and bit
void HC595_SendData(uint8_t disp_num, uint8_t disp_bit)
{
    HC595_WriteData(disp_num);
    HC595_WriteData(1 << disp_bit);
    Display_Out();
}
//HC595 display 4 LEDs
void Display_4bData(uint16_t data)
{
    uint16_t temp;
    uint8_t num_q,num_b,num_s,num_g;

    temp = data;
    num_q = temp / 1000;
    num_b = temp / 100 % 10;
    num_s = temp / 10 % 10;
    num_g = temp % 10;
    HC595_SendData(Disp_DX[num_q],3);
    HC595_SendData(Disp_DX[num_b],2);
    HC595_SendData(Disp_DX[num_s],1);
    HC595_SendData(Disp_DX[num_g],0);
}
//HC595 display 8 LEDs
void Display_8bData(uint16_t dataH, uint16_t dataL)
{
    uint16_t tempH,tempL;
    uint8_t num_q,num_b,num_s,num_g;

    tempH = dataH;
    num_q = tempH / 1000;
    num_b = tempH / 100 % 10;
    num_s = tempH / 10 % 10;
    num_g = tempH % 10;
    HC595_SendData(Disp_DX[num_q],7);
    HC595_SendData(Disp_DX[num_b],6);
    HC595_SendData(Disp_DX[num_s],5);
    HC595_SendData(Disp_DX[num_g],4);

    tempL = dataL;
    num_q = tempL / 1000;
    num_b = tempL / 100 % 10;
    num_s = tempL / 10 % 10;
    num_g = tempL % 10;
    HC595_SendData(Disp_DX[num_q],3);
    HC595_SendData(Disp_DX[num_b],2);
    HC595_SendData(Disp_DX[num_s],1);
    HC595_SendData(Disp_DX[num_g],0);
}
//HC595 display temperature: 3 integers, 1 decimal point: xxx.x
void Display_D3P1TempC(uint16_t data)
{
    uint16_t temp;
    uint8_t num_q,num_b,num_s,num_g;

    temp = data;
    num_q = temp / 1000;
    num_b = temp / 100 % 10;
    num_s = temp / 10 % 10;
    num_g = temp % 10;
    HC595_SendData(Disp_DX[num_q],3);
    HC595_SendData(Disp_DX[num_b],2);
    HC595_SendData(Disp_DX[num_s]&0x7F,1);
    HC595_SendData(Disp_DX[num_g],0);
}
//HC595 display temperature: 3 integers + 2 integers, 1 decimal point: xxxC + xx.xC
void Display_AD3P1TempC(uint16_t dataH, int16_t dataL)
{
    uint16_t tempH,tempL;
    uint8_t num_q,num_b,num_s,num_g;

    tempH = dataH;
    num_b = tempH / 100 % 10;
    num_s = tempH / 10 % 10;
    num_g = tempH % 10;
    if(num_b > 0)
        HC595_SendData(Disp_DX[num_b],7);
    HC595_SendData(Disp_DX[num_s],6);
    HC595_SendData(Disp_DX[num_g],5);
    HC595_SendData(Disp_DX[13],4);

    tempL = dataL;
    num_b = tempL / 100 % 10;
    num_s = tempL / 10 % 10;
    num_g = tempL % 10;
    HC595_SendData(Disp_DX[num_b],3);
    HC595_SendData(Disp_DX[num_s]&0x7F,2);
    HC595_SendData(Disp_DX[num_g],1);
    HC595_SendData(Disp_DX[13],0);
}

5、DS18B20读写函数。

//delay n us
void delay_us(uint32_t nus)
{
    delay_cycles(nus*32);
}

//DS18B20 Reset
void DS18B20_Reset(void)
{
    DS18B20_OutPut_Mode;
    DS18B20_DIO_OUT_L;
    delay_us(750);      //750us
    DS18B20_DIO_OUT_H;
    delay_us(15);       //15us
}

//DS18B20 ACK: 0 - true, 1 - false
uint8_t DS18B20_Check(void)
{
    uint8_t retry = 0;
    uint8_t rval = 0;

    while ((DS18B20_DIO_IN > 0) && (retry < 200))       //wait 200us
    {
        retry++;
        delay_us(1);
    }

    if (retry >= 200)
    {
        rval = 1;
    } else
    {
        retry = 0;

        while (!(DS18B20_DIO_IN > 0) && (retry < 240))  //wait 240us
        {
            retry++;
            delay_us(1);
        }

        if (retry >= 240) rval = 1;
    }

    return rval;
}

//DS18B20 Initialization
uint8_t DS18B20_Init(void)
{
    DS18B20_Reset();
    return DS18B20_Check();
}

//DS18B20 read 1bit
uint8_t DS18B20_Read_bit(void)
{
    uint8_t data = 0;
    DS18B20_DIO_OUT_L;
    delay_us(2);
    DS18B20_DIO_OUT_H;
    delay_us(12);
    DS18B20_InPut_Mode;
    if (DS18B20_DIO_IN > 0)
    {
        data = 1;
    }

    delay_us(50);
    return data;
}

//DS18B20 read 1Byte
uint8_t DS18B20_Read_Byte(void)
{
    uint8_t i, b, data = 0;

    for (i = 0; i < 8; i++)
    {
        b = DS18B20_Read_bit(); //LSB -> MSB

        data |= b << i;
    }

    return data;
}

//DS18B20 write 1Byte
void DS18B20_Write_Byte(uint8_t data)
{
    uint8_t j;

    for (j = 1; j <= 8; j++)
    {
        if (data & 0x01)
        {
            DS18B20_DIO_OUT_L;  //write 1
            delay_us(2);
            DS18B20_DIO_OUT_H;
            delay_us(50);
        } else
        {
            DS18B20_DIO_OUT_L;  //write 0
            delay_us(50);
            DS18B20_DIO_OUT_H;
            delay_us(2);
        }

        data >>= 1;
    }
}

//DS18B20 start convert temperature
void DS18B20_Start(void)
{
    DS18B20_Reset();
    DS18B20_Check();
    DS18B20_Write_Byte(0xcc);       //skip rom
    DS18B20_Write_Byte(0x44);       //convert
}

//DS18B20 get temperature value, 0.1C ,return C = temp/10
uint16_t DS18B20_Get_Temperature(void)
{
    uint8_t flag = 1;               //Positive and Negative flag: Positive
    uint8_t TempL, TempH;
    uint16_t temp;

    DS18B20_Start();                //DS18B20 start convert

    DS18B20_Reset();
    DS18B20_Check();
    DS18B20_Write_Byte(0xcc);       //skip rom
    DS18B20_Write_Byte(0xbe);       //convert

    TempL = DS18B20_Read_Byte();    //LSB
    TempH = DS18B20_Read_Byte();    //MSB

    if (TempH > 7)
    {
        TempH = ~TempH;
        TempL = ~TempL;
        flag = 0;                   //Negative
    }

    temp = TempH;
    temp <<= 8;
    temp += TempL;

    //convert temperature
    if (flag == 0)
    {
        temp = (double)(temp+1) * 0.625;
        temp = -temp;
    } else
    {
        temp = (double)temp * 0.625;
    }

    return temp;
}

6、main函数。

int main(void)
{
    SYSCFG_DL_init();
    
    NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);

    while (1)
    {
        if(Key1Tmp)
        {
            KeyBounce ++;
            if(KeyBounce >= 2000)
            {
                //TmpVal3++;
                KeyBounce = 0;
                BEEP_ON;
            }
            //if(TmpVal3 >= 10000) TmpVal3 = 0;
        }
        else if(((float)gDs18b20TempC/10 - (float)gAdcNtcTempC) > 3.0) //DS18B20 temperature - NTC temperature > 3.0C
        {
            BEEP_ON;
        }
        else BEEP_OFF;
        //Display_4bData(TmpVal3);

        cycle++;
        if(cycle >= 8000)
        {
            cycle = 0;
            DL_ADC12_startConversion(ADC12_0_INST);
            ReadNtcTemprature();                                //get NTC temperature
            DL_ADC12_enableConversions(ADC12_0_INST);
            gDs18b20TempC = DS18B20_Get_Temperature();          //get DS18B20 temperature
        }

        Display_AD3P1TempC(gAdcNtcTempC, gDs18b20TempC);        //display NTC & DS18B20 temperature
    }
}

四、显示效果

1715137504545.png

成果视频:

视频1:http://v.eepw.com.cn/video/play/id/15983

视频2:http://v.eepw.com.cn/video/play/id/15984

视频3:http://v.eepw.com.cn/video/play/id/15985

完结,共进!





关键词: 玩转     TIMSPM0     74HC595     数码管显示         

高工
2024-05-08 11:36:56     打赏
2楼

完结,共进!


院士
2024-05-08 19:17:51     打赏
3楼

您这儿也太详细了吧!

赞一下


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]