背景
最近在一个新的开发项目中,因一个需要一个简小的外联功能模块,考虑到体积尺寸和单一的功能需求,故而思琢采用性价比较高的STC51
单片机。项目需求中需要用到温度测量,但是后来发现,自身未带AD口,无奈,遂想到之前在图书馆借阅的老外著作的《模拟电路》中有讲解到使用GPIO+TIMER+RC
实现温度测量的原理步骤,当时觉得就蛮新奇的,在此之前也听闻过网友使用此法实现了温度测量,效果说也不错,于是就决定尝试使用该方法。
原理介绍
如下,已知电容充电放电时间计算公式:Vt=V0+(Vu-V0)* [1-exp(-t/RC)]
其中:
V0
为电容上的初始电压值;
Vu
为电容充满终止电压值;
Vt
为任意时刻t,电容上的电压值。
- 如果电压为
E
的电池通过电阻R
向初值为0
的电容C
充电V0=0
,充电极限Vu=E
,
故任意时刻t
,电容上的电压为:
Vt=E*[1-exp(-t/RC)] (2)
t=RCLn[E/(E-Vt)] (3)
如果已知某时刻电容上的电压Vt
,根据常数可以计算出时间t
。
分别计算两路的充电时间Tntc、Tref
;
据式(3)
有:Rntc=Rref*(Tntc/Tref)
然后根据手册查表即可得到当前温度。
硬件原理
可能当时记漏啦,后来PCB样板回来后,发现我画的原理,使用的是两个GPIO口
,如图1,
但是后来翻看那本书,上面使用的是三个GPIO口
,如图2。
为了保证先实现,遂在PCB上找一个空GPIO引脚飞一下。按照书上的步骤,最后总算实现了对环境温度的测量,无论是精度,稳定度,效果还是不错的。
在实现完这个之后,我就想了想,应该是可以用两个GPIO口实现温度测量,因为我那个漏掉的GPIO口,按书上逻辑是直接用来给电容C直接充放电通道的。
但是实际应该也可以使用上面两个自身的GPIO口就可以进行充放电动作。故而我更改了一下思路步骤,嘿嘿,最后还真实现啦,效果跟三线制一样的效果。
当然该方法可以在AD资源匮乏的情况下使用,如有AD建议使用AD采集方式更为可靠。
参考软件代码
- 两线制法
//-----two wire
#define Rntc_CAP_DISCHARGE() {
P34_PP_MODE();GP1=0;Delay1ms(5);} //GP1 //use for charging and discharging port//the capitor discharge equel to zero;
#define Rntc_CAP_CHARGE() {
P34_PP_MODE();GP1=1;}
#define Rref_CAP_DISCHARGE() {
P35_PP_MODE();GP2=0;Delay1ms(5);}
#define Rref_CAP_CHARGE() {
P35_PP_MODE();GP2=1;}
void two_element_charge_action()
{
ntc_charge_over_flag=0;//NTC路 充电完成标志置初值0
ntc_charge_t=0;//NTC路 充电时间置初值0
P35_HZ_MODE();//GPIO设置为高阻抗模式
Rntc_CAP_DISCHARGE();//NTC路 电容放完电
Rntc_CAP_CHARGE();//对电容充电
while(0==GP2)//开启计时并检测GPIO电平的翻转
{
T0_ON();
}
T0_OFF(); //关闭计时
ntc_charge_over_flag