技术论坛

  • FPGA

    Xilinx大学计划官方FPGA开发板(DIGILENT全球唯一原厂) & Pmods积木式传感器

    发帖数

    194
    【Basys3 FPGA个人学习笔记连载分享】第十篇:Vavido实现matlab产生信号进行FFT进行频谱分析
    Vavido实现matlab产生信号进行FFT变换进行频谱分析实验内容:利用matlab产生一个正弦波,调用FPGAFFTi核进行傅里叶变换,转换为频域信号,matlab在读取输出的频域信号进行验证。实验平台:Xilinx大学计划与Digilent联合推出的“Basys3”FPGA开发板1:matlab产生输入的正弦信号:信号的频率为1khz,采样频率为20khzf=1000;%信号频率为1khzFs=20000;%采样频率为20khzB=16;%量化位数L=512;%信号FFT转换长度t=0:1/Fs:1/Fs*(L-1);%1/Fs表示采样一个点所需要的时间s=sin(2*i*f*t);%产生正弦信号sublot(211);lot(2*f*t,s);xlabel('\omega/\i');title('时域波形');xlabel('时间','fontsize',8);ylabel('幅度','fontsize',8);f=abs(fft(s,L));%512点FFTft=[0:(Fs/L):Fs/2]*(10^(-3));%转换横坐标以kHz为单位f1=f(1:length(ft));f1=f1/max(f1);%归一化sublot(212);lot(ft,f1)title('频谱波形');xlabel('频率(KHz)','fontsize',8);ylabel('频谱','fontsize',8);输出的时域和频域波形;2:例化FFTIP核:(1)numberofchannels:FFT变换通道,可以选择多通道,实现多帧数据同时进行FFT运算;这里选择一个通道;(2)TransfromLength:FFT变换长度;本次试验选择512个点的FFT,如果下面选择了“RunTimeConfigurationTransformLength”,则该参数为FFT变换最大长度。(3)TargetclockRrequency:50MHZ;(4)ArchitectureChoice:实现架构选择,本设计中选择变换处理时间较长,耗费资源较少的基2结构;↓↓↓dataformat:为定点scalingotion:不缩放roundingmodel:truncation截断输入位宽:16输出顺序:naturalorder↓↓↓默认即可3:FFTIP核的接口信号简单介绍:(1):配置通道s_axis_config_tdata:为配置数据通道s_axis_config_tvalid:即fftcore已经准备好接收配置数据信号s_axis_config_tready:表明master提供的配置数据有效信号下面的图为配置数据通道的数据格式:NFFT为一帧的最大数据点数(可选择的)FWD/INV=1表明进行fft,FWD/INV=1进行ifft,数据八位边沿对齐,数据不够八位,填充到八位(2):输入通道s_axis_data_tdata:为输入处理数据通道s_axis_data_tvalid;即fftcore已经准备好接收处理数据信号s_axis_data_tready:表明master提供的处理数据有效信号s_axis_data_tlast:当输入数据帧的最后一个样本时将s_axis_data_tlast置高,以便于FFTcore产生后面的事件信号其中s_axis_data_tdata的数据格式,低位是实部信号,高位是虚部信号(3):输出通道m_axis_data_tdata:输出数据通道m_axis_data_tuser:包含额有输出有关的信息信号m_axis_data_tvalid:FFTcore输出数据有效指示信号m_axis_data_tready:从机准备好接收数据指示信号m_axis_data_tlast:当输出帧的最后一个样本时,core将该信号置高其中输出数据通道数据格式:低位为实部信号,高位为虚部信号至于其他的信号,参看FastFourierTransformv9.0用户手册4:FPGAFFTIP核例化代码如下,其中在代码中相应的位置有注释;点击runsynthesis,进行综合,是否错误和criticalwarnning。`timescale1ns/1s////////////////////////////////////////////////////////////////////////////////////Comany://Engineer:////CreateDate:2017/01/1520:35:56//DesignName://Deendencies:////Revision://Revision0.01-FileCreated//AdditionalComments:////////////////////////////////////////////////////////////////////////////////////modulefft(inutclk,//50mhzinutrst,//复位oututs_axis_config_tready,//fftcore准备好接收配置信号inut[31:0]s_axis_data_tdata,//fft输入的处理数据outut[31:0]xk_re,//FFT处理后输出实部信号outut[31:0]xk_im,//FFT处理后输出虚部信号oututm_axis_data_tvalid,//输出数据输出有效信号oututs_axis_data_tready//fftcore准备好接收处理数据信号);reg[9:0]cnt;//计数器regcnt_en;//计数器使能信号regs_axis_config_tvalid;regs_axis_data_tvalid;regs_axis_data_tlast;/*当s_axis_config_tready为高电平,即fftcore已经准备好接收配置数据,将s_axis_config_tvalid置为1,即配置数据有效信号置为高电平,表明master提供的配置数据有效*/always@(osedgeclkornegedgerst)if(!rst)s_axis_config_tvalid<=1'b0;elseif(s_axis_config_tready==1'b1)s_axis_config_tvalid<=1'b1;elses_axis_config_tvalid<=1'b0;/*设置两级寄存器同步捕捉s_axis_data_tready信号的上升沿*/regdata_tready_r1,data_tready_r2;always@(osedgeclkornegedgerst)if(!rst)data_tready_r1<=1'b0;elsedata_tready_r1<=s_axis_data_tready;always@(osedgeclkornegedgerst)if(!rst)data_tready_r2<=1'b0;elsedata_tready_r2<=data_tready_r1;/*s_axis_data_tready有低电平变为高电平,表明fftcore准备好接收处理数据s_axis_data_tvalid置为1,即表明master提供的处理数据有效*/always@(osedgeclkornegedgerst)if(!rst)s_axis_data_tvalid<=1'b0;elseif({data_tready_r2,data_tready_r1}==2'b01)//s_axis_data_tready信号的上升沿s_axis_data_tvalid<=1'b1;elses_axis_data_tvalid<=s_axis_data_tvalid;/*当检测到s_axis_data_tready信号的上升沿计数器使能*/always@(osedgeclkornegedgerst)if(!rst)cnt_en<=1'b0;elseif({data_tready_r2,data_tready_r1}==2'b01)cnt_en<=1'b1;elseif(cnt==10'd512)cnt_en<=1'b0;//当计数器使能信号有效,计数器计数always@(osedgeclkornegedgerst)if(!rst)cnt<=10'd0;elseif(cnt_en==1'b1)beginif(cnt==10'd512)cnt<=10'd0;elsecnt<=cnt+1'b1;endelsecnt<=10'd0;/*当输入数据流的最后一个样本时将s_axis_data_tlast置高,以便于FFTcore产生后面的事件信号*/always@(osedgeclkornegedgerst)if(!rst)s_axis_data_tlast<=1'b0;elseif(cnt==10'd510)s_axis_data_tlast<=1'b1;elses_axis_data_tlast<=1'b0;wire[63:0]m_axis_data_tdata;//ffti核处理后的数据,其中高32位为虚部,低32位为实部信号wireevent_frame_started;//表明fft开始处理一帧数据//一些事件信号,详细参看手册wireevent_tlast_unexected;wireevent_tlast_missing;wireevent_data_in_channel_halt;wireevent_data_out_channel_halt;wire[15:0]m_axis_data_tuser;wireevent_status_channel_halt;//fft例化fft_ifft_i(.aclk(clk),//inutwireaclk.s_axis_config_tdata(8'd1),//inutwire[7:0]s_axis_config_tdata.s_axis_config_tvalid(s_axis_config_tvalid),//inutwires_axis_config_tvalid.s_axis_config_tready(s_axis_config_tready),//oututwires_axis_config_tready.s_axis_data_tdata(s_axis_data_tdata),//inutwire[31:0]s_axis_data_tdata.s_axis_data_tvalid(s_axis_data_tvalid),//inutwires_axis_data_tvalid.s_axis_data_tready(s_axis_data_tready),//oututwires_axis_data_tready.s_axis_data_tlast(s_axis_data_tlast),//inutwires_axis_data_tlast.m_axis_data_tdata(m_axis_data_tdata),//oututwire[63:0]m_axis_data_tdata.m_axis_data_tuser(m_axis_data_tuser),//oututwire[15:0]m_axis_data_tuser.m_axis_data_tvalid(m_axis_data_tvalid),//oututwirem_axis_data_tvalid.m_axis_data_tready(1'b1),//inutwirem_axis_data_tready.m_axis_data_tlast(m_axis_data_tlast),//oututwirem_axis_data_tlast.event_frame_started(event_frame_started),//oututwireevent_frame_started.event_tlast_unexected(event_tlast_unexected),//oututwireevent_tlast_unexected.event_tlast_missing(event_tlast_missing),//oututwireevent_tlast_missing.event_status_channel_halt(event_status_channel_halt),//oututwireevent_status_channel_halt.event_data_in_channel_halt(event_data_in_channel_halt),//oututwireevent_data_in_channel_halt.event_data_out_channel_halt(event_data_out_channel_halt)//oututwireevent_data_out_channel_halt);assignxk_re=m_axis_data_tdata[31:0];//低32位为实部信号assignxk_im=m_axis_data_tdata[63:32];//高32位为虚部,endmodule5:综合没有问题,接下来就是功能仿真;这里就需要将matlab产生的10khz的正弦信号读入到FPGA中作为FFT处理输入信号;代码中$readmemb()函数,就是读取TXT文本中的数据输入到FPGA中。`timescale1ns/1s`defineclk_eriod20////////////////////////////////////////////////////////////////////////////////////CreateDate:2017/01/1816:40:21//DesignName://ModuleName:fft_tb//////////////////////////////////////////////////////////////////////////////////modulefft_tb;regclk;//50mhzregrst;//复位reg[31:0]s_axis_data_tdata;//fft输入的处理数据,低16位为实部信号,高16位虚部信号,本次matlab才生的信号都是失信号reg[31:0]data[511:0];////数组,将FPGA读取的信号数据寄存在数组中wires_axis_config_tready;//fftcore准备好接收配置信号wires_axis_data_tready;//fftcore准备好接收处理数据信号wire[31:0]xk_re;//FFT处理后输出实部信号wire[31:0]xk_im;//FFT处理后输出虚部信号wirem_axis_data_tvalid;//例化fftifftfft(.clk(clk),.rst(rst),.s_axis_config_tready(s_axis_config_tready),.s_axis_data_tdata(s_axis_data_tdata),.m_axis_data_tvalid(m_axis_data_tvalid),.xk_re(xk_re),.xk_im(xk_im),.s_axis_data_tready(s_axis_data_tready));initialclk=1;always#(`clk_eriod/2)clk=~clk;//产生50MHZ的系统时钟integeri;initialbegin//InitializeInutsrst=0;;//复位s_axis_data_tdata=0;//输入初始化为0#100;rst=1;//恢复$readmemb("E:/vivado/FFT/fft.txt",data);//从matlab生成文件中读取数据for(i=0;i<512;i=i+1)begins_axis_data_tdata[15:0]=data[i];//将数组的数据赋值给s_axis_data_tdata作为输入,作为实部信号,没有虚部信号#(`clk_eriod);//将输入数据以采样频率50MHZ输入end#80000;$sto;end//定义一个文件名,将处理后的实部信号发存放在此文件中integerfft_file;initialbeginfft_file=$foen("fft_file.txt");if(fft_file==0)begin$dislay("cannotoenthefile!");$sto;endendwiresigned[31:0]fft_dataout;assignfft_dataout=xk_re;//将输出的实部信号赋值给fft_dataout寄存器always@(osedgeclk)if(m_axis_data_tvalid==1'b1)//m_axis_data_tvalid有效时输出$fdislay(fft_file,"%d",fft_dataout);//定义一个文件名,将处理后的虚部信号发存放在此文件中integerfft_im_file;initialbeginfft_im_file=$foen("fft_im_file.txt");if(fft_im_file==0)begin$dislay("cannotoenthefile!");$sto;endendwiresigned[31:0]fft_im_dataout;assignfft_im_dataout=xk_im;//将输出的虚部信号赋值给fft_im_dataout寄存器always@(osedgeclk)if(m_axis_data_tvalid==1'b1)//m_axis_data_tvalid有效时输出$fdislay(fft_im_file,"%d",fft_im_dataout);endmodule6、仿真结果:从图中可以看出,在modelsim无法观察频谱,所以只能将数据输出,在matlab中读取观察,验证设计是否正确;7、matlab分析:接下来就是matlab读取FPGAffti核处理过的数据,也就是matlab读取包含实部和虚部的fft_file.txt和fft_im_file.txt文件。Fs=20000;fid_re=foen('E:\vivado\FFT\FFT.sim\sim_1\behav\fft_file.txt','r');[xn_re,num]=fscanf(fid_re,'%lg',inf);%读取fga产生的滤波后的数据fid_im=foen('E:\vivado\FFT\FFT.sim\sim_1\behav\fft_im_file.txt','r');%打开数据文件%打开数据文件%打开数据文件%注意要将这个文件放到modelsim目录下[xn_im,num1]=fscanf(fid_im,'%lg',inf);%读取fga产生的滤波后的数据f=abs(xn_re+xn_im*j);ft=[0:(Fs/L):Fs/2]*(10^(-3));%转换横坐标以kHz为单位f1=f(1:length(ft));f1=f1/max(f1);%归一化lot(ft,f1)其中频域的波形如下图,验证了fft实验的正确
    发布于 前天 10:29
  • 开源微控制器(LabVIEW支持)

    树莓派(Raspberry Pi)、BeagleBone Black、chipKIT

    发帖数

    31
    labviewmakerhub检测不到com口
    驱动已经装了但是检测不到COM6是什么情况我又用arduinoIDE试试,是可以下载程序的,但是labviewmakerhub刷新不到这个com口,是什么原因labview也检测不到设备,什么情况在上图的使用指南上,添加即插即用设备,串口,下载驱动,就可以了。。。。
    发布于 12-30
  • 口袋仪器

    Analog Discovery 2、Analog Discovery、Electronics Explorer

    发帖数

    39
    AD2+LabVIEW 实现彩色LED控制
    AD2使用一段时间后,发现其功能丰富,而且可以快速去验证一些我们的灵感和创意,这不,有外国童鞋使用AD2实现了对彩色LED的控制,有助于大家PWM波形生成等功能有进一步了解~ThegoalofthisrojectistoteachyouhowtocontroltheAnalogDiscoverywithLabVIEW.InarticularthisrojectwilldemonstratehowtocontroltheAnalogDiscovery'sdigitalIOandPWMins.ThisrojectrimarilyfocusesonthePWMgeneration.Intherojectthereisa2dcolorallet.DeendingonwhereyouclickaRGBcolorvalueisselected.ThisRGBvalueisconvertedtoaPWMdutycycleandusedtodriveatricolorLED.ThreeotherLEDSthatemitonlyRed,GreenandBluelightarealsodrivenbyPWMsignals.TheyaretheretovisualizeamountofRedGreenandBluethatareresentinselectedcolor.Wheneverthemouseisclickedwithinthecolorma,theAnalogDiscovery’sdigitalinsareusedtodriveaSevenSegmentDislay.Whendriventhesevensegmentdislayreads“On”.TodemonstratethatthecolormasvirtualRGBmatchestheactualLEDcolors,somevirtualLEDsareanimatedonthefrontaneloftheroject.TheseLEDsarechangecolorbasedonwhereyouclickinthecolorma.Aboveisavideooftherojectinaction.Ste1:MaterialsPerquisites:Youmusthavecomletedste2inthereviousroject.FollowingOtion2.1(i.eInstallLabVIEW)fromareviousrojectisrequired.HardwareRequired:Thesearetheonlymaterialsyoureallyneedtodotheroject.AnalogDiscoveryTricolorLEDwithacommoncathode.Otional:Thesematerialsareonlyneededifyouwantsomeextraeffects.ClearLEDthatroducesredlight.ClearLEDthatroducesbluelight.ClearLEDthatroducesgreenlight.DualsevensegmentdislaySoftwareWaveFormsversion2.6.2orlaterLabVIEW(versions2013and2014havebeentestedtoworksofar)Ste2:MainGUICodeOverviewInGUIMain,thecodeisasimlifiedderivativeofGUIMainfromthereviousLabFormsProject.ForneatnessalotoftheWaveformsAPIcallshavebeengrouedtogetherintosubVIs.InthenewGUIMaintherearetworimarysectionstofocuson,theDeviceSelectionLooandtheRunDeviceFunctionsSection.DeviceSelectionLooTheDeviceSelectionLoohasacoulerimaryfunctions.Firstitsearchesforcomatibledevicestoconnecttousingthe"FindConnectedDevices.vi".ArefreshbuttonotionhasbeenaddedsoyoucanconnectadeviceafterstartingtheGUIMain.vi.The"FindConnectedDevices.vi"checkstomakesurenootheralicationsarealreadyusingthedeviceyouwanttooen.Ifthedeviceisalreadyinuse,thefrontanelcontrolsareconfiguredsothe"OK"buttonisgrayedout.Thisreventsyoufromoeningadevicethatisalreadyinuse.Ifthedeviceisn'tinuseyoucanhit'OK'tomoveontotheoeningrocess.OncetheoeningrocessbeingstheDeviceSelectionLooterminates,andtheRunDeviceFunctionssectionisinitiated.RunDeviceFunctionsThefirstortionofthissectionoenstheselecteddevice.Therocessisratherselfexlanatoryanddoesnotneedtobeexlainedindetail.Refertothenumberedcommentsinthecodeformoreinfo.Oncethedeviceisoened,anycustomVIyoudesignedwillbegintorun.Inthisrojectthe"GUICustomWaveformGen.vi"isrun.Ifyouwanttoscoeyourcustomsignaloutut,youcanclicktheEnableScoebuttonbeforeselectingthedevice.ThiswilloenthestandardoscilloscoewindowfromLabForms.Ste3:WiringWiringfortherojectisfairlystraightforward.TheonlyrequiredwiringforonthebreadboardisfortheTricolorLED.IfyouwanttoknowhowtowireaTricolorLEDgohere.Thesevensegmentdislayisanotionalfeature.BecauseofthisandthefactthewiringforSevenSegmentdislaysvariesdeendingonthemanufacture,itswiringwillnotbediscussed.Asidefromthebreadboardwiring,thewiringlefttoconsiderisfortheAnalogDiscovery.IrecommendusingjumerstoconnecttheAnalogDiscovery'swirestothebreadboard.YougettoselectwhichAnalogDiscoveryinsareusedtodriveaartofthecircuit.Todosoyoujustneedtochangetheinnumbersinthecode.RefertothismanualifyouareunfamiliarwiththeAnalogDiscovery'sinout.Ste4:PrefaceToroerlyunderstandhowthisrojectfunctions,itisimortanttounderstandtheWaveformsSDK.NormallytheanalogdiscoveryiscontrolledthroughthefreesoftwareackageWaveforms.WaveFormsalsocomeswithanoensourcedevelomentkit.ThisSDKgivesyouaccesstoaC/C++APIlibraryallowinganyonetowritetheirownsoftwareinterfacefortheAnalogDiscovery.AnoverviewofallthefunctionsavailableintheAPIcanbefoundintheWaveFormsReferenceManual.AtitscorethisLabVIEWrojectissimlycallingtheC/C++APIfunctions.SecialVIsusedtocalleachindividualWaveformsAPIfunctioninLabVIEW.YoucanseelistoftheavailableAPIfunctionsbyclickingthedigilent.lvllibintherojectwindow.EveryVIinthislisthasacorresondingC/C++APIfunction.FormoreinfoabouthoweachfunctionworksrefertotheWaveFormsReferenceManual,asillustratedintheimageabove.IfyouwanttolearnmoreabouthowtocallCfunctionsinLabVIEWcheckoutthefollowinglinks.Ste5:DigitalOututGUICodeThisVIthatHandlestheGUIanimationsaswellascallingthefunctionstocontroltheanalogDiscovery.ThisstewilldiscussthecodeincontextoftheColorMaCode,theAnimationCode,theAnalogDiscoveryControlCode.NOTE:Therojectcodeisattachedabove.ColorMaBeforebeginningthelootheVIreadsinixelmaofaJPEG.TheJPEGisanimageofacolorma.TheRGBvaluesforeachixelintheixelmaaresortedintothreearrays,oneforeachcolor.A2ndcoyoftheixelmaismadeanddrawnonthefrontanelwhereitcanbeclicked.Thisclickableimageislabeled"2DColorMa".Deendingonwhereyouclickthe2DColorMaaRGBcolorvalueisselected.Thisisdonebyusingthemouseointercoordinates(relativetothe2DColorMa’sborders)toaccessthesortedcolorarraysthatwerecreatedfromtheixelma.ThesecolorvaluesareusedforanimationurosesaswellascontrollingtheAnalogDiscovery.AnimationTogiveavirtualvisualizationofwhattherealTricolorLEDwouldlooklike,virtualLEDsareanimatedonthefrontanel.TheRGBvaluesgrabbedfromthesortedcolorarraysarealiedtotheLEDsdrawnonthefrontanel.OneoftheLEDsonthefrontanel(thetricolorLED)showsthemixedRGBvalues.EachoftheotherthreeLEDsarededicatedtosinglecolorchannel(Red,Blue,orGreen).TheLEDsonthefrontanelaremadefromdecorationshaes.InLabVIEWalldecorationreferencesforaVIsfrontanelarecontainedwithinanarraycalledDecos[].Usingadecorationsreferenceyoucancontrolcertainroertiesofthedecorationsuchascolor.AfterIhaddrawntheLEDs(usingtworectangles,andonecircleforeach),IdeterminedtheirositionintheDecos[]array.Ididthisbylugginginanindexvalue(obtainingthedecorationsreference)andhidingandunhidingthedecoration.AfterseeingwhatdecorationchangeddisaearedIknewwhatindexinDecos[]corresondedtoit.UsingthisrocessIderivedtheclusterconstantsof“LEDShaeIDNumbers”.Note,thatIcallthenumber“ShaeIDNumbers”buttheyarereallyindexvaluesoftheDecos[]array.Bewareifyouaddadecoration,ormodifyadecorationtheindexvaluesinDecos[]change.Thiswillcausetheanimationtomalfunction.WiththeroerShaeIDNumbersIuseaforlootoselectagrouofdecorations,andalythearoriateRGBcolors.ThisishowtheLEDsareanimatedonthefrontanel.AnalogDiscoveryControlTocontroltheAnalogDiscoveryaneventstructureisused.Theeventstructuretriggerswheneverthemouseismoved,orclickedwithinthe2DColorMa.TheeventstructurealsotriggersifthePWMvaluesorPWMchange.ThePWMvaluesarecalculatedbasedontheRGBvalues.InaJPEGcolorsare8bitmeaningthenumbers0to255areusedtoreresenthowintenseacolorchannelis(i.ehowinteseRedGreenorBluevalueofaixelis).TocalculatethePWMdutycycleercentage,thecolorvaluesaredividedby255.Thesevaluesarefedintothe“TricolorLEDPWMOut.vi”ThisVIisrimarilyfororganization.Itcontains3identicalVIsthatgeneratePWMsignalsontheAnalogDiscovery.RefertothenextstefordetailsabouthowPWMisgenerated.TheeventstructurethatcontrolsthePWMVI'salsotriggersafewDigitalWritecommandsfortheAnalogDiscovery.Thisiswhatcausesotionalsevensegmentdislaytolightu.TheinnumberfortheDigitalWriteishardcodedintheeventstructure.Feelfreetochangethemandexeriment,butbesureyoudonottrytousethesameinforPWMandDigitalwrite.FordetailsabouthowtheDigitalWriteVIworksrefertothenextste.
    发布于 11-13

