通宵完成了一个玩具示波器。
图:正在测量的是电脑声卡的输出。
屏幕左下方的是lm386,最下面的是lm358,它们和示波器无关,是以前实验时焊的。
带字库的12864用三线串行驱动。
大可调电阻是输入信号衰减用的。
大可调电阻正下方的俩按键是设置采样频率的。
旁边还有一个特别轻的轻触开关,需要按下它才刷新屏幕。如果要实时刷新的话就用重物压在上面。
估计能测20、30K左右。 不错。不知道能测试多少的频率? 做的不错.恭喜楼主.
回复 1# dukedz 的帖子
"旁边还有一个特别轻的轻触开关,需要按下它才刷新屏幕。如果要实时刷新的话就用重物压在上面。"用带锁的按键,就用不着用重物压在上面了。 因为我既想把它当自锁开关、又想当轻触开关。:lol
该单片机AD采样最高不超过100Khz,所以测量频率很低。
打算暑假做个高速的。:lol 楼主能不能献出电路和程序,也想做一个。:handshake 下面开始挂程序,很乱哦:
显示部分的子函数与对应头文件:
//led12864.h:***************************************************************************
//extern void BMP_display(uchar bmptu[]);
//手動清屏(圖片模式)
//extern void BMP_clear();
//顯示字符串,第一個漢字的地址為0.
extern void LCD_String(unsigned char Addr,unsigned char *string);
extern void LCD_Init(void);
// LCD_COM(0x34);//切換到高級指令
// LCD_COM(0x36);//開畫圖
extern void LCD_delay(unsigned int yanshi);
extern void LCD_BUS(unsigned char adata,unsigned char LCD_S_RS);
//led12864.c:***************************************************************************
#include <reg52.h>
#include "led12864.h"
sbit LCD_CS=P1^4 ;//串口接法
sbit LCD_SID=P1^1;
sbit LCD_SCLK=P1^2;
void LCD_delay(unsigned int yanshi)
{
for(;yanshi>0;yanshi--);
}
//LCD_S_RS=0時為指令,反之。
void LCD_BUS(unsigned char adata,unsigned char LCD_S_RS)
{
unsigned char temps,c_flag,i;
unsigned char sdata1,sdata2,sdata3;
if(LCD_S_RS==0)sdata1=0x1f;//11111000(的反排序)
else sdata1=0x5f;//11111010(反序)
temps=adata;
temps=temps>>4;
sdata2=0;
for(i=0;i<4;i++)
{
c_flag = temps & 0x01;
if(c_flag == 0x01)
sdata2=(sdata2<<1)+1;
else
sdata2=(sdata2<<1);
temps=(temps>>1);
} //0000d4d5d6d7(反序)
temps=adata;
sdata3=0;
for(i=0;i<4;i++)
{
c_flag = temps & 0x01;
if(c_flag == 0x01)
sdata3=(sdata3<<1)+1;
else
sdata3=(sdata3<<1);
temps=(temps>>1);
} //0000d0d1d2d3(反序)
//開始發送數據
LCD_CS=1;
LCD_delay(5);
for(i=0;i<8;i++)
{
LCD_SID=sdata1&0x01;
LCD_SCLK=1;
LCD_delay(5);
LCD_SCLK=0;
sdata1=(sdata1>>1);
LCD_delay(10);
}
for(i=0;i<8;i++)
{
LCD_SID=sdata2&0x01;
LCD_SCLK=1;
LCD_delay(5);
LCD_SCLK=0;
sdata2=(sdata2>>1);
LCD_delay(10);
}
for(i=0;i<8;i++)
{
LCD_SID=sdata3&0x01;
LCD_SCLK=1;
LCD_delay(5);
LCD_SCLK=0;
sdata3=(sdata3>>1);
LCD_delay(10);
}
LCD_CS=0;
}
void LCD_Init()//必須先調用該程序進行初始化。
{
LCD_CS=0;
LCD_SCLK=0;
LCD_SID=0;
LCD_delay(3500);
LCD_BUS(0x30,0);
LCD_delay(3600);
LCD_BUS(0x30,0);
LCD_delay(360);
LCD_BUS(0x0c,0);
LCD_delay(336);
LCD_BUS(0x01,0);
LCD_delay(336);
LCD_BUS(0x06,0);
LCD_delay(360);
}
//顯示字符串,第一個漢字的地址為0.
void LCD_String(unsigned char Addr,unsigned char *string)
{
unsigned char wpoin;//字符指針
unsigned char wzijieshu;
wzijieshu=Addr*2;
if((Addr<=7))LCD_BUS(0x80+Addr,0);
if((Addr>=8)&&(Addr<=15))LCD_BUS(0x90+Addr-8,0);
if((Addr>=16)&&(Addr<=23))LCD_BUS(0x88+Addr-16,0);
if((Addr>=24)&&(Addr<=31))LCD_BUS(0x98+Addr-24,0);
if(Addr>31)return;
for(wpoin=0;(*(string+wpoin))!='\0';wpoin++)
{
if(wzijieshu==16)LCD_BUS(0x90,0);
if(wzijieshu==32)LCD_BUS(0x88,0);
if(wzijieshu==48)LCD_BUS(0x98,0);
if(wzijieshu==64)return;
LCD_BUS((*(string+wpoin)),1);//數據
wzijieshu++;
}
}
/*
//手動清屏(圖片模式)
void BMP_clear()
{
uchar i,j;
for(i=0;i<32;i++) //12864实际为256x32
{
LED_COM(0x80+i); //垂直坐標
LED_COM(0x80); //水平坐標
for(j=0;j<16;j++) //256/8=32 byte
{
LED_DATA(0);
LED_DATA(0);
}
}
}
void BMP_display(uchar bmptu[])
{uint bpoin;
uchar i,j;
bpoin=0;
//上半屏
for(i=0;i<32;i++) //12864实际为256x32
{
LED_COM(0x80+i); //垂直坐標
LED_COM(0x80); //水平坐標
for(j=0;j<8;j++) //256/8=32 byte
{
LED_DATA(bmptu);
LED_DATA(bmptu);
bpoin+=2;
}
}
//下半屏
for(i=0;i<32;i++) //12864实际为256x32
{
LED_COM(0x80+i); //垂直坐標
LED_COM(0x88); //水平坐標
for(j=0;j<8;j++) //256/8=32 byte
{
LED_DATA(bmptu);
LED_DATA(bmptu);
bpoin+=2;
}
}
} */ //主C文件*************************************************************************************
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
#include"led12864.h"
//ad
sfr P1M0=0x91;//设置stc12的io口模式用
sfr P1M1=0x92;
sfr ADC_CONTR=0xC5;//AD控制
sfr ADC_DATA=0xC6;//AD结果
sbit Key=P3^4;//轻触开关 刷新屏幕
sbit Key_up =P3^2;//设置采样频率
sbit Key_down=P3^3;//……
uchar code Num_Table[]="0123456789";
uchar Num_Disp[]="---";//显示当前采样频率
uchar xdata AD_Table;//存放AD结果
uchar AD_Table_pi;//AD_Table的指针
bit MODES; //0:AD采集;1:屏幕显示
uchar xdata Disp_Table1;//显示中转
uchar xdata Disp_Table2;//显示中转
uint saomiao;//扫描延时
uint caiyang;//采样频率的设置变量
void main_delay(uint delays)
{
for(;delays>0;delays--);
}
//手動清屏(圖片模式)
void BMP_clear()
{
uchar i,j;
for(i=0;i<32;i++) //12864实际为256x32
{
LCD_BUS(0x80+i,0); //垂直坐標
LCD_BUS(0x80,0); //水平坐標
for(j=0;j<16;j++) //256/8=32 byte
{
LCD_BUS(0x00,1);
LCD_BUS(0x00,1);
}
}
}
void WaveDisplay() // Disp_Table1
{
uchar i,j;
uchar temp_i;
LCD_BUS(0x34,0);//切换到扩充指令
LCD_BUS(0x36,0);//在扩充指令下打开绘图开关
BMP_clear();
/* AD_Table=0;//产生一条斜线加横线(测试用)
for(temp_i=0;temp_i<128;temp_i++)
{if(temp_i>0)
if(AD_Table<43)
AD_Table=AD_Table+1;
else
AD_Table=45;
}*/
for(j=0;j<8;j++)
{
for(temp_i=0;temp_i<64;temp_i++)
{
Disp_Table1=0x00;
Disp_Table2=0x00;
}
//
for(temp_i=0;temp_i<8;temp_i++)
{
Disp_Table1]=Disp_Table1]|(0x80>>temp_i);//0x80=1000'0000;
}
for(temp_i=0;temp_i<8;temp_i++)
{
Disp_Table2]=Disp_Table2]|(0x80>>temp_i);//0x80=1000'0000;
}
for(i=0;i<32;i++) //12864实际为256x32
{
LCD_BUS(0x80+i,0); //垂直坐標
LCD_BUS(0x80+j,0); //水平坐標
LCD_BUS(Disp_Table1,1);
LCD_BUS(Disp_Table2,1);
}
for(i=0;i<32;i++) //12864实际为256x32
{
LCD_BUS(0x80+i,0); //垂直坐標
LCD_BUS(0x80+8+j,0); //水平坐標
LCD_BUS(Disp_Table1,1);
LCD_BUS(Disp_Table2,1);
}
}
LCD_BUS(0x30,0);//从扩充指令切换到基本指令(并关绘图)
}
void RunAD(void) interrupt 1
{
if(saomiao>=caiyang)
{
ADC_CONTR=0xE8;//11101000 ;启动AD转换
while(ADC_CONTR&0x10==0x00);//等待ADC_FLAG置1
if(ADC_DATA<64)AD_Table=ADC_DATA;
else AD_Table=63;
if(AD_Table_pi<127)AD_Table_pi++;
else
{
AD_Table_pi=0;
MODES=1;
EA=0;//关中断
}
saomiao=0;
}
saomiao++;
}
void main()
{
//ad initial
P1M0=0x01;//0000'0001 //P1.3做AD(高阻)
P1M1=0x16;//0001'0110 //lcd(P1.0-P1.2)推挽
// ADC_CONTR=0xE0;//11100000 ;P1.7做AD输入,AD速度最高
main_delay(20000);//AD上电延时
//Timer0 initial
TMOD=0x02;//模式2:自动装载的8位定时器
TH0=0xff;//自动装载值
ET0=1;//open timer0 int
TR0=1;//启动定时器0
//
MODES=0; //0:AD采集;1:屏幕显示
AD_Table_pi=0;
//
LCD_Init();
LCD_String(3,"twins");
EA=1;//open globle int
AD_Table_pi=0;
while(1)
{
if(MODES==1)//显示波形
{
WaveDisplay();
MODES=0;
}
if(Key==0)//按键被按下
{
MODES=0;//切换到AD
EA=1;//重新开中断
}
if(Key_up==0)
{
if(caiyang<2000)caiyang++;
Num_Disp=Num_Table;
Num_Disp=Num_Table[(caiyang%100)/10];
Num_Disp=Num_Table;
LCD_String(6,Num_Disp);
main_delay(6000);
}
if(Key_down==0)
{
if(caiyang>0)caiyang--;
LCD_String(3,"twins");
Num_Disp=Num_Table;
Num_Disp=Num_Table[(caiyang%100)/10];
Num_Disp=Num_Table;
LCD_String(6,Num_Disp);
main_delay(6000);
}
}
}
//************************************************************完*********************** lcd误写为led,一直忘改,大家别笑我哦。
电路原理图:
实时速度不会太高,因为LCD写要花时间的。
只有带缓冲深度的才可以高速。 恩,是啊。
我这个是先扫描128次,扫描结果存到数组里。扫描完成后才调用显示。根本算不上实时。 你可以扫描一点,显示一点的。低速的时候。
原帖由 dukedz 于 2009-6-20 00:01 发表 http://www.crystalradio.cn/bbs/images/common/back.gif
恩,是啊。
我这个是先扫描128次,扫描结果存到数组里。扫描完成后才调用显示。根本算不上实时。 楼主的示波器能提高测量的频率吗. 最快用28M的晶振能做到100K每秒的扫描次数,我没找到28M的晶振,用25M代替的。
如果想再快些,采用stc12c5a60s2系列,8路10位高速A/D转换,25万次每秒。
再想快的话,只好用外置的高速AD了。
页:
[1]
2