【整个小活】基于STC8H内部RC时钟温飘的温度计,0外设测量温度
众所周知,STC8H系列内部32K时钟温飘特别大,频率温飘基本相当于一个NTC电阻的阻值。把系统时钟调低,比如11.0592MHz,这样内部16位计时器就能充分的测量一个1/32的RTC中断,即可从计时器值估测内部RTC频率;
再根据温飘映射到文档数值,就知道此时单片机的温度了。
void init_rtc() {
// 选择内部 32K
IRC32KCR = 0x80; // 启动内部 32K 振荡器
while (!(IRC32KCR & 0x01))
; // 等待时钟稳定
RTCCFG |= 0x02; // 选择内部 32K 作为 RTC 时钟源
// 设置 RTC 时间
INIYEAR = 00;
INIMONTH = 1;
INIDAY = 15;
INIHOUR = 15;
INIMIN = 30;
INISEC = 0;
INISSEC = 0;
RTCCFG |= 0x01; // 触发 RTC 寄存器初始化
RTCIF = 0; // 清中断标志
RTCIEN = 0x01; // 使能 RTC 1/32秒中断
RTCCR = 0x01;// RTC 使能
}
// @11.0592MHz
void init_tm0(void) {
AUXR &= 0x7F; // 定时器时钟12T模式
TMOD &= 0xF0; // 设置定时器模式
TMOD |= 0x01; // 设置定时器模式
}
uint8_t data temp_tl = 0;
uint8_t data temp_th = 0;
void isr_rtc() interrupt(RTC_VECTOR) using(1) {
RTCIF = 0; // 清中断标志
TR0 = 0;
temp_tl = TL0;
temp_th = TH0;
TL0 = 0xff;
TH0 = 0xff;
TF0 = 0;
TR0 = 1;
}
void main() {
init_sys();
init_uart();
init_tm0();
init_rtc();
while (1) {
uint16_t c = 0xffff - (temp_th << 8 | temp_tl);
int16_t t = (650 * ((int32_t)33563 - c)) / 7900;
printf("t: %d\r\n", t);
delay_ms(1000);
}
}
量程0 ~ 65度,上面的简单线性映射是我用冰块和热水校准的。
其中映射关系因为每个芯片的体制不一样,必须校准。
为了避免计算浮点数,温度t的数值单位是10摄氏度,既24.3C => 243。
假定电压和主时钟是稳定的。
测量精度在室温还说的过去{:4_187:}
// 室温输出
t: 242
// 手按上去加热
t: 271
// 冰块贴到芯片上
t: 18
各位愚人节快乐
测试用的芯片是stc8h8k64u,实测。 未曾设想的逆向思维 很有趣的想法{:4_174:} 楼主的想象力很丰富。 奇思妙想 还能这么搞啊 佩服楼主的思维{:4_174:} 可以,用MATLAB拟合一下可以比较准确的获取当前温度 是不是还可以将ADC参考电压和MCU电源接起来,根据ADC15通道 测量单片机的供电电压再根据电压图修正一下。。{:4_187:}
页:
[1]
2