一乐电子

一乐电子百科

 找回密码
 立即注册

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

搜索
查看: 1982|回复: 15
收起左侧

[51单片机] 玩“隔壁论坛老王电子数码DIY”的“USB电流电压表”

[复制链接]

黄金会员

Rank: 6Rank: 6

主题
36
帖子
502
一乐金币
4724
精华
0
阅读权限
40
注册时间
2011-3-11
最后登录
2019-12-2
发表于 2019-8-2 11:15 | 显示全部楼层 |阅读模式

   首先来看一下外观:

反面

反面
   

正面

正面


界面1

界面1
   

界面2

界面2

下面是店主老王的产品介绍:此USB电压电流表为我联合qq群--电子爱好者交流群的群友开发的第一款产品,产品软件经历三四个版本,最终选定群友jam的方案为最终版本,经过一系列调试能稳定运行最终才量产的。(特别鸣谢:固件所有权归群友jam,由于作者未开源,所以qq群只公布了pcb源文件;硬件组装生产为群友邱先生完成,排线跟其中一个usb接口焊接全由其手工完成;另外特别感谢一起参与开发的十余位群友!)最高电压15伏输入;usb数据位直通,支持手机快充协议;具备电压电流监测功能;充电容量统计功能;充电电流分段时间监测功能;菜单功能,各项参数可微调校准。9664串口点阵屏,12位adc采样,精度我也不知道咋算……反正挺高,达到了主流u表分辨率。反正我是实在编不下去了,需要的自个下单吧,单个最终生产成本达到五块钱多,功能是目前我用过最完善的,价格更不要说了,纯粹不是为了赚钱,屏多,想做个产品随便卖卖而已。。。最后衷心感谢每一位支持过我的朋友!谢谢你们一路支持!下一个产品预计会开发一款彩屏的,带快充诱导的U表,耐压要达到30几伏,支持各种快充诱导,必要还会加上一些其他测试功能,目前已经囤积了一款彩屏6000多片,待闲下来慢慢联合群友开发,尽请期待。最后提醒耐压最高15伏,不支持最新的qc3.0跟pd协议,如果诱导出高于20伏的充电电压将会损坏此u表。

    本人很幸运参加了这个产品QQ群,但是能力不足,没有完成所有的功能。因投入精力很多,故把以往工作在这里总结一下,留作纪念。

黄金会员

Rank: 6Rank: 6

主题
36
帖子
502
一乐金币
4724
精华
0
阅读权限
40
注册时间
2011-3-11
最后登录
2019-12-2
 楼主| 发表于 2019-8-2 11:16 | 显示全部楼层
本帖最后由 pla155 于 2019-8-2 11:22 编辑

第一步,硬件分析
主芯片        HC89F0411P @ 32MHz RC ,经过2分频,实际工作在16MHz

显示屏        1.4寸9664液晶,IIC接口液晶屏,PCF8820主控

电流采样      通过R100电阻采样电流

电压采样      输入电压通过分压电阻衰减10倍

放大电路      LM421(丝印A63A)对电流采样值放大 10 倍

电源电路      线性电源BM1117-3.3

接口电路      一个用户定义按键

借用QQ好友的图,在这里表示感谢

原理图1.png

原理图2.png

        电路说明
1.        电源:经典1117-3.3 (U1),3.3V输出。
2.        电流检测:R1,0.1欧分压电阻。
3.        电流电路:R1的电流分压经U2,R4,R5组成的放大器10倍放大后送通道AD0(P0.0)进行数模转换。
4.        电压电路:电压经R2,R2分压电路5倍衰减后送通道AD1(P0.1)进行数模转换。
                        相应的5V输入,会有1V输出到AD1。
5.        用户按键接在P0.2 , 调试中可把串口重映射到此脚。
6.        P0.3,P0.4,P2.0管脚分别对应PCF8820显示屏的SDA,SCK,Rst。
7.        背光直接接的电源,不受控。
8.        一点建议:如果 SDA接在P0.0 ,KEY接在P0.1 ,AD采样接在P0.2 ,P0.3;
        烧录线电压就不会影响AD转换了,而且方便复用串口做调试。

       设计的思考。
1.    因为3.3V供电,所以只能用内部2V的基准。
2.    电流用0.1欧采样,放大十倍,最大量程 2A
3.    电压分压系数1/5,最大量程 10V。
4.    因为AD是12位采样深度,
             2A / 4096  ,每个分度 4.88mA ;
            10V / 4096 ,每个分度 2.44mV


黄金会员

Rank: 6Rank: 6

主题
36
帖子
502
一乐金币
4724
精华
0
阅读权限
40
注册时间
2011-3-11
最后登录
2019-12-2
 楼主| 发表于 2019-8-2 11:38 | 显示全部楼层