创客圈

  • 创客小组(项目集散地)

    这里不仅有灵感与创意,更有实践、激情、与同道。创者无畏!

    发帖数

    19
    浏览器手势控制+Zynq移植方案+Distance_ip
    看到之前有浏览器手势控制的项目,之前蛮想做的,于是今天就做了一个阉割版的...基于树莓派的然后贴出之前关于zybo的移植方案我们采用ython脚本来模拟键盘输入,使用PyUserInut的库来输入值,对于浏览器来说,是几个功能键一起按下实现的,看看PyUserInut的源码就知道该怎么使用它了比如我们用到了k.ress_keys([k.alt_key+'Left'])来进行后退以此类推HC-SR04和PmodSNARMAX一样的,但是探测的最小距离更短,我觉得更适合,在这里,使用方法就是Trig给一定时长的高电平,检测echo的高电平时长,除以二乘以声速340m/s就是距离了,soeasy然后通过判断状态就可以了。距离的长短加上时间就是一个二维的栈,通过对栈的状态的判断,就可以检测当前的状态我做了四个状态,左点击,右点击,左划,右划,分别对应新建标签页,关闭标签页,后退,前进,附件里面是视频另外给出一份示例的代码,可以连上HC-SR04,打开你的浏览器,运行ython文件,进行测试对于Zybo的移植,也很简单,Xilinx给出的Zynq-ubuntu系统中安装Python,好像是自带Python环境的,然后对于距离的探测呢,我们可以通过FPGA来实现,新建一个AXI_LITE的IP核,然后通过给定一个寄存器的值,来读取距离信息,从而进行判断,相对来说,FPGA更加的经济,也更加的有效,毕竟并行的,IO口又多,所以更加方便附件里面有:1、示例程序2、展示视频3、ZYNQ的超声波AXI_LITEi,这个是我之前写的,如果有感兴趣的想移植的,直接拿去用就好了,查看SDK中xarameters.h文件看到寄存器5,6,7是距离信息,GoodLuck!
    发布于 12-03
  • 竞赛 & 活动

    全国大学生智能互联创新大赛、江苏省虚拟仪器竞赛、极客DIY限时挑战等

    发帖数

    12
    社区FPGA寒假特别活动
    嗯,寒假了。如果你是一名“行动派”的FPGA爱好者,不想让这个寒假碌碌无为,有没有想过为自己在寒假期间设定一个小目标,充分利用这个寒假来完成自己技术成长道路上的一个小小里程碑?如果你有激情但苦于没有想法,那么让DIGILENT中文技术社区来帮你设定一个小目标吧!老样子,我们始终推崇并坚信基于项目的学习(PBL,ProjectBasedLearning)是最好的自我技术成长方式,为此,在这个寒假,我们为有兴趣参与的小伙伴们设定了两个“开放式”的项目小目标:1FPGA寒假特别挑战项目一指定硬件:Basys3开发板指定软件:Vivado(基于verilog)挑战者需基于上述指定软硬件,在为期四周的时间内基于FPGA设计一个小游戏,如推箱子、走迷宫、2048、FlayBird等。游戏界面在VGA显示器上显示,玩家使用开发板上的按键或外接PmodJSTK二轴操作杆进行操作。参考项目:经典游戏俄罗斯方块的FPGA实现(www.digilent.com.cn/roject/details/103.html)2FPGA寒假特别挑战项目二指定硬件:Basys3开发板或Arty开发板指定软件:Vivado(基于verilog或microblaze)美国电气与电子工程师学会(IEEE)o出的超酷炫仿生飞行机器人,蝴蝶、水母和企鹅,每一个都栩栩如生:htt://t.cn/RI1XiWX。是不是觉得很酷?在这个挑战项目中,挑战者需基于上述指定软硬件,在为期四周的时间内基于FPGA设计一个仿生机器人,脑洞不限。参考项目:六足蜘蛛机器人(htts://www.youtube.com/watch?v=Fe1PCxCGbqs),请科学上网。参与方式及福利:●参与对象:仅限DIGILENT中文技术社区微信群成员。如何加入?扫码关注下方公众号,相信细心的你一定会找到入口。●参与方式:1.如果你想完成上述任一小目标,并且手上已经有了指定的开发板,嗯,那很好,所有你需要做的只是在群里@群主一下,告知你报名参与其中的哪个挑战即可,群主会做相应的记录哒!2.如果你想参与但没有对应的开发板。没关系,也请群内@群主,作为群里的digger,群主为想办法让你在寒假期间拿到板子倒腾的。3.寒假期间的这一特别活动不限名额,但开发板出借仅限6块(3块Basys3,3块Arty)。当然,最后你的项目最终完成结果如何,我们都希望你能够在社区内分享你的结果与经验,参考帖子:htt://www.digilent.com.cn/community/200.html。再当然,如果你只是拿了板子最后啥都没弄,你进入不单单是一个小黑屋,更是牺牲了自己在这一群内最好的学习机会。●福利我懂:两个挑战项目我们会在最终完成的童鞋中挑出做得最好的各一名,送上全新的Basys3或者ArtyFPGA开发板一块(你自个儿挑),并且在今后的社区线下活动(嗯,创客夏令营在向你招手)优先邀请你参与。好吧,就先写到这儿了,有问题帖子里问。最后,Haywintervacation,everyFPGAdiggers!
    发布于 前天 15:59
  • 工科街(校园话题区)

    一条纯粹属于在校工科生的话题街。尽情释放内心的小怪兽,海侃校园内外,闲聊天南地北

    发帖数

    16
    线性代数的本质
    在《一位工科学霸的自述:从大一到大四,我都干了些什么?》一文中,不少同学都留意到其中提到大一务必要学号线性代数。也有小伙伴反馈说不了解线性代数学了究竟派什么用,那么这篇文章我们就来聊聊线性代数的本质吧。文章略长,耐心看完哦。线性代数课程,无论你从行列式入手还是直接从矩阵入手,从一开始就充斥着莫名其妙。比如说,在全国一般工科院系教学中应用最广泛的同济线性代数教材(现在到了第四版),一上来就介绍逆序数这个古怪概念,然后用逆序数给出行列式的一个极不直观的定义,接着是一些简直犯傻的行列式性质和习题——把这行乘一个系数加到另一行上,再把那一列减过来,折腾得那叫一个热闹,可就是压根看不出这个东西有嘛用。大多数像我一样资质平庸的学生到这里就有点犯晕:连这是个什么东西都模模糊糊的,就开始钻火圈表演了,这未免太无厘头了吧!于是开始有人逃课,更多的人开始抄作业。这下就中招了,因为其后的发展可以用一句峰回路转来形容,紧跟着这个无厘头的行列式的,是一个同样无厘头但是伟大的无以复加的家伙的出场——矩阵来了!多年之后,我才明白,当老师犯傻似地用中括号把一堆傻了吧叽的数括起来,并且不紧不慢地说:“这个东西叫做矩阵”的时候,我的数学生涯掀开了何等悲壮辛酸、惨绝人寰的一幕!自那以后,在几乎所有跟“学问”二字稍微沾点边的东西里,矩阵这个家伙从不缺席。对于我这个没能一次搞定线性代数的笨蛋来说,矩阵老大的不请自来每每搞得我灰头土脸,头破血流。长期以来,我在阅读中一见矩阵,就如同阿Q见到了假洋鬼子,揉揉额角就绕道走。事实上,我并不是特例。一般工科学生初学线性代数,通常都会感到困难。这种情形在国内外皆然。瑞典数学家LarsGarding在其名著EncounterwithMathematics中说:“如果不熟悉线性代数的概念,要去学习自然科学,现在看来就和文盲差不多。然而“按照现行的国际标准,线性代数是通过公理化来表述的,它是第二代数学模型,这就带来了教学上的困难。”事实上,当我们开始学习线性代数的时候,不知不觉就进入了“第二代数学模型”的范畴当中,这意味着数学的表述方式和抽象性有了一次全面的进化,对于从小一直在“第一代数学模型”,即以实用为导向的、具体的数学模型中学习的我们来说,在没有并明确告知的情况下进行如此剧烈的aradigmshift,不感到困难才是奇怪的。大部分工科学生,往往是在学习了一些后继课程,如数值分析、数学规划、矩阵论之后,才逐渐能够理解和熟练运用线性代数。即便如此,不少人即使能够很熟练地以线性代数为工具进行科研和应用工作,但对于很多这门课程的初学者提出的、看上去是很基础的问题却并不清楚。比如说:1、矩阵究竟是什么东西?2、向量可以被认为是具有n个相互独立的性质(维度)的对象的表示,矩阵又是什么呢?3、我们如果认为矩阵是一组列(行)向量组成的新的复合向量的展开式,那么为什么这种展开式具有如此广泛的应用?特别是,为什么偏偏二维的展开式如此有用?4、如果矩阵中每一个元素又是一个向量,那么我们再展开一次,变成三维的立方阵,是不是更有用?5、矩阵的乘法规则究竟为什么这样规定?为什么这样一种怪异的乘法规则却能够在实践中发挥如此巨大的功效?很多看上去似乎是完全不相关的问题,最后竟然都归结到矩阵的乘法,这难道不是很奇妙的事情?难道在矩阵乘法那看上去莫名其妙的规则下面,包含着世界的某些本质规律?如果是的话,这些本质规律是什么?6、行列式究竟是一个什么东西?为什么会有如此怪异的计算规则?行列式与其对应方阵本质上是什么关系?为什么只有方阵才有对应的行列式,而一般矩阵就没有(不要觉得这个问题很蠢,如果必要,针对mxn矩阵定义行列式不是做不到的,之所以不做,是因为没有这个必要,但是为什么没有这个必要)?而且,行列式的计算规则,看上去跟矩阵的任何计算规则都没有直观的联系,为什么又在很多方面决定了矩阵的性质?难道这一切仅是巧合?7、矩阵为什么可以分块计算?分块计算这件事情看上去是那么随意,为什么竟是可行的?8、对于矩阵转置运算AT,有(AB)T=BTAT,对于矩阵求逆运算A-1,有(AB)-1=B-1A-1。两个看上去完全没有什么关系的运算,为什么有着类似的性质?这仅仅是巧合吗?9、为什么说P-1AP得到的矩阵与A矩阵“相似”?这里的“相似”是什么意思?10、特征值和特征向量的本质是什么?它们定义就让人很惊讶,因为Ax=λx,一个诺大的矩阵的效应,竟然不过相当于一个小小的数λ,确实有点奇妙。但何至于用“特征”甚至“本征”来界定?它们刻划的究竟是什么?这样的一类问题,经常让使用线性代数已经很多年的人都感到为难。就好像大人面对小孩子的刨根问底,最后总会迫不得已地说“就这样吧,到此为止”一样,面对这样的问题,很多老手们最后也只能用:“就是这么规定的,你接受并且记住就好”来搪塞。然而,这样的问题如果不能获得回答,线性代数对于我们来说就是一个粗暴的、不讲道理的、莫名其妙的规则集合,我们会感到,自己并不是在学习一门学问,而是被不由分说地“抛到”一个强制的世界中,只是在考试的皮鞭挥舞之下被迫赶路,全然无法领略其中的美妙、和谐与统一。直到多年以后,我们已经发觉这门学问如此的有用,却仍然会非常迷惑:怎么这么凑巧?我认为这是我们的线性代数教学中直觉性丧失的后果。上述这些涉及到“如何能”、“怎么会”的问题,仅仅通过纯粹的数学证明来回答,是不能令提问者满意的。比如,如果你通过一般的证明方法论证了矩阵分块运算确实可行,那么这并不能够让提问者的疑惑得到解决。他们真正的困惑是:矩阵分块运算为什么竟然是可行的?究竟只是凑巧,还是说这是由矩阵这种对象的某种本质所必然决定的?如果是后者,那么矩阵的这些本质是什么?只要对上述那些问题稍加考虑,我们就会发现,所有这些问题都不是单纯依靠数学证明所能够解决的。像我们的教科书那样,凡事用数学证明,最后培养出来的学生,只能熟练地使用工具,却欠缺真正意义上的理解。自从1930年代法国布尔巴基学派兴起以来,数学的公理化、系统性描述已经获得巨大的成功,这使得我们接受的数学教育在严谨性上大大提高。然而数学公理化的一个备受争议的副作用,就是一般数学教育中直觉性的丧失。数学家们似乎认为直觉性与抽象性是矛盾的,因此毫不犹豫地牺牲掉前者。然而包括我本人在内的很多人都对此表示怀疑,我们不认为直觉性与抽象性一定相互矛盾,特别是在数学教育中和数学教材中,帮助学生建立直觉,有助于它们理解那些抽象的概念,进而理解数学的本质。反之,如果一味注重形式上的严格性,学生就好像被迫进行钻火圈表演的小白鼠一样,变成枯燥的规则的奴隶。对于线性代数的类似上述所提到的一些直觉性的问题,两年多来我断断续续地反复思考了四、五次,为此阅读了好几本国内外线性代数、数值分析、代数和数学通论性书籍,其中像前苏联的名著《数学:它的内容、方法和意义》、龚昇教授的《线性代数五讲》、前面提到的EncounterwithMathematics(《数学概观》)以及ThomasA.Garrity的《数学拾遗》都给我很大的启发。不过即使如此,我对这个主题的认识也经历了好几次自我否定。比如以前思考的一些结论曾经写在自己的blog里,但是现在看来,这些结论基本上都是错误的。因此打算把自己现在的有关理解比较完整地记录下来,一方面是因为我觉得现在的理解比较成熟了,可以拿出来与别人探讨,向别人请教。另一方面,如果以后再有进一步的认识,把现在的理解给推翻了,那现在写的这个snashot也是很有意义的。今天先谈谈对线形空间和矩阵的几个核心概念的理解。这些东西大部分是凭着自己的理解写出来的,基本上不抄书,可能有错误的地方,希望能够被指出。但我希望做到直觉,也就是说能把数学背后说的实质问题说出来。首先说说空间(sace),这个概念是现代数学的命根子之一,从拓扑空间开始,一步步往上加定义,可以形成很多空间。线形空间其实还是比较初级的,如果在里面定义了范数,就成了赋范线性空间。赋范线性空间满足完备性,就成了巴那赫空间;赋范线性空间中定义角度,就有了内积空间,内积空间再满足完备性,就得到希尔伯特空间。总之,空间有很多种。你要是去看某种空间的数学定义,大致都是:存在一个集合,在这个集合上定义某某概念,然后满足某些性质,就可以被称为空间。这未免有点奇怪,为什么要用“空间”来称呼一些这样的集合呢?大家将会看到,其实这是很有道理的。我们一般人最熟悉的空间,毫无疑问就是我们生活在其中的(按照牛顿的绝对时空观)的三维空间,从数学上说,这是一个三维的欧几里德空间,我们先不管那么多,先看看我们熟悉的这样一个空间有些什么最基本的特点。仔细想想我们就会知道,这个三维的空间:1.由很多(实际上是无穷多个)位置点组成;2.这些点之间存在相对的关系;3.可以在空间中定义长度、角度;4.这个空间可以容纳运动,这里我们所说的运动是从一个点到另一个点的移动(变换),而不是微积分意义上的“连续”性的运动。上面的这些性质中,最最关键的是第4条。第1、2条只能说是空间的基础,不算是空间特有的性质,凡是讨论数学问题,都得有一个集合,大多数还得在这个集合上定义一些结构(关系),并不是说有了这些就算是空间。而第3条太特殊,其他的空间不需要具备,更不是关键的性质。只有第4条是空间的本质,也就是说,容纳运动是空间的本质特征。认识到了这些,我们就可以把我们关于三维空间的认识扩展到其他的空间。事实上,不管是什么空间,都必须容纳和支持在其中发生的符合规则的运动(变换)。你会发现,在某种空间中往往会存在一种相对应的变换,比如拓扑空间中有拓扑变换,线性空间中有线性变换,仿射空间中有仿射变换,其实这些变换都只不过是对应空间中允许的运动形式而已。因此只要知道,“空间”是容纳运动的一个对象集合,而变换则规定了对应空间的运动。下面我们来看看线性空间。线性空间的定义任何一本书上都有,但是既然我们承认线性空间是个空间,那么有两个最基本的问题必须首先得到解决,那就是:1.空间是一个对象集合,线性空间也是空间,所以也是一个对象集合。那么线性空间是什么样的对象的集合?或者说,线性空间中的对象有什么共同点吗?2.线性空间中的运动如何表述的?也就是,线性变换是如何表示的?我们先来回答第一个问题,回答这个问题的时候其实是不用拐弯抹角的,可以直截了当的给出答案:线性空间中的任何一个对象,通过选取基和坐标的办法,都可以表达为向量的形式。通常的向量空间我就不说了,举两个不、那么平凡的例子:1、L1是最高次项不大于n次的多项式的全体构成一个线性空间,也就是说,这个线性空间中的每一个对象是一个多式。如果我们以x0,x1,...,xn为基,那么任何一个这样的多项式都可以表达为一组n+1维向量,其中的每一个分量ai其实就是多项式中x(i-1)项的系数。值得说明的是,基的选取有多种办法,只要所选取的那一组基线性无关就可以。这要用到后面提到的概念了,所以这里先不说,提一下而已。L2是闭区间[a,b]上的n阶连续可微函数的全体,构成一个线性空间。也就是说,这个线性空间的每一个对象是一个连续函数。对于其中任何一个连续函数,根据魏尔斯特拉斯定理,一定可以找到最高次项不大于n的多项式函数,使之与该连续函数的差为0,也就是说,完全相等。这样就把问题归结为L1了。后面就不用再重复了。所以说,向量是很厉害的,只要你找到合适的基,用向量可以表示线性空间里任何一个对象。这里头大有文章,因为向量表面上只是一列数,但是其实由于它的有序性,所以除了这些数本身携带的信息之外,还可以在每个数的对应位置上携带信息。为什么在程序设计中数组最简单,却又威力无穷呢?根本原因就在于此。这是另一个问题了,这里就不说了。下面来回答第二个问题,这个问题的回答会涉及到线性代数的一个最根本的问题。线性空间中的运动,被称为线性变换。也就是说,你从线性空间中的一个点运动到任意的另外一个点,都可以通过一个线性变化来完成。那么,线性变换如何表示呢?很有意思,在线性空间中,当你选定一组基之后,不仅可以用一个向量来描述空间中的任何一个对象,而且可以用矩阵来描述该空间中的任何一个运动(变换)。而使某个对象发生对应运动的方法,就是用代表那个运动的矩阵,乘以代表那个对象的向量。简而言之,在线性空间中选定基之后,向量刻画对象,矩阵刻画对象的运动,用矩阵与向量的乘法施加运动。是的,矩阵的本质是运动的描述。如果以后有人问你矩阵是什么,那么你就可以响亮地告诉他,矩阵的本质是运动的描述。可是多么有意思啊,向量本身不是也可以看成是nx1矩阵吗?这实在是很奇妙,一个空间中的对象和运动竟然可以用相类同的方式表示。能说这是巧合吗?如果是巧合的话,那可真是幸运的巧合!可以说,线性代数中大多数奇妙的性质,均与这个巧合有直接的关系。接着理解矩阵,上面说“矩阵是运动的描述”,到现在为止,好像大家都还没什么意见。但是我相信早晚会有数学系出身的网友来拍板转。因为运动这个概念,在数学和物理里是跟微积分联系在一起的。我们学习微积分的时候,总会有人照本宣科地告诉你,初等数学是研究常量的数学,是研究静态的数学,高等数学是变量的数学,是研究运动的数学。大家口口相传,差不多人人都知道这句话。但是真知道这句话说的是什么意思的人,好像也不多。简而言之,在我们人类的经验里,运动是一个连续过程,从A点到B点,就算走得最快的光,也是需要一个时间来逐点地经过AB之间的路径,这就带来了连续性的概念。而连续这个事情,如果不定义极限的概念,根本就解释不了。古希腊人的数学非常强,但就是缺乏极限观念,所以解释不了运动,被芝诺的那些著名悖论(飞箭不动、飞毛腿阿喀琉斯跑不过乌龟等四个悖论)搞得死去活来。因为这篇文章不是讲微积分的,所以我就不多说了。有兴趣的读者可以去看看齐民友教授写的《重温微积分》。我就是读了这本书开头的部分,才明白“高等数学是研究运动的数学”这句话的道理。不过在我这个《理解矩阵》的文章里,“运动”的概念不是微积分中的连续性的运动,而是瞬间发生的变化。比如这个时刻在A点,经过一个“运动”,一下子就“跃迁”到了B点,其中不需要经过A点与B点之间的任何一个点。这样的“运动”,或者说“跃迁”,是违反我们日常的经验的。不过了解一点量子物理常识的人,就会立刻指出,量子(例如电子)在不同的能量级轨道上跳跃,就是瞬间发生的,具有这样一种跃迁行为。所以说,自然界中并不是没有这种运动现象,只不过宏观上我们观察不到。但是不管怎么说,“运动”这个词用在这里,还是容易产生歧义的,说得更确切些,应该是“跃迁”。因此这句话可以改成:“矩阵是线性空间里跃迁的描述”。可是这样说又太物理,也就是说太具体,而不够数学,也就是说不够抽象。因此我们最后换用一个正牌的数学术语——变换,来描述这个事情。这样一说,大家就应该明白了,所谓变换,其实就是空间里从一个点(元素/对象)到另一个点(元素/对象)的跃迁。比如说,拓扑变换,就是在拓扑空间里从一个点到另一个点的跃迁。再比如说,仿射变换,就是在仿射空间里从一个点到另一个点的跃迁。附带说一下,这个仿射空间跟向量空间是亲兄弟。做计算机图形学的朋友都知道,尽管描述一个三维对象只需要三维向量,但所有的计算机图形学变换矩阵都是4x4的。说其原因,很多书上都写着“为了使用中方便”,这在我看来简直就是企图蒙混过关。真正的原因,是因为在计算机图形学里应用的图形变换,实际上是在仿射空间而不是向量空间中进行的。想想看,在向量空间里相一个向量平行移动以后仍是相同的那个向量,而现实世界等长的两个平行线段当然不能被认为同一个东西,所以计算机图形学的生存空间实际上是仿射空间。而仿射变换的矩阵表示根本就是4x4的。有兴趣的读者可以去看《计算机图形学——几何工具算法详解》。一旦我们理解了“变换”这个概念,矩阵的定义就变成:矩阵是线性空间里的变换的描述。到这里为止,我们终于得到了一个看上去比较数学的定义。不过还要多说几句。教材上一般是这么说的,在一个线性空间V里的一个线性变换T,当选定一组基之后,就可以表示为矩阵。因此我们还要说清楚到底什么是线性变换,什么是基,什么叫选定一组基。线性变换的定义是很简单的,设有一种变换T,使得对于线性空间V中间任何两个不相同的对象x和y,以及任意实数a和b,有:T(ax+by)=aT(x)+bT(y),那么就称T为线性变换。定义都是这么写的,但是光看定义还得不到直觉的理解。线性变换究竟是一种什么样的变换?我们刚才说了,变换是从空间的一个点跃迁到另一个点,而线性变换,就是从一个线性空间V的某一个点跃迁到另一个线性空间W的另一个点的运动。这句话里蕴含着一层意思,就是说一个点不仅可以变换到同一个线性空间中的另一个点,而且可以变换到另一个线性空间中的另一个点去。不管你怎么变,只要变换前后都是线性空间中的对象,这个变换就一定是线性变换,也就一定可以用一个非奇异矩阵来描述。而你用一个非奇异矩阵去描述的一个变换,一定是一个线性变换。有的人可能要问,这里为什么要强调非奇异矩阵?所谓非奇异,只对方阵有意义,那么非方阵的情况怎么样?这个说起来就会比较冗长了,最后要把线性变换作为一种映射,并且讨论其映射性质,以及线性变换的核与像等概念才能彻底讲清楚。以下我们只探讨最常用、最有用的一种变换,就是在同一个线性空间之内的线性变换。也就是说,下面所说的矩阵,不作说明的话,就是方阵,而且是非奇异方阵。学习一门学问,最重要的是把握主干内容,迅速建立对于这门学问的整体概念,不必一开始就考虑所有的细枝末节和特殊情况,自乱阵脚。什么是基呢?这个问题在后面还要大讲一番,这里只要把基看成是线性空间里的坐标系就可以了。注意是坐标系,不是坐标值,这两者可是一个“对立矛盾统一体”。这样一来,“选定一组基”就是说在线性空间里选定一个坐标系。好,最后我们把矩阵的定义完善如下:“矩阵是线性空间中的线性变换的一个描述。在一个线性空间中,只要我们选定一组基,那么对于任何一个线性变换,都能够用一个确定的矩阵来加以描述。”理解这句话的关键,在于把“线性变换”与“线性变换的一个描述”区别开。一个是那个对象,一个是对那个对象的表述。就好像我们熟悉的面向对象编程中,一个对象可以有多个引用,每个引用可以叫不同的名字,但都是指的同一个对象。如果还不形象,那就干脆来个很俗的类比。比如有一头猪,你打算给它拍照片,只要你给照相机选定了一个镜头位置,那么就可以给这头猪拍一张照片。这个照片可以看成是这头猪的一个描述,但只是一个片面的的描述,因为换一个镜头位置给这头猪拍照,能得到一张不同的照片,也是这头猪的另一个片面的描述。所有这样照出来的照片都是这同一头猪的描述,但是又都不是这头猪本身。同样的,对于一个线性变换,只要你选定一组基,那么就可以找到一个矩阵来描述这个线性变换。换一组基,就得到一个不同的矩阵。所有这些矩阵都是这同一个线性变换的描述,但又都不是线性变换本身。但是这样的话,问题就来了如果你给我两张猪的照片,我怎么知道这两张照片上的是同一头猪呢?同样的,你给我两个矩阵,我怎么知道这两个矩阵是描述的同一个线性变换呢?如果是同一个线性变换的不同的矩阵描述,那就是本家兄弟了,见面不认识,岂不成了笑话。好在,我们可以找到同一个线性变换的矩阵兄弟们的一个性质,那就是:若矩阵A与B是同一个线性变换的两个不同的描述(之所以会不同,是因为选定了不同的基,也就是选定了不同的坐标系),则一定能找到一个非奇异矩阵P,使得A、B之间满足这样的关系:A=P-1BP。线性代数稍微熟一点的读者一下就看出来,这就是相似矩阵的定义。没错,所谓相似矩阵,就是同一个线性变换的不同的描述矩阵。按照这个定义,同一头猪的不同角度的照片也可以成为相似照片。俗了一点,不过能让人明白。而在上面式子里那个矩阵P,其实就是A矩阵所基于的基与B矩阵所基于的基这两组基之间的一个变换关系。关于这个结论,可以用一种非常直觉的方法来证明(而不是一般教科书上那种形式上的证明),如果有时间的话,我以后在blog里补充这个证明。这个发现太重要了。原来一族相似矩阵都是同一个线性变换的描述啊!难怪这么重要!工科研究生课程中有矩阵论、矩阵分析等课程,其中讲了各种各样的相似变换,比如什么相似标准型,对角化之类的内容,都要求变换以后得到的那个矩阵与先前的那个矩阵式相似的,为什么这么要求?因为只有这样要求,才能保证变换前后的两个矩阵是描述同一个线性变换的。当然,同一个线性变换的不同矩阵描述,从实际运算性质来看并不是不分好环的。有些描述矩阵就比其他的矩阵性质好得多。这很容易理解,同一头猪的照片也有美丑之分嘛。所以矩阵的相似变换可以把一个比较丑的矩阵变成一个比较美的矩阵,而保证这两个矩阵都是描述了同一个线性变换。这样一来,矩阵作为线性变换描述的一面,基本上说清楚了。但是,事情没有那么简单,或者说,线性代数还有比这更奇妙的性质,那就是,矩阵不仅可以作为线性变换的描述,而且可以作为一组基的描述。而作为变换的矩阵,不但可以把线性空间中的一个点给变换到另一个点去,而且也能够把线性空间中的一个坐标系(基)表换到另一个坐标系(基)去。而且,变换点与变换坐标系,具有异曲同工的效果。线性代数里最有趣的奥妙,就蕴含在其中。理解了这些内容,线性代数里很多定理和规则会变得更加清晰、直觉。首先来总结一下前面部分的一些主要结论:1.首先有空间,空间可以容纳对象运动的。一种空间对应一类对象。2.有一种空间叫线性空间,线性空间是容纳向量对象运动的。3.运动是瞬时的,因此也被称为变换。4.矩阵是线性空间中运动(变换)的描述。5.矩阵与向量相乘,就是实施运动(变换)的过程。6.同一个变换,在不同的坐标系下表现为不同的矩阵,但是它们的本质是一样的,所以本征值相同。下面让我们把视力集中到一点以改变我们以往看待矩阵的方式。我们知道,线性空间里的基本对象是向量。向量是这么表示的:[a1,a2,a3,...,an]。矩阵是这么表示的:a11,a12,a13,...,a1n,a21,a22,a23,...,a2n,...,an1,an2,an3,...,ann不用太聪明,我们就能看出来,矩阵是一组向量组成的。特别的,n维线性空间里的方阵是由n个n维向量组成的。我们在这里只讨论这个n阶的、非奇异的方阵,因为理解它就是理解矩阵的关键,它才是一般情况,而其他矩阵都是意外,都是不得不对付的讨厌状况,大可以放在一边。这里多一句嘴,学习东西要抓住主流,不要纠缠于旁支末节。很可惜我们的教材课本大多数都是把主线埋没在细节中的,搞得大家还没明白怎么回事就先被灌晕了。比如数学分析,明明最要紧的观念是说,一个对象可以表达为无穷多个合理选择的对象的线性和,这个概念是贯穿始终的,也是数学分析的精华。但是课本里自始至终不讲这句话,反正就是让你做吉米多维奇,掌握一大堆解偏题的技巧,记住各种特殊情况,两类间断点,怪异的可微和可积条件(谁还记得柯西条件、迪里赫莱条件...?),最后考试一过,一切忘光光。要我说,还不如反复强调这一个事情,把它深深刻在脑子里,别的东西忘了就忘了,真碰到问题了,再查数学手册嘛,何必因小失大呢?言归正传,如果一组向量是彼此线性无关的话,那么它们就可以成为度量这个线性空间的一组基,从而事实上成为一个坐标系体系,其中每一个向量都躺在一根坐标轴上,并且成为那根坐标轴上的基本度量单位(长度1)。现在到了关键的一步。看上去矩阵就是由一组向量组成的,而且如果矩阵非奇异的话(我说了,只考虑这种情况),那么组成这个矩阵的那一组向量也就是线性无关的了,也就可以成为度量线性空间的一个坐标系。结论:矩阵描述了一个坐标系。“慢着!”,你嚷嚷起来了,“你这个骗子!你不是说过,矩阵就是运动吗?怎么这会矩阵又是坐标系了?”嗯,所以我说到了关键的一步。我并没有骗人,之所以矩阵又是运动,又是坐标系,那是因为——“运动等价于坐标系变换”。对不起,这话其实不准确,我只是想让你印象深刻。准确的说法是:“对象的变换等价于坐标系的变换”。或者:“固定坐标系下一个对象的变换等价于固定对象所处的坐标系变换。”说白了就是:“运动是相对的。”让我们想想,达成同一个变换的结果,比如把点(1,1)变到点(2,3)去,你可以有两种做法。第一,坐标系不动,点动,把(1,1)点挪到(2,3)去。第二,点不动,变坐标系,让x轴的度量(单位向量)变成原来的1/2,让y轴的度量(单位向量)变成原先的1/3,这样点还是那个点,可是点的坐标就变成(2,3)了。方式不同,结果一样。从第一个方式来看,那就是把矩阵看成是运动描述,矩阵与向量相乘就是使向量(点)运动的过程。在这个方式下,Ma=b的意思是:“向量a经过矩阵M所描述的变换,变成了向量b。”而从第二个方式来看,矩阵M描述了一个坐标系,姑且也称之为M。那么:Ma=b的意思是:“有一个向量,它在坐标系M的度量下得到的度量结果向量为a,那么它在坐标系I的度量下,这个向量的度量结果是b。”这里的I是指单位矩阵,就是主对角线是1,其他为零的矩阵。而这两个方式本质上是等价的。我希望你务必理解这一点,因为这是本篇的关键。正因为是关键,所以我得再解释一下。在M为坐标系的意义下,如果把M放在一个向量a的前面,形成Ma的样式,我们可以认为这是对向量a的一个环境声明。它相当于是说:“注意了!这里有一个向量,它在坐标系M中度量,得到的度量结果可以表达为a。可是它在别的坐标系里度量的话,就会得到不同的结果。为了明确,我把M放在前面,让你明白,这是该向量在坐标系M中度量的结果。”那么我们再看孤零零的向量b:b多看几遍,你没看出来吗?它其实不是b,它是:Ib也就是说:“在单位坐标系,也就是我们通常说的直角坐标系I中,有一个向量,度量的结果是b。”而Ma=Ib的意思就是说:“在M坐标系里量出来的向量a,跟在I坐标系里量出来的向量b,其实根本就是一个向量啊!”这哪里是什么乘法计算,根本就是身份识别嘛。从这个意义上我们重新理解一下向量。向量这个东西客观存在,但是要把它表示出来,就要把它放在一个坐标系中去度量它,然后把度量的结果(向量在各个坐标轴上的投影值)按一定顺序列在一起,就成了我们平时所见的向量表示形式。你选择的坐标系(基)不同,得出来的向量的表示就不同。向量还是那个向量,选择的坐标系不同,其表示方式就不同。因此,按道理来说,每写出一个向量的表示,都应该声明一下这个表示是在哪个坐标系中度量出来的。表示的方式,就是Ma,也就是说,有一个向量,在M矩阵表示的坐标系中度量出来的结果为a。我们平时说一个向量是[2357]T,隐含着是说,这个向量在I坐标系中的度量结果是[2357]T,因此,这个形式反而是一种简化了的特殊情况。注意到,M矩阵表示出来的那个坐标系,由一组基组成,而那组基也是由向量组成的,同样存在这组向量是在哪个坐标系下度量而成的问题。也就是说,表述一个矩阵的一般方法,也应该要指明其所处的基准坐标系。所谓M,其实是IM,也就是说,M中那组基的度量是在I坐标系中得出的。从这个视角来看,M×N也不是什么矩阵乘法了,而是声明了一个在M坐标系中量出的另一个坐标系N,其中M本身是在I坐标系中度量出来的。回过头来说变换的问题,我刚才说,“固定坐标系下一个对象的变换等价于固定对象所处的坐标系变换”,那个“固定对象”我们找到了,就是那个向量。但是坐标系的变换呢?我怎么没看见?请看:Ma=Ib我现在要变M为I,怎么变?对了,再前面乘以个M-1,也就是M的逆矩阵。换句话说,你不是有一个坐标系M吗,现在我让它乘以个M-1,变成I,这样一来的话,原来M坐标系中的a在I中一量,就得到b了。我建议你此时此刻拿起纸笔,画画图,求得对这件事情的理解。比如,你画一个坐标系,x轴上的衡量单位是2,y轴上的衡量单位是3,在这样一个坐标系里,坐标为(1,1)的那一点,实际上就是笛卡尔坐标系里的点(2,3)。而让它原形毕露的办法,就是把原来那个坐标系:2003的x方向度量缩小为原来的1/2,而y方向度量缩小为原来的1/3,这样一来坐标系就变成单位坐标系I了。保持点不变,那个向量现在就变成了(2,3)了。怎么能够让“x方向度量缩小为原来的1/2,而y方向度量缩小为原来的1/3”呢?就是让原坐标系:2003被矩阵:1/2001/3左乘。而这个矩阵就是原矩阵的逆矩阵。下面我们得出一个重要的结论:“对坐标系施加变换的方法,就是让表示那个坐标系的矩阵与表示那个变化的矩阵相乘。”再一次的,矩阵的乘法变成了运动的施加。只不过,被施加运动的不再是向量,而是另一个坐标系。如果你觉得你还搞得清楚,请再想一下刚才已经提到的结论,矩阵MxN,一方面表明坐标系N在运动M下的变换结果,另一方面,把M当成N的前缀,当成N的环境描述,那么就是说,在M坐标系度量下,有另一个坐标系N。这个坐标系N如果放在I坐标系中度量,其结果为坐标系MxN。在这里,我实际上已经回答了一般人在学习线性代数是最困惑的一个问题,那就是为什么矩阵的乘法要规定成这样。简单地说,是因为:1.从变换的观点看,对坐标系N施加M变换,就是把组成坐标系N的每一个向量施加M变换。2.从坐标系的观点看,在M坐标系中表现为N的另一个坐标系,这也归结为,对N坐标系基的每一个向量,把它在I坐标系中的坐标找出来,然后汇成一个新的矩阵。3.至于矩阵乘以向量为什么要那样规定,那是因为一个在M中度量为a的向量,如果想要恢复在I中的真像,就必须分别与M中的每一个向量进行內积运算。我把这个结论的推导留给感兴趣的朋友吧。应该说,其实到了这一步,已经很容易了。综合以上,矩阵的乘法就得那么规定,一切有根有据,绝不是哪个神经病胡思乱想出来的。我已经无法说得更多了。矩阵又是坐标系,又是变换。到底是坐标系,还是变换,已经说不清楚了,运动与实体在这里统一了,物质与意识的界限已经消失了,一切归于无法言说,无法定义了。到了这个时候,我们不得不承认,我们伟大的线性代数课本上说的矩阵定义,是无比正确的:“矩阵就是由m行n列数放在一起组成的数学对象。”好了,这基本上就是我想说的全部了。
    发布于 01-10

