mcu5i51 发表于 2008-4-27 07:26:37

使用RC冲放电的温度计

______
IN)----|__100_|-------
             ______       |   | |
REF)----|__10K_|------------| |---(GND)
             ______       |   | |
RX)---------|__RT _|-------

http://cache.amobbs.com/bbs_upload782111/files_9/ourdev_261002.jpg
(原文件名:测温.jpg)
使用夏普传真上拆的LCD的测试图;
这是主程序,不含RT转换函数和LCD显示,稍加修改就能用:
#include <avr/io.h> //MCU为ATmega48
#include <stdio.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <avr/sleep.h>

#include "lcd.h"
#include "lcdTimer.h"
#include "r2t.h"

#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long

//电阻测试引脚
#define RESPOR PORTD
#define RESDDR DDRD
#define RESPIN PIND

#define INP 2
#define RXP 1
#define RFP 0

//开始计时
#define STARCT() TCCR1B = 0x01;        //1=不分频;2=8分频内部计数器
unsigned char buff;

#define TESTN        10        //测试平均数

int Vout;

ISR(SIG_OUTPUT_COMPARE0A)
{
        uint ms;
        ms++;
        if(ms > Vout)LCD_write_char(15,'1');
        elseLCD_write_char(15,'0');
       
        if(ms > 5000) ms = 0;
                       
}
ISR(SIG_INTERRUPT0)
{
        //停止计数
        TCCR1B = 0;       
        EIMSK &=~_BV(INT0);                //禁用外部中断0
}
void resinit(void)
{
        ///////////////////////////////////////////
        /////////////电阻测试初始化////////////////
       
        //端口设置为输入
        RESPOR &= ~(_BV(RFP) | _BV(INP) | _BV(RXP));
        RESDDR &= ~(_BV(RFP) | _BV(INP) | _BV(RXP));
       
        //定时器设置
        TCCR1A = 0x00;
        //TCCR1B = 0x02;        //8分频内部计数器
        TCCR1C = 0x00;
        //TIMSK1 |= _BV(TOIE1);        //开定时中断;
        TIFR1 |= _BV(TOV1);                //清定时中断;
       
        //输入中断设置
        EICRA = 0x2;                //外部中断0为引脚下降沿触发
        EIFR|=_BV(INT0);
        EIMSK |=_BV(INT0);                //允许外部中断0
}
void testrf(void)
        //测试基准电阻
{
        ////////////////电阻时间测试//////////////////

        //端口设置为输入
        RESPOR &= ~(_BV(RFP) | _BV(INP) | _BV(RXP));
        RESDDR &= ~(_BV(RFP) | _BV(INP) | _BV(RXP));
        //放电
        RESDDR |= _BV(INP);
        RESPOR |= _BV(INP);
        Delay_10ms(50);
        RESDDR &= ~_BV(INP);
        RESPOR &= ~_BV(INP);
                       
        //清零
        TCNT1 = 0;
               
        //开外部中断
        EIMSK |= _BV(INT0);
        EIFR|=_BV(INT0);
        EIMSK |=_BV(INT0);                //允许外部中断0
               
        //充电
        RESPOR &= ~_BV(RFP);
        RESDDR |= _BV(RFP);
       
        //开始计数
        STARCT();
               
        //等待转换结果
        while((RESPIN & _BV(INP)))
        {
                set_sleep_mode(0);
        }
}       
void testrx(void)
        //测试输入电阻
{
        ////////////////电阻时间测试//////////////////

        //端口设置为输入
        RESPOR &= ~(_BV(RFP) | _BV(INP) | _BV(RXP));
        RESDDR &= ~(_BV(RFP) | _BV(INP) | _BV(RXP));
        //放电
        RESDDR |= _BV(INP);
        RESPOR |= _BV(INP);
        Delay_10ms(50);
        RESDDR &= ~_BV(INP);
        RESPOR &= ~_BV(INP);
                       
        //清零
        TCNT1 = 0;
               
        //开外部中断
        EIMSK |= _BV(INT0);
        EIFR|=_BV(INT0);
        EIMSK |=_BV(INT0);                //允许外部中断0
               
        //充电
        RESPOR &= ~_BV(RXP);
        RESDDR |= _BV(RXP);
       
        //开始计数
        STARCT();
               
        //等待转换结果
        while((RESPIN & _BV(INP))) set_sleep_mode(0);
}       
int main(void)
{
        timers_init();                //初始化系统定时器
    LCD_init();                 //初始化LCD1602
        write_command(0x01);//清屏--对应清屏指令
        Delay_10ms(2);
        resinit();                        //初始化电阻测试
        sei();
       
        while(1)
        {
                float tmprf,tmprx,tmp;
                uint bufrf,bufrx,h,l;
                uchar i,tn;
               
                if(++tn >=TESTN) tn = 0;
                testrf();
                bufrf = TCNT1;
               
                testrx();
                bufrx = TCNT1;
               
               
                tmprf = 0;
                for(i=0;i<TESTN;i++)
                {
                        tmprf += bufrf;
                }
                tmprf /= TESTN;
               
                tmprx = 0;
                for(i=0;i<TESTN;i++)
                {
                        tmprx += bufrx;
                }
                tmprx /= TESTN;
                tmp = (tmprx * 10)/tmprf;
               
                h = r2t(tmp)/10;
                l = r2t(tmp)%10;
               
//                sprintf(buff,"R=%d,T=%d.%dC",(int)(tmp*10),h,l);
                sprintf(buff,"O=%d,T=%d.%d   ",Vout,h,l);
            LCD_write_string(0,buff);
               
//                Vout = pid(r2t(tmp),Vout,200);
//                if(Vout >=5000) Vout = 5000;
//                if(Vout <=0) Vout=0;
        }
}

