OLED數字示波器 基于STC8A8K64S4A12單片機 原作者 老劉愛搗鼓 PCB板是在B站的一個大佬那下載然后改的 希望大家喜歡
功能.png (82.9 KB, 下載次數: 106)
下載附件
2020-10-17 14:12 上傳
Altium Designer畫的原理圖和PCB圖如下:(51hei附件中可下載工程文件)
51hei.png (18.61 KB, 下載次數: 130)
下載附件
2020-10-17 17:03 上傳
51hei.png (26.84 KB, 下載次數: 118)
下載附件
2020-10-17 17:03 上傳
51hei.png (3.28 KB, 下載次數: 138)
下載附件
2020-10-17 17:03 上傳
單片機源程序如下:
- 簡易示波器
- 版本:V0.3
- 作者:老劉愛搗鼓
- 單片機型:STC8A8K64S4A12 @27MHz
- 老劉愛搗鼓(全網同名)期待您的關注!
- B站教程(初版):https://www.bilibili.com/video/BV1ai4y1t79R
- B站教程(V0.3):https://www.bilibili.com/video/BV1ai4y1t79R
- 操作說明:
- 主界面-選項設置模式:
- 單擊編碼器:切換開始/暫停采樣
- 雙擊編碼器:切換波形水平滾動模式/選項設置模式
- 長按編碼器:進入設置界面
- 旋轉編碼器:修改當前參數
- 按下同時旋轉編碼器:在參數間切換
-
- 主界面-波形水平滾動模式:
- 單擊編碼器:切換開始/暫停采樣
- 雙擊編碼器:切換波形水平滾動模式/選項設置模式
- 長按編碼器:進入設置界面
- 旋轉編碼器:水平滾動波形(在暫停采樣狀態下有效)
- 按下同時旋轉編碼器:垂直滾動波形(僅在暫停采樣狀態下有效)
-
- 設置界面:
- 單擊編碼器:無效
- 雙擊編碼器:無效
- 長按編碼器:返回主界面
- 旋轉編碼器:修改當前選項
- 按下同時旋轉編碼器:切換選項
- 主界面參數:
- 橫軸時間區間:"500ms", "200ms", "100ms", "50ms", "20ms", "10ms","5ms", "2ms", "1ms", "500us", "200us", "100us"(100us僅在自動觸發模式下可用)
- 縱軸電壓區間:設定電壓量程上限,最大30V,順時針旋轉編碼器將電壓上限設置為0則進入自動量程,逆時針旋轉進入手動量程
- 觸發值:設定觸發電壓值,觸發位置被放在屏幕中心
- 觸發方向:上下箭頭,分別代表上升沿觸發和下降沿觸發
- 觸發方式:
- Auto(自動觸發) :連續采樣,指示燈始終點亮,通過單擊編碼器控制啟停;觸發成功時,觸發點位于屏幕中心,觸發失敗則波形無規律滾動,屏幕左側顯示Fail標志
- Normal(普通觸發):等待預采樣,待指示燈亮起表示預采樣結束,這時可以輸入信號;
- 觸發成功后,顯示波形,并繼續等待下次觸發;
- 如果有新的觸發成功,則自動顯示新的波形,如沒有新的觸發成功則屏幕波形保持并一直等待下次觸發;
- 需注意設置正確的觸發值,否則一直處于等待觸發狀態,屏幕不會顯示波形
- Single(單次觸發):等待預采樣,待指示燈亮起表示預采樣結束,這時可以輸入信號;
- 觸發成功后,顯示波形,并停止采樣,需用戶單擊編碼器開始下次采樣
- 需注意設置正確的觸發值,否則一直處于等待觸發狀態,屏幕不會顯示波形
-
- 主界面狀態顯示:
- Run:正在采樣
- Stop:停止采樣
- Fail:自動模式下,觸發值超出波形范圍引起觸發失敗
- Auto:自動量程
-
- 設置界面選項:
- PMode(繪圖模式):
- Vector:波形以矢量顯示
- Dots :波形以點陣顯示
- LSB(采樣系數):分壓系數的100倍,比如用10k加2k的電阻進行分壓,分壓系數為(10+2/2)=6,LSB理論取值為6x100=600,根據實際電阻精度進行微調
- BRT:OLED亮度
- 保存設置:長按編碼器退出設置界面時,設置界面和主界面的所有參數被保存到EEPROM
- 2020-04-30更新
- 1. 增加單次觸發和普通觸發功能,可自定義觸發點用來捕捉波形變化
- 2. 按照規格書要求將ADC采樣端口設置為高阻輸入
- 2020-5-3更新
- 1. 增加波形頻率顯示
- 2. 使用編碼器水平/垂直滾動波形
- 3. 使用編碼器垂直縮放波形
- 4. 用戶可設定觸發電平
- */
- #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 //電池電壓采樣分壓系數*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; //初始化觸發點位置
- TriPosOffset = 0; //初始化觸發點偏移量
- TriFail = 0; //清零觸發失敗標志
- VMax = 0; //清零波形電壓最大值
- VMin = 0; //清零波形電壓最小值
- WaveLengthSumNum = 0; //清零波形長度求和次數
- 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);
- }
- /* 更新參數
- Update parameters */
- if (DisplayUpdate)
- {
- DisplayUpdate = 0;
- PlotSettings();
- OLED_Display();
- }
- }
- /* 保存設置
- Save Settings */
- EA = 0;
- if (OptionChanged)
- {
- OptionChanged = 0;
- ClearDisplay = 0;
- /* 保存設置并顯示保存狀態
- 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;
- /* 分析緩存中完成采樣的采樣數據
- Analyse completed sampling data in buffer */
- AnalyseData();
- ClearDisplay = 1;
- /* 清空屏幕,繪制波形
- Clear display and draw waveform */
- if (ScaleH == ScaleH_tmp)
- {
- /* 采樣點數有限,不支持橫向縮放波形,只有時間區間與完成采樣的時間區間相同才繪制波形
- 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();
- }
- }
- /* 只更新屏幕上的參數,波形不變
- Update parameters on display only, keep waveform */
- else
- {
- ClearDisplay = 0;
- PlotChart();
- }
- OLED_Display();
- IE0 = 0;
- EX0 = 1;
- }
- }
- }
- }
- void runWhenADCComplete()
- {
- /* ADC采樣完成 - 單次觸發
- 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采樣完成 - 自動觸發或普通觸發
- ADC Sampling Complete - Auto or Normal Trigger Mode */
- else
- {
- //EX0 = 0;
- ClearDisplay = 1; //置位清空屏幕標志
- AnalyseData(); //分析采樣數據
- 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觸發方式,上升沿和下降沿
- PX0 = 1; //外部中斷0高優先級,可打斷按鍵中斷,用于判斷按下同時旋轉
- EX0 = 1; //開啟外部中斷0
- /* 編碼器按鍵外部中斷
- Interrupt for clicking of Encoder */
- IT1 = 1; //外部中斷1觸發方式,下降沿
- PX1 = 0; //外部中斷1低優先級
- 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)
- {
- /* 由編碼器旋轉中斷執行操作
- 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狀態
- 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提供下載:
老劉的示波器2.zip
(6.69 MB, 下載次數: 362)
2020-10-17 14:09 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
MiniDSO簡易示波器_老劉愛搗鼓.zip
(561.99 KB, 下載次數: 299)
2020-10-17 14:12 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|