加载中
加载中
表情图片
评为精选
鼓励
加载中...
分享
加载中...
文件下载
加载中...
修改排序
加载中...
自制示波器,带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
新版本公告
~~空空如也
路人乙 作者
10年8个月前 IP:上海
739554
2.jpg
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
路人乙作者
10年8个月前 IP:上海
739555
频谱显示功能演示(FFT)对着数字信号处理教材自己写的,用递归和非递归两种方式实现,和MATLAB对照确认计算无误。

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

11.jpg 12.jpg

13.png
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
路人乙作者
10年8个月前 IP:上海
739559
Other
#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 = 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=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=(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);                 write_data((fft_out+tem));                 write_data((fft_out+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);             }             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++)></(fft_cnt);i++)></lcdlength;i++)></lcdlength;i++)></2;></app.h>
控制部分代码
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
潜伏
10年8个月前 IP:浙江
739562
不错 精度如何?
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
1176764177
10年8个月前 IP:北京
739578
21ic看过这个
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
虎哥
10年8个月前 IP:四川
739592
不错啊,就是拍照水平太损形象[s::L]
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
wzg1199
10年8个月前 IP:浙江
739602
你好,看到你的工作我很感兴趣,最近我在想示波器改装成电化学工作站的可能性。只可惜我不是学这个的。如果你感兴趣,请联系我。我可以进一步跟你介绍这一块的市场。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
wzg1199
10年8个月前 IP:浙江
739605
电化学工作站的功能主要是能测电流随电压的变化,电流值一般在十的负五安培左右。要求检测限要低。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ssungirl
10年8个月前 IP:广东
739656
5M的宽带,用来DIY什么的还是不错的啊
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
金坷仙
10年8个月前 IP:湖北
739703
不错啊,希望能加你好友交流学习,小弟表示很感兴趣
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
量子隧道
10年8个月前 IP:北京
739735
引用 路人乙:
频谱显示功能演示(FFT)对着数字信号处理教材自己写的,用递归和非递归两种方式实现,和MATLAB对照确认计算无误。
这个得赞
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
量子隧道
10年8个月前 IP:北京
739736
引用 路人乙:
高通滤波器与低通滤波器功能演示(理想FIR滤波器+汉明窗)单独开任务计算FIR参数。每输入一次计算一次参数。
做得不错
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
novakon
10年8个月前 IP:广东
739764
引用 wzg1199:
电化学工作站的功能主要是能测电流随电压的变化,电流值一般在十的负五安培左右。要求检测限要低。
10-5安就是0.01毫安,并不难,不是示波器的事情,是模拟设计的事。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
novakon
10年8个月前 IP:广东
739770
楼主不会画板子是好事,以后大把人帮你画板子,程序写好就行了。

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

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

这个水平的设计人员还要天天加班,无良企业。建议投简历到科创仪表局
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
路人乙作者
10年8个月前 IP:上海
739858
引用 潜伏:
不错 精度如何?
商用示波器很多不过8位AD而已。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
路人乙作者
10年8个月前 IP:上海
739860
引用 novakon:
楼主不会画板子是好事,以后大把人帮你画板子,程序写好就行了。

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

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

这个水平的设计人员还要天天加班,无良企业。建议投简历到科创仪表局
还在上学就表好为人师了。(我毕业半年)
我自己水平我自己心里有数(上次面试就被虐了)
主要因为在校生普遍比较水,上学的时候还拿过电赛国奖,出来还不是被虐……
最后弱弱的问下 所谓仪表局待遇几何?
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
wzg1199
10年8个月前 IP:浙江
739949
你好,你对示波器有研究?微型的专业电化学工作站很有市场。价格十几万。
引用 novakon:
10-5安就是0.01毫安,并不难,不是示波器的事情,是模拟设计的事。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
novakon
10年8个月前 IP:广东
739967
引用 路人乙:
还在上学就表好为人师了。(我毕业半年)
我自己水平我自己心里有数(上次面试就被虐了)
主要因为在校生普遍比较水,上学的时候还拿过电赛国奖,出来还不是被虐……
最后弱弱的问下 所谓仪表局待遇几何?
我没有为您人师的意思,只是发言习惯。我画板子画得还可以,我写码也不一定就比你少嘛。
而且我是学电气工程的,不是学电子的,我们的课里面没有FPGA也没有ARM,为不了你的师。。。

科创仪表局目前是搞无线电测试设备的,之前曾经贴过启事,待遇肯定不是最好的,但是氛围很好。具体有劳您私信一下仪表局局长“虎哥”。



拍照水平确实有待提高,这个是大实话,不过既然大家都看得出来,我觉得提也是多余。那就不好意思,请当我没说吧
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
量子隧道
10年8个月前 IP:北京
739973
撸主面试时被虐只能说面试官不识才。我干过很多面试工作,知道很多负责面试的人水平也就那个工匠样而已。他们唯一擅长的,就是用自己干了好多年很熟悉的非常窄的专业知识来难为面试者。
我要是面试,会收你。
从你干的这个看来,你的基础知识和思考能力都不错。而且在电子工程师类别里还属于相当不错的那类。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
科创用户_018
1年4个月前 IP:河北
930552

什么ad模块,带宽怎么样?


引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

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

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

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

主体类型:个人
所属领域:无
认证方式:邮箱
IP归属地:未同步
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

笔记
{{note.content}}
{{n.user.username}}
{{fromNow(n.toc)}} {{n.status === noteStatus.disabled ? "已屏蔽" : ""}} {{n.status === noteStatus.unknown ? "正在审核" : ""}} {{n.status === noteStatus.deleted ? '已删除' : ''}}
  • 编辑
  • 删除
  • {{n.status === 'disabled' ? "解除屏蔽" : "屏蔽" }}
我也是有底线的