聚豐項目 > 基于AB32VG1的Mini示波器
基于AB32VG1芯片制作Mini示波器,硬件部分參考老劉愛搗鼓等開源作品,謝謝他們無私的開源精神。
是唐棠啊
分享是唐棠啊
團隊成員
是唐棠啊 學生
Mini示波器采用了一套成本低廉但高效的硬件,配合層次化的軟件框架,實現(xiàn)對常規(guī)低頻信號波形的采集、分析、顯示。
硬件部分的主要工作有:電源管理(5V、2.5V、-5V);對信號的衰減、限幅、偏置。最后將處理好的電壓信號送入AB32VG1的ADC外設,進行數(shù)據(jù)采集。由于ADC外設只能采集正電壓,因此我們通過增加偏置電壓的方式,將負電壓抬高來采集。
電源管理模塊由三部分組成。第一部分輸出+5V直流電壓,供給MCU和運放;第二部分輸出-5V直流電壓,供給運放;第三部分輸出正2.5V直流電壓,作為偏置電壓。取2.5V的原因是,正好是5V的一半,作為測量負電壓的參考基準點。下面我們進行詳細說明:
電源輸出+5V部分。這里是由外部+5V電壓直接供給,作為整個電路系統(tǒng)的電源。
電源輸出-5V部分。選擇ICL7660電源芯片,將+5V轉換成-5V。ICL7660是Maxim公司生產的小功率極性反轉電源轉換器。ICL7660的靜態(tài)電流典型值為170μA,輸入電壓范圍為1.5-10V,只需外接10μF的小體積電容效率高達98%合輸出功率可達700mW(以DIP封裝為例),符合輸出100mA的要求。
電源輸出+2.5V部分。采用TL431芯片,把+5V降到+2.5V。TL431是可控精密穩(wěn)壓源。它的輸出電壓用兩個電阻就可以任意的設置到從Vref(2.5V)到36V范圍內的任何值。
前置采樣這一部分作用是對直流信號和交流信號分別處理,同時進行電壓的衰減,和進行限幅保護。信號進入電路以后,首先經過一個開關,撥動開關決定是否串接一個電容進入電阻,如果串接的電容,那么根據(jù)“通交阻直”的特性,將對交流信號和直流信號進行區(qū)分。之后經過兩個串聯(lián)電阻分壓,和并聯(lián)電容濾除毛刺。0歐電阻過去,是四個1N4148,兩兩方向相同,一正一反并聯(lián)在電路上。將信號限幅在正負1.5V。
TL074是一種在單片集成電路中配有高電壓雙極晶體管的輸入運算放大器,一個芯片帶有四個運放。這里使用了其中的三個,第一個運放的作用是對信號進行了放大處理,將輸入進來的電壓信號(<=±1.4V)放大到正負2.5V,然后緊接一級運放做電壓跟隨器,之后接入2.5V的偏置電壓,最后將信號輸入MCU的ADC外設引腳。
調試電路主要用于串口下載和仿真調試,引出了MCU的串口引腳和電源引腳。人機交互電路分為旋鈕電路和按鍵電路。旋鈕電路選擇EC11,支持單擊、旋轉、按下旋轉;按鍵電路有三個,對應復位按鈕,設置按鍵,切換選項按鍵。要注意的是EC11的A和B引腳,需要上拉電阻下拉電容。
主控電路這一部分主要包含MCU模塊、顯示屏電路、指示燈電路。MCU負責ADC數(shù)據(jù)采樣,和對人機交互部分的電路進行控制;顯示屏電路的核心是OLED顯示屏,主要進行界面顯示和波形顯示,對信號處理后結果的一個直觀反饋;指示燈電路的作用是顯示電源狀態(tài)和ADC工作狀態(tài),方便對整個心態(tài)進行一個直觀的觀察。
軟件部分的主要工作有:底層驅動SDK框架、ADC濾波算法、波形數(shù)據(jù)處理、人機交互界面。SDK提供基本的模塊和外設驅動支持,濾波算法去除噪聲和毛刺,波形處理計算電壓值和頻率,并為波形顯示做準備;人機交互界面提供屏幕顯示(OLED屏)和操作方式(旋鈕和按鍵)。
首先打開Rtt studio創(chuàng)建AB32VG1開發(fā)板的工程,如下圖所示:
由此已經創(chuàng)建好基于這款AB32VG1芯片開發(fā)板的基礎工程,點擊編譯看看是否有沒有配置的選項導致編譯失敗。
在建立好基礎工程并且編譯完成無錯后,下一步驟先添加官方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]; //經過計算整理后的波形數(shù)據(jù) uint8 triPre; //觸發(fā)位置前方等值點 uint8 triAft; //觸發(fā)位置后方等值點 uint16 plotADCMax, plotADCMin; void GetWaveData() { pADCSampling = GetWaveADC(ADC_DSO, ScaleH); } /*@note #define ADC_DSO ADC_CHS_06 ADC采樣通道設置 int8 ScaleH = 2; //時間區(qū)間,0-11對應500ms-100us */ /* 獲得自動量程縱軸上下限 Calculate voltage range for Auto Range*/ void getRulerV() { //自動量程,根據(jù)采樣點的最大最小值,按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; /* 查找距離屏幕中心最近的觸發(fā)點 Search the trigger poiont closest to the center of chart */ if (right_or_left) //向右查找臨時觸發(fā)點 / 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 //向左查找臨時觸發(fā)點 / 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--) //查詢觸發(fā)位置左側的等值點 / Search equal point left side { if (triSlope_tmp) //上升觸發(fā),查找下降點 / Trigger on rising edge, search on falling edge { if (*(ADCbuf + i) >= triLevel && *(ADCbuf + i + 1) <= triLevel) { tri_pre = i; break; } } else //下降觸發(fā),查找上升點 / 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++) //查詢觸發(fā)位置右側的等值點 / Search equal point right side { if (triSlope_tmp) //上升觸發(fā),查找下降點 / Trigger on rising edge, search on falling edge { if (*(ADCbuf + i) >= triLevel && *(ADCbuf + i + 1) <= triLevel) { tri_aft = i; break; } } else //下降觸發(fā),查找上升點 / 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; //求和次數(shù) uint8 n_num; //求平均值右移位數(shù) //ADC停止采樣時,每次動作都會顯示波形頻率,因此不求平均值 if (!ADCRunning) { WaveLengthSumNum = 0; WaveLengthSum = 0; } //自動模式下為了讓頻率不頻繁變動,取平均值,大于等于100ms區(qū)間不取平均值,一個原因是100ms波形變化慢,所以頻率跳動不頻繁, //另一方面越長的時間區(qū)間取平均值的延遲越高,影響使用體驗 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; //達到求和次數(shù)后 if (++WaveLengthSumNum >= m_num) { WaveLength = WaveLengthSum >> n_num; //求波長平均值 WaveLengthSumNum = 0; //清零波長求和次數(shù) WaveLengthSum = 0; //清零波長總和 } //沒達到求和次數(shù),則返回,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; } /* 獲取觸發(fā)點位置 Get Trigger Position */ bit GetTriggerPos(uint16 d1, uint16 d2, uint16 dTrigger, bit triSlope) { /* 上升沿觸發(fā) Trigger on Rising Edge */ if (triSlope) { if (d1 <= dTrigger && d2 >= dTrigger) { return 1; } } /* 下降沿觸發(fā) Trigger on Falling Edge */ else { if (d1 >= dTrigger && d2 <= dTrigger) { return 1; } } return 0; } /* 分析采樣數(shù)據(jù) 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; //記錄完成采樣的時間區(qū)間,由于采樣點的數(shù)量較少,因此不支持實時根據(jù)時間區(qū)間縮放波形,時間區(qū)間改變則清空波形 //將采樣點復制到另一個數(shù)組,避免采樣中斷造成數(shù)據(jù)混亂 //若采樣被中斷,則使用緩存中舊采樣點顯示波形 for (i = 0; i < SAMPLE_NUM; i++) { *(ADCbuf + i) = *(pADCSampling + i); } //計算觸發(fā)點位置 //ADC采樣停止時,TriPos不變,所以不進行下列計算 TriPos = SAMPLE_NUM / 2; TriFail = 1; //置位觸發(fā)失敗標志 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; //清零觸發(fā)失敗標志 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); //計算波形的頻率 //如果當前的時間區(qū)間和采樣數(shù)據(jù)的時間間隔一致則進行頻率計算 //為避免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(); /* 圖表邊框 波形橫向繪圖區(qū)101格,26~126 波形縱向繪圖區(qū)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(" "); } /* 觸發(fā)值 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); /* 觸發(fā)方向標志 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上箭頭,上升沿觸發(fā) } else { OLED_DrawChar(72, 0, 124); //124下箭頭,下降沿觸發(fā) } OLED_Reverse(0); /* 觸發(fā)方式標志 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); /* 觸發(fā)失敗標志 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"); } /* 橫軸時間區(qū)間 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); /* 縱軸電壓區(qū)間 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
這是演示視頻: