当前位置: 网站首页 > 技术应用 > 单片机应用 > 应用范例

RC 充放电的原理和硬体

1、RC 充放电的原理和硬体

我们知道,电阻R 与电容C 充电时间的关系如下图:

图片关键词

 

注:Rs 为标准电阻  Rt 为热敏电阻

由上图可以看出在RC 充电开始阶段,我们可以认为是近似线性的。

那么:

Tt=K*Rt*C (1)

Ts=K*Rs*C (2)

其中: K 为常数

由(1)、(2)可知充电时间的比例与R 有关,而C 无关。

Rt=(Rs*Tt)/Ts

当然,随环境温度的变化电容C 变化比较大,我们完成标准电阻和热敏电阻对同一电容的充放电在很短的时间

内,因而电容C 变化引起的误差可以消除。为了提高精度,对电容C 的选取也有关系,电容容量不能太小,也不能太大,

与传感器的标称值有关。

下面是我自己写的程序,仅着参考:

///////////////////////////////////////

RC充放电---得到NTC的阻值

电路: p2.3(IOntc)接NTC,P2.4(IOrs)接一个1k的电阻,二电阻一端连接一个10uf的电容到地

思路:

; 放电:

; 二个端口是都输出0,

; 充电:(NTC)

; IOrs 输入检测 0  当 IOrs 为高,继续检测直到为0为止

; IOntc 输出 1 ,进行充电,并开始计时,

; 时刻检测IOrs的电平,当 IOrs 端口为高电平的时候,说明充电已经完成,并停止计时,把时间保持给t_ntc_middle和t_ntc_low

; 放电:同上

; 充电:(RS)

; IOntc 输入检测 0  当 IOntc 为高,继续检测直到为0为止

; IOrs 输出 1 ,进行充电,并开始计时,

; 时刻检测 IOntc 的电平,当 IOntc 端口为高电平的时候,说明充电已经完成,并停止计时,把时间保持给t_rs_middle和t_rs_low

; 注:这里所说的计时是根据指令的长短计时的,比如我这里一条指令为0.25US,一周为7跳指令

///////////////////////////////////////

///////////////////////////////////////

.DATA

t_ntc_middle ds      1 ;

t_ntc_low ds      1 ;

t_rs_middle ds      1 ;

t_rs_low ds      1 ;

///////////////////////////////////////

.CODE

///////////////////////////////////////

rc:

///////////////////////////////////////

;放电

///////////////////////////////////////

rc_sub:

  bset IOntcm

  bset IOrsm

  bclr IOntc ;输出 0

  bclr IOrs

///////////////////////////////////////

bclr IOrsm ;输入检测 0,为0 说明放电完全

bts0 IOrs

jmp $-1

///////////////////////////////////////

  bts0 f_turn ;为谁充电

  jmp rc_rs_add

///////////////////////////////////////

;充电:(NTC)

///////////////////////////////////////

rc_ntc_add:

  clr t_ntc_low

  clr t_ntc_middle

bset IOntcm ;输出 1,充电

  bset IOntc

  incms t_ntc_low

  jmp $+2

  incms t_ntc_middle

  bclr IOrsm

  bts1 IOrs ;检测1,为1 说明充电完成

  jmp $-5

  bset f_turn

  jmp rc_pro90

///////////////////////////////////////

;充电:(RS)

///////////////////////////////////////

rc_rs_add:

  bset IOrsm ;输出 1,充电

  bset IOrs

  incms t_rs_low

  jmp $+2

  incms t_rs_middle

  bclr IOntcm

  bts1 IOntc ;检测1,为1 说明充电完成

  jmp $-5

  bclr f_turn

  jmp rc_pro90

///////////////////////////////////////

rc_pro90:

  Ret

 

RC 测温的实现方法是利用电阻R 给电容C 充放电时间来测量温度的(此处的温度感测器为热敏电阻)。

用不同的电阻给电容充放电时间不一样,对RC 测量温度的精度与电阻R 和电容C 的选取有关。我们通常是选用一个标准电阻(随温度变化其阻值变化很小,可忽略不计,通常为高精度的金属膜电阻),它的阻值Rs 与温度传感器在标准大气压下、25℃时的阻值相同。当温度发生变化时,热敏电阻的阻值Rt 发生变化,那么热敏电阻Rt 给电容C 的充放电时间也发生变化。而标准电阻Rs 给电容C 的充放电时间则不发生变化。

    以下介绍的这个方法是用没有ADC 功能的芯片来检测模拟量,如采集温度。

 

