dukedz 发表于 2009-6-19 08:33:08

通宵完成了一个玩具示波器。

图:


正在测量的是电脑声卡的输出。
屏幕左下方的是lm386,最下面的是lm358,它们和示波器无关,是以前实验时焊的。
带字库的12864用三线串行驱动。
大可调电阻是输入信号衰减用的。
大可调电阻正下方的俩按键是设置采样频率的。
旁边还有一个特别轻的轻触开关,需要按下它才刷新屏幕。如果要实时刷新的话就用重物压在上面。
估计能测20、30K左右。

lrving163 发表于 2009-6-19 08:51:25

不错。不知道能测试多少的频率?

浪漫人生 发表于 2009-6-19 10:10:12

做的不错.恭喜楼主.

diannaoyisheng 发表于 2009-6-19 10:45:41

回复 1# dukedz 的帖子

"旁边还有一个特别轻的轻触开关,需要按下它才刷新屏幕。如果要实时刷新的话就用重物压在上面。"
用带锁的按键,就用不着用重物压在上面了。

dukedz 发表于 2009-6-19 12:09:10

因为我既想把它当自锁开关、又想当轻触开关。:lol
该单片机AD采样最高不超过100Khz,所以测量频率很低。
打算暑假做个高速的。:lol

nnn2688 发表于 2009-6-19 12:11:48

楼主能不能献出电路和程序,也想做一个。:handshake

dukedz 发表于 2009-6-19 12:13:51

下面开始挂程序,很乱哦:

显示部分的子函数与对应头文件:

//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;
                }               
   }       
}        */

dukedz 发表于 2009-6-19 12:20:00

//主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);
                }
       
        }
}
//************************************************************完***********************

dukedz 发表于 2009-6-19 12:32:38

lcd误写为led,一直忘改,大家别笑我哦。
电路原理图:

shmu 发表于 2009-6-19 19:03:37

快乐毛毛虫 发表于 2009-6-19 22:51:26

实时速度不会太高,因为LCD写要花时间的。
只有带缓冲深度的才可以高速。

dukedz 发表于 2009-6-20 00:01:22

恩,是啊。
我这个是先扫描128次,扫描结果存到数组里。扫描完成后才调用显示。根本算不上实时。

快乐毛毛虫 发表于 2009-6-20 13:51:45

你可以扫描一点,显示一点的。低速的时候。

原帖由 dukedz 于 2009-6-20 00:01 发表 http://www.crystalradio.cn/bbs/images/common/back.gif
恩,是啊。
我这个是先扫描128次,扫描结果存到数组里。扫描完成后才调用显示。根本算不上实时。

浪漫人生 发表于 2009-6-21 08:14:43

楼主的示波器能提高测量的频率吗.

dukedz 发表于 2009-6-21 11:04:01

最快用28M的晶振能做到100K每秒的扫描次数,我没找到28M的晶振,用25M代替的。
如果想再快些,采用stc12c5a60s2系列,8路10位高速A/D转换,25万次每秒。
再想快的话,只好用外置的高速AD了。
页: [1] 2
查看完整版本: 通宵完成了一个玩具示波器。