迪文科技论坛

 找回密码
 立即注册
搜索
查看: 434|回复: 0

【开源】COF案例分享:简易示波器

[复制链接]

574

主题

169

回帖

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
12353
发表于 2022-4-22 11:30:08 | 显示全部楼层 |阅读模式
——文档转载自电子发烧友

一、简易示波器(界面设计)

因为平时喜欢在家里折腾一些小玩意,但是没有示波器就会很不方便,当看到迪文推出了COF屏试用体验时,就想着做一个简易示波器。下面直接开始分享我的开发过程。

1.主要界面

经过很多次调整最终确定了这一版的界面,还是暗色调的界面符合示波器的气质。

      
1启动界面
   
2单通道波形显示
   
3多通道波形显示   
                                                                                                                             
2.DGUS设计

通过基础触控可以轻松的实现界面直接的跳转。
   
  图4启动界面设计

按键功能的实现是通过“按键返回”控件实现的,设置键值和变量地址后,当触控按键被按下时,键值就会填充到变量地址对应的存储空间内,方便通过C语言进行访问。这里我尝试了“按字写入变量”和“位控制”两种方式,按位控制可以将多个按键的状态存放在一个变量里,大大减少了存储空间的占用,但是这样也有弊端,再C语言处理按键动作时,需要对按键的对应的bit进行复位,这会加大代码上的实现难度。按字写入变量整体上会便的简单许多,只需要判断地址上是不是指定的键值即可。地址和键值可以自由设定,实现很多功能。

      
5按键设计
这里我设置了居中对齐,但是最终效果还是左对齐,可能还有某个地方设置的不对。

     
  图6数值显示设计

“动态曲线”控件实现曲线显示时遭遇了一些困难,开发工具上的配置项在大面积显示曲线时不太灵活,给大家分享以下经过一些尝试后我的做法。曲线显示时Y_CentralVD_Central配置成065535,这样可以让数据范围变得很大,纵轴放大倍数建议设置成2,设置为1时数据范围只能覆盖屏幕的一部分,设置为2可以覆盖到屏幕外,这是可以通过代码处理波形数据,让波形的变化便的非常灵活。六个通道我使用的是16号数据源通道,我把0号留给了显示和触控变量。描述指针在官方文档中有给出设定范围,通过描述指针开发者可以对控件的配置信息在线修改。

      
7曲线显示设计                                                                                                8字库设置

