ADSP BF609实际开发中的问题及解决.docx

上传人:b****6 文档编号:4332234 上传时间:2022-11-29 格式:DOCX 页数:19 大小:1.10MB
下载 相关 举报
ADSP BF609实际开发中的问题及解决.docx_第1页
第1页 / 共19页
ADSP BF609实际开发中的问题及解决.docx_第2页
第2页 / 共19页
ADSP BF609实际开发中的问题及解决.docx_第3页
第3页 / 共19页
ADSP BF609实际开发中的问题及解决.docx_第4页
第4页 / 共19页
ADSP BF609实际开发中的问题及解决.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

ADSP BF609实际开发中的问题及解决.docx

《ADSP BF609实际开发中的问题及解决.docx》由会员分享,可在线阅读,更多相关《ADSP BF609实际开发中的问题及解决.docx(19页珍藏版)》请在冰豆网上搜索。

ADSP BF609实际开发中的问题及解决.docx

ADSPBF609实际开发中的问题及解决

ADSPBF609实际开发中的问题及解决

一、程序仿真OK,烧写到目标板就挂了

问题原因:

BF609L1内存用超了,程序跑飞造成;仿真的时候,变量是放在仿真器中的,不需要到目标内存中,所以仿真OK,烧写到目标板就挂了。

解决方法:

将大体积的变量放到L2中;

如:

原(未指定位置的变量默认放到L1中):

float VolDataBufFft1024[3][1024];//3x4KB 

float CurDataBufFft1024[9][1024]; // 9x4KB

改为:

#pragmaalign4

#pragmasection("L2_sram")

float VolDataBufFft1024[3][1024];//1024pointswithin10peroids,for3voltagechannels

#pragmaalign4

#pragmasection("L2_sram")

float CurDataBufFft1024[9][1024]; //1024pointswithin10peroids,for6currentchannels

二、ADSP-BF609乘除运算需要的周期数及测试方法  

1cycle=1/主频;当BF609运行在最高主频500MHz时,1cycle=2ns;需要说明的是:

DSP是流水线指令,同样的运算,放到代码的不同位置,测得的时间不完全相同,看编译效果;

1.完成1次常量的乘法:

6cycles; 例如:

14.05 * 177777777.888888888;

2.完成1次常量的除法:

10cycles;例如:

14.05 / 177777777.888888888;

3.完成1次变量的乘法:

72cycles;例如:

float i * floatk;

4.完成1次变量的除法:

251cycles;例如:

float i / floatk;

5.完成变量的乘除法:

 317 cycles;例如:

float i * floatj  / floatk;

测试方法:

CCES提供代码运行周期数的测试函数,

#include

#definePROFBEG(TAG)  asmvolatile("%0=cycles;":

"=d"(TAG.nCycles))

#definePROFEND(TAG) asmvolatile("r0=cycles;%0=r0-%0;%1=%0+%1;":

"+d"TAG.nCycles), "+d"TAG.nSum):

:

"R0")

typedefstruct

{

  uint32_t  nCycles;

  uint32_t  nSum;

}prof_t  goProfile;

PROFBEG(goProfile); //在需要测试的代码前加PROFBEG()

Result=14.05/177777777.888888888;

PROFEND(goProfile); //在结束点加PROFEND()

