打印
[STM32G4]

基于STM32的简易示波器设计

[复制链接]
221|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主


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

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

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



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




使用特权

评论回复
沙发
梅花香自123|  楼主 | 2024-6-30 01:05 | 只看该作者
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发送初始化

使用特权

评论回复
板凳
梅花香自123|  楼主 | 2024-6-30 01:06 | 只看该作者
程控电路,通过按键控制继电器实现放大倍数变化
        处理部分
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;
        }

使用特权

评论回复
地板
梅花香自123|  楼主 | 2024-6-30 01:06 | 只看该作者
程控函数:

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

使用特权

评论回复
5
梅花香自123|  楼主 | 2024-6-30 01:06 | 只看该作者
采样控制,控制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);
    }
   
}

使用特权

评论回复
6
梅花香自123|  楼主 | 2024-6-30 01:07 | 只看该作者
定时器设置:

nARR数组存储了不同频率下的自动重装载寄存器(ARR)值。这个值决定了定时器计数器溢出的周期,间接控制了定时器的周期。
nPSC数组存储了不同频率下的预分频器(PSC)值。预分频器决定了定时器时钟的分频比,进一步影响了定时器的计数频率。
定时器初始化函数:

TIM5_Int_Init(nARR[ideTimr]-1, nPSC[ideTimr]-1)用于初始化定时器TIM5。
TIM5_Int_Init函数的具体实现可能包括设置ARR和PSC寄存器,配置定时器的工作模式和时钟源等。
采样频率控制:

stimeradd()函数用于增加ideTimr变量,从而切换到更高的采样频率。
stimersub()函数用于减少ideTimr变量,从而切换到更低的采样频率。
在切换采样频率时,会调用TIM5_Int_Init重新配置定时器TIM5以更新采样时间间隔。

使用特权

评论回复
7
梅花香自123|  楼主 | 2024-6-30 01:07 | 只看该作者
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;
    }
}

使用特权

评论回复
8
梅花香自123|  楼主 | 2024-6-30 01:07 | 只看该作者
电压测量及组合表

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格

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

92

主题

1059

帖子

0

粉丝