自制示波器,带dds,频谱计算功能。
路人乙2015/01/09仪器仪表 IP:上海
前段时间闲着自制了一个示波器。
基于ucos+ARMcortexM4+FPGA。
带FIR,FFT,Kalman算法。
最高采样率50M。存储8K*2字节数据。每秒64次波形(VGA刷屏63次/秒,快了也显示不出)
fpga:数据采集,DDS波形产生,提供VGA时序驱动屏幕。
ARMcortexM4:外设接口控制,数据处理,跑RTOS调度。
FPGA与CPU通过8位并行总线通信。CPU给FPGA内置RAM写 命令/数据

……后来想弄成虚拟的,下位机USB发数据,上位机用C#做数据处理,波形绘制。没时间弄,最近天天加班。

刚来科创的时候我才大二,现在都毕业半年了。
PS:我不会画板

先上张图
251959227623414.jpg
来自:仪器与装备 / 仪器仪表
22
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
路人乙 作者
10年0个月前 IP:上海
739554
2.jpg
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
路人乙作者
10年0个月前 IP:上海
739555
频谱显示功能演示(FFT)对着数字信号处理教材自己写的,用递归和非递归两种方式实现,和MATLAB对照确认计算无误。

3.jpg
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
路人乙作者
10年0个月前 IP:上海
739556
高通滤波器与低通滤波器功能演示(理想FIR滤波器+汉明窗)单独开任务计算FIR参数。每输入一次计算一次参数。 4.jpg 5.jpg 6.jpg m1.jpg m2.jpg m3.jpg
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
路人乙作者
10年0个月前 IP:上海
739558
卡尔曼滤波算法(kalman算法对于随机噪声为最优),一维卡尔曼算法,无转置矩阵。

11.jpg 12.jpg

13.png
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
路人乙作者
10年0个月前 IP:上海
739559
<code class="lang-text">#include <app.h>
#include  "ucos_ii.h"          //uC/OS-II系统函数头文件
#include  "sysinit.h"          //系统配置
  
  
#include "task_header.h" //任务相关宏 结构体
#include "fpga_data.h"   //与FPGA通信部分
#include "bsp.h"       //ARM驱动
  
  
#include "character.h"   //字模
#include "dds_data.h"   //dds数据
  