本帖最后由 pla155 于 2019-8-2 11:40 编辑

     关于 主芯片 HC89F0411P   的资料可以到上海芯圣电子股份有限公司查看 。
8脚的芯片,12K程序区,512RAM,5个定时器,2个高速串口,12位的AD转换应该是“老王”选择的理由之一。


HC89F0411P . PDF


HC89F0411P  ISP烧写软件

ISP.jpg


使用USB串口链接相应的管脚即可。
特别注意的是,如果下载不成功(不能连接单片机),可能是放大器锁死串口管脚电平的原因。
解决这个问题可以用断开地线(GND)后连接地线的方法给单片机供电,成功的几率比断开5V要高。



背面.jpg

黄金会员

Rank: 6Rank: 6

主题
36
帖子
502
一乐金币
4724
精华
0
阅读权限
40
注册时间
2011-3-11
最后登录
2019-12-2
 楼主| 发表于 2019-8-2 11:47 | 显示全部楼层
工作总结:

   程序完全用汇编写的,很难懂,也就不开源了。
实现了基本要求,但是没有电压、电流校正的功能。故没有完成作业,很遗憾。

Umeter-20190118.jpg

小字体.rar (2.41 MB, 下载次数: 46)

黄金会员

Rank: 6Rank: 6

主题
36
帖子
502
一乐金币
4724
精华
0
阅读权限
40
注册时间
2011-3-11
最后登录
2019-12-2
 楼主| 发表于 2019-8-2 11:48 | 显示全部楼层
本帖最后由 pla155 于 2019-8-2 14:22 编辑

  电流采样分度5mA,对应5V功率为25mW,每秒可以累加的能量最小分度25mW秒/3600秒 = 0.000007Wh。
  实时功率累计值能显示的最小单位应保持小数点后3位。
  最大值参考最大功率10V*2A = 20W , 最大分度0.005556Wh ;10Wh 分度 0.002778Wh
  按照2天48小时计算,最大能量960Wh .
  使用4字节进行计数,最大功率20W可以计时59小时。  0X100000000 / 0X4E20(20W)/3600(秒) = 59.65小时
  兼顾最大值和最小分度可以显示,最后采用格式 XXX.XXXXXWh 比较稳妥。


