——文档转载自电子发烧友
一、简易示波器(界面设计)
因为平时喜欢在家里折腾一些小玩意,但是没有示波器就会很不方便,当看到迪文推出了COF屏试用体验时,就想着做一个简易示波器。下面直接开始分享我的开发过程。
1.主要界面
经过很多次调整最终确定了这一版的界面,还是暗色调的界面符合示波器的气质。
2.DGUS设计
通过基础触控可以轻松的实现界面直接的跳转。
按键功能的实现是通过“按键返回”控件实现的,设置键值和变量地址后,当触控按键被按下时,键值就会填充到变量地址对应的存储空间内,方便通过C语言进行访问。这里我尝试了“按字写入变量”和“位控制”两种方式,按位控制可以将多个按键的状态存放在一个变量里,大大减少了存储空间的占用,但是这样也有弊端,再C语言处理按键动作时,需要对按键的对应的bit进行复位,这会加大代码上的实现难度。按字写入变量整体上会便的简单许多,只需要判断地址上是不是指定的键值即可。地址和键值可以自由设定,实现很多功能。
这里我设置了居中对齐,但是最终效果还是左对齐,可能还有某个地方设置的不对。
“动态曲线”控件实现曲线显示时遭遇了一些困难,开发工具上的配置项在大面积显示曲线时不太灵活,给大家分享以下经过一些尝试后我的做法。曲线显示时Y_Central和VD_Central配置成0和65535,这样可以让数据范围变得很大,纵轴放大倍数建议设置成2,设置为1时数据范围只能覆盖屏幕的一部分,设置为2可以覆盖到屏幕外,这是可以通过代码处理波形数据,让波形的变化便的非常灵活。六个通道我使用的是1到6号数据源通道,我把0号留给了显示和触控变量。描述指针在官方文档中有给出设定范围,通过描述指针开发者可以对控件的配置信息在线修改。
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.4、P0.5
SetPinOut( 0, 4 ); SetPinIn( 0, 5 );
SCON2 = 0x50; //0011 0000 ,即将sm2,REN置1,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); } }
模拟通道使用AD1、AD2、AD3读取外面电压并绘制对应的波形。 #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/
|