请问DSP数据手册中有关flash大小128K然后写着16-bit word这是多大的?


1.“输出数据格式”这个因你的是多少bit声卡而定,不知道自己的声卡是多少的

一下资料。高于16位(bit)才选“抖动(dither)”,目前一般的低端声卡大部

2.注意“抖动”会较大占用资源。

3.关掉“显示削波失真警告”。

4.音量控制-3dB可减少削波(clipping)。可以使用foobar2000控制软件自身音量,

但要小于或等于-3dB(如-4dB)。

1.红框内的上下顺序不能错,往下看如果你决定不使用红框内某个DSP,要移到

3.加“音量控制”的作用前面说过了。

4.用耳机听的话,“简单环绕”能增大空间感,喜欢这种感觉可以加上。类似这样

效果更好的第三方插件自己。

5.如果你还需要增加DSP请按以下顺序添加:

1.均衡器,作用是拟补播放设备频率响应的不足,例如低音弱就调高一点。最好

当然是厂家给了产品频率响应图+上自己到医院验到耳朵的频率响应图。高频部

分衰减的话有助于减低听觉疲劳。不懂的请看《资料篇》信号频率部分介绍。

46XX系列自带了硬件均衡器,建议不用foobar2000的均衡器。

3.部分耳机频率响可可参考以下网址(它里面的耳机应该会越来越多的):

设置后应另地方保存方案。

1.如果使用了上面的重采样,推荐数值(参考自DearHoney的RMAA数据库):

问:SBLive!系列、Audigy系列、(目前绝大部分声卡都是)符号AC97标准声卡

为何需要音频播放软件重采样?

答:因为其最后输出采样频率都定在48khz(一个失败的设计),而目前的音乐

重采样器)算法差影响音质,所以需要用比它算法好的音频播放软件的SSRC(软

正确的应该是这样,有部分声卡能做到。

2.问:为何使用lame压制mp3不干脆在编码前就把WAV转换成48khz?

答:因为lame是为44.1khz优化的,之前的转换恐怕lame压制后会带来更差的

音质,所以这种情况用SSRC更好。

3.如果播放歌曲时出现痴呆慢吞吞的现象请放弃软件重采样,其很占用资源,可

选择放弃或改用PPHS重采样,本书已附带了PPHS重采样的信息。

4.只有在播放像8000Hz这种非常低的采样率音乐时才把“缓慢模式”选上。

选择解压MP2/MP3时用哪个解码器,据音乐地铁的kuxinren说:mad的声音比

较柔和,mpglib声音轻快一些。

2.确认你的声卡在用模拟输出还是数字输出,如果你不知道什么是数字输出那你

除1的情况,模拟输出用这里选哪个音质都是没有区别的,区别的只是一些辅助

除1的情况,数字输出推荐KernelStreaming;ASIO(不分先后),因为其绕过

了kmix做到数字输出时bit精确。两个你的系统都不支持就Windows2000/XP

因为KernelStreamin(出现死机;杂音;没声音;cpu占用率暴高等异常情况就

不要使用了)会跳过WindowsKernelMixer,所以效果之一等于把系统音量中的

Wave(波形)开到最大,但又不是使用wave,你就可以在欣赏音乐时把系统音

量中的Wave设静音,一般的声音(如QQ上线)就不会干扰你了。

引用1ran4:有人说使用KernelStreaming如果声卡用数字输出方式,输出数据

会不正确,目前根据foobar2000官方自带的faq内容刚好与其相反,声卡数字输

出情况下KernelStreaming可能更好,没有确切证据前先认为官方自带的faq是

点是许多声卡不支持ASIO输出。

(1)有时候用上面这两种输出方式播放开头就有错误的歌曲可能无法播放,他多

数能实现播放,也就是容错性好。

模拟输出不选更能保证音质不出问题。数字输出不选可能输出bit不精确,选了

一样可能出现音质问题,请看foobar2000官方自带的faq、指引资料篇里的《对

于Directsound而言,软件混音及硬件混音有何不同》。

3.如果出现噪音,试试相应输出的缓冲长度(Bufferlength)加大。

以下只是为了方便或节省资源而做的,自己可按实际情况进行选择。

简单频谱表也不会显示,建议需要时才打开。

有些音频文件损坏了还能播,就是每次都会弹出“控制台”告诉你,选“控制台”按

“选项”可以选择关掉。

设置完重启foobar2000,某些选项才能生效。

2000部分常用功能快捷键可以记熟一下,方便控制。

的声音都能转换成常用的格式,我们推荐你用其做中介转换软件。方法:

首先软件安装时要选择你转换需要用到的编码器(special版、增强版才有),其

中CLI编码器不是一个编码器,只是一个类似万能外挂的程序,你只要有某个

格式的编码器文件就可以用CLI编码器指向编码器文件即可转换到此格式。

格式转换才需要用到,如一些非标准的wav或者ac3文件拥有多个声道要转化成

多声道转化为stereo(立体声)。}

如果没有显示,就用之前说的CLI编码器,“编码器”指向你到的编码器文件即

可转换到此格式,“预设”里是一些常用的编码参数方案。

红框内的选项一般的转换是不需要用到的。

“单独文件输出”意思是把你选择的歌曲自上到下合并成一个文件,之前你就要调

3.“Replaygain(回放增益)”功能避免绝大多数削波、使所有非专辑的歌曲(也

就是单曲、散曲)音量大小一样,暂时不会列出,需要者请学习相关文章。

4.削波只存在于有损音乐。

5.软件安装目录下的文件是foobar2000设置保存文件。

2000外观可通过插件改变。

个革命性的高级音频播放器。foobar2000之所以出现在于他不满于Winamp2.x

的插件体系架构和更倾向于图形、皮肤的发展方向的Winamp3。

foobar2000值得关注的在于他良好的体系架构。除了重要的音频管道

以外,播放器所有功能部件均是模块化的。可视化的核心由一个插件提供,即使

使用了不同的接口界面。

1.开放的组件体系结构允许第三方开发者来扩展播放器的功能

6.低内存占用,有效处理大量的播放列表

7.高级文件信息处理能力(常规文件信息窗口和批量标签)

8.高度自定义播放列表显示

10.在BSD许可协议下大部分标准组件都是开放源代码的(SDK里包含源码)

Foobar的定位是专业数字音频播放工具,它更注重技术,所以在使用

过程中涉及到了很多的专业数字音频知识,对于普通的用户常常无从下手。我将

为大家讲解一下它的使用和设置,希望大家能享受到Foobar更专业的音乐享受。

在讲解前,先说说Foobar对数字音频的处理顺序:解码—〉回放—〉DSP

(数字音频处理)—〉转化为输出格式—〉输出。知道了音乐的处理流程,下面

我们基本按照这个顺序来介绍Foobar的设置

毫不夸张的说Foobar是对现在音乐格式支持种类最全的,安装完成之后,

对于大部分的主流和非主流音乐格式上都可以直接播放了,一般不需要特别的设

置,不过这里对参数的设置做简单的介绍,供您使用时根据自己的需要选择。首

先点击“Foobar2000”—》“Preferences”进入参数设置的对话框,再选择

Input的各个小项。如下图所示

这里需要说明的是“StandardInputs”项目,各个具体参数含义见图1。

这里仅仅对界面中反复涉及到的TAG说明一下,音乐文件中除了保存声音信息

外,还可以同时保存一些和曲目相关的文本信息,比如歌名、演唱者、专辑名等

等,这些信息就称为tag(标签)信息。现在最流行的两种Tag格式是:ID3和

APE,一般播放器对于两种格式都能支持。

另外在“ModuleDecoder”选项中(见下图2),这个项目中可以看到有

“SampleRate(采样率)”、Surround(环绕)等参数设置,可能会有人认为

这些参数是关乎所有音乐解码的关键参数,其实这些和普通用户一般听到的

MP3,AAC,MPC、WMA等格式的音乐一点关系也没有,他只是专门针对XM,IT,S3M,

MIDI的一种音乐格式)来使用的,所以如果你使用的只是MP3这样的音乐格式,

这项参数如何设置都不会对你有影响。

重采样就是对你的数字音频流进行重新的采样,产生较高速率的音频数字

流,那么很多人就会认为,是不是设置的重采样速率越高越好呢?其实并非这样,

打个比方,Resamplar就想调整图片的大小,调整过大小的图片和原始图片之间

看上去很类似,不过他们的细节上却绝不相同,你更不可能用一张小图,任意放

大,还期望得到原始图象的清晰效果。说到底,不管多高的重采样速率,都是不

可能改进音乐本身品质。

那么重采样对我们有什么具体作用呢?大家都知道,我们的声卡,都有一个

固定的可接受的数据速率(例如48Khz/16bit),所以对其他速率的音频流,最

终输出到声卡之前,都由驱动程序或者Windows混音器来对这个数据流进行重采

样,变换成声卡可以接受的(48K/16bit)速率。一般来说,Foobar的SSRC算