printf("[CORE0]1:

needcycles=%d!

\n",goProfile.nCycles);

三、BF609SPIFlash烧写完成,但跑不起来(CCES自带的Device_ProgrammerDriver)  

BF609的开发板上用到了Winbond的SPIFlash W25Q32BV;于是官方在CCES自带了这款Flash的烧写驱动,这个驱动可以将你的LDR文件,通过仿真器下载到你的目标板上的Flash;(当然,如果你有编程器,如:

周立功的SmartPRO,就不用走这种方式了)。

BF609的开发板上,25Q32的连接图如下:

他实际上是支持QUAD,4线模式的;在CCES的驱动中,下载程序时也是设置在QUAD模式;

如果,你不幸忽略了WP,HOLD,将这两个信号直接上拉完事,如这样:

那么,你再用官方提供的driver下载ldr就会出现:

虽然烧写提示done,但复位后跑不起来,实际上是没有烧写成功!

有两种解决方法:

1.如果BF609的SPI0D2,SPI0D3这两只脚有拉线出来,OK,把它们分别连到WP,HOLD,保持跟开发板一样;

2.如果这两只脚没有拉线出来,那就改驱动;

因为driver的源码是提供的,在“ADSP-BF609_Evaluation_Board-Rel1.0.3\BF609_EZ-Board\Blackfin\Examples\Device_Programmer\serial\”目录下,找到w25q32bv.c,修改flashinfo,使它只支持STANDARD模式;

 重新编译生成.dxe文件,下载程序时,使用该文件就可以完成下载了;

四、电力谐波FFT 

谐波次数与采样频率的关系,假设要求的谐波次数为Nharm=50次,那么要求的采样频率:

fs >= 2*Nharm *工频= 50*50*2;

以上关系需要用奈奎斯特定理来解释:

50次谐波对应的信号频率为50*50Hz=2.5KHz,根据奈奎斯特定理,采样频率fs>=2*2.5KHz;

做FFT时,从10周波采样点中抽取1024个点出来处理,相当于采样频率降到5.12KHz,还满足奈奎斯特定理; 

用ADSP-BF609(工作频率500MHz),1024点FFT需要时间17.5ms;

五、用BF609的SPORT读取AD7606的Bug解决方法  

1.硬件框图:

Bug:

通过SPORT读取的数据有怪点,怪点的值为正常值的2倍,且两个怪点的距离为20个点;如图(正常应该是平滑的正弦波):

可以排除AD7606本身输出数据不正确的原因,将bug锁定在SPORT读的问题,或者说是SPORT读数据的时序问题;

设定7606的量程为5V,第一通道的输入数据为5V,那么AD7606的理论输出值应该是0x7FFF;

用示波器抓取实际波形如图:

从时序上看,实际波形与理论输出值是相符合的,为0x7FFF;但这只能说明这次抓波没有找到怪点;

尝试修改SPORTCLK,FS的配置(只有这两个地方会产生时序问题),发现:

驱动中配置CLK,FS如下:

 这样的配置对应的波形输出如下:

就像图片里添加的文字所说,这种配置让读到的所有数据左移了一位,从而造成读取值翻倍;但这种配置不会出现怪点!

为了避免无解的怪点,我采用了这种配置,因为读取值左移了一位,需要右移一位,不足之处在于:

造成了1位误差,相当于16位的ADC,只有15位是有效的。

当量程为+-5V时,这个误差是LSB=152uV;当量程为+-10V时,这个误差是LSB=304uV;

 PS:

对这种高精度的ADC来说,模拟电源的要求很高,电源纹波>152uV,以上的误差就可以忽略不计了;

两种现象的因果关系是这样的:

软件配置-->输出波形不同-->读取数据不对-->实际结果不同。

可以用截图表示出来,第一种情况:

1.软件配置:

2.输出波形:

 

3.发现跳点:

 

 

4.打印结果:

 

第二种情况:

 

 

 

 

 

OK,既然所以结果都是那两处配置引起,不妨再试另外两种组合。

组合三:

 结果与以上第二种情况一样

 

组合四:

 

输出值不正确,而且是不确定的;

在本项目中,两个地方用的了SPORT来产生SPI的时序,都出现了问题,而且很难解决;

对于ADI的SPORT来说,他不是全能的串口,在BF609的手册Page1627第一句就有说,SPORT不兼容SPI;

以此,谨记!

五、正弦函数的频谱图(FFT)  

从理论上讲,正弦函数的傅里叶变换是冲击函数:

它的幅值为原正弦信号幅值的1/2倍;即:

若x(t)=Acos(Ωt),则其频谱幅值最大值为A/2;

 

但是,我们用matlab求出来的频谱图却不是这样的;

原因是:

1.理论中的正弦信号是无限长连续信号,而matlab,参与运算的信号只是截取了其中1个周期或多个周期的信号,就变成   了有限长信号了;无限长信号和有限长信号的傅里叶变换是不一样的!

    

2.理论中的正弦信号是连续的模拟信号,而应用中的正弦信号都是采样,量化处理的,是数字信号;模拟信号和数字信    号的傅里叶变换是不一样的!

对于已知周期的信号,通常只需要取其中一个周期做代表分析;但实际应用中,信号的频率通常已知,但噪声的频率却不固定,所以,应尽可能长的截取信号;

下面介绍在Matlab中,如何分析正弦函数的FFT:

已知正弦信号x(t)=4.6sin(2*pi*f0*t),每周波采样点数Ns=512,采样频率fs=f0*512;(f0为正弦信号的固有频率)

在Matlab中需要做一下处理:

1.将时间轴离散化:

  ts=tp*n=(T0/Ns)*n=n/f0*512=n/fs; n=0:

511;tp为每周波采样512点的时间间隔;

2.将连续信号x(t)离散化:

x(ts)= 4.6sin(2*pi*f0*ts)=4.6sin(2*pi*n/N);

  可以看出x(t)离散化后,已经与信号的固有频率没关系了,这个信号已经变成了与n相关的函数:

x(n)= 4.6sin(2*pi*n/N); n=0:

511;

3.离散信号在Matlab中求FFT就很容易了:

X(n)=FFT(x(n))*2/Ns;

4.根据周期信号的傅里叶变换的性质:

时域的周期,造成频域的离散;时间的离散,造成频域的周期;

  可知:

X(n)为离散的,且有周期;离散点的间距正好是正弦信号的固有频率f0;周期为采样周期1/fs;

  X(0),X

(1)....分别对应x(t)的第0次,1次...谐波;

5.如果要在二维图上显示频率与频谱幅值的关系,还需要:

  将横轴映射为频率值,映射关系为f=n*f0;

6.根据奈奎斯特采样定理,当采样频率为fs时,可以得到FFT后的最高有效频率为fs/2;最高谐波次数为Ns/2-1;

  

具体实现如下(Matlab中,已调试通过):

%求正弦信号的傅里叶变换

Ns=512;%采样点

n=0:

Ns-1;

xn= 4.6*sin(2*pi*n/Ns); %离散的正弦信号

Xn=  fft(xn);   %fft的结果是复数

Xn=abs(Xn)*2/Ns; %求绝对值得到幅值,乘以2,乘以Ns是由傅里叶变换公式导致的

%用二维图显示原始正弦信号

subplot(3,1,1),plot(n,xn);%画出原始正弦信号

xlabel('n=0:

511');ylabel('振幅');

title('原始的正弦信号');

%用二维图显示信号0~255次的谐波

Nyquist = Ns/2-1;%根据奈奎斯特定理,只需显示前255次的谐波

subplot(3,1,2),plot(n(1:

Nyquist),Xn(1:

Nyquist)); 

xlabel('n=0:

255');ylabel('谐波幅值');

title('0~255次的谐波');

%用二维图显示信号频率与幅值的关系

f0=50;  %假设信号的固有频率为50Hz

f=n*f0;  %频率与横轴序列n的映射关系

subplot(3,1,3),plot(f(1:

Nyquist),Xn(1:

Nyquist)); %根据奈奎斯特定理,只需显示前fs/2部分的频谱

xlabel('f=0,50Hz...255*f0Hz');ylabel('幅值');

title('频率与幅值的关系');

运行结果如下:

图中,在f=f0=50Hz时,幅值为4.6;即一次谐波幅值为4.6;

六、BF609CCES下的SPI驱动调试 

在CCES环境下,ADI自带了驱动接口函数,为驱动调试省下一大杯子事;但是这为人熟知的SPI,在调试过程中还是遇到了挫折,几度想撞墙;

最大的问题:

死机

实际的SPI驱动接口是全双工功能的,所以传输完成后,接口函数的返回值是ADI_SPI_TRANSCEIVER_PROCESSED,没有区分是发送完成还是接收完成;我的应用只需要半双工就可以了,按我的思路,是需要区分的,所以,我在驱动的StartInterruptTransceiver()函数里做了修改,判断如果提交的接收buffer是NULL时,只使能transmit;如果提交的发送buffer是NULL时,只使能resecver;这本来毫无争议,实际上这是对驱动的一种优化;但当发送21个字节时,系统崩溃了,PC指针留在出中断,返回主函数时,很像堆栈溢出,查找每个流程和函数,没有发现任何原因,人都快崩溃了;一个偶然的机会,找到了原因,跟代码毫无关系,是由于CCES没有配置使用外部128MB的RAM,导致内存不足,系统崩溃;

第二个bug:

丢数据

发送8字节以上的帧,会插入0X00,经琢磨,想到是总线速度太慢的问题(之前是50MHz,SPI波特率是25MHz,slave模式),总线改为25MHz,丢的字节更多了;改为最大的200MHz,居然还是丢;最终放弃了datainterrupt模式,改为DMA模式,问题得解!

七、Blackfin入门教程SPORT(转)  

ADSP-BF53x上有两个SPORT口,SPORT(synchronousserialports)接口是ADSP-BF53x上速度最快的串口,其速度可以达到系统时钟的1/2,每一个SPORT口有两根接收数据线和两根传输数据线,支持全双工模式传输。

SPORT接口通常用做一些高速的数据传输,它支持I2S模式,通常将SPORT接口连接音频的编解码器芯片,作为音频数据输出接口。

  SPORT时钟频率配置:

SPORTx_TCLKfrequency=(SCLKfrequency)/(2x(SPORTx_TCLKDIV+1))

XML:

NAMESPACEPREFIX=O/>SPORTx_RCLKfrequency=(SCLKfrequency)/(2x(SPORTx_RCLKDIV+1))SPORT同步信号频率配置:

  SPORTxTFSfrequency=(TSCLKxfrequency)/(SPORTx_TFSDIV+1)

  SPORTxRFSfrequency=(RSCLKxfrequency)/(SPORTx_RFSDIV+1)

XML:

NAMESPACEPREFIX=V/>寄存器功能SPORTx_TX_CONFIGSPORTx传输配置寄存器SPORTx_RX_CONFIGSPORTx传输配置寄存器SPORTx_TXSPORTx传输寄存器SPORTx_RXSPORTx接收寄存器SPORTx_TSCLKDIVSPORTx传输时钟配置寄存器SPORTx_RSCLKDIVSPORTx接收时钟配置寄存器SPORTx_TFSDIVSPORTx传输同步信号配置寄存器SPORTx_RFSDIVSPORTx接收同步信号配置寄存器SPORTx_STATSPORTx状态寄存器*pSPORT0_TCLKDIV=TCLKDIV;//配置SPORT传输接口的时钟频率

*pSPORT0_TFSDIV=TFSDIV;//配置SPORT传输接口的同步频率

  *pSPORT0_TCR1=ITFS|TFSR|ITCLK;//配置SPORT传输工作模式

  *pSPORT0_TCR2=31;//配置SPORT以32Bit数据传输

  *pDMA2_PERIPHERAL_MAP=0x2000;//设置SPORT传输接口DMA

  *pDMA2_CONFIG=WDSIZE_32|DI_EN|FLOW_1;//设置DMA工作模式

  *pDMA2_START_ADDR=(void*)iTxBuffer;//设置DMA传输数据起始地址

  *pDMA2_X_COUNT=1000;//设置DMA传输次数

  *pDMA2_X_MODIFY=4;//设置DMA每次地址增量变化

  *pDMA2_CONFIG=(*pDMA2_CONFIG|DMAEN);//使能传输DMA

  *pSPORT0_TCR1=(*pSPORT0_TCR1|TSPEN);//使能传输SPORT

  *pSIC_IAR0=0xffffffff;

  *pSIC_IAR1=0xfffff

研发项目管理XML:

NAMESPACEPREFIX=ST1/>

xml:

namespaceprefix=st1/>32f;//配置SPORTDMA中断等级

  *pSIC_IAR2=0xffffffff;

  register_handler(ik_ivg9,Sport0_RX_ISR);//注册接收中断

  register_handler(ik_ivg10,Sport0_TX_ISR);//注册传输中断

  *pSIC_IMASK=0x00000600;//使能中断

  EX_INTERRUPT_HANDLER(Sport0_TX_ISR)//传输DMA中断函数

  {

  *pDMA2_IRQ_STATUS=0x0001;//清楚中断标志位

  printf("SPORTTXDMADone!

\n");//打印信息

  *pSIC_IMASK&=~0x00000400;//关闭传输中断

}

代码实现了通过SPORT0接口利用SPORT0DMA传输数据和接收数据,SPORT接口时钟和同步信号采用内部由系统时钟配置分频获取。

  代码描述了SPORT接口使用DMA传输时常用的配置,没有和其他设备做通讯,所以看不到接收的实际数据。

对于BF60x系列,只能用CCES环境编译,CCES中自带了SPORT驱动,与VDSP环境不同的是,CCES提供的驱动,兼容RTOS;就是说CCES中系统自带的接口驱动是操作系统格式接口的;所以这种方式下的驱动,需要摸索:

如图中的两个merroy,要是独立的;否则,两个HSPORT只能有一个被配置(重复配置);

八、ADC位数与LSB误差(转)  

当选择模数转换器(ADC)时,最低有效位(LSB)这一参数的含义是什么?

有位工程师告诉我某某生产商的某款12位转换器只有7个可用位。

也就是说,所谓12位的转换器实际上只有7位。

他的结论是根据器件的失调误差和增益误差参数得出的,这两个参数的最大值如下:

失调误差=±3LSB,

增益误差=±5LSB,

  乍一看,觉得他似乎是对的。

从上面列出的参数可知最差的技术参数是增益误差(±5LSB)。

进行简单的数学运算,12位减去5位分辨率等于7位,对吗?

果真如此的话,ADC生产商为何还要推出这样的器件呢?

增益误差参数似乎表明只要购买成本更低的8位转换器就可以了,但看起来这又有点不对劲了。

正如您所判断的,上面的说法是错误的。

  让我们重新来看一下LSB的定义。

考虑一个12位串行转换器,它会输出由1或0组成的12位数串。

通常,转换器首先送出的是最高有效位(MSB)(即LSB+11)。

有些转换器也会先送出LSB。

在下面的讨论中,我们假设先送出的是MSB(如图1所示),然后依次送出MSB-1(即LSB+10)和MSB-2(即LSB+9)并依次类推。

转换器最终送出MSB-11(即LSB)作为位串的末位。

  LSB这一术语有着特定的含义,它表示的是数字流中的最后一位,也表示组成满量程输入范围的最小单位。

对于12位转换器来说,LSB的值相当于模拟信号满量程输入范围除以212或4,096的商。

如果用真实的数字来表示的话,对于满量程输入范围为4.096V的情况,一个12位转换器对应的LSB大小为1mV。

但是,将LSB定义为4096个可能编码中的一个编码对于我们的理解是有好处的。

  让我们回到开头的技术指标,并将其转换到满量程输入范围为4.096V的12位转换器中:

失调误差=±3LSB=±3mV,

增益误差=±5LSB=±5mV,

  这些技术参数表明转换器转换过程引入的误差最大仅为8mV(或8个编码)。

这绝不是说误差发生在转换器输出位流的LSB、LSB-1、LSB-2、LSB-3、LSB-4、LSB-5、LSB-6和LSB-7八个位上,而是表示误差最大是一个LSB的八倍(或8mV)。

准确地说,转换器的传递函数可能造成在4,096个编码中丢失最多8个编码。

丢失的只可能是最低端或最高端的编码。

例如,误差为+8LSB((+3LSB失调误差)+(+5LSB增益误差))的一个12位转换器可能输出的编码范围为0至4,088。

丢失的编码为4088至4095。

相对于满量程这一误差很小仅为其0.2%。

与此相对,一个误差为-3LSB((-3LSB失调误差)—(-5LSB增益误差))的12位转换器输出的编码范围为3至4,095。

此时增益误差会造成精度下降,但不会使编码丢失。

丢失的编码为0、1和2。

这两个例子给出的都是最坏情况。

在实际的转换器中,失调误差和增益误差很少会如此接近最大值。

  在实际应用中,由于ADC失调或增益参数的改进而使性能提升的程度微不足道,甚至可以忽略。

但是,对于那些将精度作为一项设计目标的设计人员来说,这种假设太过绝对。

利用固件设计可以很容易地实现数字校准算法。

但更重要的是,电路的前端放大/信号调理部分通常会产生比转换器本身更大的误差。

  通过上面的讨论可以对本文开头提到的错误结论有一个更为全面而清晰的认识。

事实上,上述的12位转换器的精度约为11.997位。

采用微处理器或单片机可以利用简单的校准算法消除这种失调和增益误差,这对设计人员来说无疑是个好消息。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 初中教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1