#include "mcu_math.h"    //数学算法部分
//#include "arm_math.h" 
/********临时定义变量******************/void system_init_task(void *pdata)
{
      
    //double cc;
  
    pdata = pdata;
      
#if OS_CRITICAL_METHOD == 3   //关中断的方法为3
    OS_CPU_SR cpu_sr;
#endif
      
    OS_ENTER_CRITICAL();
    OS_CPU_SysTickInit(CPU_frequency/1000); //初始化OS节拍无比重要
      
    port_init();          //设置所有IO为低电平&&输出
      
    //UART4_Init(115200);
    init_LED();
    key_init();         //将四个IO配备成中断
    lcd_data_init();     //lcd 数据传输
    PIT0_Init(CPU_frequency/64);     //pit定时中断,VGA刷屏速率约为63次/秒
    //PIT0_Init(5000000); 
      
    //初始化四个电位器AD
    AD_init();
      
    OS_EXIT_CRITICAL();
    //计算sin相关参数,尼玛不要手动输入。
      
      
    read_data_init();
      
    LED1(0);
    LED2(0);
    LED3(0);
    LED4(0);
      
    //状态
    trigger.state =0;
    kalman.state = 0;
    fft_wave.state =0;
    freq_selc.state =0;
    dds.state = 0;
    trigger_lock.state =0;
      
    //默认值
    trigger.value =0;
    kalman.value = 0;
    fft_wave.value =0;
    freq_selc.value =0;
    dds.value = 0;
    trigger_lock.value =0;
      
    //光标
    trigger.cursor =0;
    kalman.cursor = 0;
    fft_wave.cursor =0;
    freq_selc.cursor =0;
    dds.cursor = 0;
    trigger_lock.cursor =0;
      
    //双向循环链表
    fft_wave.next_menu = &trigger;
    trigger.last_menu = &fft_wave;
    fft_wave.value_num = 2;
    fft_wave.menu_num =1;
      
    trigger.next_menu =  &kalman;
    kalman.last_menu = &trigger;
    trigger.value_num = 3;//上升 下降 双向
    trigger.menu_num =2;
      
    kalman.next_menu = &freq_selc;
    freq_selc.last_menu = &kalman;
    kalman.value_num =2;
    kalman.menu_num =3;
      
    freq_selc.next_menu = &trigger_lock;
    trigger_lock.last_menu = &freq_selc;
    freq_selc.value_num = 3;//开启,关闭,确认输入
    freq_selc.menu_num =4;
      
    trigger_lock.next_menu = &dds;
    dds.last_menu = &trigger_lock;
    trigger_lock.value_num = 2;//锁定,解锁
    trigger_lock.menu_num =5;
      
    dds.next_menu = &fft_wave;
    fft_wave.last_menu = &dds;
    dds.value_num = 4;//方波,正弦,合成波(滤波演示),干扰波(卡尔曼演示)
    dds.menu_num =6;
      
      
    menu_p = &fft_wave;
    menu_head = &fft_wave;
    
      
    //key事件标志
    KeyFlag = OSFlagCreate(0,&err);
      
    Menu = OSFlagCreate(0,&err);
      
    Data_Process = OSFlagCreate(0,&err);
    //menu信号量,保护全局变量 
    MenuSem = OSSemCreate(1);
    FirParamSem = OSSemCreate(1);
    //这里换成互斥信号量,避免优先级反转标记一下。
    //LCDdataSem = OSSemCreate(1);
    LCDdataSem = OSMutexCreate(Mutex_prio,&err);
      
    //发送参数的邮箱
    ParaMbox = OSMboxCreate((void*)0);
    FirMbox = OSMboxCreate((void*)0);    
      
    OSFlagPost(Menu,(OS_FLAGS)0x01,OS_FLAG_SET,NULL);
     
      
    /*临时测试add与clk信号是否能用*/
    OSTimeDly(5);
    OSTaskDel(Init_task_prio);
}
void key_task(void *pdata)
{
    pdata = pdata;
      
    while(1)
    {
                                            //等待置1           
        OSFlagPend(KeyFlag,(OS_FLAGS)0x0f,OS_FLAG_WAIT_SET_OR,0,&err);
        OSTimeDly(40);
        if(!((GPIOD_PDIR>>8)&0x01))    //确认键
        {
            led_2 = !led_2;
            while(!((GPIOD_PDIR>>8)&0x01))
                OSTimeDly(1);
            OSTimeDly(40);
            LED2(led_2);
            key_menu(1);
            OSFlagPost(KeyFlag,(OS_FLAGS)0x01,OS_FLAG_CLR,NULL);
            OSFlagPost(Menu,(OS_FLAGS)0x01,OS_FLAG_SET,NULL);
            OSFlagPost(FirFlag,(OS_FLAGS)0x01,OS_FLAG_SET,NULL);
        }
        else if(!((GPIOD_PDIR>>10)&0x01))  //退出键
        {
            led_2 = !led_2;
            while(!((GPIOD_PDIR>>10)&0x01))
                OSTimeDly(1);
            OSTimeDly(40);
            LED2(led_2);
            key_menu(2);
            OSFlagPost(KeyFlag,(OS_FLAGS)0x02,OS_FLAG_CLR,NULL);
            OSFlagPost(Menu,(OS_FLAGS)0x02,OS_FLAG_SET,NULL);
        }
        else if(!((GPIOD_PDIR>>12)&0x01))    //左
        {
            led_2 = !led_2;
            while(!((GPIOD_PDIR>>12)&0x01))
                OSTimeDly(1);
            OSTimeDly(20);
            LED2(led_2);
            key_menu(3);
            OSFlagPost(KeyFlag,(OS_FLAGS)0x04,OS_FLAG_CLR,NULL);
            OSFlagPost(Menu,(OS_FLAGS)0x04,OS_FLAG_SET,NULL);
        }
        else if(!((GPIOD_PDIR>>14)&0x01))   //右
        {
            led_2 = !led_2;
            while(!((GPIOD_PDIR>>14)&0x01))
                OSTimeDly(1);
            OSTimeDly(20);
            LED2(led_2);
            key_menu(4);
            OSFlagPost(KeyFlag,(OS_FLAGS)0x08,OS_FLAG_CLR,NULL);
            OSFlagPost(Menu,(OS_FLAGS)0x08,OS_FLAG_SET,NULL);
        }
        else
            OSFlagPost(KeyFlag,(OS_FLAGS)0x0f,OS_FLAG_CLR,NULL);//清按键数据
          
    }
      
      
}
  