法比驱动程序或者Windows混音器的重采样算法要好一些,所以在还原声音的效

根据上段的解释,我们在设置重采样速率的时候,需要根据你声卡的具体参

数来采用不同的速率,SBLive!系列/Audigy系列/AC97兼容的声卡,都已经将输

出的取样频率固定为48khz,所以我们最好选择48000Hz的采样速率,再高的采

样率在输出时,Windows混音器或者驱动就会再次用他们较差的算法采样到48K,

(如下图3),选择合适的采样频率。

每一张不同的CD在录制的时候,音量选择都会不同,即使同一张专集,为

了增强音乐的情感表现,音量也会有所不同,那么压缩出来的MP3音量就更相互

不同。回放增益能够自动的计算该音乐文件(专辑)平均强度和标准强度(83SLB)

之间的差值,并且保存这些增益信息。提供给播放器自动调整音量使用。具体操

作,首先选中希望计算增益的歌曲,点右键“Replaygain”。

对于选中的音乐属于同一专集的可以使用“ScanselectionasAlbum”命

的为每一首音乐计算出增益大小、音量峰值、专辑的增益大小、和音量封值(见

有了回放增益在播放时候时候就可以自动调整音量了,在参数设置面板中

是按照专集调整,这样属于这个专集的音乐音量有所变化,保持了音乐的情感变

化的表现,专集和专集之间音量相同;TrackerBased是对每首的歌曲都调整到

标准强度,使所有音乐音量都相同,这样可能就损失了音乐人想表达的效果(想

象一下情歌和摇滚用一个音调播放的效果,嘿嘿,不堪忍受吧?)。

DSP是数字音频处理,可以利用数字处理技术,对音乐进行一些特殊处理以

产生出特殊效果,同样在参数设置面板下,点击进入“DSPManager”面板,就

可以选择需要使用的DSP处理效果了。

不过需要说明的是,增加DSP处理插件,会占用系统资源,如果不是非常必

要,应当尽量减少DSP插件的数量。根据实际使用经验建议只开下面几个DSP:

环绕)就可以了,而且顺序也不能变。

在参数设置的面板下,选择Playback的项目面板

在“OutputDataFormat”中选择一个合适的是数据输出格式,这里也需要

根据你声卡来设置,一般的现在的AC97的声卡,都是16位的,选择16bit就可

以了,如果你的声卡是32位或者24位的极品卡的话。那么选择32bit吧。下面

的Dither选项用来设置是否采用抖动,这个选项只有在播放高位音乐(如

32bit),采用低位(24bit)输出时才有作用。采用Dither,即使将32位音乐

通过Dither输出到16位的声卡,效果也有不少提升,建议打开该选项。

Waveout是Windows过时的数字音频输出API,无硬件加速,使用时占用系统资

建立在32位Windows之上,支持硬件加速、多重混音等众多功能,且资源占用

少,支持所有的Windows系统。是笔者推荐使用的一种输出形式,不过系统需要

输出到声卡的一种方式,这种方式能提供更低的输出延迟,但是这种方式是一种

最新的技术,目前只能支持2000和XP的系统,而且有一些声卡并不支持这种方

式。如果你的声卡和系统都能支持这种方式的话,这是笔者最推崇的方式。设置

方法,在参数面板中选择“OutPut”项目面板中(见下图),通过“Output

Method”的下拉框选择。

A:Waveout是在32位的Windows上的一种老旧且过时,用来播放数字音讯

这些操作系统设计的),如果你想获得最好的效能,你应该在这些操作系统上使

用Waveout输出。然而Waveout的功能有所局限,它无法支持「混和多重音讯

流」的功能。这显示在Win2k/XP下的Waveout,只是为了旧的软件的兼容性所

提供的,也因此Win2k/XP下Waveout的完成度很糟,它没有使用任何的硬件

加速功能,所有的混音动作都是用软件来执行(因此当CPU的使用率很高时,

常常会发生类似CD跳针的断音现象)。

Directsound是种较新、较现代化的声音播放API,都已经内建在最近

的32位Windows操作系统中。Directsound支持混和多重音讯流、独立的音量

控制、硬件加速层及硬件仿真层(如果某些功能硬件无法支持,可以用软件来

仿真,因此程序设计师无须担心他们的新l33t码无法在旧的声霸卡16上运作)。

一般来说,只要你的操作系统安装了适当的声卡驱动程序及最新的DirectX,

相对的比waveout来的更高(比waveout占用较少的CPU资源,自由度较高,

且不会有Waveout常见的小毛病)。Directsound原本是被设计来让游戏利用系