1. 温度检测电路图

图片关键词

  2. 温度检测步骤 

       第一步:放电 P85  P86设置为高阻态,P87 输出“1” ,电容放电 

       第二步:测标准电阻 P85  P87设置为高阻态,P86 输出“0” ,电容充电,并对充电时间计时 计时功能说明:计时最小时基为 30US,用定时器中断来实现。每 30US中断一次,计时器+1 计时器长度=16BIT 高字节的 BIT4 代表溢出位。 所以实际有效长度为 12 位超出则判为溢

出,可能是被测电阻开路和电容短路等故障引起的。

    第三步:放电 P85  P86设置为高阻态,P87 输出“1” 电容放电

    第四步:测温度电阻 P86  P87设置为高阻态,P85 输出“0” ,电容充电,并对充电时间计时 计时功能说明: (同第二步) 

       第五步:计算电阻比率 计算公式: 电阻比率=温度电阻

 

AD中的顺序查表

说明:在做温度检测并由数码管显示的时候由于一个温度对应一个 AD值,而我们的 AD 值是在一段时间的平均值,很大一部分 AD 在表中是不能够一对一对应的,所以我们只能取隔他最近的 AD,此为 AD 转换后用于查表的顺序程序,这样查表很容易理解,但是也存在很多不足,比如 CPU 在此程序运行周期长等等,当然我会在以后会添加

输入:高位 AD_Data_high,低位 AD_Data_low,

输出:数码管显示的数值  b_room_temp

.data//把 AD 值转换成数值,
 ad_new_tab ds 1   ;查表的地址给A(如 0 1 2 74 99 105之类的,比如99就对应的是99度)
 ad_old_tab ds 1   ;旧
 ad_old_h ds 1   ;旧值的高位
 ad_old_l ds 1   ;旧值的低位
 ad_new_h ds 1   ;新值的高位
 ad_new_l ds 1   ;新值的低位
 ad_mean_h ds 1   ;平均值的高位
 ad_mean_l ds 1   ;平均值的低位
 b_room_temp ds 1   ;显示的数值,是十进制的
////////////////////////////////////////////////////////
.code
ad_change:
////////////////////////////////////////////////////////;;这里可以单独检查其他程序的错误性
/*    MOV    a,  #0x0f   ;;
  B0MOV  AD_Data_High, a   ;;ad数据存放
  MOV   a, #0x00b   ;;
  B0MOV  AD_Data_low, a    ;;ad数据存放     */   

  MOV_ ad_old_tab, #0
check_tab:
  b0mov y,#temp_tab$m    ;
  b0mov z,#temp_tab$l    ;
  mov a,ad_old_tab    ;查表的地址给A(如 0 1 2 74 99 105之类的,比如99就对应的是99度)
  b0add z,a     ;
  b0bts0 fc     ;
  incms y     ;
  nop      ;
  movc      ;
  mov ad_old_l,a    ;低8位存放在temp_l中
  mov a,r     ;高4位存放在temp_h中
  mov ad_old_h,a    ;
////////////////////////////////////////////////////////;把旧值赋给新值,这里是为平均那里作准备
  mov  a,ad_old_l
  mov  ad_new_l,a 
  mov  a,ad_old_h
  mov  ad_new_h,a
  mov  a,ad_old_tab
  mov  ad_new_tab,a                
////////////////////////////////////////////////////////
 cjne_  AD_Data_high, ad_new_h, ad_change10;判断高位是否相等,不等跳转到 ad_change10 继续查找
 cjne_  AD_Data_low, ad_new_l, ad_change10;如果高位相等,那比较低位,如果不等,跳转到ad_change10    
 mov_ b_room_temp, ad_new_tab    
 jmp ad_change_exit    ;如果刚好 等于 则把 b_ad_tab 给 b_room_temp, 然后跳出程序