3.一些代码
void key_operate( void )
{
        static unsigned char index_cnt = 0;

        IF( buff.word_t[ index_cnt*8 + 6 ] == 0xAAAA ) /* time - */
        {
                sys_write_vp( (0x100C + index_cnt*8 + 0) , def_byte_t , 1 );

                if( operate.word_t[ index_cnt*3 + 0 ] > 1 )
                {
                        operate.word_t[ index_cnt*3 + 0 ] --;

                        sys_write_vp( (0x1400 + index_cnt*3 + 0) , &(operate.byte_t[ (index_cnt*3 + 0)*2 ]) , 1 );

                        set[0] = (unsigned char)(index_cnt+1);
                        set[1] = (unsigned char)operate.word_t[ index_cnt*3 + 0 ];
                        sys_write_vp( (0x5000 + index_cnt*256 + 9) , set , 1 );
                }
        }

        if( buff.word_t[ index_cnt*8 + 7 ] == 0xAAAA ) /* time + */
        {
                sys_write_vp( (0x100C + index_cnt*8 + 1) , def_byte_t , 1 );

                if( operate.word_t[ index_cnt*3 + 0 ] < 255 )
                {
                        operate.word_t[ index_cnt*3 + 0 ] ++;

                        sys_write_vp( (0x1400 + index_cnt*3 + 0) , &(operate.byte_t[ (index_cnt*3 + 0)*2 ]) , 1 );

                        set[0] = (unsigned char)(index_cnt+1);
                        set[1] = (unsigned char)operate.word_t[ index_cnt*3 + 0 ];
                        sys_write_vp( (0x5000 + index_cnt*256 + 9) , set , 1 );
                }
        }

        if( buff.word_t[ index_cnt*8 + 8 ] == 0xAAAA ) /* amp - */
        {
                sys_write_vp( (0x100C + index_cnt*8 + 2) , def_byte_t , 1 );

                if( operate.word_t[ index_cnt*3 + 1 ] > 1 )
                {
                        operate.word_t[ index_cnt*3 + 1 ] --;

                        sys_write_vp( (0x1400 + index_cnt*3 + 1) , &(operate.byte_t[ (index_cnt*3 + 1)*2 ]) , 1 );
                }
        }

        if( buff.word_t[ index_cnt*8 + 9 ] == 0xAAAA ) /* amp + */
        {
                sys_write_vp( (0x100C + index_cnt*8 + 3) , def_byte_t , 1 );

                if( operate.word_t[ index_cnt*3 + 1 ] < 10 )
                {
                        operate.word_t[ index_cnt*3 + 1 ] ++;

                        sys_write_vp( (0x1400 + index_cnt*3 + 1) , &(operate.byte_t[ (index_cnt*3 + 1)*2 ]) , 1 );
                }
        }

        if( buff.word_t[ index_cnt*8 + 10 ] == 0xAAAA ) /* size - */
        {
                sys_write_vp( (0x100C + index_cnt*8 + 4) , def_byte_t , 1 );

                if( operate.word_t[ index_cnt*3 + 2 ] > 0 )
                {
                        operate.word_t[ index_cnt*3 + 2 ] --;

                        sys_write_vp( (0x1400 + index_cnt*3 + 2) , &(operate.byte_t[ (index_cnt*3 + 2)*2 ]) , 1 );

                        set[0] = (unsigned char)(operate.word_t[ index_cnt*3 + 2 ]);
                        set[1] = 0x00;
                        sys_write_vp( (0x5000 + index_cnt*256 + 10) , set , 1 );
                }
        }

        if( buff.word_t[ index_cnt*8 + 11 ] == 0xAAAA ) /* size + */
        {
                sys_write_vp( (0x100C + index_cnt*8 + 5) , def_byte_t , 1 );

                if( operate.word_t[ index_cnt*3 + 2 ] < 7 )
                {
                        operate.word_t[ index_cnt*3 + 2 ] ++;

                        sys_write_vp( (0x1400 + index_cnt*3 + 2) , &(operate.byte_t[ (index_cnt*3 + 2)*2 ]) , 1 );

                        set[0] = (unsigned char)(operate.word_t[ index_cnt*3 + 2 ]);
                        set[1] = 0x00;
                        sys_write_vp( (0x5000 + index_cnt*256 + 10) , set , 1 );
                }
        }

        index_cnt ++;
        if( index_cnt >= 6 )
        {
                index_cnt = 0;
        }
}


二、简易示波器(测试代码)

前面已经分享了我的界面的设计,现在分享一下我的测试代码。示波器的数字通道用串口接收数据,并绘制对应的波形。
unsigned char uart_rx_buff[9] = {
0x5A, 0x5A,
0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
};

unsigned char uart_tx_buff[3] = {
0x5A, 0xA5,
0x00
};

unsigned char uart_rx_cnt = 0;
unsigned char uart_tx_cnt = 0;

unsigned char uart_rx_num = 0;
unsigned char uart_tx_num = 0;

unsigned char uart_rx_finish = 0;
unsigned char uart_tx_finish = 0;

void UART2_Init(unsigned long bdt)
{
        unsigned short tmp;
        tmp = 1024 - FOSC / 64 / bdt;                 
        MUX_SEL |= 0x40; //复用选择口, 选择复用为UART2, 接口引出到 P0.4P0.5

        SetPinOut( 0, 4 );
        SetPinIn( 0, 5 );

        SCON2 = 0x50;        //0011 0000 ,即将sm2REN1,SM2:只有当接收到第9位数据(RB8)为1时,才把接收到的前8位数据送入SBUF,且置位RI 发出中断申请 ,即发送方式为8N1   
        ADCON = 0x80;        //波特率发生器选择,要使用  SREL0H 自行设置

        SREL2H = (unsigned char)( tmp >> 8 );
        SREL2L = (unsigned char)tmp;
        ES2 = 1;
        EA = 1;
}