统的硬件加速功能,而无须直接接触低阶的硬件函数(就如同DirectX其它的

A:在Win2k/XP中,改变waveout的音量似乎会改变整体音量的设定,然

而Directsound的音量是独立控制的。换句话说,你用waveout来播放音乐,

你将音量设为50%,你就会得到50%的音量,然后你用Directsound来播放,你

将音量设为50%,你只会得到最大音量的25%。解决之道:别使用waveout,并

在Windows的音量控制中将音量设为最大。

软件混音,因此较少造成系统中的特殊问题,而Dircetsound可以使用硬件混音,

因此会造成某些已知的,声音品质的问题。

阶的方式来控制硬件,因此这就像拿两种不同的驱动程序来配合waveout及

线的频宽,有着会将音讯资料降低取样率至22khz8bit(或者其它相近的取样

Q:对于Directsound而言,软件混音及硬件混音有何不同?

者是驱动程序来进行硬件混音,都很容易碰到问题。目前已经证实,在Winxp下

使用硬件混音来传输音讯资料时,即使是使用不同的声卡,皆会碰上「取样频率」

的问题。特别是某些驱动程序存在已久的问题(著名的创新未来Audigy声卡

Skipping问题,在某些设定中会出现不间断、静态的杂音,甚至在某些例子中,

会发生声音品质骤降的情形,天晓得为何会如此!)。如果你想稳定的运作计算机,

那建议你最好把硬件加速给关掉。硬件混音可以foobar2000的偏好设定中的

的激活了这个功能(Directsound会在没有可用资源时自动使用软件混音)。

Q:如果我使用重新取样的功能,能够增进(improve)声音的品质吗?

A:不行,你无法利用重新取样来「增进」声音的品质,重新取样是个有耗

损的过程。你可以试看看改变一张bmp图片的大小,改过大小的图片会和原本

的图片极为相似,不过假如你把两张图都放大(zoom-in)来看,你会发现它们在细

节上并不相同。在某些硬件上,如果你使用高品质的重新取样软件,来避免让你

的驱动程序/硬件处理重新取样的过程,你可以避免大量资料的损失(也就是避

免音讯品质降低)。我知道某些人在他们的声霸卡16上将取样率提升为96khz

会将取样率降回44khz16bit),别听他们所说的屁话。

Q:我应该将重新取样的参数设为多少比较好?

A:首先,你应该查询你声卡的硬件资料。某些声卡(例:在SBAwesome

系列以前发售的声霸卡)不需要重新取样,这表示你不需要额外的重新取样就已

经得到最好的品质了(不会有重新取样造成的品质降低)。所有的SBLive!系列

/Audigy系列/AC97兼容的声卡,都已经将输出的取样频率固定为48khz,重新

取样的品质会因为驱动程序/硬件装置/Windows混音设定而改变。在许多例子中,

SSRC重新取样软件会优先于你的硬件/驱动程序,因此你需要将重新取样的参数

设为48khz/16bits,以避免你的硬件/驱动程序来进行它们较差的重新取样。

A:当然可以,Windows混音器会将取样率降回你硬件能够接受的格式(例

如:48khz/16bits),这会造成额外的品质降低。不要提升取样率,除非你的硬

件真的能够接受这些格式。Ditheringdither在计算机绘图上称为「递」,而在

处理音讯上,也有着相似的意思。以下有三张图,大家可以看看dither的差异在

何处。原始的图(24bit高彩),左上角的小方块是从黑框中放大的。有dither的

图(8bit256),较远处看可以说看不出与原图的差异。无dither的图(8bit256

),彩的分布不平顺,与原图可以看出根本的差异。启用这个功能,将会在

这意指没有用到的位会被砍掉并丢弃。在许多较安静的音乐中有淡入或淡出的情

况时,会造成「断裂」的听觉效果(也就是淡入/出的效果不平顺)。Dithering只

有在你将高位(例如:32bit)的音讯以低位(例如:16bit)来播放时才真正有

用。输出位设定(Outputbitdepth)这里有个下拉式选单,可以让你选择输出的位

率。如果你有张24bit的声卡,你当然会想让那些没有用到的位使用ditherto

需要激活dithering,因为从译码器直接传送过来的资料就是32bit。

卡。这种方式有着较低的输出延迟,也许可以被视为ASIOoutput之外的另一

A:如果你的声卡及驱动程序能支持,且你使用KernelStreaming没有什么

音变的更大声或者明亮?

A:声音并没有变的明亮,只有变大声。因为输出资料给声卡的方式不同,

的,而且都以最大音量来输出。如果你将音量控制中的wave音量设为最大,

在使用Resampler之后,再试试播放上面提及的两个测试讯号,听听是否

只听到很纯很尖的超高频声音,而且听不出两个档案的分别。如果是的话,高质

Windows音量控制里按选项>进阶控制,看看是否有高低音控制,如果有的话,

把高低音都移到正中间再试试看(如果本身已经在中间就不用移了),如果还是

的wave输出可能会无法控制,那是正常的现象。接着到Playback一栏,会有

前面一个篇章:算法的嵌入式移植(一)C代码优化部分 侧重语言层面的优化,而更多针对DSP特性进行的优化将在本篇章进行介绍 ,内容大多是摘抄书本和网络资源,因为是整理以往的笔记,来源已经不可靠了,不过不影响其中内容的经典。

1.图像算法在嵌入式移植时(主要针对DSP芯片)优化的原则和步骤?

原则:算法效果达到预期之前最好不要做过多的优化

步骤:windows下的算法级优化—>C语言的优化—>DSP下的C编译器优化(如软件流水等) —>C语言代码和结构的优化(如浮点转定点) —> (线性)汇编做极限优化

2.需要对程序中的哪些代码进行优化?

大家都知道程序中最费时的莫过于循环操作了,主要是针对循环进行优化(一般我都是针对100次以上的循环进行优化,特别是复杂度在O(m*n)以及O(n^2)以上的循环优化)(关于循环中复杂度的计算方法大嘴会在以后介绍,请留意)。

算法效果达到预期之前最好不要做过多的优化,为啥?算法未稳定就草率

优化是做算法和移植的大忌,一是因为算法以后修改后你还得优化,二是各种优化后你的算法代码如果未充分注释,多日后可能连本人都无法看懂。

大的方面:在做算法前咱们首先要衡量的算法本身的复杂度和效果,如背景建模/前景检测(即运动目标检测)采用的是“单高斯”?“混合高斯(GMM)”?“VIBE”?“codebook”?等等;

小的方面:针对某一基本算法函数优化,比如采用的sobel边缘检测,还是canny边缘检测,或者其他更好的方法。选择一个效果好又稳定的算法方向和基本函数对以后的移植和优化会有很大帮助。

再比如:你非要用神经网络做车牌识别,在PC下当然可以,但在嵌入式中却无法实时,也许有牛人真能在DSP下基于神经网络做高效又稳定的、识别率又高的车牌识别(如8168和C66系列芯片),至少在大嘴身边未发现。

C语言本身优化是老生常谈,这里不做介绍,比如什么少用if…else之类,这里不再复述,感兴趣的朋友请自己在网络上找资料。

3.DSP下的C编译器优化

3.1设置编译选项,使编译器先自行优化

最主要的编译选项:O1,O2,O3等几个等级(如DSP开发环境CCS中自带的可选编译选项)

代码风格没有充分遵守CCS编译器的约定则会导致编译器不做优化,即使开了不同等级,也还是不会做优化,日后大嘴会逐步介绍

(i)方法:设置编译选项(一大堆),

是否开启软件流水,通过生成的.asm文件查看

(ii)无法开启流水的一些原因

代码风格(如过多的条件跳转指令条件寄存器个数有限,达到资源限)、错误编译选项等等

说的不多,但展开了内容却很多,详细的还要靠大家去研究下TI提供的那几本手册(C6000优化编译器手册、C6000程序员手册、C6000汇编手册等),建议主要看英文原版,中文版(《TMS320C6000系列DSP编程工具与指南》)作为辅助(几年前阅读过,个人觉得里面很多翻译的不是很到位)。

4.DSP代码和结构的优化

浮点数:是属于有理数中某特定子集的数的数字表示,在计算机中用以近似

表示任意某个实数。具体的说,这个实数由一个整数或定点数(即尾数)乘以某个基数(计算机中通常是2)的整数次幂得到,这种表示方法类似于基数为10的科学计数法。

定点数:参与运算的数的小数点位置固定不变

浮点数形式上可以简单认为是float和double类型,定点数形式上可以简单认为是个整数。

(i)简单方法:在精度满足的情况下:把数据放大n倍,运算后再缩小,

(ii)但为了准确把握好精度,通常用Q定标小数点移位(关于Q定标小数点移位较复杂,大嘴以后专门介绍)

(i)能用移位和逻辑运算的绝不用加减乘除

(ii)能用加减法的绝不用乘除法,

(iii)能用乘法的绝不用除法

(iv)能用16位(16位 * 16位= 32位结果)乘法的绝不用32位乘法,DSP有相应16位乘法器(硬件),而32位成为一般用软实现.

(i)inline ,语句只能几行,有各种限制

(ii)intrinsic函数,总是被内联,汇编封装,常用一些操作函数和数**算(如求绝对值,乘法),速度很难超越,intrinsic函数不影响软件流水,TI充分考虑到这点

4.4充分利用Bit图(bit二值图),针对二值图的操作,

(1)传统的二值像素: 0和255

a)基于像素操作(慢):每个二值像素占1个字节(8位,即8个bit);基于bit图操作(快):每个像素占1位(1个bit)

32bit包,可放于1个int类型的变量中,其充分利用了32位机每次加载

一个字,这样相当于一次加载32个二值像素

//传统的像素操作,无法并行

循环跳转320次,无法并行操作

基于比特图(长度为10个int型数组即可存储320个像素)

//32bit图打包 并行操作,每32个像素可以并行执行

理论上提高了32倍,至少20倍以上

c)汇编->内存和寄存器、寄存器和寄存器之间频繁操作

d)Bit二值图主要针对腐蚀、膨胀、各种滤波、轮廓查找等等和二值图相关的操作,内部只采用与、或、非、移位等运算而没有加减乘除,所以超快

Bit图的所有操作写程序比较困难,一旦写成则效率大幅提升

直接存储器存取,块儿复制数据,不需要CPU 进行干预,数据直接在源地址和目的地址之间传送,不需要是中间媒介。

要求8字节对齐,即源地址和目的地址必须是8 的倍数

字节对齐后硬件可直接加载字,为了兼容正在迅速普及的64位机,使得你的程序可以不经修改直接编译成 64 位程序

如果没有一点发展的眼光,在现在这种 32 到 64 位过渡时期他不这样做的话将会导致太多的32位平台上开发的程序为了能运行在64位平台上不得不修改源代码。那样不仅会大大增加软件成本,还会导致人们为了不改动程序而拒绝接受64位平台。

Cache较小,但速度快,内层循环中最费时的部分要用L2 cache,高速缓存的速度超快。

这里简单知道下即可,篇幅有限,以后再慢慢介绍

restrict保证所定义的指针指向特定对象的唯一指针,即存储器不相关,否则默认编译器认为存储器相关,会影响编译器的优化

4.7 DSP下专有的视觉库(VLIB,封装)和开源图片库(IMGLIB)

使用(VLIB,封装)和开源图片库(IMGLIB)里面包括一些基础图像处理函数,将更多的时间留给自己的其它各种优化,节省时间。

5.(线性)汇编做极限优化

如果觉得采用上述优化后算法效率仍未达到要求,最后可以采用(线性)汇编对循环内非个别语句做优化,由于本人汇编水平也比较懒,这里就不介绍了,向汇编高手们学习!

以上就是大嘴主要采用的方法,篇幅有限,实在无法更具体的展开介绍,以后大嘴会慢慢详细介绍,敬请关注,同时如果朋友还有什么更好的DSP移植优化方法,希望和大嘴交流,互相学习、共同进步

三、C6XX优化经验总结

一、c6x的编译的常用选项
(一)c6x的编译程序为“cl6x.exe”使用的方法

编译选项是一个字母或者两个字母,对大小写不敏感。
编译选项的前面需要有一个“-”符号。
一个字母的选项可以合并在一起。比如“-sgq”与“-s -g -q”相同。
两个字母的选项如果第一个字母相同也可以合并在一起。比如“-mgt”与“-mg -mt”相同。

-mt:表示在程序中没有使用alaising技术,这使得编译器可以进行比较好的优化。
-o3:对文件级别进行最强的优化,一般在编译时应该使用这个选项。但是在个别情况下使用这个选项优化程序可能会出现
错误(-o2有相同现象,-o0和-o1不会出现错误)。可能是在优化循环,组织流水线的时候发生错误。如果有这种现象出现可以同时
使用-g选项,程序优化就不会出现错误,但是优化效果会下降。另外可以调整程序的表达方式,可能会避免编译器发生错误。
-pm:在程序级别进行优化。可以将所以文件联合在一起进行优化,主要有去掉没有被调用的函数、总是常数的变量以及没有使用的
函数返回值。建议由程序员自己进行这种优化工作。使用这个选项在win98下编译可能会出现找不到编译程序的情况。
-ms0:不使用冗余循环进行优化,减小程序的大小。一般情况下这个选项对程序大小的优化作用不明显。
-mh[n]:去掉流水线的epilog,减小程序的大小。这个选项的作用比较明显。但是有可能出现读取地址超出有效范围的问题,
所以要在数据段的开始和结尾处增加一些pading,或者在分配内存时保证数组的前面和后面一段范围内都是有效的地址。
可选的参数n给出这种pading的长度字节数。