干货热帖

  • 【Basys3 FPGA个人学习笔记连载分享】第十篇:Vavido实现matlab产生信号进行FFT进行频谱分析
    Vavido实现matlab产生信号进行FFT变换进行频谱分析实验内容:利用matlab产生一个正弦波,调用FPGAFFTi核进行傅里叶变换,转换为频域信号,matlab在读取输出的频域信号进行验证。实验平台:Xilinx大学计划与Digilent联合推出的“Basys3”FPGA开发板1:matlab产生输入的正弦信号:信号的频率为1khz,采样频率为20khzf=1000;%信号频率为1khzFs=20000;%采样频率为20khzB=16;%量化位数L=512;%信号FFT转换长度t=0:1/Fs:1/Fs*(L-1);%1/Fs表示采样一个点所需要的时间s=sin(2*i*f*t);%产生正弦信号sublot(211);lot(2*f*t,s);xlabel('\omega/\i');title('时域波形');xlabel('时间','fontsize',8);ylabel('幅度','fontsize',8);f=abs(fft(s,L));%512点FFTft=[0:(Fs/L):Fs/2]*(10^(-3));%转换横坐标以kHz为单位f1=f(1:length(ft));f1=f1/max(f1);%归一化sublot(212);lot(ft,f1)title('频谱波形');xlabel('频率(KHz)','fontsize',8);ylabel('频谱','fontsize',8);输出的时域和频域波形;2:例化FFTIP核:(1)numberofchannels:FFT变换通道,可以选择多通道,实现多帧数据同时进行FFT运算;这里选择一个通道;(2)TransfromLength:FFT变换长度;本次试验选择512个点的FFT,如果下面选择了“RunTimeConfigurationTransformLength”,则该参数为FFT变换最大长度。(3)TargetclockRrequency:50MHZ;(4)ArchitectureChoice:实现架构选择,本设计中选择变换处理时间较长,耗费资源较少的基2结构;↓↓↓dataformat:为定点scalingotion:不缩放roundingmodel:truncation截断输入位宽:16输出顺序:naturalorder↓↓↓默认即可3:FFTIP核的接口信号简单介绍:(1):配置通道s_axis_config_tdata:为配置数据通道s_axis_config_tvalid:即fftcore已经准备好接收配置数据信号s_axis_config_tready:表明master提供的配置数据有效信号下面的图为配置数据通道的数据格式:NFFT为一帧的最大数据点数(可选择的)FWD/INV=1表明进行fft,FWD/INV=1进行ifft,数据八位边沿对齐,数据不够八位,填充到八位(2):输入通道s_axis_data_tdata:为输入处理数据通道s_axis_data_tvalid;即fftcore已经准备好接收处理数据信号s_axis_data_tready:表明master提供的处理数据有效信号s_axis_data_tlast:当输入数据帧的最后一个样本时将s_axis_data_tlast置高,以便于FFTcore产生后面的事件信号其中s_axis_data_tdata的数据格式,低位是实部信号,高位是虚部信号(3):输出通道m_axis_data_tdata:输出数据通道m_axis_data_tuser:包含额有输出有关的信息信号m_axis_data_tvalid:FFTcore输出数据有效指示信号m_axis_data_tready:从机准备好接收数据指示信号m_axis_data_tlast:当输出帧的最后一个样本时,core将该信号置高其中输出数据通道数据格式:低位为实部信号,高位为虚部信号至于其他的信号,参看FastFourierTransformv9.0用户手册4:FPGAFFTIP核例化代码如下,其中在代码中相应的位置有注释;点击runsynthesis,进行综合,是否错误和criticalwarnning。`timescale1ns/1s////////////////////////////////////////////////////////////////////////////////////Comany://Engineer:////CreateDate:2017/01/1520:35:56//DesignName://Deendencies:////Revision://Revision0.01-FileCreated//AdditionalComments:////////////////////////////////////////////////////////////////////////////////////modulefft(inutclk,//50mhzinutrst,//复位oututs_axis_config_tready,//fftcore准备好接收配置信号inut[31:0]s_axis_data_tdata,//fft输入的处理数据outut[31:0]xk_re,//FFT处理后输出实部信号outut[31:0]xk_im,//FFT处理后输出虚部信号oututm_axis_data_tvalid,//输出数据输出有效信号oututs_axis_data_tready//fftcore准备好接收处理数据信号);reg[9:0]cnt;//计数器regcnt_en;//计数器使能信号regs_axis_config_tvalid;regs_axis_data_tvalid;regs_axis_data_tlast;/*当s_axis_config_tready为高电平,即fftcore已经准备好接收配置数据,将s_axis_config_tvalid置为1,即配置数据有效信号置为高电平,表明master提供的配置数据有效*/always@(osedgeclkornegedgerst)if(!rst)s_axis_config_tvalid<=1'b0;elseif(s_axis_config_tready==1'b1)s_axis_config_tvalid<=1'b1;elses_axis_config_tvalid<=1'b0;/*设置两级寄存器同步捕捉s_axis_data_tready信号的上升沿*/regdata_tready_r1,data_tready_r2;always@(osedgeclkornegedgerst)if(!rst)data_tready_r1<=1'b0;elsedata_tready_r1<=s_axis_data_tready;always@(osedgeclkornegedgerst)if(!rst)data_tready_r2<=1'b0;elsedata_tready_r2<=data_tready_r1;/*s_axis_data_tready有低电平变为高电平,表明fftcore准备好接收处理数据s_axis_data_tvalid置为1,即表明master提供的处理数据有效*/always@(osedgeclkornegedgerst)if(!rst)s_axis_data_tvalid<=1'b0;elseif({data_tready_r2,data_tready_r1}==2'b01)//s_axis_data_tready信号的上升沿s_axis_data_tvalid<=1'b1;elses_axis_data_tvalid<=s_axis_data_tvalid;/*当检测到s_axis_data_tready信号的上升沿计数器使能*/always@(osedgeclkornegedgerst)if(!rst)cnt_en<=1'b0;elseif({data_tready_r2,data_tready_r1}==2'b01)cnt_en<=1'b1;elseif(cnt==10'd512)cnt_en<=1'b0;//当计数器使能信号有效,计数器计数always@(osedgeclkornegedgerst)if(!rst)cnt<=10'd0;elseif(cnt_en==1'b1)beginif(cnt==10'd512)cnt<=10'd0;elsecnt<=cnt+1'b1;endelsecnt<=10'd0;/*当输入数据流的最后一个样本时将s_axis_data_tlast置高,以便于FFTcore产生后面的事件信号*/always@(osedgeclkornegedgerst)if(!rst)s_axis_data_tlast<=1'b0;elseif(cnt==10'd510)s_axis_data_tlast<=1'b1;elses_axis_data_tlast<=1'b0;wire[63:0]m_axis_data_tdata;//ffti核处理后的数据,其中高32位为虚部,低32位为实部信号wireevent_frame_started;//表明fft开始处理一帧数据//一些事件信号,详细参看手册wireevent_tlast_unexected;wireevent_tlast_missing;wireevent_data_in_channel_halt;wireevent_data_out_channel_halt;wire[15:0]m_axis_data_tuser;wireevent_status_channel_halt;//fft例化fft_ifft_i(.aclk(clk),//inutwireaclk.s_axis_config_tdata(8'd1),//inutwire[7:0]s_axis_config_tdata.s_axis_config_tvalid(s_axis_config_tvalid),//inutwires_axis_config_tvalid.s_axis_config_tready(s_axis_config_tready),//oututwires_axis_config_tready.s_axis_data_tdata(s_axis_data_tdata),//inutwire[31:0]s_axis_data_tdata.s_axis_data_tvalid(s_axis_data_tvalid),//inutwires_axis_data_tvalid.s_axis_data_tready(s_axis_data_tready),//oututwires_axis_data_tready.s_axis_data_tlast(s_axis_data_tlast),//inutwires_axis_data_tlast.m_axis_data_tdata(m_axis_data_tdata),//oututwire[63:0]m_axis_data_tdata.m_axis_data_tuser(m_axis_data_tuser),//oututwire[15:0]m_axis_data_tuser.m_axis_data_tvalid(m_axis_data_tvalid),//oututwirem_axis_data_tvalid.m_axis_data_tready(1'b1),//inutwirem_axis_data_tready.m_axis_data_tlast(m_axis_data_tlast),//oututwirem_axis_data_tlast.event_frame_started(event_frame_started),//oututwireevent_frame_started.event_tlast_unexected(event_tlast_unexected),//oututwireevent_tlast_unexected.event_tlast_missing(event_tlast_missing),//oututwireevent_tlast_missing.event_status_channel_halt(event_status_channel_halt),//oututwireevent_status_channel_halt.event_data_in_channel_halt(event_data_in_channel_halt),//oututwireevent_data_in_channel_halt.event_data_out_channel_halt(event_data_out_channel_halt)//oututwireevent_data_out_channel_halt);assignxk_re=m_axis_data_tdata[31:0];//低32位为实部信号assignxk_im=m_axis_data_tdata[63:32];//高32位为虚部,endmodule5:综合没有问题,接下来就是功能仿真;这里就需要将matlab产生的10khz的正弦信号读入到FPGA中作为FFT处理输入信号;代码中$readmemb()函数,就是读取TXT文本中的数据输入到FPGA中。`timescale1ns/1s`defineclk_eriod20////////////////////////////////////////////////////////////////////////////////////CreateDate:2017/01/1816:40:21//DesignName://ModuleName:fft_tb//////////////////////////////////////////////////////////////////////////////////modulefft_tb;regclk;//50mhzregrst;//复位reg[31:0]s_axis_data_tdata;//fft输入的处理数据,低16位为实部信号,高16位虚部信号,本次matlab才生的信号都是失信号reg[31:0]data[511:0];////数组,将FPGA读取的信号数据寄存在数组中wires_axis_config_tready;//fftcore准备好接收配置信号wires_axis_data_tready;//fftcore准备好接收处理数据信号wire[31:0]xk_re;//FFT处理后输出实部信号wire[31:0]xk_im;//FFT处理后输出虚部信号wirem_axis_data_tvalid;//例化fftifftfft(.clk(clk),.rst(rst),.s_axis_config_tready(s_axis_config_tready),.s_axis_data_tdata(s_axis_data_tdata),.m_axis_data_tvalid(m_axis_data_tvalid),.xk_re(xk_re),.xk_im(xk_im),.s_axis_data_tready(s_axis_data_tready));initialclk=1;always#(`clk_eriod/2)clk=~clk;//产生50MHZ的系统时钟integeri;initialbegin//InitializeInutsrst=0;;//复位s_axis_data_tdata=0;//输入初始化为0#100;rst=1;//恢复$readmemb("E:/vivado/FFT/fft.txt",data);//从matlab生成文件中读取数据for(i=0;i<512;i=i+1)begins_axis_data_tdata[15:0]=data[i];//将数组的数据赋值给s_axis_data_tdata作为输入,作为实部信号,没有虚部信号#(`clk_eriod);//将输入数据以采样频率50MHZ输入end#80000;$sto;end//定义一个文件名,将处理后的实部信号发存放在此文件中integerfft_file;initialbeginfft_file=$foen("fft_file.txt");if(fft_file==0)begin$dislay("cannotoenthefile!");$sto;endendwiresigned[31:0]fft_dataout;assignfft_dataout=xk_re;//将输出的实部信号赋值给fft_dataout寄存器always@(osedgeclk)if(m_axis_data_tvalid==1'b1)//m_axis_data_tvalid有效时输出$fdislay(fft_file,"%d",fft_dataout);//定义一个文件名,将处理后的虚部信号发存放在此文件中integerfft_im_file;initialbeginfft_im_file=$foen("fft_im_file.txt");if(fft_im_file==0)begin$dislay("cannotoenthefile!");$sto;endendwiresigned[31:0]fft_im_dataout;assignfft_im_dataout=xk_im;//将输出的虚部信号赋值给fft_im_dataout寄存器always@(osedgeclk)if(m_axis_data_tvalid==1'b1)//m_axis_data_tvalid有效时输出$fdislay(fft_im_file,"%d",fft_im_dataout);endmodule6、仿真结果:从图中可以看出,在modelsim无法观察频谱,所以只能将数据输出,在matlab中读取观察,验证设计是否正确;7、matlab分析:接下来就是matlab读取FPGAffti核处理过的数据,也就是matlab读取包含实部和虚部的fft_file.txt和fft_im_file.txt文件。Fs=20000;fid_re=foen('E:\vivado\FFT\FFT.sim\sim_1\behav\fft_file.txt','r');[xn_re,num]=fscanf(fid_re,'%lg',inf);%读取fga产生的滤波后的数据fid_im=foen('E:\vivado\FFT\FFT.sim\sim_1\behav\fft_im_file.txt','r');%打开数据文件%打开数据文件%打开数据文件%注意要将这个文件放到modelsim目录下[xn_im,num1]=fscanf(fid_im,'%lg',inf);%读取fga产生的滤波后的数据f=abs(xn_re+xn_im*j);ft=[0:(Fs/L):Fs/2]*(10^(-3));%转换横坐标以kHz为单位f1=f(1:length(ft));f1=f1/max(f1);%归一化lot(ft,f1)其中频域的波形如下图,验证了fft实验的正确
    亮了(0) 56 0 前天 10:29
  • 【Basys3 FPGA个人学习笔记连载分享】第九篇:Matlab运用fdatool工具设计fir滤波器和vavido实现
    Matlab运用fdatool工具设计fir滤波器和vavido实现实验内容:使用matlab的fdatool工具设计fir滤波器,并产生10KHZ和30KHZ的相加信号,作为fir滤波器的输入信号,通过低通滤波器,将30khz的信号滤除掉。实验平台:Xilinx大学计划与Digilent联合推出的“Basys3”FPGA开发板1:FDATOO设计fir低通滤波器要求:采用等波纹方式设计,通带截止频率为12KHZ,阻带截止频率为25KHZ,采样频率为500KHZ,通带最大衰减1dB,阻带最小衰减80dB,滤波器阶数由软件选择。直接在matlab的命令窗口输入fdatool,点击回车,就会弹出↓↓↓设置采用等波纹方式设计,通带截止频率为12KHZ,阻带截止频率为25KHZ,采样频率为500KHZ,通带最大衰减1dB,阻带最小衰减80dB↓↓↓点击界面左下方的图标setquantizationarameters设置系数为定点类型,量化位宽16,如下图所示,系数必须设置为定点类型,否则不能输出系数↓↓↓输出fir滤波器系数coe文件:点击targets->xilinxcoefficient(.COE)file输出滤波器系数。其中FrequencyResonse框中的即为所设计滤波器的幅频响应,从图中可以检出设计的滤波器符合设计要求。到此为止滤波器的设计工作完成。下面简单介绍一下FDAtool工具,在设计滤波器方面很方便MATLABFDAtool:(1)Designmethod选项:IIR:Butterworth(巴特沃思)法、ChebyshevTyeI(切比雪夫I型)法、ChebyshevTyeII(切比雪夫II型)法、Ellitic(椭圆滤波器)法FIR:Equirile(等波纹法)、Least-Squares(最小乘方)法、Window(窗函数)法。(2)FilterOrder(滤波器阶数)选项:定义滤波器的阶数,包括SecifyOrder(指定阶数)和MinimumOrder(最小阶数)。在SecifyOrder中填入所要设计的滤波器的阶数(N阶滤波器,SecifyOrder=N-1),如果选择MinimumOrder则MATLAB根据所选择的滤波器类型自动使用最小阶数。(3)FrenquencySecifications选项:可以详细定义频带的各参数,包括采样频率Fs和频带的截止频率。它的具体选项由FilterTye选项和DesignMethod选项决定,例如Bandass(带通)滤波器需要定义Fsto1(下阻带截止频率)、Fass1(通带下限截止频率)、Fass2(通带上限截止频率)、Fsto2(上阻带截止频率),而Lowass(低通)滤波器只需要定义Fsto1、Fass1。采用窗函数设计滤波器时,由于过渡带是由窗函数的类型和阶数所决定的,所以只需要定义通带截止频率Fc,而不必定义阻带参数。(4)MagnitudeSecifications选项:可以定义幅值衰减的情况。例如设计带通滤波器时,可以定义Wsto1(频率Fsto1处的幅值衰减)、Wass(通带范围内的幅值衰减)、Wsto2(频率Fsto2处的幅值衰减)。当采用窗函数设计时,通带截止频率处的幅值衰减固定为6db,所以不必定义。2:matlab设计FPGA的输入信号10kz+30khz,其中代码如下:f1=10000;%输入信号的10khzf2=30000%输入信号的30khzFs=500000;%采样频率500khzN=16;%量化位数L=1024;%数据长度+t=0:1/Fs:1/Fs*(L-1);%1/Fs表示采样一个点所需要的时间s1=sin(2*i*f1*t);%生成具随机起始相位的正弦波输入s2=sin(2*i*f2*t);%生成具随机起始相位的正弦波输入si=s1+s2;si=round(si*(2^(N-1)-1));%10bit量化f_s=si/max(abs(si));%归一化处理Q_s=round(f_s*(2^(N-1)-1));sublot(211);lot(t,Q_s);xlabel('时间(s)','fontsize',8);ylabel('幅度(v)','fontsize',8);title('时域信号波形','fontsize',8);f=abs(fft(si,L));%1024点FFTft=[0:(Fs/L):Fs/2]*(10^(-3));%转换横坐标以kHz为单位f1=f(1:length(ft));f1=f1/max(f1);%归一化sublot(212);lot(ft,f1)xlabel('频率(KHZ)','fontsize',8);ylabel('幅频(v)','fontsize',8);title('幅频响应','fontsize',8);%以二进制补码形式输出所设计的信号fid=foen('C:\Users\Administrator\Deskto\SinIn.txt','w');fork=1:length(Q_s)B_s=dec2bin(Q_s(k)+(Q_s(k)<0)*2^N,N);%k;forj=1:NifB_s(j)=='1'tb=1;elsetb=0;endfrintf(fid,'%d',tb);endfrintf(fid,'\r\n');endfrintf(fid,';');fclose(fid);matlab出输出的信号波形以及频谱3:firi核例化:(1)selectsource:选择coe文件cofficientfile:选择fdatool工具生成的fir滤波器的系数FilterTye:选择单速率↓↓↓inutsamlingfrequency:0.5MHZ采样频率clockfrequency:2MHZ:fir工作时钟↓↓↓inutdatatye:输入数据类型为有符号inutdatawidth:输入数据位宽位宽16↓↓↓其他选项默认4:firl滤波器代码:很简单,就是把firi核例化过去,在代码中相应的位置有注释;点击runsynthesis,进行综合,是否错误和criticalwarnning。`timescale1ns/1s////////////////////////////////////////////////////////////////////////////////////Comany://Engineer:////CreateDate:2017/01/1620:25:37//DesignName://ModuleName:fir//ProjectName://TargetDevices://ToolVersions://Descrition://Deendencies://Revision://Revision0.01-FileCreated//AdditionalComments:////////////////////////////////////////////////////////////////////////////////////modulefir(clk,rst,s_axis_data_tready,s_axis_data_tdata,m_axis_data_tvalid,m_axis_data_tdata);inutclk;//系统时钟inutrst;//复位inut[15:0]s_axis_data_tdata;//输入数据oututs_axis_data_tready;//fir滤波器准备好接收输入数据指示信号outut[39:0]m_axis_data_tdata;//输出数据oututm_axis_data_tvalid;//输出数据有效指示信号regs_axis_data_tvalid;//输入数据有效信号//复位时没有输入数据输入always@(osedgeclkornegedgerst)if(!rst)s_axis_data_tvalid<=1'b0;elses_axis_data_tvalid<=1'b1;fir_comiler_0fir_comiler(.aclk(clk),//inutwireaclk.s_axis_data_tvalid(s_axis_data_tvalid),//inutwires_axis_data_tvalid.s_axis_data_tready(s_axis_data_tready),//oututwires_axis_data_tready.s_axis_data_tdata(s_axis_data_tdata),//inutwire[15:0]s_axis_data_tdata.m_axis_data_tvalid(m_axis_data_tvalid),//oututwirem_axis_data_tvalid.m_axis_data_tdata(m_axis_data_tdata)//oututwire[39:0]m_axis_data_tdata);endmodule5:综合没有问题,接下来就是功能仿真;这里就需要将matlab产生的10khz+30khz的正弦信号读入到FPGA中作为滤波器输入信号;代码中$readmemb()函数,就是读取TXT文本中的数据输入到FPGA中,作为输入信号。输出的混频信号通过创建文件的方式,写入到txt文件中,具体实现参看下面的代码;最后再通过matlab读取输出的混频信号进行分析`timescale1ns/1s`defineclk_eriod500//2MHZ`definedata_eriod2000//500kHZ////////////////////////////////////////////////////////////////////////////////////Comany://Engineer:////CreateDate:2017/01/1714:09:56//DesignName://ModuleName:fir_tb//ProjectName://TargetDevices://ToolVersions://Descrition:////Deendencies:////Revision://Revision0.01-FileCreated//AdditionalComments:////////////////////////////////////////////////////////////////////////////////////modulefir_tb;regclk;//系统时钟regrst;//复位reg[15:0]s_axis_data_tdata;//wires_axis_data_tready;//wirem_axis_data_tvalid;//wire[39:0]m_axis_data_tdata;reg[15:0]data[1023:0];//数组,将FPGA读取的信号数据寄存在数组中firfir(.clk(clk),.rst(rst),.s_axis_data_tready(s_axis_data_tready),.s_axis_data_tdata(s_axis_data_tdata),.m_axis_data_tvalid(m_axis_data_tvalid),.m_axis_data_tdata(m_axis_data_tdata));integeri;initialclk=1;always#(`clk_eriod/2)clk=~clk;////产生2MHZ的系统时钟initialbeginrst=0;//复位#100;rst=1;/恢复$readmemb("E:/vivado/FIR/SinIn.txt",data);//从matlab生成文件中读取数据for(i=0;i<1023;i=i+1)begins_axis_data_tdata=data[i];//将数组的数据赋值给s_axis_data_tdata作为输入#(`data_eriod);//将输入数据以采样频率500KHZ输入end#(`clk_eriod*800000);$sto;end//定义一个文件名integerDome_samle_fir_file;initialbeginDome_samle_fir_file=$foen("E:/vivado/FIR/Dome_samle_fir_file.txt");//打开所创建的文件if(Dome_samle_fir_file==0)begin$dislay("cannotoenthefile!");//创建文件失败,显示cannotoenthefile!$sto;endendwiresigned[39:0]fir_dataout;assignfir_dataout=m_axis_data_tdata;//将输出的滤波信号赋值给fir_dataout寄存器always@(osedgeclk)if(s_axis_data_tready==1'b1)$fdislay(Dome_samle_fir_file,"%d",fir_dataout);//s_axis_data_tready有效时,将滤波信号写入到所创建的文件中endmodule6、仿真结果:10KHZ和30KHZ的相加信号,作为fir滤波器的输入信号,通过低通滤波器,30khz的信号滤除掉,只含有一种频率的信号。同时为了验证30khz的信号滤除掉,可以在matlab中分析5:matlab分析:读取FPGA滤波后的信号,进行分析,30khz的信号已经被滤除掉,但是在频谱中可以看出有一些干扰信号的产生,但是能量较小,可以忽略不计。L=1024;Fs=500000;fid=foen('E:\vivado\FIR\Dome_samle_fir_file.txt');%打开data_file.txt文件[data_out,count]=fscanf(fid,'%d',inf);%读取data_file.txt文件,将数据赋值给data_outt=1:1:1024;sublot(211);lot(t,data_out(t));xlabel('时间','fontsize',8);ylabel('幅度(v)','fontsize',8);title('时域信号波形','fontsize',8);f=abs(fft(data_out,L));%1024点FFTft=[0:(Fs/L):Fs/2]*(10^(-3));%转换横坐标以kHz为单位f1=f(1:length(ft));f1=f1/max(f1);%归一化sublot(212);lot(ft,f1)xlabel('频率(KHZ)','fontsize',8);ylabel('幅频(v)','fontsize',8);title('幅频响应','fontsize',8);同时观察matlab画出信号的波形,不是很像正弦信号,主要是因为滤波器的工作时钟为2MHZ,而采样频率(数据输入到滤波器的频率为500KHZ),这样输入数据存在4个时钟周期,若将滤波器的工作时钟将为500KHZ,则matlab画出的波形更加完美。
    亮了(0) 85 0 01-16
  • 【Basys3 FPGA个人学习笔记连载分享】第七篇:matlab和Vivado之间进行数据交换
    matlab和Vivado之间进行数据交换实验内容:利用matlab产生一个250KHZ的正弦信号,与fga内部产生的250KHZ正弦信号进行混频(相乘),将混频的信号输出到TXT文件中;最后在matlab中读取TXT文件,分析产生的信号是否符合要求实验平台:Xilinx大学计划与Digilent联合推出的“Basys3”FPGA开发板1:matlab产生一个250KHZ的正弦信号(10bit位宽)采样频率5MHZ,将产生的数据存储在SinIn.txt;%设置系统参数fi=250000;%输入信号的频率Fs=5000000;%采样频率L=1024;%数据长度N=10;%量化位数%产生信号t=0:1/Fs:1/Fs*(L-1);%1/Fs表示采样一个点所需要的时间si=sin(2*i*fi*t);%生成具随机起始相位的正弦波输入信号f_s=si/max(abs(si));%归一化处理Q_s=round(f_s*(2^(N-1)-1));%10bit量化%将输出的信号转化为2进制补码的形式,因为fga输入的数据类型为2进制补码fid=foen('C:\Users\Administrator\Deskto\SinIn.txt','w');fork=1:length(Q_s)B_s=dec2bin(Q_s(k)+(Q_s(k)<0)*2^N,N);%k;forj=1:NifB_s(j)=='1'tb=1;elsetb=0;endfrintf(fid,'%d',tb);endfrintf(fid,'\r\n');endfrintf(fid,';');fclose(fid);2:在生成一个rom的初始化coe文件,包含另一个250KHZ的正弦信号波形,matlab生成coe文件的代码如下fi=250000;%输入信号的频率Fs=5000000;%采样频率N=10;%量化位数L=1024;%数据长度t=0:1/Fs:1/Fs*(L-1);%1/Fs表示采样一个点所需要的时间si=sin(2*i*fi*t);%生成具随机起始相位的正弦波输入信号si=round(si*(2^(N-1)-1));%10bit量化fid=foen('C:\Users\Administrator\Deskto\cos.coe','wt');frintf(fid,'memory_initialization_radix=10;\r\n');frintf(fid,'memory_initialization_vector=\r\n');fori=1:1:1024if(i==1024)frintf(fid,'%.0f;\n',si(i));elsefrintf(fid,'%.0f,\n',si(i));endendfclose(fid);3:编写混频器的verilog代码(1)首先是romi核的生成,其中相关参数,深度=1024,位宽=10bit;下面是生成romi核的相应界面。↓↓↓↓↓↓(2)接下来就是乘法器i核的生成,其中相关参数,两输入为有符号,位宽10bit;下面是生成乘法器i核的相应界面(3)接下来就是混频器代码,在代码中相应的位置有注释;点击runsynthesis,进行综合,是否错误和criticalwarnning。`timescale1ns/1s////////////////////////////////////////////////////////////////////////////////////Comany://Engineer://CreateDate:2017/01/1514:07:36//DesignName://ModuleName:mix//ProjectName//Revision://Revision0.01-FileCreated//AdditionalComments://////////////////////////////////////////////////////////////////////////////////modulemix(clk,rst_n,sin_250khz,dout);inutclk;//FPGA系统时钟5MHzinut[9:0]sin_250khz;//输入的250KHz单频信号inutrst_n;//复位信号,高电平有效oututreg[19:0]dout;//输出混频后的的500kHz单频信号和直流信号wire[9:0]sine;//rom产生的正弦信号regena;//ROM使能信号reg[9:0]addra;//rom的地址信号//rom的地址信号always@(osedgeclkornegedgerst_n)if(!rst_n)addra<=10'd0;elseif(addra==8'd1023)addra<=10'd0;elseaddra<=addra+1'b1;//ROM使能信号always@(osedgeclkornegedgerst_n)if(!rst_n)ena<=1'b0;elseena<=1'b1;//romblk_mem_gen_0rom(.clka(clk),//inutwireclka.ena(ena),//inutwireena.addra(addra),//inutwire[9:0]addra.douta(sine)//oututwire[9:0]douta);wiresigned[9:0]sin_250khz_signed;assignsin_250khz_signed=sin_625khz;//将乘数转换成有符号数运算wiresigned[9:0]sine_signed;assignsine_signed=sine;//将乘数转换成有符号数运算wiresigned[19:0]mult_data;//混频信号输出//乘法运算实现混频输出mult_gen_0mult(.CLK(clk),//inutwireCLK.A(sin_250khz_signed),//inutwire[9:0]A.B(sine_signed),//inutwire[9:0]B.P(mult_data)//oututwire[19:0]P);//混频输出复制给doutalways@(osedgeclkornegedgerst_n)if(!rst_n)dout<=20'd0;elsedout<=mult_data;endmodule(4)综合没有问题,接下来就是功能仿真;这里就需要将matlab产生的250khz的正弦信号读入到FPGA中作为输入混频的一路信号;代码中$readmemb()函数,就是读取TXT文本中的数据输入到FPGA中,作为输入信号。输出的混频信号通过创建文件的方式,写入到data_file.txt文件中,具体实现参看下面的代码;最后再通过matlab读取输出的混频信号进行分析`timescale1ns/1s`defineclk_eriod200//系统时钟5MHZ,200ns////////////////////////////////////////////////////////////////////////////////////Comany://Engineer://CreateDate:2017/01/1514:58:52//DesignName://ModuleName:mixer_tb//ProjectName://TargetDevices://Revision://Revision0.01-FileCreated//AdditionalComments//////////////////////////////////////////////////////////////////////////////////modulemixer_tb;//Inutsregrst_n;//复位regclk;//系统时钟reg[9:0]sin_250khz;//输入的一路250KHZ信号//Oututswire[19:0]dout;//混频输出reg[9:0]data[1023:0];//数组,将FPGA读取的一路250KHZ信号数据寄存在数组中//InstantiatetheUnitUnderTest(UUT)mixmix(.clk(clk),.rst_n(rst_n),.sin_625khz(sin_250khz),.dout(dout));integeri;initialclk=1;always#(`clk_eriod/2)clk=~clk;//产生5MHZ的系统时钟initialbegin//InitializeInutsrst_n=0;//复位sin_250khz=0;#100;rst_n=1;//恢复#100;$readmemb("E:/vivado/charge/SinIn.txt",data);//从matlab生成文件SinIn.txt中读取250KHZ信号数据for(i=0;i<1023;i=i+1)beginsin_250khz=data[i];//将数组的数据赋值给sin_250khz输入寄存器#(`clk_eriod);end#1000;$sto;end//定义一个文件名integerdout_file;initialbegindout_file=$foen("C:/Users/Administrator/Deskto/data_file.txt");//打开所创建的文件if(dout_file==0)begin$dislay("cannotoenthefile!");//创建文件失败,显示cannotoenthefile!$sto;endendwiresigned[19:0]dout_data;//assigndout_data=dout;//将输出的混频信号赋值给dout_data寄存器wireen;assignen=clk&am;(rst_n);//写入使能信号always@(osedgeclk)if(en)$fdislay(dout_file,"%d",dout_data);//使能信号有效,每来一个时钟,混频信号混频信号写入到所创建的文件中endmodule(5)仿真结果:两输入的250KHZ的正弦信号,输出dout信号波形不是我们一眼就能分辨出来的,因为这里面包含在直流分量和500KHZ的正弦波,那么通过MATLAB进行频谱分析,就很容易分辨出信号,以便验证我们所做的混频器是否正确。(6)matlab分析:接下来就是matlab读取FPGA输出的混频信号,也就是matlab读取data_file.txt文件。其中时域和频域的波形如下图,从频谱中可以很容易看出输出的信号中只包含一个直流分量和一个500KHZ的正弦信号。验证了FPGA所设计的混频器是正确的。
    亮了(0) 107 0 01-15
  • 【Artix-7开发实战】 第四篇: 定时器中断
    此篇基于平台:ArtyFPGA开发板最近忙完各大考试和项目之后,菜鹏又来和大家交流交流Microblaze心得了。在上两次已经成功的驱动了Microblaze的GPIO模块和UART模块,最近菜鹏我研究了研究定时器功能,今天和大家分享一下。回忆我当初我跟着郭天祥老师从51的一个点灯程序踏入了电子领域的世界。此刻我依然清晰的记得,书中曾说到,单片机最重要的一个概念是中断,其中最常用的就是定时器中断,而在上两次试验的时候我都没有涉及到中断相关的概念,而有了上两次试验的基础,这次我尝试的则是一个定时器中断的配置。好的,闲话少说,直插主题。在搭建定时器中断的时候硬件环境需要什么呢?1.处理器Microblaze2.USBTOUART(上次说过,十分好用的调试方法)3.时钟4.复位5.定时器Timer6.中断控制器InterrutController7.DDR3搭建硬件环境之后,导入到SDK里头,就是追溯底层代码的时候了~首先我给出以下表:Timer寄存器CSR控制/状态寄存器基地址:0x41C00000偏移量:0x003116保留150保留CEAEPIOETEILARECEGDCCMBIT0:(CatureMode):1:配置为捕获模式当外部捕捉线有效时0:比较模式(默认)BIT1:(DownCount):1:计数器向下计数0:计数器向上计数(默认)BIT2:(EXTGenerate):1:使能外部输出0:关闭外部输出(默认)BIT3:(EXTCature):1:使能外部输入给定时器计数器0:关闭外部输入给定时器计数器(默认)BIT4:(AutoReload):在比较模式中:1:计数器值从Reload寄存器中自动重装载0:关闭自动重装载(默认)在捕获模式中:1:不保持原先的捕获值0:捕获原先捕获值(默认)BIT5:(Load):1:使用原先TLR寄存器的装载值0:不使用原先TLR寄存器的装载值(默认)BIT6:(EnableINT):1:使能输出中断0:关闭输出中断(默认)BIT7:(EnableTMR):1:使能特定定时器0:关闭特定定时器(默认)BIT8:(INTOccured)(中断发生位)如果置1,则代表发生了中断,随后将被清0BIT9:(EnablePWM):1:使能PWM0:关闭PWM(默认)BIT10:(EnableAll):1:使能所有定时器计数器0:未使能所有定时器计数器(默认)BIT11:(CASC):级联模式#defineXTC_TCSR_OFFSET0/**<Control/Statusregister*/#defineXTC_TLR_OFFSET4/**<Loadregister*/#defineXTC_TCR_OFFSET8/**<Timercounterregister*/其余三个寄存器则为装载寄存器(TLR),定时器计数器寄存器(TCR)。好,接下来我们直接上代码。使用定时器中断的配置:1.配置TLR装载寄存器XTmrCtr_mSetLoadReg(TIMER_BASEADDR,0,10000000);找到它的来源:#defineXTmrCtr_SetLoadReg(BaseAddress,TmrCtrNumber,RegisterValue)\XTmrCtr_WriteReg((BaseAddress),(TmrCtrNumber),XTC_TLR_OFFSET,\(RegisterValue))定时器主频100M情况下,将装载值填为10M,则100ms将会溢出触发定时器中断一次。2.配置CSR(状态/控制寄存器)XTmrCtr_mSetControlStatusReg(TIMER_BASEADDR,0,XTC_CSR_ENABLE_TMR_MASK|XTC_CSR_ENABLE_INT_MASK|XTC_CSR_AUTO_RELOAD_MASK|XTC_CSR_DOWN_COUNT_MASK);来源:#defineXTmrCtr_SetControlStatusReg(BaseAddress,TmrCtrNumber,RegisterValue)\XTmrCtr_WriteReg((BaseAddress),(TmrCtrNumber),XTC_TCSR_OFFSET,\(RegisterValue))其实发现也是进行写寄存器操作,只不过改变了偏移量。根据上边对CSR寄存器的解析,我们很容易的看到,该种配置下,使能了特定定时器,使能了定时器中断,开启了自动重装载,向下计数模式,默认为比较计数模式。3.打开Microblaze中断microblaze_enable_interruts();该指令位于mb_interface.h,里边有许多常规的许多指令,菜鹏我也没有用过太多,不过这部分应该引起重视才行。4.注册中断控制器到Microblaze上microblaze_register_handler(XIntc_DeviceInterrutHandler,INTC_DEVICE_ID);关于官方的函数说明为:*Registersato-levelinterruthandlerfortheMicroBlaze.The*argumentrovidedinthiscallastheDataPtrisusedastheargument*forthehandlerwhenitiscalled.关于中断以及其中内部菜鹏我还在探索,等有结果后再和大家交流交流。5,将定时器中断注册到中断控制器XIntc_RegisterHandler(INTC_BASEADDR,XPAR_MICROBLAZE_0_AXI_INTC_AXI_TIMER_0_INTERRUPT_INTR,(XInterrutHandler)timer_int_handler,(void*)0);其中time_int_handler是用户自己定义的定时器中断函数,按照我的理解就是将定时器中断挂载在中断控制器上,并注册了定时器中断函数。6.使能中断控制器的主使能XIntc_mMasterEnable(INTC_BASEADDR);7.使能中断控制器上的定时器中断源XIntc_mEnableIntr(INTC_BASEADDR,XPAR_AXI_TIMER_0_INTERRUPT_MASK);配置好了定时器以及中断之后,就到了定时器中断函数里边的代码了;为了检测到确实了发生了中断,我们需要到CSR中读取第8位读取InterrutOccurred.如果为1,则发生中断,反之没有。#defineXTmrCtr_GetControlStatusReg(BaseAddress,TmrCtrNumber)\XTmrCtr_ReadReg((BaseAddress),(TmrCtrNumber),XTC_TCSR_OFFSET)此后我们还需要有一步非常重要的操作,如果没有此操作,就无法达到精确的计时,反馈时间非常奇怪。在发生中断进入中断函数之后,需要刷新CSR寄存器中的值//将状态寄存器写回XTmrCtr_mSetControlStatusReg(TIMER_BASEADDR,0,timer_csr);完整中断函数如下voidtimer_int_handler(void){unsignedinttimer_csr;timer_cnt++;//读取定时器的状态寄存器,确认是否真的产生了中断timer_csr=XTmrCtr_mGetControlStatusReg(TIMER_BASEADDR,0);if(timer_csr&am;XTC_CSR_INT_OCCURED_MASK){//将状态寄存器写回XTmrCtr_mSetControlStatusReg(TIMER_BASEADDR,0,timer_csr);i++;if(i==10){j++;xil_rintf("***i=%d\n\r",j);i=0;}}}由此,Timer即可使用,对其中有不同见解的,欢迎大家来交流。
    亮了(0) 61 0 01-13
  • PmodACL三轴加速度传感器Verilog代码分享
    这是一个PmodACL三轴加速度传感器的示例项目。工程文件分为在Vivado中开发的Basys3版本和在ISE中开发的Nexys3版本(Verilog代码是一样的)。将PmodACL插入FPGA板卡的JB接口。使用拨码开关SW0和SW1选择数码管上查看X/Y/Z轴的加速度数据。具体说明见附件中文档。
    亮了(0) 41 0 01-10
  • 基于Microblaze的Pmod_ACL加速度计驱动设计(运动加速度特征采集系统)
    图1三轴加速度方向示意图前言:计步器是一种颇受欢迎的日常锻炼进度监控器,可以激励人们挑战自己,增强体质,帮助瘦身。早期设计利用加重的机械开关检测步伐,并带有一个简单的计数器。晃动这些装置时,可以听到有一个金属球来回滑动,或者一个摆锤左右摆动敲击挡块。如今,应用先进的MEMS惯性传感加速度计和复杂的算法来精确监测真实的步伐,较之传统计步器精确度大大提高。加速度计可以测量如上图所示三个方向的加速度,用来分析跑步或步行的特征。本文所使用的Pmod_ACL是以ADI公司的三轴加速度计ADXL345为核心的模块,小巧纤薄,功耗极低。Starting....硬件平台:CMODA7-35T(Xilinx)软件平台:VIVADO/SDK2015.2设计目标:基于Microblaze系统,实现对加计的数据实时采集并保存。通过按键的控制完成数据采集以及传输至PC。1.按键第一次按下,开始采集X,Y,Z三轴加速度信息并保存;2.按键第二次按下,停止采集;3.按键第三次按下,将采集到的数据通过串口发送至PC机。4.将数据导入Matlab进行各种算法测试。硬件环境搭建在VIVADO中搭建好系统,部分重要设定参数:1.Microblaze32KBLocal_memory;2.EnableInstructionandDataCaches(forSRAM);3.AddIP:Pmod_ACL,USB_Uart,Cell_RAM,PushButton。上述IP都是出自Board.xml或Pmodgithub中(见附件),搭建好的系统框图如下图所示。图2硬件系统框图硬件系统描述:将12Mhz板载晶振工作频率倍频至100MHz供系统使用,使用了32KBBram作为Microblaze内存,同时考虑到C程序数据处理量大的情况,将板载的512KBSRAM添加为系统内存,添加axi_uartIP作为串口驱动,将保存的数据最终传输给PC机。具体硬件环境搭建流程请参考:htt://xilinx.eetrend.com/blog/10459如何使用IP配合Microblaze开发请参考:htts://reference.digilentinc.com/learn/rogrammable-logic/tutorials/mod-is/start进入SDKC开发环境使用GITHUB上的IP库非常便利,里面有Digilent的美国工程师写好的库函数,看懂库函数并学会调用即可。新建好一个应用工程后,将硬件平台写好的demo复制进APP工程源文件下:图3操作示意1双击打开main.c文件,会发现一个写好的驱动Pmod_ACL的demo,非常方便于二次开发。这里需要自己写一个按键的驱动,代码如下:图451即视感的按键消抖XGio_ReadReg(XPAR_GPIO_0_BASEADDR,0);//读按键对应的//IO口DATA寄存器,如果是1,则按键按下。接着,给大家看下主程序代码:程序流程:按键第一次按下,开始读取加速度;第二次按下,停止读取加速度,同时,若读取10s加速度之后自动停止;第三次按下,将读取的数据通过串口发送至PC机。这里需要注意下:需要讲Microblaze的堆栈大小扩大,才能使程序正常运行。程序中申请了4个大容量数组,对原有的StackandHea来讲溢出了。将堆和栈扩大至2KB。图5扩容堆栈大小测试结果1.静止不动2.将设备握在手中正常行走初步数据处理展示,目前使用拟合矢量法计算步数:图6初步计算结果这只是暂时结果,下面需要做中值滤波、卡尔曼滤波等来精确步伐数。市面上能够实现计步功能的产品有很多,但是精度很差,甚至有“刷步数”的情况。笔者想实现精确计步的功能,日后可以添加磁传感器,GPS信号等做数据融合,就可以精确计步。硬件实物图:图7实物图1.CMODA7开发板2.Pmod_ACL三轴加计3.Uart4.电池仓(三节干电池)若需要过程文件的请留言。笔者联系邮箱:x_eng2016@163.com版权声明:原创作品,允许转载,转载时务必以超链接形式标明文章原始出处、作者信息和本声明,否则追究法律责任。
    亮了(0) 62 1 01-09