/////////////////////////////////////////////////////////  ;如果不等
ad_change10:
 cjae2 AD_Data_High,AD_Data_Low,ad_new_h,ad_new_l,ad_change30
///////////////////////////////////////////////////////// 当小              
ad_change20:       
 incms ad_old_tab         
 jmp check_tab
///////////////////////////////////////////////////////// 当大
ad_change30:      ;先判断是否超出范围(00-99),如果在的话查出上一次的值
 cjae2 AD_Data_High,AD_Data_Low,#0x0f,#0x17,ad_change70 ;0度的 AD 值为0xf16,防止下于 0度
 cjbe2 AD_Data_High,AD_Data_Low,#0x3,#0xd2,ad_change80 ;100 度的AD 值为0x3d3,防止超过 99度

 decms ad_old_tab
 b0mov y,#temp_tab$m    ;
 b0mov z,#temp_tab$l    ;
 mov a,ad_old_tab    ;查表的地址给A(如 0 1 2 74 99 105之类的,比如99就对应的是99度)
 b0add z,a     ;
 b0bts0 fc     ;
 incms y     ;
 nop      ;
 movc      ;
 mov ad_old_l,a    ;低8位存放在temp_l中
 mov a,r     ;高4位存放在temp_h中
 mov ad_old_h,a
/////////////////////////////////////////////////////////上次(大)的减去这次(小)的值,得的值再平均一下,再加上现在 Ad 的低位
 mov a,ad_old_h  ;平均值的高位
 sub a,ad_new_h
 mov x,a 
 b0bclr fc    
  rrcm  x
 add_ x,ad_new_h                     
 mov_ ad_mean_h, x
 
 mov a,ad_old_l  ;平均值的低位
 sub a,ad_new_l
 mov x,a 
 b0bclr fc    
 rrcm  x
 add_ x,ad_new_l                     
 mov_ ad_mean_l,x
/////////////////////////////////////////////////////////看采样的 AD 值更靠那一边,那个距离短 就取那个值
 cjae2 AD_Data_High,AD_Data_Low,ad_mean_h,ad_mean_l,ad_change60 
/////////////////////////////////////////////////////////取新值,,比如一个AD为86,80和90的平均值为85,86>85,则选择90
ad_change50:      ;(AD大的,温度小的)
 mov_ b_room_temp, ad_new_tab     
 jmp ad_change_exit                                             
/////////////////////////////////////////////////////////取旧值
ad_change60:      ;(AD大的,温度小的)
 mov_ b_room_temp, ad_old_tab    
 jmp ad_change_exit
/////////////////////////////////////////////////////////// 小于 00
ad_change70:
 mov_ b_room_temp, #0    
 jmp ad_change_exit
///////////////////////////////////////////////////////////  大于 99
ad_change80:
 mov_ b_room_temp, #99    
 jmp ad_change_exit
/////////////////////////////////////////////////////////
ad_change_exit:
  ret

MCU芯片中时常碰到口线不够用的时候,我们会采用口线复用的方法,将io口同时既作为输入口驱动led灯,同时又作驱动数码管,又将按键也复用下面看下这个图

图片关键词

   当我们需要同时点亮led灯,数码管,同时需要判断按键的时候我们就必需合理处理它们之间的关系,在扫描led灯的时候我们可以设定扫描周期为1ms扫描一次,每次扫描led灯的时候,需要初始化led灯的口线状态,扫描完led灯再扫描数码管,设定数码管的扫描周期为3ms,同时需要初始化数码管的口线,为输出模式同时为输出为1。最后是扫描按键,在扫描按键的时候我们设定按键为输入上拉电阻模式。扫描的周期为5ms,由于程序运行时间即短,所以它们之间不会相互影响。

     上面的按键公共端接地,连接单片机的这端必需接个10k的上拉电阻,这样按键按下或按键长按的时候不会影响数码管的亮度,或者可以将数码管的公共接地端改为直接接单片机的io口,扫描按键的时候io口输出为0,扫描数码管的时候设定为输入模式,按键按下或长按时,这样不会影响数码管的亮度。

点击次数:  【关闭

下一条:PCB板材选取
  • 壹零零单片机©版权所有 2008-2023 粤ICP备17151077号

Powered by  xinfuke  5.2.5 ©2008-2024  www.100mcu.com