基于STM32的简易示波器设计

疫情期间闲来无事,正好学习STM32F407,因此设计、制作了简易示波器,以助学习。长话短说方案如下:

(1)单片机,选择STM32F407VET6,采用SWD方式仿真及程序烧写。五路独立按键和两个LED指示灯。使用ADC1/通道5/PA5。细见附件原理图。

(2)程控放大电路,使用继电器和运放组成,实现不同放大倍数。如下:

(3)显示面板采用3.2寸TFT液晶屏。使用FSMC接口,9341驱动。

(4)串口通信,用于与上位机通信,实现虚拟示波器功能。

2、PCB设计

见下图:

3软件设计

软件大体分为四部分:

(1)软件主体框架,主要包括单片机基本软件部分、LED、按键等功能实现

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
    delay_init(168);      //初始化延时函数
    LED_Init();                   //初始化LED
    i=LCD_Init();           //初始化LCD FSMC接口
    /*<24C02初始化>*/
    AT24CXX_Init(); 
    delay_ms(1);
    i=5;
    while(i--)
    {
        n8tmp=AT24CXX_Check();
        if(n8tmp==0) 
        {
            break;
        }
        delay_ms(1);
    }
    Adc_Init();         //初始化ADC

    /*<定时器初始化>*/
    TIM5_Int_Init(4-1,21-1);// 0.001ms
    UART2_Init(115200);//   
    // DMA1_Config(DMA1_Stream4,DMA_Channel_4,(u32)&UART4->DR,(u32)BUF4,SENTDATA_LEN2);//串口4DMA发送初始化
    DMA1_Config(DMA1_Stream6,DMA_Channel_4,(u32)&USART2->DR,(u32)BUF2,SENTDATA_LEN2);//串口2DMA发送初始化

(2)程控电路,通过按键控制继电器实现放大倍数变化

        处理部分

if(KEY1==0||KEY2==0||KEY3==0||KEY4==0||KEY5==0)
        {
            BEEP=1;
            delay_ms(10);
            if(KeyDown==0)
            {
            Key_Got=1;
            if(KEY1==0) 
            {KEY_NUM=1;
            stimeradd();
            KeyDown=1;
            }
            else if(KEY2==0) 
            {KEY_NUM=2;
            KeyDown=1;
            stimersub();
            }
            else if(KEY3==0) 
            {KEY_NUM=3;
            OKpchage(1);
            KeyDown=1;
            }
            else if(KEY4==0) {
                KEY_NUM=4;
                OKpchage(0);
                KeyDown=1;
            }
            else if(KEY5==0) 
            {KEY_NUM=5;
                spmark=!spmark;
                KeyDown=1;
            }
            else KEY_NUM=0;
            }

        }
        else
        {
            KeyDown=0;
        }

程控函数:

float Kbc=1;//1.538F;
void OKpchage(u8 ca)
{
    static u8 nKv=7;
    if(ca)
    {
        // 增加每格电压
        if(nKv<7)nKv++;
    }
    else
    {
        if(nKv>0)nKv--;
        // 减小每格电压
    }
    if(nKv>7)nKv=7;
    // 放大倍数控制
    if(nKv<3)
    {
        if(nKv==0)
        {
            Kpsh=500*Kbc;
        }
        else if(nKv==1)
        {
            Kpsh=250*Kbc;
        }
        else if(nKv==2)
        {
            Kpsh=50*Kbc;
        }
        rK2=1;
        rK3=0; 
    }
    else if(nKv<4)
    {
        Kpsh=25*Kbc;
        rK2=1;
        rK3=1; 
    }
    else if(nKv<6)
    {
        if(nKv==4)
        {
            Kpsh=12.5F*Kbc;
        }
        else if(nKv==5)
        {
            Kpsh=5*Kbc;
        }
        rK2=0;
        rK3=0; 
    }
    else
    {
        if(nKv==6)
        {
            Kpsh=2.5F*Kbc;
        }
        else if(nKv==7)
        {
            Kpsh=1.25F*Kbc;
        }
        rK2=0;
        rK3=1; 
    }
    nSVinx=nKv;
}

(3)采样控制,控制ADC采样时间,实现不同频率采样