(三)保留编译和优化信息的选项
-k:保留优化后生成汇编语言文件。
-s:汇编语言文件中加入优化信息,如果没有则加入C语言源程序作为注释。
-mw:在汇编语言文件加入软件流水线信息。

(四)有关调试和剖析的选项
-g:允许符号调试,在“out”文件中包含符号信息和行号信息,可以在c语言级别进行调试和剖析。使用联合使用-g、-mt和-o3可以保
证能够进行符号调试的情况下最大限度的优化。
-mg:允许profile优化后的程序。 在“out”文件中包含符号信息和很少的行号信息。允许在c语言的函数基本进行剖析。
如果联合使用这两个选项,-g选项可能被忽略,结果与只用-mg相同。

-mln:生成大内存模式的程序。
-ml0:缺省情况下将集合变量(数组和结构)作为far型。
-ml1:缺省情况下将全部函数作为far型
-ml3: 缺省情况下将全部数据和函数作为far型

(六)建议使用的编译方式
方式1用于程序的调试,这种方式具有比较强的优化能力,并且支持符号调试。在编译的过程中不会发生错误。
由于生成的“out”文件中包含了符号信息和行号信息,所以比较大。
方式2用于程序的剖析(profile),这种方式的优化能力几乎最强(绝大多数情况下与方式3相同),
并且支持对程序进行profile。文件中只包含了符号信息和很少的行号信息,所以“out”文件比较小。
方式3用于最终的发行版本程序,可以对程序进行最强的优化,并且去掉了全部的符号和行号信息,所以“out”文件比较小。
由多个文件组成的程序应该编写makefile,将编译参数放在该文件中,并在其中说明使用的编译器的版本号。

-heap:指定堆的大小
-stack: 指定栈的大小
连接的各种选项应该统一放在“cmd”文件中
二、双重循环和多重循环的优化总结

双重循环多重循环看起来比较复杂,但实际上多重循环优化方法比较简单,就在于一个字:“拆”,一旦完成这一步之后,
多重循环就成为单层循环,优化就可以按照普通的单层循环来做了。
多重循环的特点是在优化器优化时只在最内层循环中形成一个pipeline,这样循环语句就不能充分利用C6的软件流水线,
而且对于内部循环的次数较少的情况,消耗在prolog和eplog上的cycle数也是不可忽视的。
针对这种状况可以考虑将多重循环拆开形成一个单层循环,可以拆外层循环也可以拆内层循环,
一般视具体情况而定。这样就可以充分利用优化器构成的Pipeline。如下例:

内层循环循环次数较少,运算量也不大,资源方面只占用了一个乘法器,一个cycle只使用一次乘法器,
而事实上我们可以在一个cycle内使用两个乘法器,所以还可以充分利用另外的一个乘法器。因此考虑将内层循环拆开来执行,如下:

这样虽然代码长度增加了,可变成了单循环,所有的运算都参加到pipeline中来,在Piped loop kernal
中产生每一个cycle内都使用了两个乘法器,充分利用了DSP内部的资源,提高了运行效率。又如下例:

C6000编译器提供的intrinsic 可快速优化C代码,intrinsic用前下划线表示同调用函数一样可以调用它,即直接内联为C6000的函数。
例如,在上例的源代码中没有使用intrinsics,每一行C代码需多个指令周期,在改编后的代码中,每一行代码仅需一个指令周期。
该书还提供了另外的例子。这些内联函数定义在CCS所在的C6000/CGTOOLS/Include目录下的C6X.h文件中。

在C语言的调试全部通过以后,可以尝试将尽可能多的语句使用intrinsics函数加以改编,
尤其在循环体内,这种改编可以大幅度减少执行时间。

C6000编译器如果确定两条指令是不相关的,则安排它们并行执行。 关键字const可以指定一个变量或者一个变量的存储单元保持不变。
这有助于帮助编译器确定指令的不相关性。例如上例中,源代码不能并行执行,而结果改编后的代码可以并行执行。

使用const可以限定目标,确定存在于循环迭代中的存储器的不相关性。

用内联指令_add2、_mpyhl、_mpylh完成两组16位数的加法和乘法,效率比单纯16位数的加法和乘法提高一倍。

六、if…else…语句的优化

如果在循环中出现if…else…语句,由于if…else…语句中有跳转指令,而每个跳转指令有5个延迟间隙,
因此程序执行时间延长;另外,循环内跳转也使软件流水受到阻塞。直接使用逻辑判断语句可以去除不必要的跳转。
例如在例1的源代码最多有两次跳转,而改编后不存在跳转。例2和例3同样也去掉了跳转。

尽可能地用逻辑判断语句替代if…else…语句,减少跳转语句。

求数组的最小值程序,优化时为了提高程序效率在一个循环之内计算N=1,3,5..和n=2,4,6…的最小值,
然后在比较二者的大小以求得整个数组的最小值。

源程序中在循环中含有许多的if结构,在优化时对if结构首先进行化简,
再将化简后的if结构用条件运算表达式进行改写,最后使循环可以Pipeline。

源程序也为一个求中值的问题,由于已知循环次数固定为5,因此将循环展开使用if语句直接求取中值。

源程序按照数据位流定义取出参数,为双重循环结构,优化中采用重新根据位流的bit长度定义循环次数,
化简为单重循环,然后优化循环,去除boundary,使pipeline的数目最小。

十一、copy程序的优化

(1)要求数组长度能被2整除

(2)要求数组长度能被4整除

把一次循环拷贝一个word16的数改为一次循环拷贝2个word16或4个word16的数。
充分利用c6xx一次读取32位数的特性,并利用一个指令周期能读取两个数据的特点。

(1)数组长度能被2整除

(2)数组长度能被4整除

实现16位的除法,要求被除数var1和除数var2都是整数,且var1<=var2。利用C6XX特有的指令subc,实现除法的循环移位相减操作。
把被除数和除数都转换成32位数来操作,返回时取低16位数。

观察上面这个循环,循环体本身比较大,且含有两个函数L_divide()和
fnLog10(),而C62内部只有32个寄存器,且有些寄存器是系统用的,如B14、B15这样循环体太大将会导致寄存器不够分配,
从而导致系统编译器无法实现循环的pipeline。

为了实现循环的pipeline。我们需要把循环体进行拆分,拆分时要考虑以下几点:
(1)、拆分成几个循环比较合适?在各个循环能pipeline的前提下,拆开的循环个数越少越好。这就要求尽可能让各个
(2)考虑在什么地方把程序拆开比较合适?循环体里的数据流往往并不是单一的,在拆开的断点处势必要用中间变量保
存上次的循环运算结果,供以后的循环用。适当的拆开循环体,使所需的中间变量越少越好。
(3)循环体中的函数调用必须定义成内嵌形式,含有函数调用的循环系统是无法使之pipeline的;各个循环体中的判断分支
机构不可太多,否则系统也无法使之pipeline,为此应近可能把可以确定下来的分支确定下来,并尽可能用内嵌指令。

针对上面这个例子,考虑:
(1)为让各个循环的运算量大致相当,应把L_divide()和fnLog10()分到两个循环中去,从循环体大小上考虑,
估计拆成两个循环比较合适。
(2)考虑在什么地方把程序拆开比较合适?在
后拆开,因为后面用到的数据只有Ltmp2,故只需用一个数组保存每次循环的Ltmp2值即可。
(3)循环体中的两处函数调用L_divide()和fnLog10()都定义了其内嵌形式,IL_divide()和IfnLog10()。
当把可以确定下来的分支作确定处理,并尽可能用内嵌指令后,该循环体中所剩的分支结构已很少,循环体可以pipeline。

内存地址形式: 奔腾,C6000都是32位计算机,字长32,但内存地址都是按字节组织的 一个字4字节(查看内存时候各个字
时候:例如两个连续字ox1000 ox1004) 写汇编程序时候,下一个字也需要+4,但写 C语言时候,int 型,+1就是加4

但是,在Tiger SHARC中,虽然也是32位机,但内存是地址是按字组织的,查看内存时,连续的字地址相差1

MCU是Microcontroller Unit 的简称,中文叫微控制器,俗称单片机,是把CPU的频率与规格做适当缩减,并将内存、计数器、USB、A/D转换、UART、PLC、DMA等周边接口,甚至LCD驱动电路都整合在单一芯片上,形成芯片级的计算机,为不同的应用场合做不同组合控制,诸如手机、PC外围、遥控器,至汽车电子、工业上的步进马达、机器手臂的控制等,都可见到MCU的身影。

