概述

系统的规划界面见第一页,大致分为三类页面: - 数据刷新页面 - 寄存器设置界面 - 其他辅助界面

系统初始化

由于串口1是主串口,切换到I2C后,将无法使用上位机的串口连接,只能通过TF卡刷机,因此我们的方法是第一屏显示一个LOGO界面,然后初始化函数放在“进入”按钮的事件中,并且在按钮status状态里面设置一个定时事件,这样无论手工点击进入还是自动延时进入,都会执行初始化函数;同时在刚上电的时候,系统可以通过串口连接上位机,完成ROM更新;

void system_init(){    //系统硬件初始化
    int a;
    //E1- 4052 切换
    gpio_mode(0,1);//设置E1为输出
    gpio_out(0,0);    //输出低电平,切换到第1路

    gpio_mode(1,1);//设置E2为输出
    gpio_out(1,1);    //输出高电平,1路的CC1空载;高电平时cc1接5.1K

    gpio_mode(2,1);//设置E3为输出
    gpio_out(2,1);    //输出高电平,2路的CC1空载;高电平时cc1接5.1K

    i2c_init(0,1,0x3c);//串口0
    a=i2c_recvbyte(1,1);    //读取版本号
    if (a==0){
        //cls(0);
        ds(16,0,0,"未发现充电器设备!",1);
        return;
    }
}

数据采集获取

按照shmictrl的开发规范,每个页面都首先调用appbase控件,也可以理解为全局控件,因此数据的采集和处理要放在appbase控件中;因此数据采集需要放在appbase控件中,采集代码如下:

int status=1310720; //通过appbase的status属性设置定时,系统会0.3秒左右调用一次ontimer()事件

void ontimer()
{   //在此书写有关定期器对数据的修改代码
    readval();
}

因此系统无论在哪个页面,都会每隔0.3秒左右调用一次readval()函数,因此我们可以在readval()函数中书写读取I2C接口获取电压电流参数的代码;

//-----下面在appbase中设置属性(全局变量),以方便其他代码直接调用------
int inV=0;    //输入电压,单位mV

int V1=0;    //1路输出电压,单位mV
int A1=0;    //1路输出电流,单位mA
int XY1=0;    //1路协议

int V2=0;    //2路输出电压,单位mV
int A2=0;    //2路输出电流,单位mA
int XY2=0;    //2路协议

void on1sdraw(){}    //用于数据刷新后界面继承
void readval()    //获取i2c的快捷值,1秒一次
{    int a;
    int b;
    str s;

    gpio_out(0,0);    //输出低电平,切换到第1路

    i2c_sendbyte(0x3a,2,1);
    //a=i2c_recvbyte(0x03,1);b=i2c_recvbyte(0x04,1);
    //a=(a<<4)+(b>>4);
    a=i2c_recvbyte(0x3B,1);b=i2c_recvbyte(0x3c,1);
    a=(a<<4)+(b&0x0f);
    V1=a*6;  //Buck输出电压

    i2c_sendbyte(0x3a,3,1);
    a=i2c_recvbyte(0x3B,1);b=i2c_recvbyte(0x3c,1);
    a=(a<<4)+(b&0x0f);
    A1=a*2.5; //3B精密读取电流

    a=i2c_recvbyte(0x30,1);
    inV=a*160;//输入电压:(mV)

    a=i2c_recvbyte(0x06,1);
    XY1=a&0x0f; //协议

    if ((XY1==5)|(XY1==6)){
        gpio_out(1,0);    //输出低电平,1路的CC1空载;
    }
    else{
        gpio_out(1,1);    //输出高电平,cc1接5.1K
    }

    gpio_out(0,1);    //输出高电平,切换到第2路

    i2c_sendbyte(0x3a,2,1);
    a=i2c_recvbyte(0x3B,1);b=i2c_recvbyte(0x3c,1);
    a=(a<<4)+(b&0x0f);
    V2=a*6;  //Vout输出电压

    i2c_sendbyte(0x3a,3,1);
    a=i2c_recvbyte(0x3B,1);b=i2c_recvbyte(0x3c,1);
    a=(a<<4)+(b&0x0f);
    A2=a*2.5; //3B精密读取电流

    a=i2c_recvbyte(0x06,1);
    XY2=a&0x0f; //协议

    if ((XY2==5)|(XY2==6)){
        gpio_out(2,0);    //输出低电平,1路的CC1空载;
    }
    else{
        gpio_out(2,1);    //输出高电平,cc1接5.1K
    }

    on1sdraw();//界面刷新
}

