原創(chuàng)作者是:老劉愛搗鼓 大家可以去看他的視頻:https://space.bilibili.com/40587802
Altium Designer畫的原理圖和PCB圖如下:(51hei附件中可下載工程文件)
51hei.png (37.02 KB, 下載次數(shù): 83)
下載附件
2021-9-28 02:43 上傳
51hei.png (36.06 KB, 下載次數(shù): 96)
下載附件
2021-9-28 02:44 上傳
制作出來的實物圖如下:
IMG_6298.jpg (848.05 KB, 下載次數(shù): 86)
下載附件
2021-9-28 02:52 上傳
Main_Interface.jpg (717.44 KB, 下載次數(shù): 78)
下載附件
2021-9-28 02:52 上傳
operation.jpg (365.19 KB, 下載次數(shù): 76)
下載附件
2021-9-28 02:52 上傳
Settings_Interface.JPG (416.02 KB, 下載次數(shù): 85)
下載附件
2021-9-28 02:52 上傳
單片機源程序如下:
- /*
- Mini DSO with STC MCU
- 操作說明:
- 主界面-選項設置模式:
- 單擊編碼器:切換開始/暫停采樣
- 雙擊編碼器:切換波形水平滾動模式/選項設置模式
- 長按編碼器:進入設置界面
- 旋轉編碼器:修改當前參數(shù)
- 按下同時旋轉編碼器:在參數(shù)間切換
-
- 主界面-波形水平滾動模式:
- 單擊編碼器:切換開始/暫停采樣
- 雙擊編碼器:切換波形水平滾動模式/選項設置模式
- 長按編碼器:進入設置界面
- 旋轉編碼器:水平滾動波形(在暫停采樣狀態(tài)下有效)
- 按下同時旋轉編碼器:垂直滾動波形(僅在暫停采樣狀態(tài)下有效)
-
- 設置界面:
- 單擊編碼器:無效
- 雙擊編碼器:無效
- 長按編碼器:返回主界面
- 旋轉編碼器:修改當前選項
- 按下同時旋轉編碼器:切換選項
- 主界面參數(shù):
- 橫軸時間區(qū)間:"500ms", "200ms", "100ms", "50ms", "20ms", "10ms","5ms", "2ms", "1ms", "500us", "200us", "100us"(100us僅在自動觸發(fā)模式下可用)
- 縱軸電壓區(qū)間:設定電壓量程上限,最大30V,順時針旋轉編碼器將電壓上限設置為0則進入自動量程,逆時針旋轉進入手動量程
- 觸發(fā)值:設定觸發(fā)電壓值,觸發(fā)位置被放在屏幕中心
- 觸發(fā)方向:上下箭頭,分別代表上升沿觸發(fā)和下降沿觸發(fā)
- 觸發(fā)方式:
- Auto(自動觸發(fā)) :連續(xù)采樣,指示燈始終點亮,通過單擊編碼器控制啟停;觸發(fā)成功時,觸發(fā)點位于屏幕中心,觸發(fā)失敗則波形無規(guī)律滾動,屏幕左側顯示Fail標志
- Normal(普通觸發(fā)):等待預采樣,待指示燈亮起表示預采樣結束,這時可以輸入信號;
- 觸發(fā)成功后,顯示波形,并繼續(xù)等待下次觸發(fā);
- 如果有新的觸發(fā)成功,則自動顯示新的波形,如沒有新的觸發(fā)成功則屏幕波形保持并一直等待下次觸發(fā);
- 需注意設置正確的觸發(fā)值,否則一直處于等待觸發(fā)狀態(tài),屏幕不會顯示波形
- Single(單次觸發(fā)):等待預采樣,待指示燈亮起表示預采樣結束,這時可以輸入信號;
- 觸發(fā)成功后,顯示波形,并停止采樣,需用戶單擊編碼器開始下次采樣
- 需注意設置正確的觸發(fā)值,否則一直處于等待觸發(fā)狀態(tài),屏幕不會顯示波形
-
- 主界面狀態(tài)顯示:
- Run:正在采樣
- Stop:停止采樣
- Fail:自動模式下,觸發(fā)值超出波形范圍引起觸發(fā)失敗
- Auto:自動量程
-
- 設置界面選項:
- PMode(繪圖模式):
- Vector:波形以矢量顯示
- Dots :波形以點陣顯示
- LSB(采樣系數(shù)):分壓系數(shù)的100倍,比如用10k加2k的電阻進行分壓,分壓系數(shù)為(10+2/2)=6,LSB理論取值為6x100=600,根據(jù)實際電阻精度進行微調
- BRT:OLED亮度
- 保存設置:長按編碼器退出設置界面時,設置界面和主界面的所有參數(shù)被保存到EEPROM
- 2020-04-30更新
- 1. 增加單次觸發(fā)和普通觸發(fā)功能,可自定義觸發(fā)點用來捕捉波形變化
- 2. 按照規(guī)格書要求將ADC采樣端口設置為高阻輸入
- 2020-5-3更新
- 1. 增加波形頻率顯示
- 2. 使用編碼器水平/垂直滾動波形
- 3. 使用編碼器垂直縮放波形
- 4. 用戶可設定觸發(fā)電平
- */
- #include <reg51.h>
- #include "global.h"
- #include "delay.h"
- #include "adc_stc8.h"
- #include "config_stc.h"
- #include "settings.h"
- #include "chart.h"
- #include "ssd1306.h"
- // #include "uart.h"
- // #include "stdio.h"
- #define VBAT_UPDATE_FREQ 40 //電池電壓信息的更新頻率 VBAT_UPDATE_FREQ*25ms
- #define VBAT_LSB 600 //電池電壓采樣分壓系數(shù)*100
- #define INT_0 0 //外部中斷0序號,編碼器旋轉
- #define INT_1 2 //外部中斷1序號,編碼器按下
- #define TIMER_0 1 //定時器0中斷序號
- void init()
- {
- InSettings = 0; //初始化開機界面
- OptionInSettings = 0; //初始化設置界面的選項編號
- OptionInChart = 0; //初始化主界面的選項標號
- WaveScroll = 0; //清零波形滾動標志
- OptionChanged = 0; //清零設置修改標志
- ADCRunning = 1; //置位采樣標志
- ADCInterrupt = 0; //清零ADC中斷標志
- ADCComplete = 0; //清零ADC完成標志
- WaveUpdate = 0; //清零波形更新標志
- ClearWave = 0; //清零清除波形標志
- ClearDisplay = 1; //置位清空屏幕標志
- EC11PressAndRotate = 0; //清零編碼器旋轉標志
- UpdateVbat = 0; //清零采樣電池電壓標志
- ADCComplete = 0; //清零ADC完成采樣標志
- WaveFreq = 0; //清零波形頻率
- TriPos = 50; //初始化觸發(fā)點位置
- TriPosOffset = 0; //初始化觸發(fā)點偏移量
- TriFail = 0; //清零觸發(fā)失敗標志
- VMax = 0; //清零波形電壓最大值
- VMin = 0; //清零波形電壓最小值
- WaveLengthSumNum = 0; //清零波形長度求和次數(shù)
- WaveLengthSum = 0; //清零波形長度求和
- /* 波形滾動模式下正在采樣則禁用外部中斷0(編碼器旋轉)
- Disable external interrupt 0(Encoder rotation) in waveform scroll mode when sampling*/
- if (ADCRunning && WaveScroll)
- EX0 = 0;
- /* 獲取內部參考電壓值
- Get internal reference voltage */
- BGV = GetBGV();
- }
- void runWhenInSettrings()
- {
- P_Ready = 0;
- ClearDisplay = 1;
- while (InSettings)
- {
- /* 更新電池電壓信息
- Update voltage infor of battery */
- if (UpdateVbat)
- {
- UpdateVbat = 0;
- VBat = GetVoltage(ADC_BAT, VBAT_LSB);
- }
- /* 更新屏幕亮度
- Update OLED Brightness */
- if (OLED_BrightnessChanged)
- {
- OLED_BrightnessChanged = 0;
- OLED_Write_Command(0x81);
- OLED_Write_Command(OLED_Brightness * 10);
- }
- /* 更新參數(shù)
- Update parameters */
- if (DisplayUpdate)
- {
- DisplayUpdate = 0;
- PlotSettings();
- OLED_Display();
- }
- }
- /* 保存設置
- Save Settings */
- EA = 0;
- if (OptionChanged)
- {
- OptionChanged = 0;
- ClearDisplay = 0;
- /* 保存設置并顯示保存狀態(tài)
- Save settings and display saving status*/
- PlotSaveStatus(Save_Options());
- OLED_Display();
- Delay1000ms();
- }
- /* 退出settings后刷新屏幕
- Redraw display after exit settings */
- ClearDisplay = 1;
- PlotChart();
- OLED_Display();
- IE0 = 0;
- IE1 = 0;
- EA = 1;
- }
- /*
- ADCRuning=1
- | WaveUpdate=1
- | | ClearWave=1
- | | ClearWave=0
- | WaveUpdate=0
- ADCRuning=0
- DisplayUpdate=1
- WaveUpdate=1
- | ClearWave=1
- | ClearWave=0
- WaveUpdate=0
- */
- void runWhenADCInterrupt()
- {
- ADCInterrupt = 0;
- P_Ready = 0;
- /* ADC采樣運行
- ADC Sampling Running */
- if (ADCRunning)
- {
- EX0 = 0;
- if (WaveUpdate)
- {
- WaveUpdate = 0;
- ClearDisplay = 1;
- /* 清空波形緩存
- Clear waveform in buffer*/
- if (ClearWave)
- {
- ClearWave = 0;
- memset(ADCbuf, 0x00, SAMPLE_NUM * 2);
- WaveFreq = 0;
- TriFail = 0;
- VMax = 0;
- VMin = 0;
- PlotChart();
- }
- /* 顯示緩存中的波形
- Display waveform in buffer*/
- else
- {
- AnalyseData();
- PlotChart();
- PlotWave();
- }
- }
- else
- {
- ClearDisplay = 0;
- PlotChart();
- }
- OLED_Display();
- /* ADCRuning和WaveScroll同時置位時,不開啟外部中斷0(編碼器旋轉)
- Not to enable external interrupt 0(Encoder Rotation) when both of ADCRunning and WaveScroll set. */
- if (!WaveScroll)
- {
- IE0 = 0;
- EX0 = 1;
- }
- }
- /* ADC采樣停止
- ADC Sampling Stopped */
- else
- {
- while (!ADCRunning && !InSettings)
- {
- if (DisplayUpdate)
- {
- EX0 = 0;
- DisplayUpdate = 0;
- if (WaveUpdate)
- {
- WaveUpdate = 0;
- /* 分析緩存中完成采樣的采樣數(shù)據(jù)
- Analyse completed sampling data in buffer */
- AnalyseData();
- ClearDisplay = 1;
- /* 清空屏幕,繪制波形
- Clear display and draw waveform */
- if (ScaleH == ScaleH_tmp)
- {
- /* 采樣點數(shù)有限,不支持橫向縮放波形,只有時間區(qū)間與完成采樣的時間區(qū)間相同才繪制波形
- Since the sampling points limitation, scaling waveform along horizontal is not support.
- Show waveform only when time scale is same as that when sampling completed */
- PlotChart();
- PlotWave();
- }
- /* 清空屏幕,不繪制波形
- Clear display and no waveform */
- else
- {
- WaveFreq = 0; //清零WaveFreq,繪制界面時,頻率位置會顯示****Hz
- PlotChart();
- }
- }
- /* 只更新屏幕上的參數(shù),波形不變
- Update parameters on display only, keep waveform */
- else
- {
- ClearDisplay = 0;
- PlotChart();
- }
- OLED_Display();
- IE0 = 0;
- EX0 = 1;
- }
- }
- }
- }
- void runWhenADCComplete()
- {
- /* ADC采樣完成 - 單次觸發(fā)
- ADC Sampling Complete - Single Trigger Mode */
- if (TriMode == 2)
- {
- EX0 = 0;
- ADCInterrupt = 1;
- DisplayUpdate = 0;
- WaveUpdate = 0;
- ADCRunning = 0; //清零ADC運行標志,停止采樣
- AnalyseData();
- ClearDisplay = 1;
- PlotChart();
- PlotWave();
- OLED_Display();
- IE0 = 0;
- EX0 = 1;
- }
- /* ADC采樣完成 - 自動觸發(fā)或普通觸發(fā)
- ADC Sampling Complete - Auto or Normal Trigger Mode */
- else
- {
- //EX0 = 0;
- ClearDisplay = 1; //置位清空屏幕標志
- AnalyseData(); //分析采樣數(shù)據(jù)
- PlotChart(); //繪制主界面
- PlotWave(); //繪制波形
- OLED_Display();
- //IE0 = 0;
- //EX0 = 1;
- }
- }
- /* 程序入口
- Program Entry */
- void main()
- {
- /* 將ADC端口P0.4,P0.6設置為高阻
- Set ADC port P0.4, P0.6 as high-impedance */
- P0M1 |= 0x50;
- P0M0 &= ~0x50;
- /* 設置指示燈端口P1.1為推挽輸出
- Set indicator port P1.1 as push-pull output */
- P0M1 &= ~0x02;
- P0M0 |= 0x02;
- /* 設置編碼器端口P3.2,P3.3,P3.4為準雙向
- Set Encoder port P3.2, P3.3, P3.4 as quasi bidirectional */
- P3M1 &= ~0x1C;
- P3M0 &= ~0x1C;
- /* 設置OLED端口P2.3,P2.4,P2.5,P2.6,P2.7為準雙向
- Set OLED port P2.3, P2.4, P2.5, P2.6 as quasi bidirectional */
- P2M1 &= ~0xF8;
- P2M0 &= ~0xF8;
- /* 編碼器旋轉外部中斷
- Interrupt for rotating of Encoder */
- IT0 = 0; //外部中斷0觸發(fā)方式,上升沿和下降沿
- PX0 = 1; //外部中斷0高優(yōu)先級,可打斷按鍵中斷,用于判斷按下同時旋轉
- EX0 = 1; //開啟外部中斷0
- /* 編碼器按鍵外部中斷
- Interrupt for clicking of Encoder */
- IT1 = 1; //外部中斷1觸發(fā)方式,下降沿
- PX1 = 0; //外部中斷1低優(yōu)先級
- EX1 = 1; //開啟外部中斷1
- /* 定時器0,為更新電池電壓信息計時
- Timer 0, for updating voltage of battery */
- AUXR &= 0x7F; //定時器時鐘12T模式
- TMOD &= 0xF0; //設置定時器模式
- TL0 = 0x46; //設置定時初值 //27MHz,25ms
- TH0 = 0x24; //設置定時初值
- TF0 = 0; //清除TF0標志
- ET0 = 1; //允許定時器0中斷
- /* 開總中斷
- Enable global interrupt */
- EA = 1;
- //UartInit();
- Read_Options();
- init();
- OLED_Init();
- OLED_SetFontWidth(6);
- PlotChart();
- OLED_Display();
- while (1)
- {
- P_Ready = 0;
- /* 采樣波形
- Sampling*/
- GetWaveData();
- /* 進入設置界面
- Enter Settings Interface */
- if (InSettings)
- {
- runWhenInSettrings();
- }
- /* ADC采樣中斷
- ADC Sampling Interrupt */
- else if (ADCInterrupt)
- {
- runWhenADCInterrupt();
- }
- /* ADC采樣完成
- ADC Sampling Complete */
- else
- {
- runWhenADCComplete();
- }
- }
- }
- /* 分析編碼器旋轉
- Analyse Rotation of Encoder */
- void Scan_EC11(void)
- {
- /* 延時去抖動
- Delay to remove jitter */
- Delay500us();
- /* 正轉
- Clockwise */
- if (EC11_A != EC11_B)
- {
- Change_Val(1);
- }
- /* 反轉
- Anticlockwise */
- else if (EC11_A == EC11_B)
- {
- Change_Val(0);
- }
- }
- /* 編碼器旋轉中斷
- Interrput for Encoder Rotated */
- void INT0_interrupt(void) interrupt INT_0
- {
- Delay500us();
- /* 編碼器是否被按下
- Whether the Encoder is pressed */
- if (!EC11_KEY)
- EC11PressAndRotate = 1;
- else
- EC11PressAndRotate = 0;
- Scan_EC11();
- ADCInterrupt = 1;
- DisplayUpdate = 1;
- IE1 = 0; //清零外部中斷1標志位
- IE0 = 0; //清零外部中斷0標志位
- }
- /* 編碼器點擊中斷
- Interrput for Encoder Pressed */
- void INT1_interrupt(void) interrupt INT_1
- {
- Delay50ms();
- if (!EC11_KEY)
- {
- EC11PressAndRotate = 0;
- /* 長按編碼器按鍵 - 切換主界面和設置界面
- Long presse Encoder - Switch main interface and settings interface */
- if (Delay800ms_Long_Press())
- {
- InSettings = ~InSettings;
- /* 進入設置界面
- Enter Settings */
- if (InSettings)
- {
- DisplayUpdate = 1;
- UpdateVbat = 1;
- TF0 = 0; //清零定時器0溢出標志
- TR0 = 1; //定時器0開始計時,開始電池電壓信息更新計時
- IE0 = 0; //清零外部中斷0中斷標志
- EX0 = 1; //開啟外部中斷0(編碼器旋轉)
- }
- /* 回到主界面
- Retrurn to main interface */
- else
- {
- TR0 = 0; //清零定時器0溢出標志
- TF0 = 0; //定時器0停止計時,停止電池電壓信息更新計時
- WaveFreq = 0;
- TriFail = 0;
- VMax = 0;
- VMin = 0;
- DisplayUpdate = 1;
- WaveUpdate = 1;
- ClearWave = 0;
- }
- ADCInterrupt = 1;
- }
- /* 按住編碼器同時旋轉
- Rotate Encoder while pressing */
- else if (EC11PressAndRotate)
- {
- /* 由編碼器旋轉中斷執(zhí)行操作
- Operations Performed by Interrupt of Encoder Rotation */
- }
- /* 雙擊編碼器按鍵 - 在主界面,滾動波形和選項模式之間切換
- Double click Encoder - Switch between Waveform Scroll Mode and Parameter Mode in Main Interface */
- else if (Delay300ms_Double_Click())
- {
- /* 主界面
- Main Interface*/
- if (!InSettings)
- {
- WaveScroll = ~WaveScroll;
- OptionChanged = 1;
- ADCInterrupt = 1;
- DisplayUpdate = 1;
- ClearWave = 0;
- }
- }
- /* 單擊編碼器按鍵 - 在主界面,切換Stop/Run狀態(tài)
- Single click Encoder - Switch Run/Stop in main interface */
- else if (!InSettings)
- {
- EX0 = 0;
- ADCRunning = ~ADCRunning;
- if (ADCRunning)
- {
- WaveUpdate = 1;
- ClearWave = 1;
- }
- else
- {
- DisplayUpdate = 1;
- WaveUpdate = 1;
- }
- ADCInterrupt = 1;
- IE0 = 0;
- IE1 = 0;
- }
- }
- IE1 = 0;
- }
- /* 為更新Vbat計時
- Timer for updating Vbat */
- void TIMER0_interrupt(void) interrupt TIMER_0
- {
- static uint8 n;
- if (++n >= VBAT_UPDATE_FREQ)
- {
- n = 0;
- UpdateVbat = 1;
- DisplayUpdate = 1;
- }
- }
復制代碼
所有資料51hei附件下載(PCB與代碼):
MINI示波器2.0-LQFP48開源文件.7z
(4.83 MB, 下載次數(shù): 283)
2021-9-28 02:57 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|