从网上找到一个用STC12C5A60S2制作示波器的程序,源程序为大道必成作品。由于手头上只有STC15F2K60S2,于是尝试用STC15F2K60S2+12864(KS0108版)制作示波器。程序中仅仅修改了管脚,按钮只装了T+、T-,能够出图,但是取样时间不准,测频时对波形也有干扰,测频也不准,50HZ测成了63HZ,如图所示。新手不知如何修改,还望大师指教。
制作出来的实物图如下:
本源程序由"大道必成"提供.
本人仅作些整理,及少许修改,本着开源精神,提供给大家学习.
Xushunfa
============================================================
一.系统构成
STC12C5A60S2单片机内部AD采样(10位采样,用高8位值);
LCD12864(驱动为SD7565)SPI方式显示波形.
LM393组成迟滞比较器,用于测量频率(不需要频率显示时该部分可以省略)(本案用TL072代替)
最大程度简化设计,信号通过电容直接进入单片机AD输入端(因没有放大电路,测不了太小的信号.)
小于100us/div(50/20/10)采用直接采样,软件延时.
大于等于100us/div采用定时器采样.
二.基本功能及使用说明
1.(X轴)时间/每格:10ms/5ms/2ma/1ms/500us/200us/100us/50us/20us/10us.(基本能显示20~25Kh信号)
2.(Y轴)电压/每格:1V/0.5V/0.2V/0.1V。
3.Hold功能:冻结后,波形左右平移共可显示4屏(含当前屏)波形.
4.有一路5Khz方波输出(由MCU的内部独立频率发生器产生),还有一路500hz方波输出(由PCA定时器产生)
5.正常运行时,会自动将最近运行的参数保存在Eeprom中,供下次开机时调用.
6.有"设置模式"(仅设置对比度).然后按"Grid"键,将"默认参数"及已调正好的"对比度值"重新写入Eeprom中.
7.如Eeprom中的数据丢失或出错,开机时会自动进入"设置模式".
8.如先按住"Hold键"不放,再上电开机就可进入"设置模式".
9.首次使用时,最好先进入"设置模式",将默认参数等写入Eeprom中.
10.无信号输入时,调整输入端的2M电位器使波形线处于Y轴的中心位置.
三.按键说明:
正常运行:
1.K1(HOLD)键:"波形冻结"与"正常显示"(解冻)切换.
短按:"冻结/解冻"切换,("冻结"状态下,左下角会显示Hold!字样).
长按:"自动/手动"切换,("自动"状态下,右上角会显示Auto字样).
2.K6(Grid)键:短按:坐标线样式切换(1.散点加坐标线;2.仅坐标线;3.仅散点;4.空白(四种样式轮流切换))。
长按:波形线"粗/细"切换
3.K2/K3(V+/V-)键:"电压/每格"调整.(1V/0.5V/0.2V/0.1V轮流切换)
4.K4/K5(T+/T-)键:"正常显示状态"时为"时间/每格"调整."波形冻结"状态时为"波形左右平移".
设置模式:
1.K2/K3(V+/V-)键:(短按)分别+/-调整对比度值.
2.K6(Grid)键:(短按)存入默认参数及当前的对比度值,并退出.
*/
单片机源程序如下:
- #include <stdio.h>
- #include <intrins.h>
- #include "ADC.h"
- #include "PCA.h"
- //#include "Chars.h"
- #include "EEPROM.h"
- #include "LCD12864(ks0108).h"
- #include "STC15.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初始化
- init_ks0108();
- // 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
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
简易示波器源程序stc15f2k60s2+12864(KS0108版)4ok.rar
(1.17 MB, 下载次数: 85)
|