017 数字示波表

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

制作名称:数字示波表
1、制作编号:017
2、难度等级:★★★(适合第4学期制作)
3、设计要求
1)用单片机STC12C5A60S2为主控芯片设计一数字示波表。

2)能对连续信号进行采集并实时显示,且具有锁存功能。

3)测量电压幅度范围在规定范围内,误差应控制在一定范围以内。

4)测量频率范围在规定范围内,误差应控制在一定范围以内。

5)用继电器控制电路来实现交直流藕合方式切换。

6)用3*4矩阵键盘实现一些控制操作。

如V/格、TIME/格的调节,交直流藕合方式的选择,屏幕的锁定等等。

7)LED电路来指示程序的运行状态。

8)用液晶模块显示波形。

9)系统用78和79系列三端集成稳压块提供所需稳定直流电压。

4、电路原理图
5、参考电路板图
6、元件说明
参考资料文件夹内PDF文件。

7、3D仿真图
8、制作实物照片
9、参考程序
/**此程序是采用ST7920为主控芯片的128*64LCD点阵屏(YM12864)MCU采用的是STC12C5A60S2构成的数字示波器。

128*64其实是256*32人为地将它分成上下两块.现在将12864分为X轴0-127列,Y轴0-63行,那么Y轴第0行和Y轴
第32行其实是共用了同一个Y地址,也就是Y轴0-31与32-63的Y地址都是0-31,不同的是X地址**/
#include <AT89X55.H>
#define uchar unsigned char
#define uint unsigned int
sfr P1ASF = 0x9d;
sfr ADC_CONTR = 0xbc;
sfr ADC_RES = 0xbd;
sfr ADC_RESL = 0xbe;
sfr AUXR1 = 0xa2;
sbit RS = P0^5;
sbit RW = P0^6;
sbit EN = P0^7;
sbit RET = P0^4;
sbit jdq = P1^4;
sbit fmq = P1^7;
sbit led1 = P1^5;
sbit led2 = P1^6;
sbit by = P2^7;
#define Dataport P2
uchar code key[]={0xe7,0xd7,0xb7,0x77,
0xed,0xdd,0xbd,0x7d,
0xee,0xde,0xbe,0x7e}; //0-11键值
uchar code tab1[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};//描点数组定义8个点的值
uchar tab2[128];
uchar tab3[16];
uchar freq,vv=4;
void nop()
{}
void delay(uint z)
{
uint x,y;
for(y=z;y>0;y--)
for(x=1495;x>0;x--);
}
void lcd_busy() //判忙{
RS=0;RW=1;Dataport=0xff;
while(1)
{
EN=1;
nop();
nop();
nop();
if(by==0)break;
EN=0;
}EN=0;
}
void wcomd(uchar c) //写命令{
lcd_busy();
RS=0;
RW=0;
EN=1;
nop();
nop();
nop();
Dataport=c;
EN=0;
}
void wdata(uchar d) //写数据
{
lcd_busy();
RS=1;
RW=0;
EN=1;
nop();
nop();
nop();
Dataport=d;
EN=0;
}
void RESET()
{
RET=0;
delay(1);
RET=1;
}
void lcd_init()
{
RESET();
wcomd(0x30); //功能设定(8位指令,基本功能)wcomd(0x04); //显示器控制
wcomd(0x01); //清屏
wcomd(0x0c); //整体显示
}
uchar ad()
{
uchar temp;
P1ASF=0x03; //P1.0,P1.1选为模拟量输入通道P1.0为1:1 P1.1为10:1
ADC_CONTR=0x80; //开启AD电源,AD通道选为1:1
ADC_CONTR=ADC_CONTR|freq; //TIME/格选择
nop();
ADC_CONTR=ADC_CONTR|0x08; //开始AD转换
while(1) //等待AD转换完成
{
temp=ADC_CONTR<<3;
temp=temp&0x80;
led2=0;
if(temp!=0)break;
nop();
}led2=1;
ADC_CONTR=ADC_CONTR&0xe0;
temp=ADC_RES;
/********if来实现量程的自动转换*********/
if(temp==0xff) //如果temp的值为FF则1:1通道的模拟值大于5V
{ //此时的值不准,需用10:1通道
ADC_CONTR=0x81; //开启AD电源,AD通道选为10:1
ADC_CONTR=ADC_CONTR|freq; //TIME/格选择
nop();
ADC_CONTR=ADC_CONTR|0x08; //开始AD转换
while(1) //等待AD转换完成
{
temp=ADC_CONTR<<3;
temp=temp&0x80;
if(temp!=0)break;
nop();
}
ADC_CONTR=ADC_CONTR&0xe1;
temp=ADC_RES;
}
return temp;
}
/*********清屏********/
//在送显示数据之前给全屏送0,清除全屏
void lcd_clr()
{
uchar i,k;
for(k=0;k<32;k++)
{
wcomd(0x80+k); //送Y地址
wcomd(0x80); //送X地址
for(i=0;i<16;i++) //送16个16位的数据,用的是X值会自加1的功能
{
wdata(0x00);
wdata(0x00);
}
}
}
/************写屏的一线数据*************/
//先写Y地址再写X地址(X地址会自加1)接着写16位的数据.
void lcd_xy(uchar x,uchar y,uchar data1,uchar data2)
{
if(y<32) //Y小于32表示要显示的部分在屏的下半部
{
wcomd(0x80+31-y); //写Y地址(0-31)0为最上一行31为最下一行
wcomd(0x88+x); //写X地址屏的下半部为88H-8FH
}else //Y大于32表示要显示的部分在屏的上半部
{
wcomd(0x80+63-y); //写Y地址(0-31)0为最上一行31为最下一行
wcomd(0x80+x); //写X地址屏的上半部为8班H-87H
}
wdata(data1);
wdata(data2);
}
/***********LCD显示子程序************/
//
void display()
{
uchar i,k,x,y,z,hh1,hh2,temp1;
lcd_init();
wcomd(0x34); //设置为扩展指令集绘图功能关
wcomd(0x01); //待命
lcd_clr(); //清屏
for(k=0;k<16;k++)tab3[k]=0; //全部清0,便于以后存数。

for(i=0;i<64;i++) //分别取出Y轴64个点
{
for(k=0;k<128;k++) //得到Y轴点的X地址
{
if(tab2[k]==i) //一行128个点分为8个区(0-7),每个区又分为2个位(0和1)
{ //128/16=8,
hh1=k/16; //得到区号
hh2=k%16; //得到位号(0和1)
temp1=tab1[k%8]; //得到位地址,到描点数组取值
if(hh2<8)tab3[hh1*2]=temp1|tab3[hh1*2];//0号位区
else
tab3[hh1*2+1]=temp1|tab3[hh1*2+1]; //1号位区
}temp1=0;hh1=0;hh2=0;
}
for(k=0;k<8;k++) //写一行数据
{
y=i; //y为垂直地址(也就是i值)
x=k; //x为水平地址(0-8)
z=k*2;
lcd_xy(x,y,tab3[z],tab3[z+1]);
}
for(k=0;k<16;k++)tab3[k]=0;//全部清0,便于下次存数。

}wcomd(0x36); //开显示
}
/**********键盘扫描子程序************/
//返回键值
uchar kkey()
{
uchar key1,key2,i;
P3=0xf0;
key1=P3;
if(key1!=0xf0)
{
delay(3);
key1=P3;
if(key1!=0xf0)
{
key2=key1;
P3=0x0f;
key1=P3;
key2=key2|key1;
key1=P3;
fmq=0;
delay(5);
fmq=1;
while(key1!=0x0f)key1=P3;
}
for(i=0;i<12;i++)
{
if(key2==key[i])break;
}
}return i;
}
/***********初始化子程序************/
void init()
{
EN=0;
RS=0;
RW=0;
lcd_init();
ADC_CONTR=0xe1; //打开AD转换电源
delay(5); //打开AD转换电源后需要延时一段时间}
void main()
{
uchar i,key1;
bit aa;
key1=0xff;
freq=0x60;
while(1)
{
init();
for(i=0;i<128;i++) //采集一行数据128个点
{
tab2[i]=ad()/vv; //幅值变换,将256个Y值变成64个改变VV 可以改变Y幅值
}
display(); //显示
key1=kkey(); //键盘扫描并取键值
/*******以下为键值的功能********/
//还有几个键没有给它定义功能
if(key1==1)jdq=~jdq; //交/直流藕合方式选择
if(key1==2)aa=1; //锁屏
if(key1==3)vv++; //幅值减小
if(key1==4)vv--; //幅值增加
/**********以下是四个A/D转换周期的选择**************/
if(key1==8)freq=0x60; //周期最短
if(key1==9)freq=0x40;
if(key1==10)freq=0x20;
if(key1==11)freq=0x00; //周期最长
key1=0xff; //键值清除
while(aa) //锁屏后执行
{
key1=kkey(); //键盘扫描且取键值
if(key1==2)aa=0; //取消锁屏
}
led1=0;
delay(70); //延时,让屏幕静态显示一段时间时间太短屏幕闪的看不太清。

led1=1;
}
}。

相关文档
最新文档