控制/MCU
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 = 40961.2V/Nbg= 409612000mV/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=Nin1200/Nbg=0x4b0Nin/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位变量(范围065535)与一个定值(500,范围065535)相乘
// 两个乘数可以为定值,也可为变量
// 同为定值时可直接用“*”运算符
//注意事项:
// 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
;-----------------------------------------------
全部0条评论
快来发表一下你的评论吧 !