单片机出现的历史并不长,但发展十分迅猛。它的产生与发展和微处理器(CPU)的产生与发展大体同步,自1971年美国英特尔公司首先推出4位微处理器以来,它的发展到目前为止大致可分为5个阶段。下面以英特尔公司的单片机发展为代表加以介绍。

单片机发展的初级阶段。1971年11月英特尔公司首先设计出集成度为2000只晶体管/片的4位微处理器英特尔4004,并配有RAM、 ROM和移位寄存器, 构成了第一台MCS—4微处理器, 而后又推出了8位微处理器英特尔8008, 以及其它各公司相继推出的8位微处理器。

低性能单片机阶段。以1976年英特尔公司推出的MCS—48系列为代表, 采用将8位CPU、 8位并行I/O接口、8位定时/计数器、RAM和ROM等集成于一块半导体芯片上的单片结构, 虽然其寻址范围有限(不大于4 KB), 也没有串行I/O, RAM、 ROM容量小, 中断系统也较简单, 但功能可满足一般工业控制和智能化仪器、仪表等的需要。

高性能单片机阶段。这一阶段推出的高性能8位单片机普遍带有串行口,有多级中断处理系统, 多个16位定时器/计数器。片内RAM、 ROM的容量加大,且寻址范围可达64 KB,个别片内还带有A/D转换接口。

16位单片机阶段。1983年英特尔公司又推出了高性能的16位单片机MCS-96系列,由于其采用了最新的制造工艺, 使芯片集成度高达12万只晶体管/片。

单片机在集成度、功能、速度、可靠性、应用领域等全方位向更高水平发展。

二、单片机的分类及应用

MCU按其存储器类型可分为无片内ROM型和带片内ROM型两种。对于无片内ROM型的芯片,必须外接EPROM才能应用(典型为8031);带片内ROM型的芯片又分为片内EPROM型(典型芯片为87C51)、MASK片内掩模ROM型(典型芯片为8051)、片内Flash型(典型芯片为89C51)等类型。

按用途可分为通用型和专用型;根据数据总线的宽度和一次可处理的数据字节长度可分为8、16、32位MCU。

目前,国内MCU应用市场最广泛的是消费电子领域,其次是工业领域、和汽车电子市场。消费电子包括家用电器、电视、游戏机和音视频系统等。工业领域包括智能家居、自动化、医疗应用及新能源生成与分配等。汽车领域包括汽车动力总成和安全控制系统等。

对于绝大多数MCU,下列功能是最普遍也是最基本的,针对不同的MCU,其描述的方式可能会有区别,但本质上是基本相同的:

1、TImer(定时器):TImer的种类虽然比较多,但可归纳为两大类:一类是固定时间间隔的TImer,即其定时的时间是由系统设定的,用户程序不可控制,系统只提供几种固定的时间间隔给用户程序进行选择,如32Hz,16Hz,8Hz等,此类TImer在4位MCU中比较常见,因此可以用来实现时钟、计时等相关的功能。

另一类则是Programmable Timer(可编程定时器),顾名思义,该类Timer的定时时间是可以由用户的程序来控制的,控制的方式包括:时钟源的选择、分频数(Prescale)选择及预制数的设定等,有的MCU三者都同时具备,而有的则可能是其中的一种或两种。此类Timer应用非常灵活,实际的使用也千变万化,其中最常见的一种应用就是用其实现PWM输出。

由于时钟源可以自由选择,因此,此类Timer一般均与Event Counter(事件计数器)合在一起。

2、IO口:任何MCU都具有一定数量的IO口,没有IO口,MCU就失去了与外部沟通的渠道。根据IO口的可配置情况,可以分为如下几种类型:

纯输入或纯输出口:此类IO口由MCU硬件设计决定,只能是输入或输出,不可用软件来进行实时的设定。

直接读写IO口:如MCS-51的IO口就属于此类IO口。当执行读IO口指令时,就是输入口;当执行写IO口指令则自动为输出口。

程序编程设定输入输出方向的:此类IO口的输入或输出由程序根据实际的需要来进行设定,应用比较灵活,可以实现一些总线级的应用,如I2C总线,各种LCD、LED Driver的控制总线等。

对于IO口的使用,重要的一点必须牢记的是:对于输入口,必须有明确的电平信号,确保不能浮空(可以通过增加上拉或下拉电阻来实现);而对于输出口,其输出的状态电平必须考虑其外部的连接情况,应保证在Standby或静态状态下不存在拉电流或灌电流。

3、外部中断:外部中断也是绝大多数MCU所具有的基本功能,一般用于信号的实时触发,数据采样和状态的检测,中断的方式由上升沿、下降沿触发和电平触发几种。外部中断一般通过输入口来实现,若为IO口,则只有设为输入时其中断功能才会开启;若为输出口,则外部中断功能将自动关闭(ATMEL的ATiny系列存在一些例外,输出口时也能触发中断功能)。外部中断的应用如下:

外部触发信号的检测:一种是基于实时性的要求,比如可控硅的控制,突发性信号的检测等,而另一种情况则是省电的需要。

信号频率的测量:为了保证信号不被遗漏,外部中断是最理想的选择。

数据的解码:在遥控应用领域,为了降低设计的成本,经常需要采用软件的方式来对各种编码数据进行解码,如Manchester和PWM编码的解码。

按键的检测和系统的唤醒:对于进入Sleep状态的MCU,一般需要通过外部中断来进行唤醒,最基本的形式则是按键,通过按键的动作来产生电平的变化。

4、通讯接口:MCU所提供的通讯接口一般包括SPI接口,UART,I2C接口等,其分别描述如下:

SPI接口:此类接口是绝大多数MCU都提供的一种最基本通讯方式,其数据传输采用同步时钟来控制,信号包括:SDI(串行数据输入)、SDO(串行数据输出)、SCLK(串行时钟)及Ready信号;有些情况下则可能没有Ready信号;此类接口可以工作在Master方式或Slave方式下,通俗说法就是看谁提供时钟信号,提供时钟的一方为Master,相反的一方则为Slaver。

对于大多数的MCU来讲,数据位的长度、数据校验方式(奇校验、偶校验或无校验)、停止位(Stop Bit)的长度及Baud Rate是可以通过程序编程进行灵活设定。此类接口最常用的方式就是与PC机的串口进行数据通讯。

I2C接口:I2C是由Philips开发的一种数据传输协议,同样采用2根信号来实现:SDAT(串行数据输入输出)和SCLK(串行时钟)。其最大的好处是可以在此总线上挂接多个设备,通过地址来进行识别和访问;I2C总线的一个最大的好处就是非常方便用软件通过IO口来实现,其传输的数据速率完全由SCLK来控制,可快可慢,不像UART接口,有严格的速率要求。

5、Watchdog(看门狗定时器):Watchdog也是绝大多数MCU的一种基本配置(一些4位MCU可能没有此功能),大多数的MCU的Watchdog只能允许程序对其进行复位而不能对其关闭(有的是在程序烧入时来设定的,如Microchip PIC系列MCU),而有的MCU则是通过特定的方式来决定其是否打开,如Samsung的KS57系列,只要程序访问了Watchdog寄存器,就自动开启且不能再被关闭。一般而言watchdog的复位时间是可以程序来设定的。Watchdog的最基本的应用是为MCU因为意外的故障而导致死机提供了一种自我恢复的能力。

四、全球主流单片机制造商

(排名不分先后,整理为主流厂商,如有缺少请在评论区补充)

1、Freescale+NXP(飞思卡尔+恩智浦):荷兰,主要提供16位、32位MCU。应用范围:汽车电子、LED和普通照明、医疗保健、多媒体融合、家电和电动工具、楼宇自动化技术电机控制、电源和功率转换器、能源和智能电网、自动化、计算机与通信基础设施。

2、Microchip+Atmel(微芯科技+爱特梅尔):美国,主要提供16位、32位MCU。应用范围:汽车电子、工业用、电机控制、汽车、楼宇自动化、家用电器、家庭娱乐、工业自动化、照明、物联网、智能能源、移动电子设备、计算机外设。

3、Cypress+Spansion(赛普拉斯+飞索半导体):美国,主要提供8位、16位、32位MCU。应用范围:汽车电子、家用电器、医疗、消费类电子、通信与电信、工业、无线。

4、ADI(亚德诺半导体):美国,主要提供8位、16位、32位MCU。应用范围:航空航天与国防、汽车应用 、楼宇技术 、通信 、消费电子 、能源 、医疗保健 、仪器仪表和测量 、电机、工业自动化 、安防。

5、Infineon(英飞凌):德国,主要提供16位、32位MCU。应用范围:汽车电子、消费电子、工程、商用和农用车辆、数据处理、电动交通、工业应用、医疗设备、移动设备、电机控制与驱动、电源、面向摩托车电动自行车与小型电动车、智能电网、照明、太阳能系统解决方案、风能系统解决方案。

