一、系統構成
STC12C5A60S2單片機內部AD采樣;LCD12864顯示波形;LM393組成遲滯比較器測量小信號頻率,不需要頻率顯示時該部分可以省略。
為最大程度簡化設計,信號通過電容直接進入單片機AD輸入端,無輸入時,通過調整R10使波形處于中心線位置即可。
二、基本功能
1、時間每格:10ms/5ms/2ma/1ms/500us/200us/100us/50us/20us;灸茱@示20~20Kh信號。
2、電壓每格:1V/0.5V/0.2V。
3、HOLD功能:凍結波形后,左右平移能顯示共4屏(含當前屏)波形。
4、自帶一路5Khz方波輸出。
5、用戶設置參數斷電保持。該功能對電源電壓穩定性要求較高,欠壓或過壓參數會被沖掉或不能正常開機。
三、使用說明
1、K6按鍵,坐標線樣式轉換:(1)散點加坐標線,該樣式參考了上一屆DIY大賽吳老師的示波器顯示樣式;(2)僅有坐標線;(3)空白。三種樣式輪流切換。
2、K1按鍵,波形凍結與正常顯示切換。波形凍結狀態下,左下角顯示頻率的地方會顯示HOLD MODE。
3、K2/K3,每格電壓值調整,1V/0.5V/0.2V輪流切換。
4、K4/K5,正常顯示時,調整每格時間;波形凍結后,實現波形平移。所以在波形凍結狀態下是不能調節時間的!
實物圖:
實物.png (725.98 KB, 下載次數: 121)
下載附件
2018-5-17 02:21 上傳
8.png (342.63 KB, 下載次數: 113)
下載附件
2018-5-17 02:21 上傳
7.png (399.1 KB, 下載次數: 111)
下載附件
2018-5-17 02:21 上傳
6.png (273.92 KB, 下載次數: 102)
下載附件
2018-5-17 02:21 上傳
5.png (254.74 KB, 下載次數: 108)
下載附件
2018-5-17 02:21 上傳
4.png (327.16 KB, 下載次數: 128)
下載附件
2018-5-17 02:21 上傳
3.png (355.77 KB, 下載次數: 94)
下載附件
2018-5-17 02:21 上傳
2.png (279.55 KB, 下載次數: 117)
下載附件
2018-5-17 02:21 上傳
1.png (460.44 KB, 下載次數: 113)
下載附件
2018-5-17 02:21 上傳
電路原理圖如下:
0.png (147.45 KB, 下載次數: 111)
下載附件
2018-5-17 02:20 上傳
0.png (25.75 KB, 下載次數: 94)
下載附件
2018-5-17 02:20 上傳
單片機源程序如下:
- #include <stdio.h>
- #include <intrins.h>
- #include "ADC.h"
- #include "PCA.h"
- #include "Chars.h"
- #include "EEPROM.h"
- #include "LCD12864.h"
- #include "STC12C5A60S2.h"
- //時間/每格3-10ms 4-5ms 5-2ms 6-1ms 7-500us 8-200us 9-100us 10-50us 11-20us 12-10us
- unsigned char timpd;
- unsigned char volpd; //示波器 電壓/每格 1--1V/d,2--0.5V/d,3--0.2V/d
- unsigned long freqin; //示波器輸入的信號頻率,單位Hz
- unsigned int T1count; //T1定時器,頻率計數
- unsigned int PCA0loop; //PCA0循環初值
- unsigned int PCA1loop; //PCA1循環初值
- unsigned int PCA0count; //PCA0計時累計
- unsigned int PCA1count; //PCA1循環遞增值,即輸出方波周期/2.5
- unsigned int samptime; //采樣時間,即定時器0的初值
- unsigned int T0count; //定時器采樣時間間隔計數
- unsigned int index; //每次采樣的wave0數組下標
- unsigned int shiftindex; //移位時數組下標位置
- unsigned char hold; //hold鍵標志位
- unsigned char autotim; //是否根據頻率自動選擇時間每格,是=1,否=其它
- unsigned char shift; //hold狀態移位標志位。1、左移;2、右移
- //unsigned char grid; //點格樣式
- unsigned char shap; //波形失真修正,上下輪流顯示
- unsigned char ROMEN; //需要寫EEPROM時=0x55;不需要=其它
- unsigned char EEPROM[5]; //四字節掉電保存數據,點格樣式,時間/每格,電壓/每格,波形樣式,自動選時間檔
- unsigned char idata wave[127]; //當前顯示數組
- unsigned char xdata wave0[512]; //采樣數組,處于不斷更新狀態
- unsigned char xdata wavep[512]; //顯示及HOLD緩存數組
- //******************************************************************//
- //小于100us/div(50/20/10)采用直接采樣,軟件延時
- //大于等于100us/div采用定時器采樣
- //******************************************************************//
- void main(void)
- {
- unsigned char disp; //disp顯示刷新標志位
- unsigned char grid; //點格樣式
- unsigned char wavemode; //波形樣式
- // unsigned char volmax;
- unsigned int i,j;
- unsigned int delaybtn; //按鍵消抖延時
- unsigned long int delay,delaymin,freqauto;
- disp=0;
- freqin=0;
- autotim=0; //默認設置,手動
- timpd=8; //默認設置200us/div
- volpd=1; //默認設置1V/div
- index=0; //賦值0非常重要
- shiftindex=0;
- T0count=0;
- T1count=0;
- PCA0loop=50000; //PCA0定時20ms //不分頻時PCA0loop=62500; 480個周期1s
- PCA0count=0;
- //PCA1loop=15000; //PCA1(P1.4)輸出500Hz方波(產生LCD負壓),本程序沒開啟
- //PCA1count=15000;
- hold=0;
- shift=0;
- grid=1; //默認設置,坐標線
- wavemode=1; //默認設置,粗線;=2細線
- samptime=0xfee3; //精確延時100us,此值嚴禁任何改動samptime=0xfee2;
- EEPROM[0]=grid;
- EEPROM[1]=timpd;
- EEPROM[2]=volpd;
- EEPROM[3]=wavemode;
- EEPROM[4]=autotim;
- ROMEN=0x55; //臨時測試,正式必須=0;
- //M1/M0:00弱上拉,01強推挽,10輸入(高阻),11開漏
- P0M1=0x00;P0M0=0x00; //
- P1M1=0xee;P1M0=0x11; //P1.0/P1.4推挽輸出,其余設為輸入
- P2M1=0x00;P2M0=0x00; //
- P3M1=0x00;P3M0=0x00; //
- init_st7565(); //12864初始化
- dispchar16(1,8,16,7,HZ1); //開機LOGO
- write_string8(3,16,"www.crystalradio.cn");
- dispchar16(5,10,12,9,HZ2);
- ADCinit();
- timerinit();
- PCAinit();
- //for(i=500;i>0;i--)for(j=5000;j>0;j--); //延時1
- IAPReadData(0,5,EEPROM); //讀取上一次關機前最后的用戶設置
- if((EEPROM[0]>=0)&&(EEPROM[0]<=2)&&(EEPROM[1]>=3)&&(EEPROM[1]<=16)
- &&(EEPROM[2]>=1)&&(EEPROM[2]<=4)&&(EEPROM[3]>=1)&&(EEPROM[3]<=2)&&(EEPROM[4]==0)||(EEPROM[4]==1))
- { //讀取到合法設置則賦值,否則顯示默認設置
- grid=EEPROM[0];
- timpd=EEPROM[1];
- volpd=EEPROM[2];
- wavemode=EEPROM[3];
- autotim=EEPROM[4];
- }
-
- //for(i=500;i>0;i--)for(j=5000;j>0;j--); //延時2
- disp_grid(grid); //顯示網格
- disp_osc_settings(); //顯示示波器設置
- while(1)
- {
- //---------------------1、采樣-----------------------//
- //按了HOLD鍵,采樣繼續,但不允許對wavep緩存數組更新
- if(hold==0)
- {
- switch(timpd)
- {
- case 3:
- case 4: //5ms/div
- case 5: //2ms/div
- case 6: //1ms/div
- case 7: //500us/div
- case 8: //200us/div
- case 9: //100us/div
- {
- TR0=1;ET0=1;
- if(index>=511)
- {
- for(i=0;i<512;i++)
- {
- wavep[i]=wave0[i];
- }
- index=0; //采樣下一組數據
- disp=1; //刷新標志置位
- }
- break;
- }
- case 10: //50us/div
- {
- TR0=0;ET0=0;
- for(i=0;i<512;i++) //50us/div
- {
- wavep[i]=getADC(1);
- _nop_();_nop_();
- _nop_();_nop_();
- }
- disp=1; //刷新標志置位
- break;
- }
- case 11: //20us(40us插值得來)
- {
- TR0=0;ET0=0;
- fastADC();
- for(i=0;i<512;i++) //賦值(包含插值運算)
- {
- if(!(i%2))
- {wavep[i]=wave0[i/2];}
- else
- {wavep[i]=(unsigned int)(wave0[i/2]+wave0[i/2+1])/2;}
- }
- disp=1; //刷新標志置位
- break;
- }
- case 12: //10us(40us兩次插值得來)
- {
- TR0=0;ET0=0;
- fastADC();
- for(i=0;i<512;i++) //賦值(包含插值運算)
- {
- if(!(i%2))
- {wavep[i]=wave0[i/2];}
- else
- {wavep[i]=(unsigned int)(wave0[i/2]+wave0[i/2+1])/2;}
- }
- for(i=0;i<512;i++) //賦值(包含插值運算)
- {
- wave0[i]=wavep[i];
- }
- for(i=0;i<512;i++) //賦值(包含插值運算)
- {
- if(!(i%2))
- {wavep[i]=wave0[i/2];}
- else
- {wavep[i]=(unsigned int)(wave0[i/2]+wave0[i/2+1])/2;}
- }
- disp=1; //刷新標志置位
- break;
- }
- }//switch(timpd)采樣結束
- }
- //-------------------2-1:波形觸發處理-----------------//
- if((disp==1)&&(hold==0)) //接收到新數據且正常顯示時才處理
- {
- for(i=2;i<127;i++)
- {
- if( (((signed int)wavep[i-2]-127)<=0)&&(((signed int)wavep[i-1]-127)<=0)//&&(((signed int)wavep[i]-127)<=0)
- &&(((signed int)wavep[i+1]-127)>=0)&&(((signed int)wavep[i+2]-127)>=0)&&(((signed int)wavep[i+3]-127)>0) )
- {
- shiftindex=i;
- break;
- }
- }
- }//if((disp==1)&&(hold==0))波形觸發處理結束
- //-------------------2-2:HOLD狀態移位處理-----------------//
- if(hold==1)
- {
- if(shift==2) //左移
- {
- shiftindex=shiftindex+9;
- if((shiftindex+126)>=512)
- {
- shiftindex=shiftindex-9;
- }
- }
- if(shift==1) //右移
- {
- shiftindex=shiftindex-9; //注意無符號數
- if(shiftindex>512) //相當于判斷小于0
- {
- shiftindex=shiftindex+9;//防止無限遞減
- }
- }
- }
- //-------------------3、電壓衰減處理-----------------//
- switch(volpd) //此部分余數計算可能有問題,需改進
- {
- case 1: //1v/div
- {
- for(i=0;i<127;i++)
- {
- if(((signed int)wavep[i+shiftindex]>=127))
- {
- if(((wavep[i+shiftindex]-127)*35/256)<128)
- wave[i]=(unsigned int)(wavep[i+shiftindex]-127)*35/256+28;
- else
- wave[i]=(unsigned int)(wavep[i+shiftindex]-127)*35/256+29;
- }
- else
- {
- if(((127-wavep[i+shiftindex])*35/256)<128)
- wave[i]=27-(unsigned int)(127-wavep[i+shiftindex])*35/256;
- else
- wave[i]=26-(unsigned int)(127-wavep[i+shiftindex])*35/256;
- }
- }
- break;
- }
- case 2: //0.5v/div
- {
- for(i=0;i<127;i++)
- {
- if(((signed int)wavep[i+shiftindex]>=127))
- {
- if(((wavep[i+shiftindex]-127)*35/128)<64)
- wave[i]=(unsigned int)(wavep[i+shiftindex]-127)*35/128+28;
- else
- wave[i]=(unsigned int)(wavep[i+shiftindex]-127)*35/128+29;
- }
- else
- {
- if(((127-wavep[i+shiftindex])*35/128)<64)
- wave[i]=27-(unsigned int)(127-wavep[i+shiftindex])*35/128;
- else
- wave[i]=26-(unsigned int)(127-wavep[i+shiftindex])*35/128;
- //注意 要防止顯示越界@@@@@@@@@@@@@@@@3(見LCD12864.c)
- if(wave[i]>27)wave[i]=0; //防止超出LCD12864顯示邊界
- }
- }
- break;
- }
- case 3: //0.2v/div
- {
- for(i=0;i<127;i++)
- {
- if(((signed int)wavep[i+shiftindex]>=127))
- {
- if(((wavep[i+shiftindex]-127)*35/51)<26)
- wave[i]=(unsigned int)(wavep[i+shiftindex]-127)*35/51+28;
- else
- wave[i]=(unsigned int)(wavep[i+shiftindex]-127)*35/51+29;
- //if(wave[i]>56)wave[i]=56;
- }
- else
- {
- if(((127-wavep[i+shiftindex])*35/51)<26)
- wave[i]=27-(unsigned int)(127-wavep[i+shiftindex])*35/51;
- else
- wave[i]=26-(unsigned int)(127-wavep[i+shiftindex])*35/51;
- if(wave[i]>27)wave[i]=0; //防止超出LCD12864顯示邊界
- }
- }
- break;
- }
- case 4: //0.1v/div
- {
- for(i=0;i<127;i++)
- {
- if(((signed int)wavep[i+shiftindex]>=127))
- {
- if(((wavep[i+shiftindex]-127)*70/51)<26)
- wave[i]=(unsigned int)(wavep[i+shiftindex]-127)*70/51+28;
- else
- wave[i]=(unsigned int)(wavep[i+shiftindex]-127)*70/51+29;
- //if(wave[i]>56)wave[i]=56;
- }
- else
- {
- if(((127-wavep[i+shiftindex])*70/51)<26)
- wave[i]=27-(unsigned int)(127-wavep[i+shiftindex])*70/51;
- else
- wave[i]=26-(unsigned int)(127-wavep[i+shiftindex])*70/51;
- if(wave[i]>27)wave[i]=0; //防止超出LCD12864顯示邊界
- }
- }
- break;
- }
- }//switch(volpd)電壓衰減處理結束
-
- //---------------------4、波形顯示-------------------//
- if((disp==1)&&(hold==0)) //正常顯示
- {
- TR0=0;ET0=0; //刷新過程不允許中斷
- if(ROMEN==0x55)
- {
- EEPROM[0]=grid;
- EEPROM[1]=timpd;
- EEPROM[2]=volpd;
- EEPROM[3]=wavemode;
- EEPROM[4]=autotim;
- IAPWriteData(0,5,EEPROM);
- ROMEN=0;
- }
- if(wavemode==1){dispwave2(grid);} //矢量圖
- if(wavemode==2){dispwave(grid);} //散點圖
- if(autotim==1)write_string8(3,106,"Auto");
- disp=0; //刷新標志清零
- index=0; //刷新后重新采樣
- TR0=1;ET0=1;
- }
- if(hold==1) //HOLD狀態的顯示
- {
- if(wavemode==1){dispwave2(grid);} //矢量圖
- if(wavemode==2){dispwave(grid);} //散點圖
- if(autotim==1)write_string8(3,106,"Auto");
- for(i=40;i>0;i--) //顯示延時
- {
- for(j=1200;j>0;j--);
- //if(P1&0x38)break; //有按鍵按下提前退出延時循環
- }
- }
-
- //---------------5、按鍵處理及顯示延時---------------//
- shift=0; //按鍵處理前清移位標志位
- if(wavemode==1) //矢量顯示延時小
- {
- if(timpd==3){i=1;}
- else if(timpd==4){i=2;}
- else {i=30;}
- }
- if(wavemode==2) //散點顯示延時大
- {
- if(timpd==3){i=1;}
- else if(timpd==4){i=2;}
- else {i=120;}
- }
- for(;i>0;i--) //散點顯示刷新i=120
- {
- //不同采樣率采用不同延時,以得到相同刷新率
- switch(timpd)
- {
- case 3:{j=1;delaymin=180000;delaybtn=60000;break;} //10ms/div
- case 4:{j=1;delaymin=140000;delaybtn=60000;break;} //5ms/div
- case 5:{j=100;delaymin=120000;delaybtn=40000;break;} //2ms/div
- case 6:{j=200;delaymin=120000;delaybtn=40000;break;} //1ms/div
- case 7:{j=400;delaymin=90000;delaybtn=30000;break;} //500us/div
- case 8:{j=200;delaymin=60000;delaybtn=20000;break;} //200us/div
- case 9:{j=120;delaymin=30000;delaybtn=10000;break;} //100us/div
- case 10:{j=1000;delaymin=250000;delaybtn=80000;break;} //50us/div
- case 11:{j=1000;delaymin=250000;delaybtn=80000;break;} //20us(40us插值得來)
- case 12:{j=1000;delaymin=250000;delaybtn=80000;break;} //10us(40us兩次插值得來)
- }
- for(;j>0;j--); //內層循環延時
- //--------按鍵處理--------//
- //--1、HOLD鍵--//
- if((P3&0x04)==0)
- {
- for(;delaybtn>0;delaybtn--);
- if((P3&0x04)==0)
- {
- delay=0;
- if(hold==1){delaymin*=3;}//hold模式定時器全關,按鍵檢測加長延時
- while((P3&0x04)==0)
- {
- delay++;
- }
- if(delay<delaymin)
- {
- if(hold==0){hold=1;TR0=0;ET0=0;}
- else{hold=0;TR0=1;ET0=1;}
- }
- else
- {
- if(hold==0) //hold模式下不切換自動手動
- {
- if(autotim==1){autotim=0;}
- else {autotim=1;}
- ROMEN=0x55;
- }
- }
- }
- }
- //--2、時間++/左移鍵--//
- if((P3&0x08)==0)
- {
- if(hold==0) //正常顯示,時間++
- {
- for(;delaybtn>0;delaybtn--);
- if((P3&0x08)==0)
- {
- while((P3&0x08)==0);
- index=0; //調整時間后必須重新采樣
- timpd--;
- ROMEN=0x55;
- if(timpd<3){timpd=12;}
- }
- }
- if(hold==1) //HOLD狀態,波形左移
- {
- for(j=50000;j>0;j--);
- if((P3&0x08)==0)
- {
- shift=1;break;
- }
- }
- }
- //--3、時間--/右移鍵--//
- if((P3&0x80)==0) //時間--
- {
- if(hold==0) //正常顯示,時間++
- {
- for(;delaybtn>0;delaybtn--);
- if((P3&0x80)==0)
- {
- while((P3&0x80)==0);
- index=0;
- timpd++;
- ROMEN=0x55;
- if(timpd>12)timpd=3;
- }
- }
- if(hold==1) //HOLD狀態,波形左移
- {
- for(j=50000;j>0;j--);
- if((P3&0x80)==0)
- {
- shift=2;break;
- }
- }
- }
- //--4、//電壓++--//
- if((P3&0x40)==0) //電壓++
- {
- for(;delaybtn>0;delaybtn--);
- if((P3&0x40)==0)
- {
- while((P3&0x40)==0);
- volpd++;
- if(volpd>4)volpd=1;
- if(hold==0){ROMEN=0x55;}
- }
- }
- //--5、//電壓----//
- if((P3&0x10)==0) //電壓--
- {
- for(;delaybtn>0;delaybtn--);
- if((P3&0x10)==0)
- {
- while((P3&0x10)==0);
- volpd--;
- if(volpd<1)volpd=4;
- if(hold==0){ROMEN=0x55;}
- }
- }
- //--6、點格樣式切換/線形切換--//
- if((P1&0x80)==0) //點格樣式切換
- {
- for(;delaybtn>0;delaybtn--);
- if((P1&0x80)==0)
- {
- delay=0;
- if(hold==1){delaymin*=3;}//hold模式定時器全關,按鍵檢測加長延時
- while((P1&0x80)==0)
- {
- delay++;
- }
- if(delay<delaymin)
- {
- grid++;
- if(grid>3)grid=0;
- if(hold==0){ROMEN=0x55;}
- }
- else
- {
- wavemode++;
- if(wavemode>2)wavemode=1;
- if(hold==0){ROMEN=0x55;}
- }
- }
- }
- }//for()按鍵處理end
- //---------------6、根據頻率自動選擇采樣時間---------------//
- if(autotim==1)
- {
- if(freqauto==freqin)
- {
- if((freqin>5)&&(freqin<20)){timpd=3;}
- else if((freqin>=20)&&(freqin<45)){timpd=4;}
- else if((freqin>=45)&&(freqin<120)){timpd=5;}
- else if((freqin>=120)&&(freqin<220)){timpd=6;}
- else if((freqin>=220)&&(freqin<500)){timpd=7;}
- else if((freqin>=500)&&(freqin<1200)){timpd=8;}
- else if((freqin>=1200)&&(freqin<2200)){timpd=9;}
- else if((freqin>=2200)&&(freqin<5000)){timpd=10;}
- else if((freqin>=5000)&&(freqin<12000)){timpd=11;}
- else if(freqin>=12000){timpd=12;}
- }
- else
- {
- freqauto=freqin;
- }
- //volmax=0;
- //for(j=0;j<512;j++)
- //{
- // if(wavep[j]>volmax){volmax=wavep[i];}
- //}
- //if(volmax>187){volpd=1;}
- //else if(volmax>151){volpd=2;}
- //else if(volmax>135){volpd=3;}
- //else if(volmax>127){volpd=4;}
- }
- }//while(1)-end
- //*/
- }
- /*
- //-------------------3、電壓衰減處理-----------------//
- switch(volpd) //此部分余數計算可能有問題,需改進
- {
- case 1: //1v/div
- {
- for(i=0;i<127;i++)
- {
- if(((signed int)wavep[i+shiftindex]>=127))
- {
- if(((wavep[i+shiftindex]-127)*35/256)<128)
- wave[i]=(unsigned int)(wavep[i+shiftindex]-127)*35/256+28;
- else
- wave[i]=(unsigned int)(wavep[i+shiftindex]-127)*35/256+29;
- }
- else
- {
- if(((127-wavep[i+shiftindex])*35/256)<128)
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
0.jpg (24.01 KB, 下載次數: 109)
下載附件
2018-5-17 02:20 上傳
所有資料51hei提供下載:
51單片機簡單示波器.rar
(3.55 MB, 下載次數: 331)
2018-5-16 21:57 上傳
點擊文件名下載附件
51單片機簡單示波器 下載積分: 黑幣 -5
|