代码中,首先通过gpio_out语句切换CD4052电子开关选择是哪路充电芯片,然后按照SW3526官方寄存器资料读取电压电流等参数;值得注意的是SW3526在C口使用PD协议的时候,如果是按照A口的电路,则可能导致拔掉USB线后电压不能恢复到5V;因此我们通过:

    if ((XY1==5)|(XY1==6)){
        gpio_out(1,0);    //输出低电平,1路的CC1空载;
    }
    else{
        gpio_out(1,1);    //输出高电平,cc1接5.1K
    }

首先,XY1=5 表示是PD FIX 协议;XY1=6是PD PPS协议,而PD协议必须使用C口才能触发,而A口是无法触发PD协议的,因此系统在识别出PD协议后,一定是使用C口触发的,因此立即改变CC1的接法,完成对应的A、C口适应;官方的SW3526芯片是无法做到这点的,这需要我们外部程序来辅助;

readval()函数最后调用on1sdraw();而在appbase原控件中,on1sdraw()方法是空代码,也就是说,这个函数是在页面代码中来继承的,通过继承,可以在页面代码中继承这个函数书写界面控件属性刷新的代码,这样读取的数据可以迅速刷新到界面中;

数据刷新页面

//在本页面代码中添加数据刷新函数
void app.on1sdraw(){
    float v;
    float a;
    float b;
    float w;
    int ww;
    lv.text=itos(app.V1,4,3)+"V";
    la.text=itos(app.A1,4,3)+"A";
    v=app.V1/1000.0;
    a=app.A1/1000.0;
    w=v*a;
    lw.text=ftos(w,2)+"W";
    if (a==0){
        lr.text="---";
    }
    else{
        b=v/a;
        lr.text=ftos(b,2)+"欧";
    }
    linv.text=itos(app.inV,4,2)+"V";
    lxy.text=app.getxy(app.XY1);
    if (type==0) {c1.set(app.V1,app.A1,0,0);}
    else{
        ww=w*1000;
        if (type==1) {c1.set(ww,app.A1,0,0);}
        if (type==2) {c1.set(ww,app.V1,0,0);}
    }
}

在前面数据采集获取中,appbase中在采集数据后调用on1sdraw()方法,因此我们在页面代码中继承函数,void app.on1sdraw();因此在此函数中,我们通过比如:

lv.text=itos(app.V1,4,3)+"V";

将appbase中获取的全局变量的电压值转换显示格式后赋值给lv.text完成显示;其他代码也都是完成界面刷新的,尤其是最后的曲线数据的刷新代码;

寄存器设置界面

首先在页面代码中设置一个全局变量route,用于确定当前读取的是哪一个I2C的数据。

int   route=0;    //=0 A路  =1表示B路

void pageinit(){
    //页面初始化
    int a;
    gpio_out(0,route);    
    a=i2c_recvbyte(0xA8,1);
    l2.num=a;
    s0.val=1-(a&1);
    s1.val=1-(a>>1)&1;
    s2.val=1-(a>>2)&1;
    s3.val=1-(a>>3)&1;
    s4.val=1-(a>>4)&1;
    s5.val=1-(a>>5)&1;
    s7.val=1-(a>>7)&1;
}
pageinit();

在页面进入后,调用pageinit();函数,读取寄存器后,然后刷新界面;当用户点击“应用”按钮时,


void sk4.onclick()
{
    int a=0;
    gpio_out(0,route);    
    a=a|(1-s0.val);
    a=a|((1-s1.val)<<1);
    a=a|((1-s2.val)<<2);
    a=a|((1-s3.val)<<3);
    a=a|((1-s4.val)<<4);
    a=a|((1-s5.val)<<5);
    a=a|((1-s7.val)<<7);
    l3.num=a;
        i2c_sendbyte(0x12,0x20,1);
        i2c_sendbyte(0x12,0x40,1);
        i2c_sendbyte(0x12,0x80,1);
    i2c_sendbyte(0xa8,a,1);
    pageinit();
}

通过界面控件的参数合成数据,写入I2C寄存器

点击“切换到B路”按钮,通过代码切换route变量,完成线路切换

void scw.onclick()
{
    if (route==0){
        scw.text="切换到B路";
        l1.text="A 路协议设置1";
        route=1;
    }
    else{
        scw.text="切换到A路";
        l1.text="B 路协议设置1";
        route=0;
    }
    pageinit();
}