6、ST Microelectronics(意法半导体):意大利/法国,主要提供32位MCU。应用范围:LED和普通照明、交通运输、医疗保健、多媒体融合、家电和电动工具、楼宇自动化技术电机控制、电源和功率转换器、能源和智能电网、自动化、计算机与通信基础设施。

7、Qualcomm(高通):美国,主要提供16位,32位MCU。应用范围:智能手机、平板电脑、无线调制解调器。

8、Texas Instruments(德州仪器):美国,主要提供16位、32位MCU。应用范围:汽车电子、消费电子、医疗设备、移动设备、通信。

9、Maxim(美信):美国,主要提供32位MCU。应用范围:汽车电子、消费电子、工业应用、安防。

1、Renesas(瑞萨):日本,主要提供16位、32位MCU。应用范围:电脑及外设、消费类电子、健康医疗电子、汽车电子、工业、通信。

2、Toshiba(东芝):日本,主要提供16位、32位MCU。应用范围:汽车电子、工业用、电机控制、无线通信、移动电话、电脑与周边设备、影像及音视频、消费类(家电)、LED照明、安全、电源管理、娱乐设备。

3、Fujitsu(富士通):日本,主要提供32位MCU。应用范围:汽车、医疗、机械,家电。

4、Samsung Electronics(三星电子):韩国,主要提供16位、32位MCU。应用范围:汽车电子、工业用、电机控制、汽车、楼宇自动化、家用电器、家庭娱乐、工业自动化、照明、物联网、智能能源、移动电子设备、计算机外设。

1、希格玛微电子:主要提供32位MCU,应用范围:电信、制造、能源、交通、电力等。

2、珠海欧比特:主要提供32位MCU,应用范围:航空航天:星箭站船、飞行器;高端工控:嵌入式计算机;舰船控制、工业控制、电力设备、环境监控。

3、兆易创新:主要提供32位MCU,应用范围:工业自动化、人机界面、电机控制、安防监控、智能家居、物联网。

4、晟矽微电子:主要提供8位、32位MCU,应用范围:小家电、消费类电子、遥控器、鼠标、锂电池、数码产品、汽车电子、医疗仪器及计量、玩具、工业控制、智能家居及安防等领域。

5、芯海科技:主要提供16、32位MCU,应用范围:仪器仪表、物联网、消费电子、家电、汽车电子。

6、联华集成电路:主要提供8位、16位MCU,应用范围:消费电子、白色家电、工业控制、通信设备、汽车电子、计算机。

7、珠海建荣:主要提供8位MCU,应用范围:家用电器 、移动电源。

8、炬芯科技:主要提供8位至32位MCU,应用范围:平板电脑、智能家居、多媒体、蓝牙、wifi音频。

9、爱思科微电子:主要提供8位、16位MCU,应用范围:消费类芯片、通讯类芯片、信息类芯片、家电。

10、华芯微电子:主要提供8位、4位MCU,应用范围:卫星接收器、手机充电器、万年历、多合一遥控器。

11、上海贝岭(华大半导体控股):主要提供8位、16位、32位MCU,应用范围:计算机周边、HDTV、电源管理、小家电、数字家电。

12、海尔集成电路:主要提供14位、15位、16位MCU,应用范围:消费电子、汽车电子、工业、智能仪表。

13、北京君正:主要提供32位MCU,应用范围:可穿戴式设备、物联网、智能家电、汽车、消费类电子、平板电脑。

14、中微半导体:主要提供8位MCU,应用范围:智能家电、汽车电子、安防监控、LED照明及景观、智能玩具、智能家居、消费类电子。

15、神州龙芯集成电路:主要提供32位MCU,应用范围:电力监控、智能电网、工业数字控制、物联网、智能家居、数据监控。

16、紫光微电子:主要提供8位、16位MCU,应用范围:智能家电。

17、时代民芯:主要提供32位MCU,应用范围:汽车导航、交通监控、渔船监管、电力电信网络。

18、华润矽科微电子(华润微旗下公司):主要提供8位、16位MCU,应用范围:消费电子、工业控制、家电。

19、国芯科技:主要提供32位MCU,应用范围:信息安全领域 、办公自动化领域、通讯网络领域、 信息安全领域。

20、中天微:主要提供32位MCU,应用范围:智能手机、数字电视、机顶盒、汽车电子、GPS、电子阅读器、打印机。

21、华润微电子:主要提供8位、16位MCU,应用范围:家电,消费类电子、工业自动化控制的通用控制电路。

22、中颖电子:主要提供4位、8位、16位、32位MCU,应用范围:家电、电机。

23、灵动微电子:主要提供32位,应用范围:电机控制、蓝牙控制、高清显示、无线充、无人机、微型打印机、智能标签、电子烟、LED点阵屏等。

24、新唐科技:主要提供8位MCU,应用范围:照明、物联网等。

25、东软载波:主要提供8位、32位MCU,应用范围:家电、智能家居、仪器仪表、液晶面板控制器、工业控制等。

26、贝特莱:主要提供32位MCU,应用范围:智能家居、工业控制以及消费类产品领域。

27、笙泉科技:主要提供8位MCU,应用范围:车用、教育、工控、医疗等中小型显示面板。

28、航顺芯片:主要提供8位、32位MCU,应用范围:汽车、物联网等。

29、复旦微电子:主要提供16位、32位MCU,应用范围:智能电表、智能门锁等。

30、华大半导体:主要提供8位、16位、32位MCU,应用范围:工业控制、智能制造、智慧生活及物联网等。

1、宏晶科技:主要提供32位MCU。应用范围:通信、工业控制、信息家电、语音。

2、盛群半导体:主要提供8位、32位MCU。应用范围:消费电子、LED照明等。

3、凌阳科技:主要提供8位、16位MCU。应用范围:家庭影音。

4、中颖电子:主要提供4位、8位MCU。应用范围:充电器、移动电源、家电、工业控制。

5、松翰科技:主要提供8位、32位MCU。应用范围:摇控器、智能型充电器、大小系统、电子秤、耳温枪、血压计、胎压计、各类量测及健康器材。

6、华邦电子:主要提供8位、16位MCU。应用范围:车用电子、工业电子、网络、计算机、消费电子、物联网。

7、十速科技:主要提供4位、8位、51位MCU。应用范围:遥控器、小家电。

8、佑华微电子:主要提供4位、8位MCU。应用范围:录音集成电路产品、消费电子、家用产品。

9、应广科技单片机:主要提供4位、8位MCU。应用范围:机械、自动化、家电、机器人。

10、义隆电子:主要提供8位、16位MCU。应用范围:消费电子、电脑、智能手机。

任何一款MCU,其基本原理和功能都是大同小异,所不同的只是其外围功能模块的配置及数量、指令系统等。

对于指令系统,虽然形式上看似千差万别,但实际上只是符号的不同,其所代表的含义、所要完成的功能和寻址方式基本上是类似的。

要了解一款MCU,首先需要知道就是其ROM空间、RAM空间、IO口数量、定时器数量和定时方式、所提供的外围功能模块(Peripheral Circuit)、中断源、工作电压及功耗等等。

了解这些MCU Features后,接下来第一步就是将所选MCU的功能与实际项目开发的要求的功能进行对比,明确哪些资源是目前所需要的,哪些是本项目所用不到的。

对于项目中需要用到的而所选MCU不提供的功能,则需要认真理解MCU的相关资料,以求用间接的方法来实现,例如,所开发的项目需要与PC机COM口进行通讯,而所选的MCU不提供UART口,则可以考虑用外部中断的方式来实现。

对于项目开发需要用到的资源,则需要对其Manua*进行认真的理解和阅读,而对于不需要的功能模块则可以忽略或浏览即可。对于MCU学习来讲,应用才是关键,也是最主要的目的。

明确了MCU的相关功能后,接下来就可以开始编程了。

对于初学者或初次使用此款MCU的设计者来说,可能会遇到很多对MCU的功能描述不明确的地方,对于此类问题,可以通过两种方法来解决,一种是编写特别的验证程序来理解资料所述的功能;另一种则可以暂时忽略,单片机程序设计中则按照自己目前的理解来编写,留到调试时去修改和完善。前一种方法适用于时间较宽松的项目和初学者,而后一种方法则适合于具有一定单片机开发经验的人或项目进度较紧迫的情况。

指令系统千万不要特别花时间去理解。指令系统只是一种逻辑描述的符号,只有在编程时根据自己的逻辑和程序的逻辑要求来查看相关的指令即可,而且随着编程的进行,对指令系统也会越来越熟练,甚至可以不自觉地记忆下来。

MCU的程序的编写与PC下的程序的编写存在很大的区别,虽然现在基于C的MCU开发工具越来越流行,但对于一个高效的程序代码和喜欢使用汇编的设计者来讲,汇编语言仍然是最简洁、最有效的编程语言。

对于MCU的程序编写,其基本的框架可以说是大体一致的,一般分为初始化部分(这是MCU程序设计与PC最大的不同),主程序循环体和中断处理程序三大部分,其分别说明如下:

