PFS122检测VDD及IO口的AD电压方法

描述

         PFS122是应广推出的一颗,可以多次烧录的2K程序空间的带数字12位AD转换的单片机。目前以高性价比重新获得用户的喜爱,其价格优势明显,比九齐的062E的价格,可能还更具有优势。

         PFS122的AD转换相对于PMS132等来说,显得比较劣势,主要是因为IC不能接外部参考电压,也不提供内部的2V,3V,  4V等参考电压。这样在处理VDD处于变化的应用环境,比如锂电池应用,就显得没有那么方便。

        在处理VDD方面,也就是获取锂电池电压的时候,还有个别工程师的设计是使用两个电阻分压,再利用一个IO口去采集分压点来处理。这样处理用是能用,但是显得很不经济,也浪费IO口,甚至还浪费静态功耗。PFS122内部提供的参考电压1.2V,就是专门用来获取VDD电压的。也就是说1.2V相对来说是稳定的,那么不同的VDD电压,采集到稳定1.2V时,所得到的AD转换结果是不一样的,但是遵循比例:VDD/1.2V=4096/Nbg.

由上面的比例可以得到VDD = 4096*1.2V/Nbg= 4096*12000mV/Nbg

=4915200mV/Nbg=((4b0000)hex)mV/Nbg,(1)

Nbg: 是使用VDD做AD转换的参考电压,采用内部特殊通道1.2的标准电压所得的数值。

      在获取IO的电压时,我们可以同样利用比列来计算,计算的基础是

;Vbg/VDD=Nbg/4096------------------(2)

;Vin/VDD=Nin/Nvdd=Nin/4096------- (3)

两个比列相除,可以消掉VDD和4096,得到Vin=(Nin/Nbg)*Vbg

;VIN=(Nin/Nbg)*Vbg=(Nin/Nbg)*1200=Nin*1200/Nbg=0x4b0*Nin/Nbg(4)

因此,只要有Nin和 Nbg的AD转换数值,就可以得到IO口的实际输入电压是多少。由公式(1)和公式(4),可以看出要得到VDD和Vin的实际电压,需要用到运算方式,三字节除以2字节,两字节乘以两字节的运算。对于习惯了MINI-C开发的用户来说,这些运算处理方式可以在“程序助手”中的/进阶实例/数据运算中获取。

EWORD    div_src3;//被除数(商)
WORD    div_val2, div_res2;//除数,余数

void    EWord_Div_Word (void)
{    //    div_src3[E] / div_val2[W]    =    div_src3[E] * div_val2[W] + div_res2[W]
    BYTE    div_cnt, div_tmp;
    div_cnt        =    8;
    div_res2    =    0;

    do
    {
        div_src3    <<=        1;
        div_res2    <<<=    1;
        div_tmp        <<<=    1;
        div_cnt++;
        A    =    (div_res2 - div_val2) >> 8;

        if (div_tmp.0 || ! CF)
        {
            div_res2$1    =    A;
            div_res2$0    -=    div_val2$0;
            div_src3.0    =    1;
        }
    } while (! div_cnt.5);
}

//--------------------------------------------------------------------------------//
//程序说明:
//    一个16位变量(范围0~65535)与一个定值(500,范围0~65535)相乘
//    两个乘数可以为定值,也可为变量
//    同为定值时可直接用“*”运算符
//注意事项:
//    1.案例为PMS154C,其他芯片可直接使用
//********************************************************************************//
#include    "extern.h"

DWORD    mul_t4;
WORD    mul_x2;
WORD    mul_y2;

void    Word_Mul_Word (void)
{    //    mul_t4[D]    =    mul_x2[W] * mul_y2[W]
    mul_t4$3    =    0;
    mul_t4$2    =    0;

    BYTE    cnt;
    cnt    =    16;

    do
    {
        mul_x2    >>=    1;
        if (CF)
        {
            mul_t4    +=    (mul_y2 << 16);
        }
        mul_t4    >>>=    1;
    } while (--cnt);
}

但是对于一些不熟悉MINI-C的工程师朋友来说,用汇编弄起来就可能有点难度了。那也没有关系,你打赏我吧,我花了一些时间,整理了一些汇编的参考程序, 哈哈(~0~)。

单片机

汇编写起来比较累人,参考一下,16进制转10进制的汇编吧。

;-------HEX to BCD subroutine-------------------------

; Name:hex2bcd

; Input:temp0(H), temp1(L)

; Output:temp3(H), temp4(M),temp5(L)

; Stack level:2

; Function:16-bit-hex to 5-bit-dec

; Temp reg:temp2(counter register),temp6,fpp0_index

; Argument:

;--------------------------------------------

hex2bcd:

        clear  hb@fpp0_index

mov    a, 0x10

mov    temp2, a

clear  temp3

clear  temp4

clear  temp5

set0   flag_c

shift:

slc    temp1

slc    temp0

slc    temp5

slc    temp4

slc    temp3

dzsn   temp2

goto   adjdec

ret

adjdec:

        mov   a, la@temp5

        mov  lb@fpp0_index, a

        call  adjbcd

        mov   a, la@temp4

        mov  lb@fpp0_index, a

        call  adjbcd

        mov   a, la@temp3

        mov  lb@fpp0_index, a

        call  adjbcd

        goto  shift

adjbcd: 

;---------------------------------

;        mov   a, 0x22

;idxm  fpp0_index, a

;---------------------------------

        idxm  a, fpp0_index

        add   a, 0x03

        mov   temp6, a

        t0sn  temp6.3

        idxm  fpp0_index, a

        idxm  a, fpp0_index

        add   a, 0x30

        mov   temp6, a

        t0sn  temp6.7

        idxm  fpp0_index, a

        ret   0x00

;-------------the end of hex2bcd--------------------- 

;----------------------------------------------- 

;

;-------unsigned (eword)eint Div unsigned int-------------------

; Name:ueint_div_uint

; Input: temp2(D1H),temp3(D1M);temp4(D1L),temp5(D2H),temp6(D2L)

; Output: temp11(QH)temp12(QL),temp13(),

;                temp7(remainer H),temp8(remainer L)

; Stack level:1

; Temp reg:temp0(bit count),temp1(bit0:flow flag),temp8(h),temp9(l)

; Function:unsigned eint div unsignedd int;D1/D2,

; Argument:

;--------------------------------------------      

ueint_div_uint:

  mov  a, 0x18

  mov  temp0, a

clear  temp9

clear  temp7

clear  temp8

ediv_loop:

sl  temp4

slc  temp3

slc  temp2

slc  temp8

slc  temp7

slc  temp9

t0sn temp9.0

goto evalid_bit

mov  a, temp8

sub  a, temp6 

mov  a, temp7

subc  a, temp5

t0sn flag_c

goto einvalid_bit 

evalid_bit:

        mov  a, temp6

        sub  temp8, a

        mov  a, temp5

        subc  temp7, a        

        set1 flag_c

        goto eshift_result

einvalid_bit:

set0 flag_c

eshift_result:        

slc  temp13

slc  temp12

slc  temp11

dzsn temp0

goto ediv_loop

ret

;-----------------------------------------------

  审核编辑:汤梓红

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分