天天看点

迪文T5L温控器如何理解并使用C语言读写DGUS变量存储器

        最近公司有使用迪文一款基于新开发的T5L ASIC芯片开发的温控器产品,产品型号为TC041C系列,此产品为4.1寸屏幕,分辨率为720*720,显示图片极其清晰,精致。

        在了解整个温控器的开发流程中,发现读写DGUS变量存储器是其中一个很关键的步骤,在迪文T5L芯片中,GUI CPU有些不能实现的功能需要OS CPU配合才能实现。而OS CPU要实现和GUI CPU的交互,必须通过读写DGUS变量存储器,从而达到控制GUI CPU的目的。   

        迪文T5L ASIC采用了成熟、稳定的8051内核,可以用Keil C51并使用C语言进行开发。通过迪文给的《迪文 T5L ASIC应用开发指南》,我们可以了解到DUGS变量储存器位宽为32bit,每个地址对应有4个字节。其中有一部分DGUS变量存储器是8051 OS CPU和GUI CPU都可以访问的,其中8051 OS中的0x00:0000 - 0x00:7FFF对应DGUS II变量存储器的0x0000-0xFFFF。而DGUS II变量存储器每个地址是对应2个字节,所以读地址的时候要做处理,如果是使用8051 OS中的地址,那就一次必须读写4个字节,而使用DGUS II的地址,就可以一次性只读写2个字节,并且通常是要读写DGUS中的VP地址,所以在写C语言读写DGUS变量存储器使用DGUS  VP地址更好。

        《迪文 T5L ASIC应用开发指南》有介绍相关的SFR特殊寄存器,并且有一个汇编例程介绍怎么读写DGUS变量存储器的值,参考了这个例程,我们就可以把读写DGUS变量存储器的相关代码封装成一个专门的函数了,前面有提到,对于形参可以使用DGUS的VP指针,但是考虑到DGUS变量存储器的位宽为32bit,所以必须定义为 long类型的,考虑到没有负数,可以确定一个形参类型为unsigned long,并且为DGUS的VP地址值的变量。还需要一个传递参数的缓存区,可以使用指针的形式,可以是用unsigned char,定义一个指针。另外还需要一个长度,方便读写,考虑到长度值,可以使用unsigned short类型。

        根据这个思路我们就可以来编写读写DGUS变量存储器的函数了,首先我们来编写读DGUS变量储存器函数,如下

void read_dgus_vp(u32 addr,u8* buf,u16 len)
{
    u32 OS_addr=0,OS_addr_offset=0;
    u16 OS_len=0,OS_len_offset=0;
    EA=0;
    OS_addr=addr/2;
    OS_addr_offset=addr%2;
    ADR_H=(u8)(OS_addr>>16)&0xFF;
    ADR_M=(u8)(OS_addr>>8)&0xFF;
    ADR_L=(u8)OS_addr&0xFF;
    ADR_INC=1;                 //DGUS  OS存储器地址在读写后自动加1
    RAMMODE=0xAF;               //启动读模式
    if(OS_addr_offset==1)       //首地址有偏移,修正
    {
        while(APP_ACK==0);      //等待
        APP_EN=1;
        while(APP_EN==1); 
        *buf++=DATA1;
        *buf++=DATA0;              
        len--;
        OS_addr_offset=0;
    }
    OS_len=len/2;
    OS_len_offset=len%2;
    if(OS_len_offset==1)
    {
         OS_len++;
    }
    while(OS_len--)
    {
        if((OS_len_offset==1)&&(OS_len==0))
        {           
            while(APP_ACK==0);
            APP_EN=1;
            while(APP_EN==1);       //读写执行结束
            *buf++=DATA3;
            *buf++=DATA2;           
            break;    
        } 
        while(APP_ACK==0);
        APP_EN=1;
        while(APP_EN==1);       //读写执行结束 
        *buf++=DATA3;
        *buf++=DATA2;
        *buf++=DATA1;
        *buf++=DATA0;                          
    }   
    RAMMODE=0x00;           //读写完成后RAMMODE必须置零
    EA=1;         
}
           

        下面我们来编写写DGUS变量存储器的函数,这里有个地方需要注意,就是只写一半的时候,要和读写flash一样,需要先将这个地址的数值读出来,然后赋值对应要写的地址的值,然后在写这个地址,所以写DGUS函数相比读DUGS变量存储器的函数就要稍微绕一下了,大家可以参考如下代码:

void write_dgus_vp(u32 addr,u8* buf,u16 len)
{
    u32 OS_addr=0,OS_addr_offset=0;
    u16 OS_len=0,OS_len_offset=0;
    EA=0;
    OS_addr=addr/2;
    OS_addr_offset=addr%2; 
    ADR_H=(u8)(OS_addr>>16)&0xFF;
    ADR_M=(u8)(OS_addr>>8)&0xFF;
    ADR_L=(u8)OS_addr&0xFF;
    ADR_INC=0x01;                 //DGUS  OS存储器地址在读写后自动加1
    RAMMODE=0x8F;               //启动写模式 
    if(OS_addr_offset==1)
    {
        ADR_INC=0;                     
        RAMMODE=0xAF;
        while(APP_ACK==0);
        APP_EN=1;
        while(APP_EN==1);       //读写执行结束
        ADR_INC=0x01; 
        RAMMODE=0x8F;
        while(APP_ACK==0);      
        DATA1=*buf++;
        DATA0=*buf++;
        APP_EN=1;
        while(APP_EN==1);       //读写执行结束
        len--;
        OS_addr_offset=0;
    }
    OS_len=len/2;
    OS_len_offset=len%2; 
    if(OS_len_offset==1)
    {
         OS_len++;
    } 
    while(OS_len--)
    {
        if((OS_len_offset==1)&&(OS_len==0))
        {
            ADR_INC=0;
            RAMMODE=0xAF;
            while(APP_ACK==0);
            APP_EN=1;                //增加一个读过程,以免写单字时会将另一个单字写0
            while(APP_EN==1);       //读写执行结束
            ADR_INC=0x01;
            RAMMODE=0x8F;
            while(APP_ACK==0);           
            DATA3=*buf++;
            DATA2=*buf++;
            APP_EN=1;
            while(APP_EN==1);       //读写执行结束
            break;
        }
        while(APP_ACK==0);        
        DATA3=*buf++;
        DATA2=*buf++;
        DATA1=*buf++;
        DATA0=*buf++;
        APP_EN=1;
        while(APP_EN==1);       //读写执行结束
    } 
    RAMMODE=0x00;       //读写完成后RAMMODE必须置零
    EA=1;  
}  
           

        对于这两个函数的地址的/2操作,是由于SFR寄存器是对应的32bit的地址,所以DGUS II变量存储器地址需要除以2,如果有偏移的话,需要先处理偏移的部分,然后在处理后面相对整体是整体的部分。我对于地址和长度偏移是这样处理的,如有有更好的办法的小伙伴可以联系下我,我们一起改进这两个函数。

        最后,感兴趣并有一定基础或者有开发疑惑的小伙伴可以加群637787562深入探讨。