1、初始化:对于所有的MCU程序的设计来讲,初始化是最基本也是最重要的一步,一般包括如下内容:

屏蔽所有中断并初始化堆栈指针:初始化部分一般不希望有任何中断发生。

清除系统的RAM区域和显示Memory:虽然有时可能没有完全的必要,但从可靠性及一致性的角度出发,特别是对于防止意外的错误,还是建议养成良好的编程习惯。

IO口的初始化:根据项目的应用的要求,设定相关IO口的输入输出方式,对于输入口,需要设定其上拉或下拉电阻;对于输出口,则必须设定其初始的电平输出,以防出现不必要的错误。

中断的设置:对于所有项目需要用到的中断源,应该给予开启并设定中断的触发条件,而对于不使用的多余的中断,则必须给予关闭。

其他功能模块的初始化:对于所有需要用到的MCU的外围功能模块,必须按项目的应用的要求进行相应的设置,如UART的通讯,需要设定Baud Rate,数据长度,校验方式和Stop Bit的长度等,而对于Programmer Timer,则必须设置其时钟源,分频数及Reload Data等。

参数的初始化:完成了MCU的硬件和资源的初始化后,接下来就是对程序中使用到的一些变量和数据的初始化设置,这一部分的初始化需要根据具体的项目及程序的总体安排来设计。对于一些用EEPROM来保存项目预制数的应用来讲,建议在初始化时将相关的数据拷贝到MCU的RAM,以提高程序对数据的访问速度,同时降低系统的功耗(原则上,访问外部EEPROM都会增加电源的功耗)。

2、主程序循环体:大多数MCU是属于长时间不间断运行的,因此其主程序体基本上都是以循环的方式来设计,对于存在多种工作模式的应用来讲,则可能存在多个循环体,相互之间通过状态标志来进行转换。对于主程序体,一般情况下主要安排如下的模块:

计算程序:计算程序一般比较耗时,因此坚决反对放在任何中断中处理,特别是乘除法运算。

实时性要求不高或没有实时性要求的处理程序;

显示传输程序:主要针对存在外部LED、LCD Driver的应用。

3、中断处理程序:中断程序主要用于处理实时性要求较高的任务和事件,如,外部突发性信号的检测,按键的检测和处理,定时计数,LED显示扫描等。

一般情况下,中断程序应尽可能保证代码的简洁和短小,对于不需要实时去处理的功能,可以在中断中设置触发的标志,然后由主程序来执行具体的事务――这一点非常重要,特别是对于低功耗、低速的MCU来讲,必须保证所有中断的及时响应。

4、对于不同任务体的安排,不同的MCU其处理的方法也有所不同:

例如,对于低速、低功耗的MCU(Fosc=32768Hz)应用,考虑到此类项目均为手持式设备和采用普通的LCD显示,对按键的反应和显示的反应要求实时性较高,因此一般采用定时中断的方式来处理按键的动作和数据的显示;而对于高速的MCU,如Fosc》1MHz的应用,由于此时MCU有足够的时间来执行主程序循环体,因此可以只在相应的中断中设置各种触发标志,并将所有的任务放在主程序体中来执行。

5、在MCU的程序设计中,还需要特别注意的一点就是:

要防止在中断和主程序体中同时访问或设置同一个变量或数据的情况。有效的预防方法是,将此类数据的处理安排在一个模块中,通过判断触发标志来决定是否执行该数据的相关操作;而在其他的程序体中(主要是中断),对需要进行该数据的处理的地方只设置触发的标志。――这可以保证数据的执行是可预知和唯一的。

七、工程师对单片机编程的总结

1、要养成总结的好习惯,总结不仅是对自己学习的一个总结,还是对学习过程的一个回顾与加深,还可避免第二次犯错。

2、编写程序之前先要有一个对该项目熟悉的了解,做到心中有数,列一个大致框架。仔细推敲该怎么布局,怎样布局最合理,该步骤很重要。要分析先做哪个模块,具体到该模块的具体步骤,各个函数怎么命名,与其他模块的衔接等。最好拿张纸记下重要过程。

3、对于c语言的模块化编程,要先分好各个模块,一个模块一个模块的编程,确定一个顺序,按顺序来,该模块成功之后再编写下一个。对于头文件,当该模块编写好之后再编写该模块的头文件。

4、出现警告不要忽视,说明该程序一定有不合理之处,要弄清其来源,找到解决办法。找来源时要有针对性,可上网搜一下该方面的资料,或向别人请教。例如,居然把另一个工程内的main函数加入了这个工程。还有居然函数命名重复。还有根据实验现象分析原因,层层递进。还有端口定义时居然选错了接口。有时,实在解决不了就休息一下,在想也挺好的。再简单的地方也要注意一下,都有可能出错。

在单片机应用开发中,代码的使用效率问题、单片机抗干扰性和可靠性等问题仍困扰着。现归纳出单片机开发中应掌握的几个基本技巧。

1、如何减少程序中的bug

对于如何减少程序的bug,应该先考虑系统运行中应考虑的超范围管理参数如下。

物理参数:这些参数主要是系统的输入参数,它包括激励参数、采集处理中的运行参数和处理结束的结果参数。

资源参数:这些参数主要是系统中的电路、器件、功能单元的资源,如记忆体容量、存储单元长度、堆叠深度。

应用参数:这些应用参数常表现为一些单片机、功能单元的应用条件。过程参数:指系统运行中的有序变化的参数。

2、如何提高C语言编程代码的效率

用C语言进行单片机程序设计是单片机开发与应用的必然趋势。如果使用C编程时,要达到最高的效率,最好熟悉所使用的C编译器。先试验一下每条C语言编译以后对应的汇编语言的语句行数,这样就可以很明确的知道效率。在今后编程的时候,使用编译效率最高的语句。各家的C编译器都会有一定的差异,故编译效率也会有所不同,优秀的嵌入式系统C编译器代码长度和执行时间仅比以汇编语言编写的同样功能程度长5-20%。

对于复杂而开发时间紧的项目时,可以采用C语言,但前提是要求你对该MCU系统的C语言和C编译器非常熟悉,特别要注意该C编译系统所能支持的数据类型和算法。虽然C语言是最普遍的一种高级语言,但由于不同的MCU厂家其C语言编译系统是有所差别的,特别是在一些特殊功能模块的操作上。所以如果对这些特性不了解,那么调试起来问题就会很多,反而导致执行效率低于汇编语言。

3、如何解决单片机的抗干扰性问题

防止干扰最有效的方法是去除干扰源、隔断干扰路径,但往往很难做到,所以只能看单片机抗干扰能力够不够强了。在提高硬件系统抗干扰能力的同时,软件抗干扰以其设计灵活、节省硬件资源、可靠性好越来越受到重视。

单片机干扰最常见的现象就是复位,至于程序跑飞,其实也可以用软件陷阱和看门狗将程序拉回到复位状态,所以单片机软件抗干扰最重要的是处理好复位状态。

一般单片机都会有一些标志寄存器,可以用来判断复位原因;另外你也可以自己在RAM中埋一些标志。在每次程序复位时,通过判断这些标志,可以判断出不同的复位原因;还可以根据不同的标志直接跳到相应的程序。这样可以使程序运行有连续性,用户在使用时也不会察觉到程序被重新复位过。

4、如何测试单片机系统的可靠性

当一个单片机系统设计完成,对于不同的单片机系统产品会有不同的测试项目和方法,但是有一些是必须测试的:

测试单片机软件功能的完善性

有时候,我们还可以模拟人为使用中,可能发生的破坏情况。例如用人体或者衣服织物故意摩擦单片机系统的接触端口,由此测试抗静电的能力。用大功率电钻靠近单片机系统工作,由此测试抗电磁干扰能力等。

综上所述,单片机已成为计算机发展和应用的一个重要方面,单片机应用的重要意义还在于,它从根本上改变了传统的控制系统设计思想和设计方法。

从前必须由模拟电路或数字电路实现的大部分功能,现在已能用单片机通过软件方法来实现了。这种软件代替硬件的控制技术也称为微控制技术,是传统控制技术的一次革命。

此外在开发和应用过程中我们更要掌握技巧,提高效率,以便于发挥它更加广阔的用途。

对芯片的操作主要是对芯片内寄存器的操作,芯片内寄存器在存储器上映射的都有自己的唯一地址,这也就是对相应的地址的操作。看芯片,首先看时序图,再了解相应的寄存器,了解是如何操作的,定义需要的端口(程序可以识别),编写写操作程序和读操作程序。

如何往芯片内写入数据,如何读出数据,通过哪个端口输入或读出(最主要的地方)。

通过总线连接芯片时,首先要了解该总线的协议。I2c总线连接的芯片,主要通过该总线去控制该芯片。

1、点阵中一个74hc595用于列的选择,令外两个用于颜色的选择,点阵相当于二极管的集合,