解决问题:29
干货热帖:89
会员总数:2991
总帖数:329
我要发帖

贡献榜

  • hahavchen

    创新创业教育知名圈内人

    常隐匿于江湖的资深攻城狮,拥有超过10年的半导体与测控行业产品研发、技术支持、市场拓展及区域销售经验。目前同时担任上海交通大学本科生企业导师。

    • 王斌Jr

      工程师

      Andorid工程师,书呆子

    • mysunday2

      本科生

      武汉大学在读研究生,懂一点Java,懂一点LabVIEW

    • 风雨兼程

      本科生

      热爱科研,忠于技术,渴望在LabVIEW的世界里遨游。

    • 地板

      媒体人

      资深媒体人,现任职于国内某知名电子行业媒体

  • EltonLiang

    工程师

    汽车电子方向系统集成工程师,坐标北京。精通LabVIEW与测控技术,乐于分享总结。

    • Superlava

      工程师

      国家电网工程师,对于创新创造,我是真爱粉!

    • chnwjian

      研究生

      擅长物理实时测量和ardunio

    • linon

      教师

      东南大学电子科学与工程学院

    • suo ivy

      创业者

      乐忠于机器人的创业少年

  • CC

    研究生

    擅长FPGA以及LabVIEW程序设计,拥有多年项目开发经验,曾开发过高速误码仪、自动泊车系统,研发并将PM2.5检测仪推入市场,目前致力于FPGA的图像处理研究。

    • 冰淇淋

      研究生

      略懂c语言,爱玩爱交流

    • Veritas

      电子技术爱好者

      非电类专业的在校纯技术爱好者

    • 竹杖芒鞋轻胜马

      研究生

      擅长电子电力,电源,逆变器,Matlab的同济骚年

    • 熊猫家的猫

      研究生

      热爱电子设计,熟悉LabVIEW编程,希望和大家一起学习进步。

    • 李比希

      电子技术爱好者

      喜欢LabVIEW,会点c语言,痴迷玩创,让激情碰出创意的火花!

    • 糊涂宝宝

      研究生

      精通C语言与电路设计。善于软硬件结合开发实际工程项目。

    • LabVIEWers

      工程师

      汽车电子电控领域工程师。个人信条:追求卓越。

    • 南瓜粥

      本科生

      致力于精密测量@天津大学

  • philo

    工程师

    刚毕业的新晋TI验证工程师一枚。内心埋有一个小小的希望靠技术改变世界的种子。CLD(认证LabVIEW开发工程师)持有者,并熟悉C语言与MATLAB。

    • 阳光的新手125

      研究生

      Strict coding is the boddy, smart thoughts are the soul.

    • AoduLabVer

      工程师

      华为数字视频领域工程师,技术宅,CLD,热衷LabVIEW

    • 西兰花教负责人

      创业者

      俗称“福建三本“的某985高校毕业,正不务正业地创业中

    • berwin

      创业者

      好奇主义 & 观察者 & 行动派

  • RockMOOC

    教师

    博士,现于哈尔滨工业大学任教。拥有超过8年基于FPGA的数字系统硬件设计经验,精通FPGA开发。

    • wonderm

      本科生

      熟悉LabVIEW/Matlab/Verilog,擅长STM32/K60硬件开发

    • diguaguowang

      研究生

      一直羡慕会各种编程的人,也在向着这个方向努力

    • 阿Q

      工程师

      精通FPGA的酷创达人

    • wigger

      工程师

      Digilent元老级大牛

  • Mr. D

    工程师

    部落的发起者与第一位"Digger",非典型张江男一枚。致力于为有执着有梦想的志同道合者缔造一个可以互相勾搭的中文开源技术社区。