程序的思路分两部分,一部分是主程序,顺序执行;基本就是界面管理,按键事件管理,一些辅助运算。另一部分是写在定时器中断服务程序里的AD采样程序和部分数据处理程序。把AD写在中断程序里的好处是采样时间均匀分布,对能量做时间的积分更加准确(当然,这只是教条主义的准确,我有强迫症,不用搭理我)。因为数据采样和转换是这个程序的核心任务,就先说一下中断和AD。
使用T5定时器做系统定时器。系统时钟2分频,CPU工作在16MHz,原则上不用这么高频的,不节能。但考虑到不差钱,浪费不了多少电能,也就在高频下工作了,并且没有设计节能操作。暂时没有设计看门狗。
T5定时器预置定时7812.5微秒中断一次,每秒钟中断128次,分给AD通道电流和电压各64次转换。每次中断,读取AD结果,做累加后存放在一个3三字节变量中(SUM += ADCR),启动另一通道进行转换(ORL    ADCC0 , #11000011B)。
因为每次都是启动转换后的7.8毫秒读取ADCR结果,所以不用判断,不用等待。
为保证AD准确度,采用最慢的AD时钟。
每一次采样是一组12位有效值,每秒钟采样64次,相当于18Bit的结果,小于24Bit,不会溢出。
T5定时器每次中断还会给一个计数器加一(T5_tick++;) ,当 T5_tick^6置位,即表示程序运行了一秒,采样了64次,可以进行数值转换了。数值转换包括实时电流值,电压值,功率值,根据功率数值做能量的累计,判断电流非零进行时间累积。当然,在这些工作之前,应该有电流和电压校准值的补偿运算,目前还未实现。

黄金会员

Rank: 6Rank: 6

主题
36
帖子
502
一乐金币
4724
精华
0
阅读权限
40
注册时间
2011-3-11
最后登录
2019-12-2
 楼主| 发表于 2019-8-2 11:49 | 显示全部楼层
本帖最后由 pla155 于 2019-8-3 16:55 编辑

关于运算:单字节乘四字节乘法程序简单,由四次单字节乘法和三次加法完成。
          SUM_ADC0 * 125 可以一次完成,SUM_ADC1 * 625分成两次,一次125,一次5,都不超过255限制。
          乘4 是通过左移位2次实现,目的是通过简单的舍弃后2字节 完成/256/64的计算,而不会引入计算误差。

SUM_ADC0 = (ADCRH,ADCRL) * 64
//  Current = SUM_ADC0 / 64 *(2000/4096)   = SUM_ADC0 * 125 / 256 / 64
//     (MAX =         07 D0 00 00)                  = SUM_ADC0 * 125 * 4 /256/256
//  舍弃后16位,07D0H =  2000mA

SUM_ADC1 = (ADCRH,ADCRL) * 64
//  Voltage = SUM_ADC1 / 64 *(10000/4096) = SUM_ADC1 * 625 / 256 / 64
//                                                           = SUM_ADC1 * 625 * 4 / 256 / 256
//     (MAX = 27 10 00 00)                          = SUM_ADC1 * 5 * 125  * 4 / 256 / 256
//  舍弃后16位,2710H = 10000mV

Power = (Current * Voltage) + 0.5 ,保留2位小数



下面是AD采样的子函数文件,被T5定时器调用,完成AD采样和相关数值计算、转换功能。

NAME        FUN_ADC
/*****************************************************************************/
#include <.\01LCD\HC89F0411P.H>
/*****************************************************************************/
EXTRN        BIT         (T5_tick_0)
// - - - - - - - - - - - - -
EXTRN        DATA         (PCF8820_X,PCF8820_Y,PCF8820_Char)
// - - - - - - - - - - - - - 电流采样值求和结果,每秒64次,最大值 4096 * 64 =04 00 00H
EXTRN        DATA         (SUM_ADC0_H,SUM_ADC0_M,SUM_ADC0_L)         
// - - - - - - - - - - - - - 电压采样每秒64次,累计高字节缓冲字
EXTRN        DATA         (SUM_ADC1_H,SUM_ADC1_M,SUM_ADC1_L)                                
// - - - - - - - - - - - - - 电压采样每秒64次,累计高字节缓冲字
EXTRN        DATA         (Capacity_T,Capacity_H,Capacity_M,Capacity_L)        
// - - - - - - - - - - - - - 充放电计时器
EXTRN        DATA         (Time_Sec , Time_Min , Time_Hor , Time_Day)
// - - - - - - - - - - - - -
EXTRN        DATA         (BUF0_T,BUF0_H,BUF0_M,BUF0_L)
EXTRN        DATA         (BUF1_T,BUF1_H,BUF1_M,BUF1_L)
// - - - - - - - - - - - - - 电流运算结果
EXTRN        DATA         (CurrentH,CurrentL)                                 
// - - - - - - - - - - - - - 电压运算结果
EXTRN        DATA         (VoltageH,VoltageL)                        
// - - - - - - - - - - - - - 功率运算结果
EXTRN        DATA         (PowerH,PowerL)                        
// - - - - - - - - - - - - -         
EXTRN        DATA         (temp)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EXTRN        CODE         (LONG_RL1)
EXTRN        CODE         (LONG_MUL_BYTE,WORD_MUL_WORD)
EXTRN        CODE         (LONG_DIV_BYTE,WORD_DIV_BYTE)
EXTRN        CODE         (WORD_To_BCD,SUB_BUF0_1Byte)
EXTRN        CODE         (SUB_WATCH_BUF)
EXTRN        CODE         (PCF8820_Char8X16)
/*****************************************************************************/
?PR?Init_ADC?FUN_ADC                        SEGMENT CODE
?PR?Voltage_To_Ascii?FUN_ADC        SEGMENT CODE
?PR?Current_To_Ascii?FUN_ADC        SEGMENT CODE
?PR?Power_To_Ascii?FUN_ADC                SEGMENT CODE
?PR?Capacity_To_LCD?FUN_ADC                SEGMENT CODE
?PR?Time_To_LCD?FUN_ADC                        SEGMENT CODE
// ------  下面这两个函数被 T5 中断调用 ---------------------------------------
?PR?AD_Sample?FUN_ADC                        SEGMENT CODE
?PR?AD_Process?FUN_ADC                        SEGMENT CODE
/*****************************************************************************/
                PUBLIC                Init_ADC
                PUBLIC                Current_To_Ascii , Voltage_To_Ascii , Power_To_Ascii
                PUBLIC                Capacity_To_LCD , Time_To_LCD
                PUBLIC      AD_Sample , AD_Process                 // 这两个函数被 T5 中断调用
/******************************************************************************
  * @说明          ADC初始化
  *        @参数        无
  * @返回值 无
  * @注                选择外部通道0,转换结果12位数据,高八位置于ADCRH寄存器,ADC时钟16分频
******************************************************************************/
RSEG        ?PR?Init_ADC?FUN_ADC
Init_ADC:
;------打开ADC转换电源,选择内部参考电压2伏。因为是3.3V供电
; 位编号    7      6      5    4    3      2        1  0
; 位符号  ADCEN  ADCST  ADCIF  -  VREFO  VREFS  INREF_S[1:0]
                                MOV                ADCC0                , #0X043
;------转换结果12位数据,高八位置于ADCRH寄存器,ADC时钟32分频
; 位编号    7     6      5  4  3    2  1  0
; 位符号  ADCL  ALIGN  ADCTS[2:0]  ADCS[2:0]
;
;ADCL   ALIGN               ADCRH                               ADCRL
;                                 7    6    5   4   3   2     1    0    7   6   5   4   3   2   1   0
;0           0                  D11  D10  D9  D8  D7   D6   D5   D4    /   /   /   /  D3  D2  D1  D0
;0           1                  /     /    /   /  D11  D10  D9   D8   D7  D6  D5  D4  D3  D2  D1  D0 选这个方式
;1          0                  D11  D10  D9  D8  D7   D6   D5   D4    /   /   /   /   /   /  D3  D2
;1          1                  /    /     /   /   /    /   D11  D10  D9  D8  D7  D6  D5  D4  D3  D2
                                MOV                DPTR                , #ADCC2
                                MOV                A                        , #01111111B
                                MOVX        @DPTR                , A
                                RET
/*****************************************************************************/

// ----------    由T5定时器中断程序调用。 -------------------------------------

// 由T5定时器中断程序调用,每一秒调用128次,交替对ADC0(电流),ADC1(电压)采样64次。
// AD结果是12位,数据右对齐。
// 累加结果存放在两个三字节整数中,最大值 0X04 00 00。
/*****************************************************************************/
RSEG        ?PR?AD_Sample?FUN_ADC
AD_Sample:                PUSH        ACC                // 两个通道轮流采样,每秒分别采样2次,通过8毫秒标志位判断
                                PUSH        PSW
                                
                                JNB         T5_tick_0        , JP1_AD_Sample        // 转电压采样
                                MOV                A                        , SUM_ADC0_L
                                ADD                A                        , ADCRL
                                MOV                SUM_ADC0_L        , A
                                MOV                A                        , SUM_ADC0_M
                                ADDC        A                        , ADCRH
                                MOV                SUM_ADC0_M        , A
                                CLR                A
                                ADDC        A                        , SUM_ADC0_H
                                MOV                SUM_ADC0_H        , A
                                MOV                ADCC1           , #001H                        //选择下一次转换外部通道1 采样电压
                                JMP                EXIT_AD_Sample
JP1_AD_Sample:   
                                MOV                A                        , SUM_ADC1_L
                                ADD                A                        , ADCRL
                                MOV                SUM_ADC1_L        , A
                                MOV                A                        , SUM_ADC1_M
                                ADDC        A                        , ADCRH
                                MOV                SUM_ADC1_M        , A
                                CLR                A
                                ADDC        A                        , SUM_ADC1_H
                                MOV                SUM_ADC1_H        , A
                                MOV                ADCC1           , #000H                        //选择下一次转换外部通道0 采样电流
EXIT_AD_Sample: // --------AD采样数据保存与启动下一轮转换--------
                                ANL                ADCC0                , #11010011B        //清除标志位
                                ORL                ADCC0                , #11000011B        //启动ADC转换,每秒采样128次,每个通道64次
                                
                                POP                PSW
                                POP                ACC
                                RET
/*****************************************************************************/
// ----------    由T5定时器中断程序调用。 -------------------------------------

// 由T5定时器中断程序调用,每一秒调用一次。
// 把SUM_ADC中64次采样累加和进行校准,补偿一个校正数
// 把校准后的SUM_ADC转换成相应量程的测量值,12BIT转化成1.999A , 9.999V 。
/*****************************************************************************/
RSEG        ?PR?AD_Process?FUN_ADC
AD_Process:                PUSH        ACC
                                PUSH        B
                                PUSH        000H
                                PUSH        PSW
/****************************************/
                                LCALL        Adjust_Current
                                LCALL        Convert_Current
                                LCALL        Adjust_Voltage
                                LCALL        Convert_Voltage
                                LCALL        Convert_Power
//                                LCALL        Convert_Capacity
/****************************************/
                                LCALL        SUB_CLR_SUM
                                
                                POP                PSW
                                POP                000H
                                POP                B
                                POP                ACC
                                
                                MOV                SBUF                , 0C2H//TL5
                                
                                RET
/*****************************************************************************/
Adjust_Current:
                                RET
/*****************************************************************************/
Adjust_Voltage:
                                RET
/*****************************************************************************/
Convert_Current:
//  把存放在 SUM_ADC0 的三字节电流64次采样累加和做平均数,并转化成相应量程数值
//  Current = SUM_ADC0 / 64 *(2000/4096)   = SUM_ADC0 * 125 / 256 / 64
//        (MAX =         07 D0 00 00)                                   = SUM_ADC0 * 125 * 4 /256/256
//  舍弃后16位,07D0 =  2000mA
//-------------------------------------
                                MOV                BUF0_H                , SUM_ADC0_H
                                MOV                BUF0_M                , SUM_ADC0_M
                                MOV                BUF0_L                , SUM_ADC0_L
                                MOV                BUF1_L                , #125D
                                LCALL        LONG_MUL_BYTE                        // SUM_ADC0 * 125
                                LCALL        LONG_RL1
                                LCALL        LONG_RL1                                // SUM_ADC0 * 125 * 4
                                MOV                CurrentH        , BUF0_T
                                MOV                CurrentL        , BUF0_H        // SUM_ADC0 * 125 * 4 /256/256
                                
                                //     通过电流是否为零来计时。故写在这里
                                MOV                A                        , CurrentH
                                ADD                A                        , CurrentL
                                ADDC        A                        , #000H
                                JZ                Exit_Convert_Current        // 电流为零,不做累计时间
                                LCALL        Convert_Time
Exit_Convert_Current:                                
                                RET
//-------------------------------------
Convert_Voltage:                                
//  把存放在 SUM_ADC1 的三字节电压64次采样累加和做平均数,并转化成相应量程数值
//  Voltage = SUM_ADC1 / 64 *(10000/4096) = SUM_ADC1 * 625 / 256 / 64
//                                                                              = SUM_ADC1 * 625 * 4 / 256 / 256
//        (MAX = 27 10 00 00)                                      = SUM_ADC1 * 125 * 5 * 4 / 256 / 256
//  舍弃后16位,2710 = 10000mV
//-------------------------------------
                                MOV                BUF0_H                , SUM_ADC1_H
                                MOV                BUF0_M                , SUM_ADC1_M
                                MOV                BUF0_L                , SUM_ADC1_L
                                MOV                BUF1_L                , #5D                // 先乘以5 ,这个数比较小,不会导致BUF0_T的溢出
                                LCALL        LONG_MUL_BYTE                        // SUM_ADC1 * 5
                                MOV                BUF1_L                , #125D
                                LCALL        LONG_MUL_BYTE                        // SUM_ADC1 * 125 * 5
                                LCALL        LONG_RL1
                                LCALL        LONG_RL1                                // SUM_ADC1 * 125 * 5 * 4
                                MOV                VoltageH        , BUF0_T
                                MOV                VoltageL        , BUF0_H         // SUM_ADC1 * 125 * 5 * 4 / 256 / 256
                                RET
//-------------------------------------
Convert_Power:        
// -----------  BUF0 =         CurrentH*VoltageH , 结果放在BUF0(最大 20 000 000 ,01 31 2D 00H)
//------转换到量程范围,20.00 W ,需要除10000(27 10H), 分两次操作,每次除100.
                                MOV                BUF0_L                , CurrentL
                                MOV                BUF0_H                , CurrentH
                                MOV                BUF1_L                , VoltageL
                                MOV                BUF1_H                , VoltageH
                                LCALL        WORD_MUL_WORD                // BUF0 = (BUF0_H,BUF0_L)*(BUF1_H,BUF1_L)
                                //----- 除1000000,转化为相应的量程 ---------------------
                                MOV                BUF1_L                , #100D
                                LCALL        LONG_DIV_BYTE
                                MOV                BUF1_L                , #10D                //  现在是 mW为单位
                                LCALL        LONG_DIV_BYTE

// Convert_Capacity:  计算累计放电电量
// -----------  Capacity += (PowerH,PowerL)
// -----------  MAX(PowerH,PowerL) = MAX_V*MAX_A = 10*2 = 20W = 2000D = 7 D0
// -----------  MAX(Capacity) = 7D0 * 86400秒 = A 4C B8 00
// -----------  4字节Capacity逻辑上可以计量最大功率(20W)不少于24天.
                                MOV                A                        , BUF0_L
                                ADD                A                        , Capacity_L
                                MOV                Capacity_L        , A
                                MOV                A                        , BUF0_M
                                ADDC        A                        , Capacity_M
                                MOV                Capacity_M        , A
                                CLR                A
                                ADDC        A                        , Capacity_H
                                MOV                Capacity_H        , A
                                CLR                A
                                ADDC        A                        , Capacity_T
                                MOV                Capacity_T        , A
                                
// 加上0.5各单位,也就是5 , 实现四舍五入.
                                MOV                A                        , #005H        
                                ADD                A                        , BUF0_L
                                MOV                BUF0_L                , A
                                CLR                A
                                ADDC        A                        , BUF0_M
                                MOV                BUF0_M                , A
                                
                                MOV                BUF1_L                , #10D        // 除这个10 ,只是为了显示方便
                                LCALL        LONG_DIV_BYTE                // POWER / 100 /100 >> xx.xx W
                                MOV                PowerH                , BUF0_M
                                MOV                PowerL                , BUF0_L
                                
                                RET
//-------------------------------------
Convert_Time:
                                INC                Time_Sec
                                MOV                A                        , Time_Sec
                                CJNE        A                         , #060D                , Exit_Convert_Time
                                MOV                Time_Sec        , #000H
                                INC                Time_Min
                                MOV                A                        , Time_Min
                                CJNE        A                         , #060D                , Exit_Convert_Time
                                MOV                Time_Min        , #000H
                                INC                Time_Hor
                                MOV                A                        , Time_Hor
                                CJNE        A                         , #024D                , Exit_Convert_Time
                                MOV                Time_Min        , #000H
                                INC                Time_Day        //         这个就不判断了,听天由命吧。
Exit_Convert_Time:               
                                RET
/*****************************************************************************/
// -----------  最后结果,以ASCII格式存在BUF0缓冲区,高位在BUF0_T 低位在BUF0_T
// -----------  字符串不含小数点,所有字节都有效,‘0’不做消隐处理
//  Ascii  = BUF0_T,BUF0_H,BUF0_M,BUF0_L
RSEG        ?PR?Current_To_Ascii?FUN_ADC
Current_To_Ascii:
                                MOV                BUF0_T                , CurrentH
                                MOV                BUF0_H                , CurrentL
                                LJMP        WORD_To_ASCII
RSEG        ?PR?Voltage_To_Ascii?FUN_ADC
Voltage_To_Ascii:        
                                MOV                BUF0_T                , VoltageH
                                MOV                BUF0_H                , VoltageL
                                LJMP        WORD_To_ASCII
RSEG        ?PR?Power_To_Ascii?FUN_ADC
Power_To_Ascii:
                                MOV                BUF0_T                , PowerH
                                MOV                BUF0_H                , PowerL
                                LJMP        WORD_To_ASCII
// -----------  被除数在BUF0_T(msb),BUF0_H(lsb) , 除数在 BUF0_L
// -----------  因为AD转换后,电流值最大 1999(07CFH) , 电压值最大 9999(270FH)
// -----------  先除一个100 ,得到的商和余数均是单字节值,再做转换可直接使用硬件指令
// -----------  先除以100 ,之后是2个单字节除法。
WORD_To_ASCII:        MOV                BUF0_L                , #100D
                                LCALL        WORD_DIV_BYTE        // 除100后,结果,商在BUF0_H  余数在BUF0_L
                                LCALL        WORD_To_BCD
                                RET
//-------------------------------------
RSEG        ?PR?Capacity_To_LCD?FUN_ADC
/*电流采样分度5mA,对应5V功率为25mW,每秒可以累加的能量最小分度25mW秒/3600秒 = 0.007mWh。
  实时功率累计值能显示mWh的最小单位应保持小数点后3位。
  最大值参考最大功率10V*2A = 20W ,按照2天48小时计算,最大能量960Wh .
  使用4字节进行计数,最大功率20W可以计时59小时。
  0X100000000 / 0X4E20(20W)/3600(秒) = 59.65小时
  最后采用格式 XXX.XXXXX Wh 比较稳妥。
               XXXXXX.XXmWh
*/
Capacity_To_LCD:
                                MOV                PCF8820_Y        , #010D
                                
                                MOV                BUF0_T                , Capacity_T
                                MOV                BUF0_H                , Capacity_H
                                MOV                BUF0_M                , Capacity_M
                                MOV                BUF0_L                , Capacity_L
                                MOV                BUF1_L                , #036D
                                LCALL        LONG_DIV_BYTE
                                //  ---------------------
                                //----  调整量程,应该除以3600,但是显示单位其实是mWh
                                //----  又因为保留小数点后5位,故除以36
                                MOV                BUF1_L                , #010D
                                LCALL        LONG_DIV_BYTE
                                MOV                A                        , BUF1_L
                                ORL                A                        , #'0'
                                MOV                PCF8820_char, A
                                MOV                PCF8820_X        , #072D
                                LCALL        PCF8820_Char8X16
                                //  ---------------------
                                MOV                BUF1_L                , #010D
                                LCALL        LONG_DIV_BYTE
                                MOV                A                        , BUF1_L
                                ORL                A                        , #'0'
                                MOV                PCF8820_char, A
                                MOV                PCF8820_X        , #064D
                                LCALL        PCF8820_Char8X16
                                //-------------------------------
                                MOV                BUF1_L                , #010D
                                LCALL        LONG_DIV_BYTE
                                MOV                A                        , BUF1_L
                                ORL                A                        , #'0'
                                MOV                PCF8820_char, A
                                MOV                PCF8820_X        , #056D
                                LCALL        PCF8820_Char8X16
                                //-------------------------------
                                MOV                BUF1_L                , #010D
                                LCALL        LONG_DIV_BYTE
                                MOV                A                        , BUF1_L
                                ORL                A                        , #'0'
                                MOV                PCF8820_char, A
                                MOV                PCF8820_X        , #048D
                                LCALL        PCF8820_Char8X16
                                //-------------------------------
                                MOV                BUF1_L                , #010D
                                LCALL        LONG_DIV_BYTE
                                MOV                A                        , BUF1_L
                                ORL                A                        , #'0'
                                MOV                PCF8820_char, A
                                MOV                PCF8820_X        , #040D
                                LCALL        PCF8820_Char8X16
                                //-------------------------------
                                MOV                BUF1_L                , #010D
                                LCALL        LONG_DIV_BYTE
                                MOV                A                        , BUF1_L
                                ORL                A                        , #'0'
                                MOV                PCF8820_char, A
                                MOV                PCF8820_X        , #024D
                                LCALL        PCF8820_Char8X16
                                //-------------------------------
                                MOV                BUF1_L                , #010D
                                LCALL        LONG_DIV_BYTE
                                MOV                A                        , BUF1_L
                                ORL                A                        , #'0'
                                MOV                PCF8820_char, A
                                MOV                PCF8820_X        , #016D
                                LCALL        PCF8820_Char8X16
                                //-------------------------------
                                MOV                BUF1_L                , #010D
                                LCALL        LONG_DIV_BYTE
                                MOV                A                        , BUF1_L
                                ORL                A                        , #'0'
                                MOV                PCF8820_char, A
                                MOV                PCF8820_X        , #008D
                                LCALL        PCF8820_Char8X16                        
EXIT_Cap_To_Asc:                                
                                RET
//-------------------------------------
RSEG        ?PR?Time_To_LCD?FUN_ADC
Time_To_LCD:        MOV                PCF8820_Y        , #013D

                                MOV                A                        , Time_Day
                                MOV                B                        , #010D
                                DIV                AB
                                ORL                A                        , #'0'
                                MOV                PCF8820_char, A
                                MOV                PCF8820_X        , #008D
                                LCALL        PCF8820_Char8X16
                                MOV                A                        , B
                                ORL                A                        , #'0'
                                MOV                PCF8820_char, A
//                                MOV                PCF8820_X        , #016D
                                LCALL        PCF8820_Char8X16
                                
                                MOV                A                        , Time_Hor
                                MOV                B                        , #010D
                                DIV                AB
                                ORL                A                        , #'0'
                                MOV                PCF8820_char, A
                                MOV                PCF8820_X        , #032D
                                LCALL        PCF8820_Char8X16
                                MOV                A                        , B
                                ORL                A                        , #'0'
                                MOV                PCF8820_char, A
//                                MOV                PCF8820_X        , #016D
                                LCALL        PCF8820_Char8X16
                                
                                MOV                A                        , Time_Min
                                MOV                B                        , #010D
                                DIV                AB
                                ORL                A                        , #'0'
                                MOV                PCF8820_char, A
                                MOV                PCF8820_X        , #056D
                                LCALL        PCF8820_Char8X16
                                MOV                A                        , B
                                ORL                A                        , #'0'
                                MOV                PCF8820_char, A
//                                MOV                PCF8820_X        , #016D
                                LCALL        PCF8820_Char8X16
                                
                                MOV                A                        , Time_Sec
                                MOV                B                        , #010D
                                DIV                AB
                                ORL                A                        , #'0'
                                MOV                PCF8820_char, A
                                MOV                PCF8820_X        , #080D
                                LCALL        PCF8820_Char8X16
                                MOV                A                        , B
                                ORL                A                        , #'0'
                                MOV                PCF8820_char, A
//                                MOV                PCF8820_X        , #016D
                                LCALL        PCF8820_Char8X16

                                RET
/*****************************************************************************/
SUB_CLR_SUM:        CLR                A
                                MOV                SUM_ADC0_H        , A
                                MOV                SUM_ADC0_M        , A
                                MOV                SUM_ADC0_L        , A
                                MOV                SUM_ADC1_H        , A
                                MOV                SUM_ADC1_M        , A
                                MOV                SUM_ADC1_L        , A
                                RET                                
/*****************************************************************************/
                                END


C语言参数调用的寄存器分派规则,
可参照编写汇编的子函数,
用来被C语言的主函数调用。

; //-------------------------------------
?PR?_SUB1?SUB        SEGMENT CODE
; //-------------------------------------
        PUBLIC        _SUB1
; //-------------------------------------
        RSEG  ?PR?_SUB1?SUB
_SUB1:
        USING        0
        RET         
; END OF _SUB

; //  ------低地址是高字节   低地址是高字节  低地址是高字节

; //-------------------------------------
; void SUB(R7)
; void SUB(R7 , R5)
; void SUB(R7 , R5 , R3 )
; //-------------------------------------
; void SUB(R6/R7)
; void SUB(R6/R7 , R4/R5 )
; void SUB(R6/R7 , R4/R5 , R2/R3 )
; //-------------------------------------
; void SUB(unsigned char i , unsigned char * cMATRIX)
;---- Variable 'ptr' assigned to Register 'R1/R2/R3' ----
;---- Variable 'i' assigned to Register 'R7' ----
        MOV          R3,#00H
        MOV          R2,#HIGH (cMATRIX)
        MOV          R1,#LOW  (cMATRIX)
; //-------------------------------------
; unsigned char SUBr2(unsigned char cCHAR1 , unsigned char cCHAR2 )
        MOV          R7,A
        RET         
; //-------------------------------------
; unsigned int SUBr5(unsigned int iINT1 , unsigned int iINT2 )
        MOV          R6,iINT
        MOV          R7,iINT+01H
        RET         

黄金会员

Rank: 6Rank: 6

主题
1
帖子
300
一乐金币
3556
精华
0
阅读权限
40
注册时间
2016-9-3
最后登录
2019-10-13
发表于 2019-8-2 13:17 | 显示全部楼层
看到老王的链接了,便宜,适合FDIY

多谢分享,顶起来

钻石会员

Rank: 7Rank: 7Rank: 7

主题
175
帖子
4330
一乐金币
15641
精华
0
阅读权限
50
注册时间
2011-5-6
最后登录
2019-12-15
发表于 2019-8-2 13:19 | 显示全部楼层
不错,看了PDF,6个腿都能作为AD输入。内部连VCC和GND都各有一路ADC检测
6路PWM,芯片功能强大啊……
要是再多两个腿,就可以通过检测D+D-电压来大致判断充电协议了……
看烧录的软件……和STC一样,可以串口下载?

点评

是的,串口烧录,和STC的相似。 这个CPU的确是功能强大,价格便宜,特别是12位的AD是个亮点,不管准度如何,精度是够高了,其它很少见12位的AD.  详情 回复 发表于 2019-8-2 14:20

黄金会员

Rank: 6Rank: 6

主题
36
帖子
502
一乐金币
4724
精华
0
阅读权限
40
注册时间
2011-3-11
最后登录
2019-12-2
 楼主| 发表于 2019-8-2 14:20 | 显示全部楼层
本帖最后由 pla155 于 2019-8-2 14:21 编辑
sdf15937 发表于 2019-8-2 13:19
不错,看了PDF,6个腿都能作为AD输入。内部连VCC和GND都各有一路ADC检测
6路PWM,芯片功能强大啊……
要 ...

是的,串口烧录,和STC的相似。
这个CPU的确是功能强大,价格便宜,特别是12位的AD是个亮点,不管准度如何,精度是够高了,其它很少见12位的AD.

不过,圣芯的单片机里,只有这一款是出厂就带ISP烧录的,其他的型号需要自己烧。

钻石会员

Rank: 7Rank: 7Rank: 7

主题
10
帖子
1089
一乐金币
7236
精华
0
阅读权限
50
注册时间
2014-7-9
最后登录
2019-12-15
发表于 2019-8-2 21:16 | 显示全部楼层
欢迎高手入群,不过那个群里太热闹,消息太多没法看,只能偶尔瞅几眼。
汇编我建议还是能不用就不用,现在的编译器已经很完美了,C的效率和汇编差不了多少。
这个东西我没买,感觉用不上,而且可扩展性没有多少,主要是觉得单片机IO太少了
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|一淘宝店|手机版|商店|电子DIY套件|一乐电子 ( 粤ICP备09076165号-1粤公网安备44522102000183号 )

GMT+8, 2019-12-16 14:18 , Processed in 0.051346 second(s), 32 queries , Gzip On.

Powered by yleee

© 2008-2020 一乐电子

快速回复 返回顶部 返回列表