void UART2_ISR_PC(void) interrupt 4
{
        EA = 0; //中断总控制位 关闭
        IF( RI2 == 1 ) //接收中断标志位 该位由硬件置位 ,软件清零
        {               
                RI2 = 0;
                uart_rx_buff[ uart_rx_cnt ]        = SBUF2;
                switch( uart_rx_cnt )
                {
                        case 0:
                                if( uart_rx_buff[ uart_rx_cnt ] == 0x5A )
                                {
                                        uart_rx_cnt ++;
                                }
                                else
                                {
                                        uart_rx_buff[ uart_rx_cnt ] = 0;
                                        uart_rx_cnt = 0;
                                }
                                break;
                        case 1:
                                if( uart_rx_buff[ uart_rx_cnt ] == 0x5A )
                                {
                                        uart_rx_cnt ++;
                                }
                                else
                                {
                                        uart_rx_buff[ uart_rx_cnt ] = 0;
                                        uart_rx_cnt = 0;
                                }
                                break;
                        case 2:
                                uart_rx_num = uart_rx_buff[ uart_rx_cnt ];
                                uart_rx_cnt ++;
                                break;
                        default:
                                uart_rx_cnt ++;
                                if( uart_rx_cnt >= ( uart_rx_num + 3 ) )
                                {
                                        uart_rx_cnt = 0;
                                        /* 处理波形 */
                                        uart_rx_finish = 1;
                                }
                                break;
                }
        }
        if( ti2 == 1 ) //发送中断标志位 该位由硬件置位 ,软件清零
        {
                if( uart_tx_cnt < uart_tx_num )
                {
                        SBUF2 = uart_tx_buff[ uart_tx_cnt ];
                        uart_tx_cnt ++;
                }
                else
                {
                        uart_tx_cnt = 0;
                        uart_tx_finish = 1;
                }
                TI2 = 0;
        }
        EA = 1; //中断总控制位 关闭
}

void UART2_Sendbyte( unsigned char dat)
{
        while( TI2 == 1 );
        SBUF2 = dat;
}

void UART2_String(unsigned char * dat , unsigned char len)
{
        unsigned char i;
        for( i = 0; i < len; i ++ )
        {
                while( TI2 == 1 );
                SBUF2 = *(dat+i);
        }
}

模拟通道使用AD1AD2AD3读取外面电压并绘制对应的波形。
#define ADC_BASE_ADDR ( 0x32 )

#define ADC_CH0 ( 0x00 )
#define ADC_CH1 ( 0x01 )
#define ADC_CH2 ( 0x02 )
#define ADC_CH3 ( 0x03 )
#define ADC_CH4 ( 0x04 )
#define ADC_CH5 ( 0x05 )
#define ADC_CH6 ( 0x06 )
#define ADC_CH7 ( 0x07 )

unsigned short adc_read( unsigned char chn )
{
        unsigned short result;
        sys_read_vp( ADC_BASE_ADDR + chn, (unsigned char *)&result, 1 );
        return result;
}

void scop_ai_read( unsigned short * val )
{
        sys_read_vp( ADC_BASE_ADDR + ADC_CH1 , (unsigned char *)&val, 3 );
}

//绘制动态曲线
//chart_id:曲线通道id,范围[0,7],系统总共支持8个曲线通道,每个曲线通道占用2K的字空间,
//                                 总缓冲区范围:0x1000-0x4FFF,没有使用的曲线缓冲区可以做其他用途
//y:写入某一个数据点的数据值
void sys_write_chart(u8 chart_id,u16 y)
{
        #define CHART_ADDR 0x0310 //动态曲线功能所对应的系统变量接口地址
        #define CHART_NUM         1                        //一次性写入几个曲线通道的数据,我们只写入chart_id指定的曲线通道,1
        #define POINT_NUM         1                  //一次性写入多少个数据点

        //构建命令
        u8 chart_cmd[6+POINT_NUM*2] = {0x5A,0xA5,CHART_NUM,0x00};
        chart_cmd[4] = chart_id;//曲线通道id
        chart_cmd[5] = POINT_NUM;//一次性写入多少个数据点
        chart_cmd[6] = (u8)(y>>8);//数据点值
        chart_cmd[7] = (u8)(y&0xff);

        //发送命令
        sys_write_vp(CHART_ADDR,chart_cmd,3+POINT_NUM);


演示视频链接:https://www.bilibili.com/video/BV173411M73j/






























本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|迪文科技论坛 ( 京ICP备05033781号-1 )

GMT+8, 2025-1-14 21:33 , Processed in 0.130667 second(s), 22 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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