u16 nARR[7]=       {10000   ,5000   ,1000   ,500    ,100    ,10     ,8};
u16 nPSC[7]=       {840     ,840    ,84     ,84     ,84     ,84     ,21};
void stimeradd()
{
    if(ideTimr<7) ideTimr++;
    if(ideTimr<7)
    TIM5_Int_Init(nARR[ideTimr]-1,nPSC[ideTimr]-1);// 0.001ms
    else
    {
        ideTimr=6;
        micTTT=1;
    }
}
void stimersub()
{
    if(ideTimr>0) ideTimr--;
    if(ideTimr<7)
    {
        micTTT=0;
       TIM5_Int_Init(nARR[ideTimr]-1,nPSC[ideTimr]-1);
    }
    
}

(4)LCD驱动、绘图与文字显示软件

void SCU_Refresh()
{
    static u8 ntmp1=0;
    static int tempstart = 0;
    static int tempend = 0;
    static int wavenum = 4;
    static int jumpwave = 5;
    static int nT = 2;
    
    char * P_Char=&gstrltemp[0];
    int i,j,k,l;
    
    u16 x,y;
    switch (SCUtype)
    {
   
    case MainScu2://Home 示波器界面
        {
            //底图
            gDrawRectangle(WHITE,5,5,300,200,1);
            // 仿真曲线
            for(x=0;x<300;x++)
            {
                line1[x]=(u8)(50*sin(0.1*x+ntmp1)+100);
            }
            ntmp1+=2;
            // 测量曲线
            // AdcBuf
            fMax=-80;
            fMin=80;
            for(x=0;x<300;x++)
            {
                ftmp2[x]=(AdcBuf[x]-2048)*Ka2V*Kbcbf[nSVinx]*Kopf[nSVinx]*2;
                if(fMax<ftmp2[x])fMax=ftmp2[x];
                if(fMin>ftmp2[x])fMin=ftmp2[x];
                ftmp=ftmp2[x]*Kpsh;
                if(ftmp>=98.00F)ftmp=98.0F;
                else if(ftmp<=-98.00F)ftmp=-98.0F;
                
                line1[x]=(u8)(ftmp+100+5);//0.04885197850512945774303859306302
                 if(micTTT)  line1_f[x]= line1[x];
            }
            if(micTTT)
            {
                // memcpy(line1_,line1,300);    
                for(x=0;x<60;x++)
                {
                    line1[x*5]=line1_f[x];
                    line1[x*5+1]=line1_f[x]+(u8)((line1_f[x+1]-line1_f[x])*0.2F);
                    line1[x*5+2]=line1_f[x]+(u8)((line1_f[x+1]-line1_f[x])*0.4F);
                    line1[x*5+3]=line1_f[x]+(u8)((line1_f[x+1]-line1_f[x])*0.6F);
                    line1[x*5+4]=line1_f[x]+(u8)((line1_f[x+1]-line1_f[x])*0.7F);
                }
            }
            fVpp=(fMax-fMin);//Kopf[nSVinx]*
            fAveV=(fMax+fMin)*0.5F;
            // 频率计算
            for(i=0;i<300;i++)
            {
                ftmp2[i]=ftmp2[i]-fAveV;
            }
            j=0;
            tempend =tempstart=0;
            for(i=0;i<299;i++)
            {
                if((ftmp2[i]<=0)&&(ftmp2[i+1]>=0)||(ftmp2[i]>=0)&&(ftmp2[i+1]<=0))
                {
                    if (j == 0) tempstart = i;
                    else if (j == 1)
                    {
                        k = i - tempstart;
                        if (k > 150) break;
                        wavenum = 150 / k;
                        if (wavenum % 2 == 1) wavenum += 1;
                        if (k < 10)
                        {
                            tempend = 0;
                            break;
                        }
                        if (k < 20) jumpwave = k / 4;
                    }
                    j = j + 1;
                    if (j > wavenum)
                    {
                        tempend = i;
                        break;
                    }
                    i = i + jumpwave;
                }
            }
            if (tempend - tempstart > 0)
            {
                CYcyc=cycyc[ideTimr];
                cycle = ((tempend - tempstart) * CYcyc) * 2 / wavenum;//um  一共wavenum/2 个周期
                freq = 1 / cycle;
               
            }
            else
            {
                cycle = -1;
                freq = -1;
            }
            if(lineMod)
            {
                for(i=1;i<299;i++)
                {
                     Gui_DrawLine(i+5,line1o[i],i+6,line1o[i+1]+3,BLACK);
                }
                memcpy(line1o,line1,300);   
                //绘制曲线 
                for(i=1;i<299;i++)
                {
                    Gui_DrawLine(i+5,line1o[i],i+6,line1o[i+1]+3,GREEN);
                }                
            }
            else
            {
                for(i=1;i<299;i++)
                {
                    LCD_Fast_DrawPoint(i+5,line1o[i]+6,BLACK);
                    // y=
                    // gDrawLine
                }
                memcpy(line1o,line1,300);   
                //绘制曲线 
                for(i=1;i<299;i++)
                {
                    LCD_Fast_DrawPoint(i+5,line1[i]+6,GREEN);
                    // y=
                    // gDrawLine
                }
            }
            gDrawLeVeLine(DGRAY,155,5,155,205,1);
            gDrawLeVeLine(DGRAY,5,103,305,103,1);
            for(i=0;i<4;i++)
            {
                for(j=0;j<6;j++)
                {
                    if(i<2)
                    {
                        x=155-(i+1)*50; 
                        if(j<3)
                        {
                            y=105-(j+1)*25; 
                        }
                        else
                        {
                            y=105+(j-2)*25; 
                        }
                    }
                    else
                    {
                        x=155+(i-1)*50; 
                        if(j<3)
                        {
                            y=105-(j+1)*25; 
                        }
                        else
                        {
                            y=105+(j-2)*25; 
                        }
                    }
                    LCD_Fast_DrawPoint(x,y,LGRAY);
                }
            }
            if(micTTT)
            gDrawString(BLUE,0,0,210,40,16,16," 20us");
            else
            gDrawString(BLUE,0,0,210,40,16,16,strts[ideTimr]);
            // strV u8 nSVinx=0;
            gDrawString(MAGENTA,0,45,210,40,16,16,strV[nSVinx]);
            gDrawString(LGRAY,0,95,210,24,12,12,"Vpp:");
            sprintf(P_Char,"% 6.2fV",fVpp);
            gDrawString(BLUE,0,120,210,56,16,16,P_Char);
            if(freq<0.0001F)
            {
                gDrawString(MAGENTA,0,180,210,64,16,16," ---.-Hz");
                gDrawString(BLUE,0,245,210,64,16,16," ---.-ms");
            }
            else if(freq<1000)
            {
                sprintf(P_Char,"% 6.2fHz",freq);
                gDrawString(MAGENTA,0,180,210,64,16,16,P_Char);
                sprintf(P_Char,"% 6.1fms",1000/freq);
                gDrawString(BLUE,0,245,210,72,16,16,P_Char);
            }
            else
            {
                freq=freq*0.001F;
                sprintf(P_Char,"% 6.2fKHz",freq);
                gDrawString(MAGENTA,0,180,210,64,16,16,P_Char);
                 sprintf(P_Char,"% 6.0fus",1000/freq);
                gDrawString(BLUE,0,245,210,72,16,16,P_Char);
            }
        }
        break;
   
    default:
        SCUtype=MainScu;
        break;
    }
}

