标题:
DSP入门学习经验
[打印本页]
作者:
苹果也疯狂
时间:
2014-4-23 17:08
标题:
DSP入门学习经验
本帖最后由 苹果也疯狂 于 2014-4-23 17:14 编辑
DSP
的特点
:
对于没有使用过
DSP
的初学者来说
,
第一个困惑就是
DSP
其他的嵌入式处理器究竟有什么不同
,
它和单片机
,ARM
有什么区别
.
事实上
,DSP
也是一种嵌入式处理器
,
它完全可以完成单片机的功能
.
唯一的重要的区别在于
DSP
支持单时钟周期的
"
乘
-
加
"
运算
.
这几乎是所有厂家的
DSP
芯片的一个共有特征
.
几乎所有的
DSP
处理器的指令集中都会有一条
MAC
指令
,
这条指令可以把两个操作数从
RAM
中取出相乘
,
然后加到一个累加器中
,
所有这些操作都在一个时钟周期内完成
.
拥有这样一条指令的处理器就具备了
;
DSP
功能
具有这条指令就称之为数字信号处理器的原因在于
,
所有的数字信号处理算法中最为常见的算术操作就是
"
乘
-
加
".
这是因为数字信号处理中大量使用了内积
,
或称
"
点积
"
的运算
.
无论是
FIR
滤波
,FFT,
信号相关
,
数字混频
,
下变频
.
所有这些数字信号处理的运算经常是将输入信号与一个系数表或者与一个本地参考信号相乘然后积分
(
累加
),
这就表现为将两个向量
(
或称序列
)
进行点积
,
在编程上就变成将输入的采样放在一个循环
buffer
里
,
本地的系数表或参考信号也放在一个
buffer
里
,
然后使用两个指针指向这两个
buffer.
这样就可以在一个
loop
里面使用一个
MAC
指令将二者进行点积运算
.
这样的点积运算对与处理器来说是最快的
,
因为仅需一个始终周期就可以完成一次乘加
.
了解
DSP
的这一特点后
,
当我们设计一个嵌入式系统时
,
首先要考虑处理器所实现的算法中是否有点积运算
,
即是否要经常进行两个数组的乘加
,(
记住数字滤波
,
相关等都表现为两个数组的点积
)
如果有的话
,
每秒要做多少次
,
这样就能够决定是否采用
DSP,
采用多高性能的
DSP
了
.
浮点与定点
浮点与定点也是经常是初学者困惑的问题
,
在选择
DSP
器件的时候
,
是采用浮点还是采用定点
,
如果用定点是
16
位还是
32
位
?
其实这个问题和你的算法所要求的信号的动态范围有关
.
定点的计算不过是把一个数据当作整数来处理
,
通常
AD
采样来的都是整数
,
这个数相对于真实的模拟信号有一个刻度因子
,
大家都知道用一个
16
位的
AD
去采样一个
0
到
5V
的信号
,
那么
AD
输出的整数除以
2^16
再乘以
5V
就是对应的电压
.
在定点
DSP
中是直接对这个
16
位的采样进行处理
,
并不将它转换成以小数表示的电压
,
因为定点
DSP
无法以足够的精度表示一个小数
,
它只能对整数进行计算
.
而浮点
DSP
的优势在于它可以把这个采样得到的整数转换成小数表示的电压
,
并不损失精度
(
这个小数用科学记数法来表示
),
原因在于科学记数法可以表示很大的动态范围的一个信号
,
以
IEEE754
浮点数为例
,
单精度浮点格式
: [31]1
位符号
[30-23]8
位指数
[22-00]23
位小数
这样的能表示的最小的数是
+-2^-149,
最大的数是
+-(2-2^23)*2^127.
动态范围为
20*log(
最大的数
/
最小的数
)=1667.6dB
这样大的动态范围使得我们在编程的时候几乎不必考虑乘法和累加的溢出
,
而如果使用定点处理器编程
,
对计算结果进行舍入和移位则是家常便饭
,
这在一定程度上会损失是精度
.
原因在于定点处理处理的信号的动态范围有限
,
比如
16
位定点
DSP,
可以表示整数范围为
1-65536,
其动态范围为
20*log(65536/1)=96dB.
对于
32
定点
DSP,
动态范围为
20*log(2^32/1)=192dB,
远小于
32
位
ieee
浮点数的
1667.6dB,
但是
,
实际上
192dB
对绝大多数应用所处理的信号已经足够了
.
由于
AD
转换器的位数限制
,
一般输入信号的动态范围都比较小
,
但在
DSP
的信号处理中
,
由于点积运算会使中间节点信号的动态范围增加
,
所以主要考虑信号处理流程中中间结果的动态范围
,
以及算法对中间结果的精度要求
,
来选择相应的
DSP.
另外就是浮点的
DSP
更易于编程
,
定点
DSP
编程中程序员要不断调整中间结果的
P,Q
值
,
实际就是不断对中间结果进行移位调整和舍入
.
TI
的
CCS
提供
BIOS,ADI
的
VDSP
提供
VDK,
都是基于各自
DSP
的嵌入式多任务内核
.DSP
编程可以用单用
C,
也可以用汇编
,
或者二者结合
,
一般软件编译工具都提供了很好的支持
.
我不想在这里多说
BIOS,VDK
怎么用这在相应的文档里说的很详细
.
我想给初学者说说
DSP
的
RTOS
原理
.
用短短几段话说这个复杂的东西也是挑战
!
其实
DSP
的
RTOS
和基于其他处理器的通用
RTOS
没什么大的区别
,
现在几乎人人皆知的
uCOSii
也很容易移植到
DSP
上来
,
只要把寄存器保存与恢复部分和堆栈部分改改就可以
.
一般在用
BIOS
和
VDK
之前
,
先看看操作系统原理的书比较好
.uCOS
那本书也不错
.
BIOS
和
VDK
其实是一个
RTOS
内核函数集
,DSP
的应用程序会和这些函数连接成一个可执行文件
.
其实实现一个简单的多任务内核并不复杂
,
首先定义好内核的各种数据结构
,
然后写一个
scheduler
函数
,
功能是从所有就绪任务中
(
通过查找就绪任务队列或就绪任务表
)
找出优先级最高的任务
,
并恢复其执行
.
然后在此基础上写几个用于任务间通信的函数就可以了
,
比如
event,message box,
等等
.
RTOS
一般采用抢先式的任务调度方式
,
举例说当任务
A
等待的资源
available
的时候
,DSP
会执行一个任务调度函数
scheduler,
这个函数会检查当前任务是否比任务
A
优先级低
,
如果是的话
,
就会把它当前挂起
,
然后把任务
A
保存在堆栈里寄存器值全部
pop
到
DSP
处理器中
(
这就是所谓的任务现场恢复
).
接着
scheduler
还会把从堆栈中取出任务
A
挂起时的程序执行的地址
,pop
到
PC,
使任务
A
继续执行
.
这样当前任务就被任务
A
抢先了
.
使用
RTOS
之后
,
每个任务都会有一个主函数
,
这个函数的起始地址就是该任务的入口
.
一般每个任务的主函数里有一个死循环
,
这个循环使该任务周期地执行
,
完成一部分算法模块的功能
,
其实这个函数跟普通函数没任何区别
,
类似于
C
语言中的
main
函数
.
一个任务创建的时候
,RTOS
会把这个函数入口地址压入任务的堆栈中
,
好象这个函数
(
任务
)
刚发生过一次中断一样
.
一旦这个新创建任务的优先级在就绪队列中是最高的
,RTOS
就会从其堆栈中弹出其入口地址开始执行
.
有一个疑问是
,
不使用
RTOS,
而是简单使用一个主循环在程序中调用各个函数模块
,
一样可以实现软件的调度执行
.
那么
,
这种常用的方法与使用
RTOS
相比有什么区别呢
?
其实
,
使用主循环的方法不过是一种没有优先级的顺序执行的调度策略而已
.
这种方法的缺点在于
,
主循环中调用的各个函数是顺序执行的
,
那么
,
即使是一个无关紧要的函数
(
比如闪烁一个
LED),
只要他不主动返回
,
也会一直执行直到结束
,
这时
,
如果发生一个重要的事件
(
比如
DMA buffer full
中断
),
就会得不到及时的响应和处理
,
只能等到那个闪烁
LED
的函数执行完毕
.
这样就使整个
DSP
处理的优先次序十分不合理
.
而在使用了
RTOS
之后
,
当一个重要的事件发生时
,
中断处理会进入
RTOS,
并调用
scheduler,
这时
scheduler
会让处理这一事件的任务抢占
DSP
处理器
(
因为它的优先级高
).
而哪个闪烁
LED
任务即使晚执行几毫秒都没任何影响
.
这样整个
DSP
的调度策略就十分合理
.
RTOS
要说的内容太多
,
我只能讲一下自己的一点体会吧
DSP
与正
(
余
)
弦波
在
DSP
的应用中
,
我们经常要用到三角函数
,
或者合成一个正
(
余
)
弦波
.
这是因为我们喜欢把信号通过傅立叶变换映射到三角函数空间来理解信号的频率特性
.
信号处理的一些计算技巧都需要在
DSP
软件中进行三角函数计算
.
然而三角函数计算是非线性的计算
,DSP
并没有专门的指令来求一个数的正弦或余弦
.
于是我们需要用线性方法来近似求解
.
一个直接的想法是用多项式拟合
,
这也正是大多数
DSP C
编译器提供正余弦库函数所采用的方法
.
其原理是把三角函数向函数空间
{1,x,x^2,x^3....}
上投影
,
从而获得一系列的系数
,
用这些系数就可以拟合出三角函数
.
比如
,
我们在
[0,pi/2]
区间上拟合
sin,
只需在
matlab
中输入以下命令
:
x=0:0.05:pi/2;
p=polyfit(x,sin(x),5)
就得到
5
阶的多项式系数
:
p =
0.00581052047605 0.00580963216172-0.17193865685360
0.00209002716293 0.999692700873120.00000809543448
于是在
[0,pi/2]
区间上
:
sin(x)=0.00000809543448+0.99969270087312*x+0.00209002716293*x^2-0.17193865685360*x^3+0.00580963216172*x^4+0.00581052047605*x^5
于是在
DSP
程序中
,
我们可以通过用乘加
(MAC)
指令计算这个多项式来近似求得
sin(x)
当然如果用定点
DSP
还要把
P
这个多项式系数表用一定的
Q
值来改写成定点数
.
这样的三角函数计算一般都需要几十个
cycle
的开销
.
这对于某些场合是不能容忍的
另一种更快的方法是借助于查表
,
比如
,
我们将
[0,pi/2]
分成
32
个区间
,
每个区间长度就为
pi/64,
在每个区间上我们使用直线段拟合
sin
曲线
,
每个区间线段起点的正弦值和线段斜率事先算好
,
存在
RAM
里
,
这样就需要在在
RAM
里存储
64
个常数
:
32
个起点的精确的正弦值
(
事先算好
): s[32]={0,sin(pi/64),sin(pi/32),sin(pi/16)....}
32
个线段的斜率
: f[32]={0.049,.....}
对于输入的每一个
x,
先根据其大小找到所在区间
i,
通常
x
用定点表示
,
一般取其高几位就是系数
i
了
,
然
后通过下式即可求出
sin(x):
sin(x)= s
*f
复制代码
这样一般只需几个
CYCLE
就可以算出正弦值
,
如果需要更高的精度
,
可以将区间分得更细
,
当然
,
也就需
要更多的
RAM
去存储常数表
.
事实上
,
不仅三角函数
,
其他的各种非线性函数都是这样近似计算的
.
1
.
接触
DSP
在参加过一次社会上多的尽乎到了泛滥地步的
"DSPxxx"
培训班之后
,
我
"
自信
"
已经具备
DSP
工师资格
,
便欣喜若狂跑道书店买了一本名为
"DSP xxx
应用
"
的书
,
作者叫
xxx,
并且是这个领域的牛人
,
这本书确实是很出色的书籍
.
但是当时
,
对于我这个对
DSP
一窍不通、刚刚入门的人来说却建立了一个错误的概念——
DSP
是个很容易的领域
,
只要培训一下
,
再稍微看看书
,
就可以成为专家
.
所以
,
现在看来
,
这些都是误导
,
我认为学习
DSP
技术应该分为两个阶段
,
第一阶段学习
DSP
技术基础概念
;
第二阶段学习
DSP
技术的行业应用
.
那本
"DSP xxx
应用
"
的书
,
它更适合书名应叫做
"DSP
中的数学或物理运用
"...
什么的
.
2
.
购买
DSP
学习套件
有了兴趣
,
就要去学习
,
于是我撺掇领导批准购买了
DSP
学习入门套件
(DSK),
许多公司均有销售
,
如
TI
等
,
大概是需要
3000-4000
人民币
.
买后不久
,
我就发现
,
这种套件对于我来说一点用处都没有
.
因为我的基础知识实在是太差了
.
这些套件对于我来说
,
只是另一种涵义的
PC
机及一些外围设备
,
想要懂的这些东西
,
我就需要去读更多的相关书籍
,
这时
,
很难没有想要放弃的念头
,
我开始有点畏惧
DSP
这种技术
,
门槛太高了
.
可是
,
我不能放弃
,
我已经投入了许多的金钱和时间
,
我不想丢掉这
4000
元钱
,
也不能对领导没有交待
.
事实上
,
我没有想到
,
我将付出更多的钱和时间去学习
.
3
.
再次参加培训班
,
再次购买
DSP
书籍
在我就感到了无助
,
困惑之际
.
我又想到了放弃
.
虽然我的数学还算不错
,
但其中遇到的一些问题在我思考后
,
还是无法解决
,
我越来越畏惧
DSP
了
.
于是
,
我开始在
"google"
上搜索
DSP
培训相关的信息
,
终于发现闻亭公司
"DSP
培训中心
"
的教程和内容正是我一直寻找的东西
.
也许是
DSP
技术对我的有着巨大的诱惑力
,
也许是我的之直着
,
我又一次勇敢的报名参加了培训
.32
个课时之后
,
解决了我半年多来积累的很多粗浅的问题
.
再翻开培训教材刚刚复读了第一章时
,
我想如果这本教材是我读到的第一本书
,
并且我没有花
4000
元买那个可
*
的学习套件
,
我会毫不犹豫的投降
,
放弃学习
DSP,
但
.......
那个可
*
的
xxx
作者
,
他的书怎么可以用作教学呀
.
他的书虽然让我对
DSP
产生了浓厚的兴趣
,
却把我引到了一条艰难的路上
,
而且花了那么多的冤枉钱
....
既然事已如此
,
我只有慢慢的去读这些书籍
,
在我读到教材的后面章节以后
,
我开始明白前面章节的内容
,
所以当你读书遇到不明白的时候
,
千万不要气馁
.
有时
,
一个内容
,
可能需要读上几遍
,
才能明白
,
这比一开始的感觉要好的多了
.
4
.
实验——至关重要的一步
现在
,
从你的架子上取下那套
DSK,
去尝试做一些小实验
,
我的第一个实验是
"
正弦发生器
",
这个实验比较简单
,
但是它也花费了我几周的时间去读大量的关于串口、编码、寄存器等的书并且进行大量的实验
.
这个执行半小时的
"
正弦发生器
",
让我查阅了恨不得够组建一个图书馆的书籍
,
而且这个东西没有任何用途
.
我是用汇编语言在
54x
中执行
,
这个实验让我很好的理解了什么是
DSP,
什么是
McBSP, DMA,
等
.
当然问题也同步产生了
,
我就又不得不做了许多的实验去验证
.
我建议
,
在系统未定型之前
,
使用
mathlab/simulink
进行仿真
,
并且可以多实验几种芯片
,
这样可以让你明白更多的内容
.
我觉得我就要成为一个真正的
DSP
工程师了
,
我度过了最困难的时期
.
我觉得自己是个英雄
.
5
.
去寻找一份与
DSP
相关的工作
,
去当个
DSP
工程师
我希望困难已经过去
,
但这种愿望为时过早了
.
在
DSP
的研究中
,
我还遇到了很多的困难
,
由于篇幅有限
,
我就不在进行描述了
.
反正
,
如果想成为真正的
DSP
专家
,
就不要期望事情会变得容易
.
有些
DSP
开发人员并不知道什么是真正的
0
和
1,
他们只会查阅各种参考书籍和参数表
,
我们并不提倡这种做法
.
因为这些人选择了一种简单的做法
,
但是他们并不是真正的
DSP
开发人员
.
他们只是编写一些他们不理解的代码
,
他们似乎在担当着一台
"
编码器
"
的角色
.
6
.
总结
;
这篇文章只是我的一点感慨
,
可能并不是很适用现在的
DSP
开发工程师
,
因为
,
市面上已经有了供你学习的
DSP
教学套件
,
搭配了多种实验供你参考
,
轻松入门
,
如
:
闻亭公司的
"
大学实验箱
"
什么的
.
这个实验箱提供了一个很好的实验环境
,
并且为初学的你设计了多种实验、教材
,
让你由浅入深的学习
.
不会向我似的
,
绕一大圈才走到正确的路上
.
另外
,
你也可以向他们的工程师咨询
.
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0