聚丰项目 > 基于AB32VG1的Mini示波器
基于AB32VG1芯片制作Mini示波器,硬件部分参考老刘爱捣鼓等开源作品,谢谢他们无私的开源精神。
是唐棠啊

是唐棠啊
团队成员
是唐棠啊 学生

Mini示波器采用了一套成本低廉但高效的硬件,配合层次化的软件框架,实现对常规低频信号波形的采集、分析、显示。
硬件部分的主要工作有:电源管理(5V、2.5V、-5V);对信号的衰减、限幅、偏置。最后将处理好的电压信号送入AB32VG1的ADC外设,进行数据采集。由于ADC外设只能采集正电压,因此我们通过增加偏置电压的方式,将负电压抬高来采集。
电源管理模块由三部分组成。第一部分输出+5V直流电压,供给MCU和运放;第二部分输出-5V直流电压,供给运放;第三部分输出正2.5V直流电压,作为偏置电压。取2.5V的原因是,正好是5V的一半,作为测量负电压的参考基准点。下面我们进行详细说明:
电源输出+5V部分。这里是由外部+5V电压直接供给,作为整个电路系统的电源。
电源输出-5V部分。选择ICL7660电源芯片,将+5V转换成-5V。ICL7660是Maxim公司生产的小功率极性反转电源转换器。ICL7660的静态电流典型值为170μA,输入电压范围为1.5-10V,只需外接10μF的小体积电容效率高达98%合输出功率可达700mW(以DIP封装为例),符合输出100mA的要求。
电源输出+2.5V部分。采用TL431芯片,把+5V降到+2.5V。TL431是可控精密稳压源。它的输出电压用两个电阻就可以任意的设置到从Vref(2.5V)到36V范围内的任何值。
前置采样这一部分作用是对直流信号和交流信号分别处理,同时进行电压的衰减,和进行限幅保护。信号进入电路以后,首先经过一个开关,拨动开关决定是否串接一个电容进入电阻,如果串接的电容,那么根据“通交阻直”的特性,将对交流信号和直流信号进行区分。之后经过两个串联电阻分压,和并联电容滤除毛刺。0欧电阻过去,是四个1N4148,两两方向相同,一正一反并联在电路上。将信号限幅在正负1.5V。
TL074是一种在单片集成电路中配有高电压双极晶体管的输入运算放大器,一个芯片带有四个运放。这里使用了其中的三个,第一个运放的作用是对信号进行了放大处理,将输入进来的电压信号(<=±1.4V)放大到正负2.5V,然后紧接一级运放做电压跟随器,之后接入2.5V的偏置电压,最后将信号输入MCU的ADC外设引脚。
调试电路主要用于串口下载和仿真调试,引出了MCU的串口引脚和电源引脚。人机交互电路分为旋钮电路和按键电路。旋钮电路选择EC11,支持单击、旋转、按下旋转;按键电路有三个,对应复位按钮,设置按键,切换选项按键。要注意的是EC11的A和B引脚,需要上拉电阻下拉电容。
主控电路这一部分主要包含MCU模块、显示屏电路、指示灯电路。MCU负责ADC数据采样,和对人机交互部分的电路进行控制;显示屏电路的核心是OLED显示屏,主要进行界面显示和波形显示,对信号处理后结果的一个直观反馈;指示灯电路的作用是显示电源状态和ADC工作状态,方便对整个心态进行一个直观的观察。
软件部分的主要工作有:底层驱动SDK框架、ADC滤波算法、波形数据处理、人机交互界面。SDK提供基本的模块和外设驱动支持,滤波算法去除噪声和毛刺,波形处理计算电压值和频率,并为波形显示做准备;人机交互界面提供屏幕显示(OLED屏)和操作方式(旋钮和按键)。
首先打开Rtt studio创建AB32VG1开发板的工程,如下图所示:


由此已经创建好基于这款AB32VG1芯片开发板的基础工程,点击编译看看是否有没有配置的选项导致编译失败。
在建立好基础工程并且编译完成无错后,下一步骤先添加官方ADC驱动,第一步打开软件包中心,点击更多配置找到使用ADC设备驱动程序选项点击添加,如下图所示:

然后点击保存,由此官方ADC驱动添加完成。



在adc_config.h文件添加如下代码:
#ifndef LIBRARIES_HAL_DRIVERS_CONFIG_ADC_CONFIG_H_ #define LIBRARIES_HAL_DRIVERS_CONFIG_ADC_CONFIG_H_ #include
在drv_adc.c文件中添加如下代码:
#include "drv_gpio.h" #ifdef BSP_USING_ADC9 #include "adc_config.h" #define LOG_TAG "drv.adc" #include
在ab32vg1_hal_conf.h中开启使用adc:
#define HAL_ADC_MODULE_ENABLED #ifdef HAL_ADC_MODULE_ENABLED #include "ab32vg1_hal_adc.h" #endif
由此我们添加完成了ADC的所以驱动,下一步骤编写上层ADC应用,在application文件新建一个.c文件,并在里面添加如下代码:
#include
#include "chart.h"
//#include "stdio.h"
uint16 *pADCSampling; //指向ADC实时采样的指针
uint16 waveBuf[SAMPLE_NUM]; //经过计算整理后的波形数据
uint8 triPre; //触发位置前方等值点
uint8 triAft; //触发位置后方等值点
uint16 plotADCMax, plotADCMin;
void GetWaveData()
{
pADCSampling = GetWaveADC(ADC_DSO, ScaleH);
}
/*@note
#define ADC_DSO ADC_CHS_06 ADC采样通道设置
int8 ScaleH = 2; //时间区间,0-11对应500ms-100us
*/
/* 获得自动量程纵轴上下限
Calculate voltage range for Auto Range*/
void getRulerV()
{
//自动量程,根据采样点的最大最小值,按500mV扩大范围取整,作为垂直标尺范围mV
if (ScaleV_Auto == 1)
{
if (VMax / 100 % 10 >= 5)
RulerVMax = (VMax + 500) / 1000 * 1000;
else
RulerVMax = VMax / 1000 * 1000 + 500;
if (VMin / 100 % 10 >= 5)
RulerVMin = VMin / 1000 * 1000 + 500;
else
RulerVMin = VMin / 1000 * 1000;
if (RulerVMax > MAX_V)
RulerVMax = MAX_V;
if (RulerVMin < MIN_V)
RulerVMin = MIN_V;
}
}
/* 计算波长
Calculate wave length*/
bit getWaveLength(uint16 triLevel, bit right_or_left)
{
int16 i;
uint8 tri_pre = 255;
uint8 tri_aft = 255;
uint8 triPos_tmp;
bit triSlope_tmp;
bit triFail = 1;
/* 查找距离屏幕中心最近的触发点
Search the trigger poiont closest to the center of chart */
if (right_or_left) //向右查找临时触发点 / Search right side
{
for (i = TriPos + TriPosOffset; i < SAMPLE_NUM - 2; i++)
{
if (GetTriggerPos(*(ADCbuf + i), *(ADCbuf + i + 1), triLevel, 1)) //按上升沿查找 / Search on rising edge
{
triPos_tmp = i;
triSlope_tmp = 1;
triFail = 0;
break;
}
else if (GetTriggerPos(*(ADCbuf + i), *(ADCbuf + i + 1), triLevel, 0)) //按下降沿查找 / Search on falling edge
{
triPos_tmp = i;
triSlope_tmp = 0;
triFail = 0;
break;
}
}
}
else //向左查找临时触发点 / Search left side
{
for (i = TriPos + TriPosOffset; i > 0; i--)
{
if (GetTriggerPos(*(ADCbuf + i), *(ADCbuf + i + 1), triLevel, 1)) //按上升沿查找 / Search on rising edge
{
triPos_tmp = i;
triSlope_tmp = 1;
triFail = 0;
break;
}
else if (GetTriggerPos(*(ADCbuf + i), *(ADCbuf + i + 1), triLevel, 0)) //按下降沿查找 / Search on falling edge
{
triPos_tmp = i;
triSlope_tmp = 0;
triFail = 0;
break;
}
}
}
if (!triFail)
{
for (i = triPos_tmp; i >= 0; i--) //查询触发位置左侧的等值点 / Search equal point left side
{
if (triSlope_tmp) //上升触发,查找下降点 / Trigger on rising edge, search on falling edge
{
if (*(ADCbuf + i) >= triLevel && *(ADCbuf + i + 1) <= triLevel)
{
tri_pre = i;
break;
}
}
else //下降触发,查找上升点 / Trigger on falling edge, search on rising edge
{
if (*(ADCbuf + i) <= triLevel && *(ADCbuf + i + 1) >= triLevel)
{
tri_pre = i;
break;
}
}
}
for (i = triPos_tmp; i < SAMPLE_NUM - 1; i++) //查询触发位置右侧的等值点 / Search equal point right side
{
if (triSlope_tmp) //上升触发,查找下降点 / Trigger on rising edge, search on falling edge
{
if (*(ADCbuf + i) >= triLevel && *(ADCbuf + i + 1) <= triLevel)
{
tri_aft = i;
break;
}
}
else //下降触发,查找上升点 / Trigger on falling edge, search on rising edge
{
if (*(ADCbuf + i) <= triLevel && *(ADCbuf + i + 1) >= triLevel)
{
tri_aft = i;
break;
}
}
}
}
if (tri_pre == 255 || tri_aft == 255 || (tri_pre == tri_aft))
{
WaveLength = 0;
return 0;
}
else
{
WaveLength = tri_aft - tri_pre;
return 1;
}
}
/* 计算波形频率
Calculate the wave frequency*/
void getWaveFreq()
{
uint16 m_num; //求和次数
uint8 n_num; //求平均值右移位数
//ADC停止采样时,每次动作都会显示波形频率,因此不求平均值
if (!ADCRunning)
{
WaveLengthSumNum = 0;
WaveLengthSum = 0;
}
//自动模式下为了让频率不频繁变动,取平均值,大于等于100ms区间不取平均值,一个原因是100ms波形变化慢,所以频率跳动不频繁,
//另一方面越长的时间区间取平均值的延迟越高,影响使用体验
else if (TriMode == 0 && ScaleH > 2)
{
switch (ScaleH)
{
case 3: //50ms
m_num = 2;
n_num = 1;
break;
case 4: //20ms
m_num = 4;
n_num = 2;
break;
default: //<10ms
m_num = 8;
n_num = 3;
break;
}
WaveLengthSum += WaveLength;
//达到求和次数后
if (++WaveLengthSumNum >= m_num)
{
WaveLength = WaveLengthSum >> n_num; //求波长平均值
WaveLengthSumNum = 0; //清零波长求和次数
WaveLengthSum = 0; //清零波长总和
}
//没达到求和次数,则返回,WaveFreq保持不变
else
return;
}
switch (ScaleH)
{
case 0: //500ms
WaveFreq = (float)50 / WaveLength + 0.5; //WaveFreq=25000/(500*WaveLength);
break;
case 1: //200ms
WaveFreq = 125 / WaveLength; //WaveFreq=25000/(200*WaveLength);
break;
case 2: //100ms
WaveFreq = 250 / WaveLength; //WaveFreq=25000/(100*WaveLength);
break;
case 3: //50ms
WaveFreq = 500 / WaveLength; //WaveFreq=25000/(50*WaveLength);
break;
case 4: //20ms
WaveFreq = 1250 / WaveLength; //WaveFreq=25000/(20*WaveLength);
break;
case 5: //10ms
WaveFreq = 2500 / WaveLength; //WaveFreq=25000/(10*WaveLength);
break;
case 6: //5ms
WaveFreq = 5000 / WaveLength; //WaveFreq=25000/(5*WaveLength);
break;
case 7: //2ms
WaveFreq = 12500 / WaveLength; //WaveFreq=25000/(2*WaveLength);
break;
case 8: //1ms
WaveFreq = 25000 / WaveLength; //WaveFreq=25000/(1*WaveLength);
break;
case 9: //500us
WaveFreq = 50000 / WaveLength; //WaveFreq=25000000/(500*WaveLength);
break;
case 10: //200us
WaveFreq = 125000 / WaveLength; //WaveFreq=25000000/(200*WaveLength);
break;
case 11: //100us
WaveFreq = 250000 / WaveLength; //WaveFreq=25000000/(100*WaveLength);
break;
}
}
/* 将mv转换为ADC
Convert voltage in mV to ADC*/
uint16 Convert_mv_ADC(uint16 mv, uint16 *BGV, uint16 ADCbg, uint16 lsb)
{
uint16 ADC;
ADC = (uint32)mv * ADCbg * 100 / (*BGV) / lsb;
return ADC;
}
/* 将mv转换为ADC
Convert ADC to voltage in mV */
uint16 c_ADC_mv(uint16 ADC, uint16 *BGV, uint16 BGADC, uint16 lsb)
{
uint16 mv;
mv = (uint32)ADC * *BGV * lsb / BGADC / 100;
return mv;
}
/* 将uint16格式的mV转化为字符型V
Convert voltage in mV to string*/
uint8 *c_mv_V(uint16 v)
{
static uint8 s[5];
if (v < 10000)
{
s[0] = v / 1000 + '0';
s[1] = '.';
s[2] = v / 100 % 10 + '0';
s[3] = v / 10 % 10 + '0';
s[4] = '\0';
}
else
{
s[0] = v / 10000 + '0';
s[1] = v / 1000 % 10 + '0';
s[2] = '.';
s[3] = v / 100 % 10 + '0';
s[4] = '\0';
}
return s;
}
/* 转换波形频率为字符
Convert frequency to string */
uint8 *c_WaveFreq_Str()
{
static uint8 s[5];
if (WaveFreq == 0)
{
s[0] = '*';
s[1] = '*';
s[2] = '*';
s[3] = '*';
s[4] = '\0';
}
else if (WaveFreq >= 10000000)
{
s[0] = WaveFreq / 10000000 + '0';
s[2] = ((WaveFreq) / 1000000) % 10 + '0';
s[3] = 'M';
s[4] = '\0';
}
else if (WaveFreq >= 1000000)
{
s[0] = WaveFreq / 1000000 + '0';
s[1] = '.';
s[2] = ((WaveFreq) / 100000) % 10 + '0';
s[3] = 'M';
s[4] = '\0';
}
else if (WaveFreq >= 100000)
{
s[0] = WaveFreq / 100000 + '0';
s[1] = (WaveFreq / 10000) % 10 + '0';
s[2] = ((WaveFreq) / 1000) % 10 + '0';
s[3] = 'k';
s[4] = '\0';
}
else if (WaveFreq >= 10000)
{
s[0] = WaveFreq / 10000 + '0';
s[1] = ((WaveFreq) / 1000) % 10 + '0';
s[2] = 'k';
s[3] = '\0';
}
else if (WaveFreq >= 1000)
{
s[0] = WaveFreq / 1000 + '0';
s[1] = '.';
if ((WaveFreq / 10) % 10 > 5)
s[2] = ((WaveFreq) / 100) % 10 + '0';
else
s[2] = ((WaveFreq) / 100) % 10 + '0';
s[3] = 'k';
s[4] = '\0';
}
else if (WaveFreq >= 100)
{
s[0] = WaveFreq / 100 + '0';
s[1] = (WaveFreq / 10) % 10 + '0';
s[2] = (WaveFreq) % 10 + '0';
s[3] = '\0';
}
else if (WaveFreq >= 10)
{
s[0] = WaveFreq / 10 + '0';
s[1] = (WaveFreq) % 10 + '0';
s[2] = '\0';
}
else if (WaveFreq >= 1)
{
s[0] = (WaveFreq) % 10 + '0';
s[1] = '\0';
}
return s;
}
/* 将采样值的映射到屏幕的显示范围,并反转
Remap sampling data to display range and inverse */
uint16 remap(uint16 val, uint16 rangeMax, uint16 rangeMin, uint16 rangeMaxNew, uint16 rangeMinNew)
{
if (val > rangeMax)
val = rangeMax;
else if (val < rangeMin)
val = rangeMin;
val = rangeMinNew + (uint32)(rangeMax - val) * (rangeMaxNew - rangeMinNew) / (rangeMax - rangeMin);
return val;
}
/* 获取触发点位置
Get Trigger Position */
bit GetTriggerPos(uint16 d1, uint16 d2, uint16 dTrigger, bit triSlope)
{
/* 上升沿触发
Trigger on Rising Edge */
if (triSlope)
{
if (d1 <= dTrigger && d2 >= dTrigger)
{
return 1;
}
}
/* 下降沿触发
Trigger on Falling Edge */
else
{
if (d1 >= dTrigger && d2 <= dTrigger)
{
return 1;
}
}
return 0;
}
/* 分析采样数据
Analyse sampling date */
void AnalyseData()
{
int16 i;
uint16 tmp;
uint16 adcMax = 0;
uint16 adcMin = 4095;
uint16 adcMid = 0;
uint16 plotADCMid = 0;
if (ADCComplete)
{
ScaleH_tmp = ScaleH; //记录完成采样的时间区间,由于采样点的数量较少,因此不支持实时根据时间区间缩放波形,时间区间改变则清空波形
//将采样点复制到另一个数组,避免采样中断造成数据混乱
//若采样被中断,则使用缓存中旧采样点显示波形
for (i = 0; i < SAMPLE_NUM; i++)
{
*(ADCbuf + i) = *(pADCSampling + i);
}
//计算触发点位置
//ADC采样停止时,TriPos不变,所以不进行下列计算
TriPos = SAMPLE_NUM / 2;
TriFail = 1; //置位触发失败标志
for (i = ((CHART_H_MAX - CHART_H_MIN) >> 1); i < SAMPLE_NUM - ((CHART_H_MAX - CHART_H_MIN) >> 1); i++)
{
if (GetTriggerPos(*(ADCbuf + i), *(ADCbuf + i + 1), TriggerADC, TriSlope))
{
TriPos = i;
TriFail = 0; //清零触发失败标志
break;
}
}
TriPosOffset = 0;
}
/* 获取屏幕显示波形的最大和最小值
Get the MAX and MIN value of waveform on display*/
for (i = 0; i <= 100; i++)
{
tmp = *(ADCbuf + TriPos + TriPosOffset - 50 + i);
if (tmp > adcMax)
adcMax = tmp;
else if (tmp < adcMin)
adcMin = tmp;
}
//将采样点的最大最小采样值转换成电压值mV
VMax = c_ADC_mv(adcMax, BGV, ADCbg, Lsb);
VMin = c_ADC_mv(adcMin, BGV, ADCbg, Lsb);
//获得垂直标尺的上下限
getRulerV();
//用垂直标尺mV范围反求出ADC值的范围作为图表的显示上下限
plotADCMax = Convert_mv_ADC(RulerVMax, BGV, ADCbg, Lsb);
plotADCMin = Convert_mv_ADC(RulerVMin, BGV, ADCbg, Lsb);
//计算波形的频率
//如果当前的时间区间和采样数据的时间间隔一致则进行频率计算
//为避免ADC采样出错时频率跳变厉害,计算波长时使用电压标尺的中点和波幅中点的较小值
//如果遇到频率跳变无法读取,将自动量程切换至合适的手动量程即可
adcMid = (adcMax + adcMin) >> 1;
plotADCMid = (plotADCMax + plotADCMin) >> 1;
if (getWaveLength(adcMid < plotADCMid ? adcMid : plotADCMid, 1) || getWaveLength(adcMid < plotADCMid ? adcMid : plotADCMid, 0))
{
getWaveFreq();
}
else
{
WaveFreq = 0;
}
//映射采样值至屏幕的显示范围
for (i = 0; i < SAMPLE_NUM; i++)
{
waveBuf[i] = remap(*(ADCbuf + i), plotADCMax, plotADCMin, CHART_V_MAX, CHART_V_MIN);
}
}
/* 绘制主界面
Draw main interface */
void PlotChart(void)
{
uint8 i;
uint8 *s;
if (ClearDisplay)
{
ClearDisplay = 0;
OLED_Clear();
/* 图表边框
波形横向绘图区101格,26~126
波形纵向绘图区45格,8~52
Frame of chart 45x101*/
OLED_DrawHLine(CHART_H_MIN, CHART_V_MIN, 4);
OLED_DrawHLine(CHART_H_MIN, CHART_V_MAX, 4);
OLED_DrawHLine(CHART_H_MAX - 3, CHART_V_MIN, 4);
OLED_DrawHLine(CHART_H_MAX - 3, CHART_V_MAX, 4);
OLED_DrawHLine(CHART_H_MIN + 25 - 2, CHART_V_MIN, 5);
OLED_DrawHLine(CHART_H_MIN + 25 - 2, CHART_V_MAX, 5);
OLED_DrawHLine(CHART_H_MIN + 50 - 2, CHART_V_MIN, 5);
OLED_DrawHLine(CHART_H_MIN + 50 - 2, CHART_V_MAX, 5);
OLED_DrawHLine(CHART_H_MIN + 75 - 2, CHART_V_MIN, 5);
OLED_DrawHLine(CHART_H_MIN + 75 - 2, CHART_V_MAX, 5);
OLED_DrawVLine(CHART_H_MIN - 1, CHART_V_MIN, CHART_V_MAX - CHART_V_MIN + 1);
OLED_DrawVLine(CHART_H_MAX + 1, CHART_V_MIN, CHART_V_MAX - CHART_V_MIN + 1);
/* 图表虚线网格
Grid of chart */
for (i = 0; i < 15; i++)
{
OLED_DrawHLine(CHART_H_MIN + 7 * i, CHART_V_MIN + ((CHART_V_MAX - CHART_V_MIN) >> 1), 3);
}
for (i = 0; i < 6; i++)
{
OLED_DrawVLine(CHART_H_MIN + 25, CHART_V_MIN + 1 + i * 8, 3);
OLED_DrawVLine(CHART_H_MIN + 50, CHART_V_MIN + 1 + i * 8, 3);
OLED_DrawVLine(CHART_H_MIN + 75, CHART_V_MIN + 1 + i * 8, 3);
}
/* 波形位置标尺
Ruler for waveform position*/
OLED_DrawHLine(0, 62, 25);
OLED_DrawVLine(0, 60, 3);
OLED_DrawVLine(24, 60, 3);
OLED_DrawVLine((TriPos + TriPosOffset - 50) * 24 / 119, 58, 4);
/* 波形电压范围
Voltage range of waveform*/
OLED_Set_Pos(26, 56);
s = c_mv_V(VMin);
OLED_DrawString(s);
OLED_DrawString("-");
s = c_mv_V(VMax);
OLED_DrawString(s);
OLED_DrawString("V");
}
OLED_Overlap(0); //设置绘图模式为覆盖
/* 频率
Frequency */
OLED_Set_Pos(92, 0);
OLED_DrawString(" ");
OLED_Set_Pos(92, 0);
s = c_WaveFreq_Str();
OLED_DrawString(s);
OLED_DrawString("Hz");
/* 自动量程标志
Flag for Auto Range*/
if (ScaleV_Auto == 1)
{
OLED_Set_Pos(0, 0);
OLED_DrawString("Auto");
}
else
{
OLED_Set_Pos(0, 0);
OLED_DrawString(" ");
}
/* 触发值
Trigger Level */
OLED_Set_Pos(33, 0);
if (OptionInChart == 2 && !WaveScroll)
{
OLED_DrawVLine(69, 0, 8);
OLED_Reverse(1);
}
else
{
OLED_Reverse(1);
OLED_DrawVLine(69, 0, 8);
OLED_Reverse(0);
}
s = c_mv_V(TriLevel);
OLED_DrawString("T");
OLED_DrawString(s);
OLED_DrawString("V");
OLED_Reverse(0);
/* 触发方向标志
Trigger Slope */
if (OptionInChart == 3 && !WaveScroll)
{
OLED_DrawVLine(71, 0, 8);
OLED_DrawVLine(78, 0, 8);
OLED_Reverse(1);
}
else
{
OLED_Reverse(1);
OLED_DrawVLine(71, 0, 8);
OLED_DrawVLine(78, 0, 8);
OLED_Reverse(0);
}
if (TriSlope)
{
OLED_DrawChar(72, 0, 123); //123上箭头,上升沿触发
}
else
{
OLED_DrawChar(72, 0, 124); //124下箭头,下降沿触发
}
OLED_Reverse(0);
/* 触发方式标志
Trigger Mode */
if (OptionInChart == 4 && !WaveScroll)
{
OLED_DrawVLine(86, 0, 8);
OLED_Reverse(1);
}
else
{
OLED_Reverse(1);
OLED_DrawVLine(86, 0, 8);
OLED_Reverse(0);
}
OLED_Set_Pos(80, 0);
if (TriMode == 0)
{
OLED_DrawString("A");
}
else if (TriMode == 1)
{
OLED_DrawString("N");
}
else if (TriMode == 2)
{
OLED_DrawString("S");
}
OLED_Reverse(0);
/* 触发失败标志
Flag for Trigger Fail*/
if (TriFail)
{
OLED_Set_Pos(0, 24);
OLED_DrawString("Fail");
}
//绘制运行/停止标志
// if (TriS && ADCRuning)
// {
// OLED_Set_Pos(0, 16);
// OLED_DrawString("Wait");
// }
if (ADCRunning)
{
OLED_Set_Pos(0, 16);
OLED_DrawString("Run ");
}
else
{
OLED_Set_Pos(0, 16);
OLED_DrawString("Stop");
}
/* 横轴时间区间
Seconds per division */
OLED_Set_Pos(97, 56);
OLED_DrawString(" ");
if (OptionInChart == 0 && !WaveScroll)
{
OLED_Reverse(1);
}
OLED_Set_Pos(97, 56);
OLED_DrawString(ScaleHTxt[ScaleH]);
OLED_Reverse(0);
/* 纵轴电压区间
Ruler for Voltage */
OLED_Set_Pos(0, 8);
OLED_DrawString(" ");
if (OptionInChart == 1 && !WaveScroll)
{
OLED_Reverse(1);
}
s = c_mv_V(RulerVMax);
OLED_Set_Pos(0, 8);
OLED_DrawString(s);
OLED_Reverse(0);
s = c_mv_V(RulerVMin);
OLED_Set_Pos(0, 46);
OLED_DrawString(s);
OLED_Overlap(1); //恢复绘图模式为叠加
}
/* 绘制波形
Draw waveform*/
void PlotWave(void)
{
uint8 i;
//Vector Mode
if (PlotMode == 0)
{
for (i = 0; i < (CHART_H_MAX - CHART_H_MIN); i++)
{
OLED_DrawLine(
i + CHART_H_MIN,
waveBuf[TriPos + TriPosOffset - ((CHART_H_MAX - CHART_H_MIN) >> 1) + i],
i + CHART_H_MIN + 1,
waveBuf[TriPos + TriPosOffset - ((CHART_H_MAX - CHART_H_MIN) >> 1) + i + 1]);
}
}
//Dots Mode
if (PlotMode == 1)
{
for (i = 0; i <= (CHART_H_MAX - CHART_H_MIN); i++)
{
OLED_DrawPixel(i + CHART_H_MIN, waveBuf[TriPos + TriPosOffset - ((CHART_H_MAX - CHART_H_MIN) >> 1) + i]);
}
}
}
/* 绘制设置界面
Draw settings */
void PlotSettings()
{
if (ClearDisplay)
{
ClearDisplay = 0;
OLED_Clear();
//LOGO
OLED_DrawBMP(18, 24, 18 + 82 - 1, 24 + 13 - 1, MINIDSO, sizeof(MINIDSO) / sizeof(MINIDSO[0]));
//Version
OLED_Set_Pos(102, 30);
OLED_DrawString("V0.3");
//CopyRight
OLED_Set_Pos(30, 39);
OLED_DrawString("By Creative Lau");
OLED_Set_Pos(44, 48);
OLED_DrwCHS_16x16(0);
OLED_DrwCHS_16x16(1);
OLED_DrwCHS_16x16(2);
OLED_DrwCHS_16x16(3);
OLED_DrwCHS_16x16(4);
}
OLED_Overlap(0);
/* 选项
Options */
/* DrawMode */
OLED_Set_Pos(0, 0);
&nbs 这是演示视频: