单片机
返回首页

51单片机,18B20,1602温度计+串口通信

2020-11-21 来源:51hei

制作出来的实物图如下:
 



仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


上位机:
  

安装程序解压到同一目录下。再运行setup安装。。。。

温度计.exe
编写环境Win10 x64.     VS2010 x86  C++ MFC
测试环境Win10 x64.   

在32位系统上,能不能正常使用还不清楚。
所以公布了源代码文件,如果在32位系统上,不能正常使用。
请使用源代码文件,在32位系统上重新生成一下应用程序。。。

单片机源程序如下:

#include

#include "math.h"


bit flag1s = 0, _up = 0;          //1s定时标志

unsigned char T0RH = 0;  //T0重载值的高字节

unsigned char T0RL = 0;  //T0重载值的低字节


void ConfigTimer0(unsigned int ms);

unsigned char IntToString(unsigned char *str, int dat);

extern bit Start18B20();

extern bit Get18B20Temp(int *temp);

extern void InitLcd1602();

extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);


//串口初始化函数

void InitUART()

{

                //IP = 0x10;

                TMOD &= 0x0F;

    TMOD |= 0x20;

    SCON = 0x50;

    TH1 = 0xF3;

    TL1 = TH1;

    PCON = 0x00;

    EA = 1;

    ES = 1;

    TR1 = 1;

}


//串口发送1字节数据

void SendOneByte(unsigned char c)

{

    SBUF = c;

    while(!TI);

    TI = 0;

}

void main()

{

    bit res;

    int temp, former=0xffff;        //读取到的当前温度值

    int intT, decT;  //温度值的整数和小数部分

    unsigned char len;

    unsigned char str[12];

               

                IP = 0x10;

                InitUART();

    // EA = 1;            //开总中断

    ConfigTimer0(10);  //T0定时10ms

    Start18B20();      //启动DS18B20

    InitLcd1602();     //初始化液晶

   

    while (1)

    {

        if (flag1s || _up)  //每秒更新一次温度

        {

            flag1s = 0;

            res = Get18B20Temp(&temp);  //读取当前温度

            if (res && ((abs(temp-former) >= 4)||_up))                 //读取成功时,刷新当前温度显示

            {

                                                                former = temp;                                                                //记录新的温度

                                                                _up = 0;

                                                                SendOneByte((unsigned char) (temp/256));

                                                                SendOneByte((unsigned char) (temp%256));

                intT = temp >> 4;             //分离出温度值整数部分

                decT = temp & 0xF;            //分离出温度值小数部分

                len = IntToString(str, intT); //整数部分转换为字符串

                str[len++] = '.';             //添加小数点

                decT = (int)((decT*100) * 0.0625 + 0.5);        //二进制的小数部分转换为1位十进制位

                str[len++] = decT/10 + '0';      //十进制小数位再转换为ASCII字符

                                                                str[len++] = decT%10 + '0';

                                                                str[len++] = 'C';

                while (len < 7)               //用空格补齐到6个字符长度

                {

                    str[len++] = ' ';

                }

                str[len] = '';              //添加字符串结束符

                LcdShowStr(0, 0, str);        //显示到液晶屏上

            }

            else                        //读取失败时,提示错误信息

            {

                                                                if(!res)

                                                                        LcdShowStr(0, 0, "error!");

            }

            Start18B20();               //重新启动下一次转换

        }

    }

}

/* 整型数转换为字符串,str-字符串指针,dat-待转换数,返回值-字符串长度 */

unsigned char IntToString(unsigned char *str, int dat)

{

    signed char i = 0;

    unsigned char len = 0;

    unsigned char buf[6];

   

    if (dat < 0)  //如果为负数,首先取绝对值,并在指针上添加负号

    {

        dat = -dat;

        *str++ = '-';

        len++;

    }

    do {          //先转换为低位在前的十进制数组

        buf[i++] = dat % 10;

        dat /= 10;

    } while (dat > 0);

    len += i;     //i最后的值就是有效字符的个数

    while (i-- > 0)   //将数组值转换为ASCII码反向拷贝到接收指针上

    {

        *str++ = buf[i] + '0';

    }

    *str = '';  //添加字符串结束符

   

    return len;   //返回字符串长度

}

/* 配置并启动T0,ms-T0定时时间 */

void ConfigTimer0(unsigned int ms)

{

    unsigned long tmp;  //临时变量

   

    tmp = 12000000 / 12;      //定时器计数频率

    tmp = (tmp * ms) / 1000;  //计算所需的计数值

    tmp = 65536 - tmp;        //计算定时器重载值

    tmp = tmp + 15;           //补偿中断响应延时造成的误差

    T0RH = (unsigned char)(tmp>>8);  //定时器重载值拆分为高低字节

    T0RL = (unsigned char)tmp;

    TMOD &= 0xF0;   //清零T0的控制位

    TMOD |= 0x01;   //配置T0为模式1

    TH0 = T0RH;     //加载T0重载值

    TL0 = T0RL;

    ET0 = 1;        //使能T0中断

    TR0 = 1;        //启动T0

}

/* T0中断服务函数,完成1秒定时 */

void InterruptTimer0() interrupt 1

{

    static unsigned char tmr1s = 0;

   

    TH0 = T0RH;  //重新加载重载值

    TL0 = T0RL;

    tmr1s++;

    if (tmr1s >= 100)  //定时1s

    {

        tmr1s = 0;

                                if(!flag1s)

                                        flag1s = 1;

    }

}


//串口中断服务函数,

void UARTInterrupt(void) interrupt 4

{

                char ch=0;

    if(RI)

    {

        RI = 0;

                                ch = SBUF;

                                if((ch=='1') && !_up)

                                        _up = 1;

        //add your code here!

    }/*

    else

        TI = 0;*/

}



进入单片机查看更多内容>>
相关视频
  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • 如何使用开关型充电器设计安全可靠、有长待机时间、且由微型电池供电的产品

  • 汽车照明应用中的高边线性 LED 驱动产品

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 新唐 8051单片机教程

    相关电子头条文章