一端给高电平,另一端给低电平,二极管才能亮。只是一端选择不同时,亮不同的颜色。

定时器工作模式的选择:高四位是设置定时器T1,低四位设置T0。然后各模式的后两位设置工作模式。当设置两个定时器时,注意使用或(|)。当用中断时,注意进入中断后,该清零的要清零。

2、串口收发:波特率的设置一般用模式2(自动重装初值),因为不同的装置,处理数据的能力不同,设置波特率主要为了照顾低速装置及为了彼此间的通讯。中断标志位要软件清零。设置串口中断时,收发无论哪一个产生都能进入中断函数,因此要注意设置中断函数。(自我感觉一般设置一种功能,当做上位机或下位机)。

发送用中断的话,要解决第一次该怎么进入中断,因此首先要发送一次,此后就可以进入中断了。一次只能发一字节,而且只有在TI置一之后才能发送下一位。

3、Pcf8591ad转换,有四个通道的输入,读pcf8591时,选通哪一个通道,读的就是那个通道输入的电压,转换后的数据存储在该芯片内,再读出。读时先写芯片的地址,在写器件的子地址(0x40|通道号),然后就是读出的数据。

4、Da转换是先向芯片内写入器件地址,在写子地址(0x40),在写要转换的数字量。器件地址芯片资料有介绍。

5、对于液晶显示,写入数据显示后,他会一直显示,不用持续刷新,要想改变,只有重新输入。

6、对于ds1302时钟芯片,读数据时是在写入数据时的第八个时钟下降沿就读出第一位数据的的,然后再为下次输出做准备,注意程序的写法,还要注意返回值放的位置。

7、Ds1302中先指明寄存器,再向其中写入数据。芯片资料上的寄存器标出的是地址。(写保护处程序还不大明白,不是一直都有写入吗?为什么还打开写保护?)

(根据前面的大侠,可以在初始化时间后设一标志,有此标志则不用再初始化时间。但是如果断电后,MCU的RAM是无法保存这个标志的,因此可以用DS1302的RAM保存该标志,待上电后读取该标志。我也是初学者,最近也打算用DS1302。不知说法对不,我也还没具体实施,多交流)

8、初始化最好还要写一下,以防以后忘记。有时注意读出或写入时,首先操作的是最低位还是最高位,可根据时序图判断出。

9、对于红外收发,接收时,他是根据两个下降沿之间的时间长短来确定是高电平还是低电平,写程序时,先用定时器确定时间长短,保存,然后再转化成二进制(该程序写法多看看,很好)。

10、步进电机:主要做开关用,步进电机的力矩随转速的升高而降低。主要用在机床上零部件加工的自动进给。对有较高精度的控制场所都可也使用。

步进电机是将电脉冲信号转变为角位移或线位移的开环控制元步进电机件。在非超载的情况下,电机的转速、停止的位置只取决于脉冲信号的频率和脉冲数,而不受负载变化的影响,当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度,称为“步距角”,它的旋转是以固定的角度一步一步运行的。可以通过控制脉冲个数来控制角位移量,从而达到准确定位的目的;同时可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的。

)是指在伺服系统中控制机械元件运转的发动机,是一种补助马达间接变速装置。伺服电机可使控制速度,位置精度非常准确,可以将电压信号转化为转矩和转速以驱动控制对象。伺服电机转子转速受输入信号控制,并能快速反应,在自动控制系统中,用作执行元件,且具有机电时间常数小、线性度高、始动电压等特性,可把所收到的电信号转换成电动机轴上的角位移或角速度输出。分为直流和交流伺服电动机两大类,其主要特点是,当信号电压为零时无自转现象,转速随着转矩的增加而匀速下降。

直流电机:范围较大,小车上都是。

为了将汉字在显示器或打印机上输出,把汉字按图形符号设计成点阵图,就得到了相应的点阵代码(字形码)。

为在计算机内表示汉字而统一的编码方式形成汉字编码叫内码(如国标码),内码是惟一的(相当于该字的身份证号)。为方便汉字输入而形成的汉字编码为输入码,属于汉字的外码,输入码因编码方式不同而不同,是多种多样的。为显示和打印输出汉字而形成的汉字编码为字形码,计算机通过汉字内码在字模库中找出汉字的字形码,实现其转换。

根据国标码的规定,每一个汉字都有了确定的二进制代码,但是这个代码在计算机内部处理时会与ASCII码发生冲突,为解决这个问题,把国标码的每一个字节的首位上加1。由于ASCII码只用7位,所以,这个首位上的“1”就可以作为识别汉字代码的标志,计算机在处理到首位是“1”的代码时把它理解为是汉字的信息,在处理到首位是“0”的代码时把它理解为是ASCII码。经过这样处理后的国标码(内码)就是机内码。

如果我们把这个“口”字图形的“.”处用“0”代替,就可以很形象地得到“口”的字形码:H 3FFAH H H H H2004H 3FFAH H 0000H。计算机要输出“口”时,先找到显示字库的首址,根据“口”的机内码经过计算,再去找到“口”的字形码,然后根据字形码(要用二进制)通过字符发生器的控制在屏幕上进行依次扫描,其中二进制代码中是“0”的地方空扫,是“1”的地方扫出亮点,于是就可以得到“口”的字符图形。

汉字字模按国标码的顺序排列,以二进制文件形式存放在存储器中,构成汉字字模字库,亦称为汉字字形库,称汉字库

两种编码方法,见头文件

// 汉字库: ,横向取模左高位,数据排列:从左到右从上到下 //

这个结构,很简单的:一个是内码,一个点阵序列,以前的点阵库是按内码顺序放的,不需要内码索引的,如果只放部分汉字,就需要内码索引了。(前面的汉字“徐”是为了要输出“徐”的时候找到该字的点阵序列,这个点阵序列是自己写的,当用1602显示时,因为该芯片内存在英文的点阵序列,所以就不用写了)一般内码两个字节就行了,多用1个字节是加了个尾0而已,这样,汉字内码处直接放汉字字符串就可;

每个显示点对应一位二进制数,1 表示亮,0 表示灭。存储这些点阵信息的RAM称为显示数据存储器。要显示某个图形或汉字就是将相应的点阵信息写入到相应的存储单元中。

绘图RAM的地址计数器(AC)只会对水平地址(X 轴)自动加一, 当水平地址=0FH 时会重新设为00H 但并不会对垂直地址做进位自动加一,故当连续写入多笔资料时,程序需自行判断垂直地址是否需重新设定

绘图显示RAM提供128×8 个字节的记忆空间,在更改绘图RAM时,先连续写入水平与垂直的坐标值,再写入两个字节的数据到绘图RAM,而地址计数器(AC)会对水平地址(X 地址)自动加一,当水平地址为0XFH 时会重新设为00H ;不会对垂直地址做进位自动加 1. 。在写入绘图 RAM的期间,绘图显示必须关闭,

对于C语言,定义的变量,自动为其分配空间,其地址为该变量的名称。通过该名称,可以在内存中招到该数据,经过运算得到新数据,而汇编中需要编程者自己定义存储空间及把数据送到累加器等进行运算,每一步都需要编程者操作。而C语言这些过程由编译器去完成。

15、一些有用的答疑解惑

①、单片机C语言,其变量的内存开辟是如何进行的?难道是编译器,在编译过程中智能地加入分配与回收的代码?关键之处在于我所做的程序,如何保证其没有内存溢出错误?如果我进行的是递归运算,这样的话,内存需求是很难自己计算的。

②、单片机C语言在变量定义上是否会受到约束?比如浮点型数据的乘除运算,通过汇编还写,代码相当复杂,如果直接C语言来写,岂不过份简单?

③、单片机C语言生成的hex文件中,指令及数据的ROM的地址分布是否编译器自动分配?可否用户进行分配?

回答1:c语言写的单片机程序,先由1个程序(好像是c51.exe)编译,编译完成后,变量的存储空间大小已经安排好,只是还没分配具体地址(地址浮动),接下来有另一个程序(好像是a51.exe)进行连接,连接以后,具体地址确定。

如果变量过多,编译会提示数据段too large,要保证其没有内存溢出错误,主要考虑堆栈是否溢出,要靠经验

单片机c语言一般禁止递归,一般都避免用递归运算,单片机毕竟不是PC,会影响速度的,要递归的话,用DSP芯片更合适,总之,要会挑合适的芯片

回答2:变量的大小(位数)一般和芯片累加器的位数一样,比如51常用8位的,因为它是8位单片机

单片机可以定义位变量,但是不可以定义位数组。用c语言写只是看着简单,实际生成的代码量是最多的,用于控制的单片机几乎不用浮点数运算,不仅慢还麻烦还占地方,如果是DSP芯片,本身有适合的硬件结构,会好很多。

回答3:一般是自动分配的,可以c语言和汇编语言混合编程,也可以用Keil C在线汇编,芯片与外部的数据交换都是通过端口进行的。

我要回帖

更多关于 16mb是多少字节 的文章

 

随机推荐