4、电压测量及组合表

AD输入电压范围 ±1.65V

检测电压范围   ±66V

硬件放大倍数       0.5                0.25           0.05            0.025

继电器控制组合     rk2=1,rk3=0;       rk2=1,rk3=1;   rk2=0,rk3=0;    rk2=0,rk3=1;

硬件放大倍数档位   0.5                0.25           0.05            0.025

显示范围          200mv 400mv  2V     4V        8V    20V       40V   80V

测量范围          ±3.3                ±6.6          ±33             ±66

每格电压          50mv  100mv  500mv  1V       2V    5V        10V   20V

表显1V电压点数     500   250    50     25       12.5   5         2.5   1.25

显示倍数Kps:     

  0.5V   1V   2V     10V    40V  //每小格电压 每小格25个像素点 上下各4格

附录:

     1、原理图与PCB:

https://download.csdn.net/download/w267309080/88292915?spm=1001.2014.3001.5501

    2、程序源代码

https://download.csdn.net/download/w267309080/88294446

  • 0
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
前言: 是德科技(NYSE:KEYS)-原安捷伦电子测量事业部,是全球电子测量技术和市场的领导者,致力于推动无线通信、模块化和软件解决方案的持续创新,专注于为客户提供卓越的测量体验。是德科技提供的电子测量仪器、系统、软件及服务广泛应用于电子设备的设计、研发、制造、安装、部署和运营。 此次,是德科技为工程师分享了包括示波器、物联网、5G通信、汽车电子等热门领域的技术知识,手把手教会工程师如何通过示波器行之有效的实现相关领域的专业测试测量。 从朋友得知ST公司在搞活动,可以申请STM32F429的探索套件,作为穷学生一枚的我不免动了心。大二上学期参加完全国大学生电子设计竞赛之后闲来无事,就自己做了一个数字示波器来作为学习STM32的实战检验,前后花费了大概1个月的时间完成了初稿,之后又断断续续的完善我的示波器,并且为它编写了上位机程序和制定了通信协议。使用了前端程控模拟电路和上层电路板,uCOS-II,uCGUI,FFT,SD,上位机等等,现在因为参加老师的项目研发也就暂时闲置了下来,之前就打算在各大论坛开源,但是一直没有时间整理设计文档,恰巧现在ST公司这个活动,所以就全部开源分享给大家吧,一起学习。下一步计划重新设计模拟电路部分使用CPLD和高速AD实现更高的采样率。 硬件平台: 主控器:STM32F103ZET664K RAM 512K ROM 屏幕器:SSD1963 分辨率:480*272 16位色 触摸屏:TSC2046 模拟电路:OP-TL084 OP-U741 SW-CD4051 CMP-LM311 PWR-LM7805 -LM7905 -MC34063 -AMS1117-3.3 DRT-ULN2003 6.继电器:信号继电器 7.电源:DC +12V 注:芯片的数据手册等信息可以在集成电路查询网站搜索https://www.datasheet5.com/ 芯片询价和在线购买链接https://www.bom2buy.com/ 软件平台: 开发环境:RealView MDK-ARM uVision4.10 C编译器:ARMCC ASM编译器:ARMASM 连机器:ARMLINK 实时内核:UC/OS-II 2.9实时操作系统 GUI内核:uC/GUI 3.9图形用户接口 底层驱动:各个外设驱动程序 数字示波器功能: 波形发生器:使用STM32一路DA实现正弦,三角波,方波,白噪声输出。 任意一种波形幅值在0-3.3V任意可调、频率在一定范围任意可调、方波占空比可调。调节选项可以通过触摸屏完成设置。 SD卡存储: SD卡波形存储输出,能够对当前屏幕截屏,以JPG格式存储在SD卡上。能够存储1S内的波形数据,可以随时调用查看。 数据传输:用C#编写上位机,通过串口完成对下位机的控制。(1)实现STOP/RUN功能(2)输出波形电压、时间参数(3)控制截屏(4)控制波形发生器(5)控制完成FFT(6)波形的存储和显示 图形接口: UCGUI 水平扫速: 250 ns*、500ns、1μs、5 μs、10μs、50μs、500 μs、5ms 、50ms 垂直电压灵敏度:10mV/div, 20mV/div, 50mV/div, 0.1V/div, 0,2V/div, 0.5V/div, 1V/div,2V/div, 5V/div 被测信号的各种参数屏幕显示,包括频率、电压峰峰值等。 数字示波器性能参数: 主控: STM32F103ZET6 液晶屏: 4.3寸TFT480×272 65K彩色LCD显示屏 FSMC AD: 12位1MHz采样率 最高实时取样率: 1MSa/s 12Bits 取样缓冲器深度: 5K 垂直灵敏度: 5V,1V,500mV,200mV,100mV,50mV,20mV,10mV; 水平时基范围:2S,1S,500mS,200mS,100mS,50mS,20mS,10mS,5mS,2mS,1mS,500uS,200uS,100uS,50uS,20uS,10uS,5uS,2uS,1uS 输入阻抗: ≥1MΩ 最高输入电压: 30Vpp 耦合方式: AC/DC 触发功能: 实现自动、常规、单次触发方式 ,上升或下降边沿触发 参数计算: 频率、周期、占空比、交流峰-峰值、平均值、光标追踪显示 RUN/STOP 数字示波器实物视频演示: 实物展示: 上位机截图: 设计心得分享: 由于程序量比较大,所以在程序中我完成了大量的注释,详细的说明了具体的实现方法,其中的示波器原理和FFT原理请自己查阅相关教材。我个人认为最值得参考的就是如何制定一个效率较高的通信协议。我查阅了很多资料最后结合实际设计了一套通信协议,这套通信协议效传输速率理论最大可达16000bps,实际采用10666bps速率传输。协议的编码、解码算法的
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GavinKing2010

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值