liqu 发表于 2008-4-27 07:47:28

以前在430上用过,是一个例程。

bjj9217 发表于 2008-4-27 11:38:17

顶!

bobo21 发表于 2008-4-28 14:18:11

我也用过RC测温的,觉得还蛮精准的。

wswh2o 发表于 2008-4-28 14:46:49

衡水的?
我是河北的

mcu5i51 发表于 2008-4-28 18:59:19

遇到老乡了!呵呵;
这一个在室温段可以接近0.2℃的精度,是一个产品的测试代码

liuqian 发表于 2008-4-29 12:57:01

430加pt1000可以作0.1度,我以前作暖气表时就是用的这种方法

mcu5i51 发表于 2008-4-30 07:07:26

有一些MCU本身有硬件的RC型AD,可以简化测试,我得这个程序使用的中断处理的,电阻较小的时候误差较大,在产品中已经修改了,是用IO直接驱动LCD的,在2。5-3。6V可以获得比较好的效果和精度,以前直接驱动LED时会有测量干扰比较大的情况,现在没有试过;
用NTC最大的特点是价格便宜,PT1000的精度很高稳定性也好,只是最便宜的也要十几,NTC国产的1%精度精度约0.3℃在20只对比时基本在0.2℃以下,采用进口的0.5%的NTC(要几元一只)接近精度0.1℃,当然工作于200℃以下还行如果到近300的时候几个小时之后就不准了,相比PT1000稳定性相差太多了,估计楼上的朋友用于暖气表时温度不会太高,可以考虑用NTC降低成本,在电线比较长的时候NTC也有较小的误差,PT的要达到精度需要考虑补偿了

lilith 发表于 2008-4-30 10:44:16

请教下,对有 AD 的 AVR 来说,RC 振荡测温、RC 充放电测温和 AD 转换测温的优缺点是什么?

mcu5i51 发表于 2008-4-30 12:13:30

AVR的AD大多是10位的,注定了测试的分辨率,假设传感器是可以变换为线性输出的电压信号,那在-20+80℃的测温范围可以得到0.1的分辨率,如果再宽的话就不行了,至少需要想些办法;RC振荡型会对环境有较高的要求,尤其是精密的电容器,也就是温度系数了,再者他需要其他元件配合,廉价的555可以做到,只是精度很低,精度高的价格又高,有时不如直接用高分辨率的ADIC;RC冲放电是比较折中的方法,精度主要依靠基准电阻和定时器,速度会比较慢,对于较小的电阻会有较大的误差,主要来源是IO电阻,会和环境电源电压有关;还有就是电容的吸收误差了,通常CBB的小些

pcwinner 发表于 2008-4-30 20:24:02

以前好像也玩过一下,一般家电用还是不错的....

anxiangbo 发表于 2009-10-30 11:42:44

记号

zhourunfa 发表于 2009-10-30 12:57:27

用傳感器做的,精度不好,為1攝氏度,有更精度更高的傳感器没?哪位大哥推薦下?

reloaded 发表于 2009-10-30 14:24:07

这照片拍的跟老录像带截图似的,,还有啊就是rx是做什么用的?(我想起来了是串口的接收端?)

daydayupper 发表于 2009-10-30 14:40:09

rx应当就是待测电阻吧,热敏电阻。

yfgww 发表于 2013-7-24 22:12:20

{:smile:}{:smile:}{:smile:}{:smile:}{:smile:}

lyflyaway 发表于 2013-8-2 13:03:27

请问可以用2个IO做吗?用2个IO做时,也就造成不同的输入电阻,会不会影响结果?
我的实验会有影响,不知大家有没这样做过?

viq505 发表于 2015-4-20 13:52:47

好帖子,收藏了

xiaoluo2009 发表于 2015-5-12 20:48:29

如果传感器断开了呢?有没有做处理?

yujian1022 发表于 2016-2-26 12:26:06

楼主可以上传一下电路图吗,在下不胜感激。

pcwinner 发表于 2017-12-27 18:18:45

记号。。。。。。

dory_m 发表于 2017-12-28 12:20:25

学习,谢谢!!!

zhcj66 发表于 2022-7-11 15:55:26

没看懂 能否解释一下过程
页: [1]
查看完整版本: 使用RC冲放电的温度计