void uart4_task(void *pdata)
{
    pdata = pdata;
      
      
    while(1)
    {
       /* LED1(0);
        Uart4_SendByte(97);
      
        OSTimeDly(100);
        LED1(1);
        OSTimeDly(100);*/
    }
}
  
  
void menu_task(void * pdata)
{
  
    //uint8 data;
      
#if OS_CRITICAL_METHOD == 3   //关中断的方法为3
    OS_CPU_SR cpu_sr;
#endif
      
    pdata = pdata;
        //cpu_sr = cpu_sr;
  
    while(1)
    {
        OSFlagPend(Menu,(OS_FLAGS)0x0f,OS_FLAG_WAIT_SET_OR+OS_FLAG_CONSUME,0,&err); //所有按键皆触发该事件
  
        //OSSemPend(LCDdataSem,0,&err);
        OSMutexPend(LCDdataSem,0,&err);
        show_menu();
          
        //OSSemPost(LCDdataSem);
        OSMutexPost(LCDdataSem);
        OSFlagPost(Menu,(OS_FLAGS)0x01,OS_FLAG_CLR,NULL);
          
    }
}
  
  
  
void data_process_task(void * pdata)
{
#if OS_CRITICAL_METHOD == 3   //关中断的方法为3
    OS_CPU_SR cpu_sr;
#endif
      
    uint16 i,j,trigger_add,add;
    uint8 data;
    int8 tem;
    uint8 wave_data[(LcdLength+FirLength-1)];
    uint16 ReadLength;
      
    struct complex_num fft_result[FFT_CNT];
    uint8 fft_out[FFT_CNT];
      
    int32 FirTem;
    //uint8 wocao[4] = {0x01,0x04,0x02,0x03};
  
    //uint8 sample_para,voltage_para,phase_para,show_para;
    uint8 Para[4]; //sample show phase vlotage
    //uint8 show_num,;
      
    pdata = pdata;
  
    while(1)
    {   
        OSFlagPend(Data_Process,(OS_FLAGS)0x01,OS_FLAG_WAIT_SET_AND+OS_FLAG_CONSUME,0,&err);
        //cc = arm_sin_f32(1.6);
        if(!trigger_lock.value)  //如果触发
        {
            //获取AD信号,分频
            Para[0] = ADC_Getdata(sample_ctrl);
            Para[0] = sample_algorithms(Para[0]);
            debug2 = Para[0];
              
            Set_fre_div(Para[0]);//1为2分频,2为四分频……
            //开始采集
            read_start(1);
              
            //寻找触发源
            trigger_add = trigger_seek();
        }
        else
        {
              
        }
  
        Para[1] = (ADC_Getdata(show_ctrl)>>4)+1;
        debug = Para[1];
          
        Para[2] = ADC_Getdata(phase_ctrl);
        Para[2] =(Para[2]>>2)<<2;                    debug1="Para[2];"         osmboxpost(parambox,¶[0]);          phase_para="0;" debug="phase_para;" 发送消息         add="trigger_add+Para[2]*Para[1];" 读取更多数据以完成fir滤波         if(freq_selc.value)             readlength="(LcdLength+FirLength-1);"         else         for(i="0;i<ReadLength;i++)"         {              os_enter_critical();             add +="Para[1];"             wave_data<i> = read_data(add);
            //OS_EXIT_CRITICAL();
        }
        read_start(0);
  
        if(freq_selc.value==2)
        {
              
            for(i=0;i<lcdlength;i++)             {                 firtem="0;"                 for(j="0;j<FirLength;j++)"                     firtem +="wave_data[i+j]*FirParam[j];"                 wave_data<i>=FirTem>>10;
            }
                      
        }
        else if(freq_selc.value==1)
        {
              
            for(i=0;i<lcdlength;i++)             {                 firtem="0;"                 for(j="0;j<FirLength;j++)"                     firtem +="wave_data[i+j]*FirParam[j];"                 wave_data<i>=(FirTem>>10)-100;
            }
                      
        }
        else;          
  
        if(kalman.value)
            KalmanFilter(&wave_data[0],KalmanInitX,KalmanInitP);
        else;
  
        if(fft_wave.value==1)
        {
            OS_ENTER_CRITICAL();
            fft(&wave_data[0],&fft_result[0],FFT_LEN,FFT_CNT);
            absfft(&fft_result[0],&fft_out[0],FFT_CNT);
            OS_EXIT_CRITICAL();
            //cc[0] = fft_out[0];
            //cc[1] = fft_out[1];
            //cc[2] = fft_out[2];
            //cc[3] = fft_out[3];
            OSMutexPend(LCDdataSem,0,&err);
            //命令切换
            data = (menu_p->state)?(0x80+clr_data_cnt):clr_data_cnt;
            write_command(data);
          
            //写波形数据
            data = (menu_p->state)?(0x80+write_data_command):write_data_command;
            write_command(data);
              
            for(i=0;i<(fft_cnt);i++)             {                 tem="(fft_out[i+1]-fft_out<i">)/3;
                write_data(fft_out<i>);
                write_data((fft_out<i>+tem));
                write_data((fft_out<i>+tem+tem));
            }
            for(i=0;i<96;i++)             {                 write_data(0x00);             }             osmutexpost(lcddatasem);           }         else         {             osmutexpend(lcddatasem,0,&err);              命令切换             data="(menu_p-">state)?(0x80+clr_data_cnt):clr_data_cnt;
            write_command(data);
          
            //写波形数据
            data = (menu_p->state)?(0x80+write_data_command):write_data_command;
            write_command(data);
              
            for(i=0;i<480;i++)             {                 write_data(wave_data<i>);
            }
            OSMutexPost(LCDdataSem);  
        }
        OSFlagPost(Data_Process,(OS_FLAGS)0x01,OS_FLAG_CLR,NULL);
          
    }
      
}
  
void dds_ctrl_task(void *pdata)
{
    pdata = pdata;
    while(1)
    {
          
        OSFlagPend(Menu,(OS_FLAGS)0x01,OS_FLAG_WAIT_SET_AND+OS_FLAG_CONSUME,0,&err);  //确认键触发该事件
        //OSFlagPend(Menu,(OS_FLAGS)0x01,OS_FLAG_WAIT_SET_AND,0,&err);  //尝试清除/不清除标志
        if((menu_p ==&dds)&&(!menu_p->state)) //在DDS选项下按了确认 并且状态非下拉
        {
            OSMutexPend(LCDdataSem,0,&err);
            dds_data(dds.value);
            OSMutexPost(LCDdataSem); 
        }
        else
        {
            //OSFlagPost(Menu,(OS_FLAGS)0x01,OS_FLAG_CLR,NULL);
            //标志不清除,留给menu事件用。
        }
            
    }
}
  
  
void FirPara_task(void *pdata)
{
    pdata = pdata;
    uint8 * ReceivePara;
    uint32 FirFre;
    while(1)
    {
          
        OSFlagPend(Menu,(OS_FLAGS)0x01,OS_FLAG_WAIT_SET_AND+OS_FLAG_CONSUME,0,&err);  //确认键触发该事件
          
        if((menu_p ==&freq_selc)&&(!menu_p->state))
        //计算fir参数
        {
            ReceivePara = OSMboxPend(ParaMbox,0,&err);
            if(freq_selc.value==1)
            {
                FirFre = ReceivePara[1]*3*(ReceivePara[0]-1)/25;
                FirPara(255,FirFre,DataLength,&FirParam[0],FirLength);
            }
            else if(freq_selc.value==2)
            {
                FirFre = ReceivePara[1]*12*(ReceivePara[0]-1)/25;
                FirPara(FirFre,0,DataLength,&FirParam[0],FirLength);
            }
            else;
        }
         OSTimeDly(10);
         
    }
    //参数计算 参数 采样频率 分频 DDS频率
    //FirPara(uint8 H,uint8 L, uint16 N,float * fir_c,FirLength)
}
  
  
void Paradata_task(void *pdata)
{
    uint8 * ReceivePara;
    pdata =pdata;
      
    while(1)
    {
    ReceivePara = OSMboxPend(ParaMbox,0,&err);
        OSMutexPend(LCDdataSem,0,&err);
        show_para(ReceivePara);
        OSMutexPost(LCDdataSem);
        OSTimeDly(3);
    }
}
复制代码</480;i++)></96;i++)></i></i></i></(fft_cnt);i++)></lcdlength;i++)></lcdlength;i++)></2;></app.h></i></i></i></i></code>
控制部分代码
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
路人乙作者
10年0个月前 IP:上海
739858
引用 潜伏:
不错 精度如何?
商用示波器很多不过8位AD而已。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
路人乙作者
10年0个月前 IP:上海
739860
引用 novakon:
楼主不会画板子是好事,以后大把人帮你画板子,程序写好就行了。

滤波器参数可以送进FPGA,让FPGA实时滤波,节省ARM上的资源。

嵌入式水平不错,拍照水平尚需提高。

这个水平的设计人员还要天天加班,无良企业。建议投简历到科创仪表局
还在上学就表好为人师了。(我毕业半年)
我自己水平我自己心里有数(上次面试就被虐了)
主要因为在校生普遍比较水,上学的时候还拿过电赛国奖,出来还不是被虐……
最后弱弱的问下 所谓仪表局待遇几何?
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

所属专业
上级专业
同级专业
路人乙
笔友
文章
25
回复
90
学术分
0
2012/10/12注册,6年11个月前活动

欢迎和各路电子设计工程师交流

主体类型:个人
所属领域:无
认证方式:邮箱
IP归属地:未同步
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}