嵌入式系统C语言

2024-05-30

嵌入式系统C语言(精选10篇)

嵌入式系统C语言 篇1

摘要:本文介绍了嵌入式系统编程语言的发展,并将C语言和时下其他较为流行的编程语言比较,分析了各自的优缺点和未来发展趋势。

关键词:MYMY关键词:嵌入式系统,编程语言,C语言,Android,Python

您在下一项目编程时所使用的最佳语言是什么?如果您是一名嵌入式系统设计人员,可能认为这一问题实在可笑。您会使用C语言,如果希望加强管理,则会使用C衍生的C++。可能会有一些关键代码片段是以汇编语言编写的,但是,据Barr集团最近的一项研究表明,目前95%的嵌入式系统代码是采用C或者C++编写的。

然而,世界是在变化的。新的程序员、新挑战以及新体系结构让C松开了在嵌入式软件上的“抓手”。据最近的一项研究表明,嵌入式计算语言发展最快的是Python,当然还有很多其他参与竞争的语言,只是这些语言仍然占少数。但是逐渐地,一直坚持使用C/C++的程序员像20年前汇编语言专家那样开始冒险——采用更快、更紧凑和更可靠的程序。图1提出了新语言能够提高嵌入式计算机领域的效能。

C语言在嵌入式领域中的地位受到冲击

嵌入式算法变革的一个主要推动力量是其他工作环境的程序员进入了嵌入式领域。这方面最明显的是刚毕业的学生进入职场。以前,刚毕业的学生在C课程中学会了编程,会用C或者C++完成他们的大部分项目。而现在,已经不再如此了。Intel软件工程经理David Stewart注意到,“现在,大部分计算机科学课程使用Python作为他们的入门语言。”计算机科学专业毕业的学生很有可能在Python、Ruby以及几种脚本语言上有丰富的经验,但是他们可能从未认真地使用过C语言。同时,其他影响也越来越多。使用Android作为平台进行相关的或者用户友好的嵌入式设计,为Android的自然语言——Java,带来了机会。在这一复杂景象的另一端,机器人、无人机或者相似的小项目业余爱好开发人员通常都有Arduino或者Raspberry-Pi背景。他们的经验会体现在非常紧凑和简单的程序发生器或者B#等小型语言环境里。

这一现象对物联网(Io T)的广泛研究也产生了影响,网络开发人员也参与到讨论中。他们认为,如果嵌入式系统的外部接口是RESTful Web,编程语言应该是Java Script或者其服务器侧相关的Node.js。热衷于使用C语言进行开发的人员应该观察一下node.js——贝宝和沃尔玛等公司在企业规模的开发中大量使用了这一可扩展平台,据跟踪调查网站modulecounts.com,在任何编程语言中,该平台的辅助支持系统增长是最快的。

选择Node.js的动机部分是源自文化,但是也有体系结构方面的因素。Io T会在客户侧、互联网以及服务器侧之间分配其嵌入式系统任务。其中,客户侧连接实际环境,通常要求尽可能少地采用硬件。客户侧很自然地采用硬件专用库支持的Web应用程序,而服务器侧则是服务器应用程序。这样,对于Web程序员,在Io T系统编程中很显然会使用Java Script和Node.js。

日益复杂的嵌入式算法是变革的另一推动力量。简单的控制环路被卡尔曼滤波器、神经网络以及基于模型的控制功能所替代,高性能计算语言——Python,开放计算语言(例如Open CL™)以及MATLAB等基于模型的环境逐渐发展起来。

强烈的动机

那么这些新人们为什么不静下心来学习C语言呢?Stewart说:“真正的原因在于开发人员的效能。”反对C语言的人一直认为这种语言编写慢,容易出错,会带来意想不到的硬件相关问题,并且除了最初的程序员,其他人很难读懂它。这些因素会对提高设计效能产生不利影响。而很多最近出现的语言逐步转向快速学习和高效的代码重用。虽然目前几乎所有语言都受益于C语言高度简洁的语法,但现在的重点已经转回可读性,而不是最少字符数。不但在现代语言中鼓励实现协调一致的文档,而且结构化约定也通常会这样定义文档。C程序员一直把这类文档看成是自由表述的例子,因为作者自己不会牵连其中。例如,这些约定使得实用工具程序能够从Python组件的结构化注释中生成用户手册。

现代语言还采用了高级数据结构,可以在C++环境中建立任何对象,并重用它。基于指针,Python还提供自然List和Dictionary数据类型。而Ruby等其他语言,基本上是面向对象的,支持结构和重用,这使其可以融入到程序员的习惯中。

影响了现代语言是否易于重用的另外两个重要因素是动态输入和模块化。动态输入是一个很有争议的因素。当程序员在使用变量时,解释程序确定程序员传送给表达式的数值的当前数据类型——几乎所有这些服务器侧语言都是解释性的,而不是编译的。然后,解释程序会选择相应的操作,评估含有该数据类型的表达式。这样,程序员不用太过担心他要调用的函数需要的是整数变量还是实数变量。但是,嵌入式程序和代码可靠性专家很快指出,动态输入在运行时实际上效率不高。另一个因素是部分程序员对模块化的偏见。有时候会有人说,Python编程实际上不是编程,而是脚本,是把别人用C语言编写的函数调用或串起来。

可读性、协调一致的文档、动态输入以及函数大量的重用等,催化了开源领域中辅助支持系统的爆发。程序员本能地会在巨大的开源库中找到他们能够使用的函数,例如,npm(用于Node.js)、Py PI(用于Python)或者Rubygems.org(用于Ruby)。如果他们不用修改组件或者编写新的组件,他们会回到库中工作。结果,库会越来越大(npm目前大概有25万个组件)。这些大规模的辅助支持系统也相应地大幅度提高了程序员的效能。

嵌入式的新编程语言的不足之处及解决方法

这些编程语言尽管有这么多的优点,但也有缺点。要想在嵌入式计算领域占据一席之地还有很多不足。

大部分这些语言最明显的问题是,它们是解释性的,而不是编译的。这意味着它们需要可观的运行时程序包,包括解释程序本身、工作存储、动态输入开销和运行时库等,都要适配到嵌入式系统中。基本上,所有这些会非常紧凑,某些Java虚拟机可以装入到几十K字节中,但是Node.js、Python以及来自服务器侧相似的语言需要自己的空间。一个兼容性还可以的Python虚拟机在加入程序员自己的代码之前可能已经占用了几兆字节。

在性能问题方面,解释程序读取每一行代码(源程序或者预处理过的中间级代码)需要解析它、进行运行时检查以及调用执行所需操作的例程。在C语言中,这会导致一行代码有很多操作,编译成很多机器语言指令。执行时间和能耗的成本都会增加。

在运行时效率方面,可以使用即时(Ji T)编译器进行改进。一个Ji T编译器可以与解释程序并行工作,为循环中的代码生成编译后的机器指令,因此,后续的代码能够更快地执行。Stewart说:“Ji T技术非常有趣,Py Py Ji T编译器把Python执行速度提高了两倍。”对于效率方面,还研究了其他方法。例如,如果函数是无阻塞的,或者使用了信令机制,有很多函数调用的程序即使是在采用循环展开等方法来建立更多的线程之前,也可以含有很多线程。因此,可以在一个组件上应用很多多线程内核——这是高性能计算已经研究应用的方向。更进一步,Ruby语言本身支持多线程,因此,即使底层操作系统不支持线程,它也能够产生线程代码。某些团队则寻求在硬件加速器中实现库或者组件,例如,图形处理单元(GPU)、Xeon Phi和FPGA。实际上,解释程序本身就会有适合加速的任务。

服务器侧语言遇到的其他困难是缺少处理实际环境的结构。在服务器环境中,除了网络和存储,没有实时限制,也没有I/O。可以通过几种方式来解决这一问题。

最简单的是,Android环境以硬件几乎无关的抽象方式包封Java代码:具有图形、触摸屏、音频、视频、多个网络以及物理传感器的虚拟机。对于更强调物理I/O,甚至能够在微控制器上运行的轻型平台,提供嵌入式Java。

Python等语言需要不同的方法。由于CPython解释程序运行在Linux上,因此,原理上能够运行在有足够速度和物理存储器的任何嵌入式Linux系统中。在这方面已经有了工作基础,通过减小装入时间开销,为物理I/O访问提供功能,使用硬件加速器,进一步适应CPython,运行时系统适应实时约束。最新的一个实例是STM32微控制器的裸金属Micro Python环境。虽然这看起来几乎不可能,但是已经在Node.js下面的Java Script引擎上有了类似的工作。

安全呈现出更多的问题。很多安全和可靠性标准不鼓励甚至禁止使用未经正式认证或者全面测试的开源代码。这些限制使得不可能重用组件,或者重用组件过于复杂,对效能的提高不大。同样等级的详细检查也延伸到虚拟机等开源环境中。在可靠和安全大环境下,CPython等开源平台很容易受到攻击。

未来的编程语言发展方向

最后,考虑到有众多的推动力量促使新语言进入嵌入式世界中,可以预见到会有多语系统,这种系统含有的组件来自多种源语言,每一种选择要使用的关键库,或者方便某类开发人员使用。当然,您可以在不同的CPU内核上放置几种虚拟机,在一个内核管理程序下相统一,然后,通过函数调用,为任务间消息的传送提供约定。但是,这样的系统最终会非常大。

另一种可能是一组语言相关解释程序,为Ji T编译器生成公共中间代码(图2)。当然,还能列出其他问题,例如,不同的任务间具有不同的通信模型、存储器模型和调试环境,但这些问题总是能够解决的。

小结

如果这些最终会到来,那么,一名经验丰富的嵌入式程序员该如何应对?您可以从Web编程、服务器甚至业余爱好者使用的开发环境中研究这些语言。您可以在下一项目中,尝试在C++和解析语言中开发组件。这需要时间学习,但是独立并行开发是值得的。

嵌入式系统C语言 篇2

volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。

用volatile关键字声明的变量i每一次被访问时,执行部件都会从i相应的内存单元中取出i的值。

没有用volatile关键字声明的变量i在被访问的时候可能直接从cpu的寄存器中取值(因为之前i被访问过,也就是说之前就从内存中取出i的值保存到某个寄存器中),之所以直接从寄存器中取值,而不去内存中取值,是因为编译器优化代码的结果(访问cpu寄存器比访问ram快的多)。

以上两种情况的区别在于被编译成汇编代码之后,两者是不一样的。之所以这样做是因为变量i可能会经常变化,保证对特殊地址的稳定访问。

volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。

使用该关键字的例子如下:

int volatile nVint;

当要求使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。

例如:

volatile int i=10;

int a = i;

...//其他代码,并未明确告诉编译器,对i进行过操作

int b = i;

volatile 指出 i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在b中。而优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在b中。而不是重新从i里面读。这样以来,如果i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问。

注意,在vc6中,一般调试模式没有进行代码优化,所以这个关键字的作用看不出来。下面通过插入汇编代码,测试有无volatile关键字,对程序最终代码的影响:

首先,用classwizard建一个win32 console工程,插入一个voltest.cpp文件,输入下面的代码:

#i nclude

void main()

{

int i=10;

int a = i;

printf(“i= %dn”,a);

//下面汇编语句的作用就是改变内存中i的值,但是又不让编译器知道

__asm {

mov dword ptr [ebp-4], 20h

}

int b = i;

printf(“i= %dn”,b);

}

然后,在调试版本模式运行程序,输出结果如下:

i = 10

i = 32

然后,在release版本模式运行程序,输出结果如下:

i = 10

i = 10

输出的结果明显表明,release模式下,编译器对代码进行了优化,第二次没有输出正确的i值。

下面,我们把 i的声明加上volatile关键字,看看有什么变化:

#i nclude

void main()

{

volatile int i=10;

int a = i;

printf(“i= %dn”,a);

__asm {

mov dword ptr [ebp-4], 20h

}

int b = i;

printf(“i= %dn”,b);

}

分别在调试版本和release版本运行程序,输出都是:

i = 10

i = 32

这说明这个关键字发挥了它的作用!

文章一:

讲讲volatile的作用

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: 1).并行设备的硬件寄存器(如:状态寄存器)

2).一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)3).多线程应用中被几个任务共享的变量 回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。

假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。

1).一个参数既可以是const还可以是volatile吗?解释为什么。2).一个指针可以是volatile 吗?解释为什么。3).下面的函数有什么错误:

int square(volatile int *ptr){ return *ptr * *ptr;} 下面是答案:

1).是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。

2).是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。

3).这段代码的有个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码: int square(volatile int *ptr){ int a,b;a = *ptr;b = *ptr;return a * b;} 由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下: long square(volatile int *ptr){ int a;a = *ptr;return a * a;} 讲讲我的理解:(欢迎打板子...~~!)

关键在于两个地方:

1.编译器的优化(请高手帮我看看下面的理解)

在本次线程内, 当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中;以后,再取变量值时,就直接从寄存器中取值;

当变量值在本线程里改变时,会同时把变量的新值copy到该寄存器中,以便保持一致

当变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致

当该寄存器在因别的线程等而改变了值,原变量的值不会改变,从而造成应用程序读取的值和实际的变量值不一致

举一个不太准确的例子:

发薪资时,会计每次都把员工叫来登记他们的银行卡号;一次会计为了省事,没有即时登记,用了以前登记的银行卡号;刚好一个员工的银行卡丢了,已挂失该银行卡号;从而造成该员工领不到工资

员工 -- 原始变量地址

银行卡号 -- 原始变量在寄存器的备份

2.在什么情况下会出现(如1楼所说)

1).并行设备的硬件寄存器(如:状态寄存器)

2).一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)3).多线程应用中被几个任务共享的变量

补充: volatile应该解释为“直接存取原始内存地址”比较合适,“易变的”这种解释简直有点误导人;

“易变”是因为外在因素引起的,象多线程,中断等,并不是因为用volatile修饰了的变量就是“易变”了,假如没有外因,即使用volatile定义,它也不会变化;

而用volatile定义之后,其实这个变量就不会因外因而变化了,可以放心使用了; 大家看看前面那种解释(易变的)是不是在误导人

------------简明示例如下:------------------

volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。使用该关键字的例子如下: int volatile nVint;>>>>当要求使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。例如:

volatile int i=10;int a = i;...//其他代码,并未明确告诉编译器,对i进行过操作 int b = i;>>>>volatile 指出 i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在b中。而优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在b中。而不是重新从i里面读。这样以来,如果i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问。

>>>>注意,在vc6中,一般调试模式没有进行代码优化,所以这个关键字的作用看不出来。下面通过插入汇编代码,测试有无volatile关键字,对程序最终代码的影响:

>>>>首先,用classwizard建一个win32 console工程,插入一个voltest.cpp文件,输入下面的代码: >> #i nclude void main(){ int i=10;int a = i;printf(“i= %d”,a);//下面汇编语句的作用就是改变内存中i的值,但是又不让编译器知道 __asm { mov dword ptr [ebp-4], 20h } int b = i;printf(“i= %d”,b);} 然后,在调试版本模式运行程序,输出结果如下: i = 10 i = 32 然后,在release版本模式运行程序,输出结果如下: i = 10 i = 10 输出的结果明显表明,release模式下,编译器对代码进行了优化,第二次没有输出正确的i值。下面,我们把 i的声明加上volatile关键字,看看有什么变化: #i nclude void main(){ volatile int i=10;int a = i;printf(“i= %d”,a);__asm { mov dword ptr [ebp-4], 20h } int b = i;printf(“i= %d”,b);} 分别在调试版本和release版本运行程序,输出都是: i = 10 i = 32 这说明这个关键字发挥了它的作用!

------------------------------------

volatile对应的变量可能在你的程序本身不知道的情况下发生改变

比如多线程的程序,共同访问的内存当中,多个程序都可以操纵这个变量 你自己的程序,是无法判定合适这个变量会发生变化

还比如,他和一个外部设备的某个状态对应,当外部设备发生操作的时候,通过驱动程序和中断事件,系统改变了这个变量的数值,而你的程序并不知道。

对于volatile类型的变量,系统每次用到他的时候都是直接从对应的内存当中提取,而不会利用cache当中的原有数值,以适应它的未知何时会发生的变化,系统对这种变量的处理不会做优化——显然也是因为它的数值随时都可能变化的情况。

------------------

典型的例子

for(int i=0;i<100000;i++);这个语句用来测试空循环的速度的

但是编译器肯定要把它优化掉,根本就不执行 如果你写成

for(volatile int i=0;i<100000;i++);它就会执行了

volatile的本意是“易变的” 由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。比如:

static int i=0;

int main(void){...while(1){ if(i)dosomething();} }

/* Interrupt service routine.*/ void ISR_2(void){ i=1;}

程序的本意是希望ISR_2中断产生时,在main当中调用dosomething函数,但是,由于编译器判断在main函数里面没有修改过i,因此

可能只执行一次对从i到某寄存器的读操作,然后每次if判断都只使用这个寄存器里面的“i副本”,导致dosomething永远也不会被

调用。如果将将变量加上volatile修饰,则编译器保证对此变量的读写操作都不会被优化(肯定执行)。此例中i也应该如此说明。

一般说来,volatile用在如下的几个地方:

1、中断服务程序中修改的供其它程序检测的变量需要加volatile;

2、多任务环境下各任务间共享的标志应该加volatile;

3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;

另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实

嵌入式系统C语言 篇3

关键词:数据同步;客户端;C语言

中图分类号:TP311.52文献标识码:A文章编号:1007-9599 (2010) 16-0000-02

The C-language Design Research of Data Synchronization System Client

Dai Xiuhong

(Liaoning Petrochemical College,Jinzhou121000,China)

Abstract:The research data synchronization system of the client's C language design,data synchronization system proposed by the client data synchronization process and data management and monitoring,this paper addresses generated in the process of enterprise information system database of multiple inter-related business data synchronization,data synchronization process in particular,face three major issues:how to accurately access the source system data,howto keep the data is safe,timely and correct sent to the target system and how to synchronize data and processes on a unified monitoring and management.

Keywords:Data synchronization;Client;C language

對于业务系统来说数据的正确性将直接影响到企业的正常工作和发展,因此对数据同步的过程和数据进行监控和管理就显得尤为重要。同步系统使用了独立的数据库来存放所有同步的数据,同步系统的客户端可以对同步的数据和过程进行管理。客户端登陆时需要设置同步系统服务器端的IP地址并输入正确的用户名、密码才能进入客户端系统进行操作。本文研究数据同步系统客户端的功能设计和异常信息日志表等数据表的设计。数据同步系统包括数据同步系统服务器端、数据同步系统客户端和数据同步系统转发器端。同步系统服务器端对源数据发送方进行身份验证并接收源系统发送的数据后保存在数据同步系统数据库的待发送表中,数据同步系统转发器端将数据从待发送表中取出发送给数据接收方,而通过数据同步系统客户端可以实现对数据同步过程中的同步数据和同步过程的监督和管理。

一、同步数据的查询、新增和修改模块

在成功登录同步系统客户端后可以对待发送数据表、已发送数据表和异常信息日志表的数据进行管理。其主要功能包括:

(一)待发送表数据的查询、修改功能。待发送表中保存了所有未发送到目标系统的正常状态消息和发送失败的异常状态消息,通过数据同步客户端可以查询到这些数据并进行修改操作,考虑为了保护数据的完整性和一致性,数据同步系统的客户端没有开放数据删除的功能。

(二)已发送表数据的查询。己发送表中保存了所有正确发送到目标系统的所有数据,可以通过数据同步系统客户端查询这些数据,但不允许修改和删除操作。

(三)异常信息日志表数据的查询。异常信息日志表记录了数据同步系统服务器本身在运行过程中发生的异常信息、源数据发送方调用同步系统服务器端接口时发生的异常信息和数据同步系统转发器端向数据接收系统发送数据时发生异常的信息,通过数据同步系统客户端可以查询所有的异常信息,为相关系统负责人进行故障排查提供了依据。

二、异常状态数据管理

在数据同步的过程中可能会出现各种的异常情况如:源系统组织的数据问题、数据接收系统服务器问题、身份验证问题等各种情况,在异常发生时需要将发生异常的数据暂停发送,并将待发送数据表中的一些相关数据的状态进行修改防止造成数据错误。若在数据同步系统转发器将正常状态的数据发送给某个数据接收方时发生了异常,则该条数据的状态将变为异常状态,所有待发送数据表中与该条数据相同转发类型和数据接收系统的所有数据的状态将同时更新为异常状态,此时数据同步系统转发器端将停止向该数据接收方发送数据,但不会对其它的数据接收方产生影响。通过数据同步客户端可以查询到异常发生时的时间和异常信息等,系统负责人可以根据异常信息快速的判断异常发生的可能原因并及时的进行处理,若是由于源系统方发送的数据问题产生异常,则可以在待发送查询页面中查询到该数据并进行修改保存操作。在系统负责人确认异常情况已经解决后可以查询待发送表中的异常状态数据并修改其状态为正常状态,此后数据同步系统转发器将自动将这些暂停发送的数据发送给数据接收方。通过数据同步系统客户端的异常状态数据管理可以有效的提高数据同步系统的可靠性和安全性。

三、转发类型管理

在同步系统服务器端发布以后将会有多个业务系统调用同步系统的服务器端接口,随着业务的发展可能会改变原先制定的数据同步对象,如原来A系统的数据需要同步给B系统,而现在则需要同时同步给C系统或者将B系统换成D系统。如果每次改变业务需求时都需要修改同步系统的代码并重新分布的话将会对其余的业务也产生影响,这应该是尽量避免的。

在同步系统服务器端接收源系统发送的数据时会根据传入的转发类型参数字段查找数据同步系统数据库转发类型表中相同转发类型的所有数据记录,然后根据每条记录中的目标系统字段生成相应的数据插入待发送数据表,例:在转发类型表中存在两条数据A和B,数据A的转发类型字段、目标系统字段、目标系统接口字段和是否可用字段分别为ES_CS_001,CA,GetDataFromA和True,数据B的转发类型字段、目标系统字段、目标系统接口字段和是否可用字段分别为ES_CS_001,CB,GetDataFromB和True,若源数据发送方传入的转发类型参数字段的值为ES_CS_001,则数据同步系统服务器端将根据A和B的值向待发送表中插入两条待发送数据,数据同步系统转发器在进行数据转发时将分别取出这两条记录并分别调用CA系统的GetDataFromA方法和CB系统的GetDataFromB方法发送数据。可以通过数据同步系统客户端将数据B记录的是否可用字段设置为false,此后在数据同步系统服务器端接收ES_CS_001转发类型的数据时将只会在待发送表中插入一条记录。因此在数据同步业务需求发生改变时只需修改转发类型表中的数据字段内容即可实现相应的数据同步业务功能的增、改而无需修改任何的代码,实现了代码的重用。

四、数据同步系统客户端实现

(一)服务器端初始化。数据同步系统主要为源数据发送系统提供了数据接收的接口,在对源数据发送方进行身份验证后将接收到的数据存储到数据库中等待转发器进行转发。本文首先数据同步的整个过程进行介绍,然后详细描述了数据同步系统客户端从初始化到运行以及接收源数据发送方的数据并存储到数据库的整个过程。在.NET中可以通过二步来实现Remoting服务器端初始化:

第一步:指定通道。在Remoting中通过通道(channel)来实现两个应用程序域之间对象的通信。为了实现跨越应用程序域进行通信,同步系统客户端必须先指定通信的通道。Remoting的通道主要有两种:Tcp类型通道和Http类型通道。在.Net的System.Runtime.Remoting.Channel命名空间里定义了IChannel接口,其中就包括了这两种通道类型。HttpChannel类型存在于命名空间System.Runtime.Remoting.Channel.Http中。通过使用Http协议,使其能在Internet上穿越防火墙传输序列化消息流。TcpChannel类型存在于命名空间System.Runtime.Remoting.Channel.Tcp中。Tcp类型通道使用了基于Socket的传输方式并通过Tcp协议来跨越Remoting边界传输序列化的消息流。TcpChannel类型默认使用二进制格式序列化消息对象,因此它具有更高的传输性能。指定通道代码如下:

public class Server

[STAThread]

static void Mai。(stringy[]args)

{

try{

//设置端口

IDictionary htPort=new Hashtable();

htPort[""port""]=9996;

//设置名称

htPort[""name""]=""channel";

//指定通道类型

BinaryServerFormatterSinkProvider serverProv=new

BinaryServerFormatterSinkProvider();

serverProv.TypeFilterLevel=

System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

BinaryClientFormatterSinkProvider clientProv=new

BinaryClientFormatterSinkProvider();

TcpChannel channel=new TcpChannel(htPort,clientProv,serverProv);

//注册通道

ChannelServices.RegisterChannel(channel);

}

第二步:设置远程对象的激活方式。在访问远程的一个对象实例时,必须在服务器端创建通道并对该对象进行初始化。这种客户端通过通道来创建远程对象的方式,称为对象的激活。在Remoting中,远程对象的激活分为两种:服务器端激活和客户端激活。服务器端激活,即WellKnow方式激活:在激活对象实例之前会在一个URI上来发布这个类型,并为此类型配置一个WellKnown对象,然后根据指定的地址或端口来发布对象.Net Remoting把服务器端激活又分为两种模式:SingleTon和SingleCall模式。SingleCall模式是一种无状态模式,客户端调用远程对象方法时,会为每一个客户端建立一个远程对象实例,而远程对象实例的销毁和资源回收则由.NET提供的垃圾回收机制自动管理。考虑到会有多个业务系统调用数据同步系统服务器端,需要为每个访问同步系统服务器端的对象建立一个远程对象实例,所以本系统采用了WellKnown模式中的SingleCall模式。

(二)接口實现。数据同步系统必须提供数据接收接口用于获得源数据发送方的数据,数据同步系统服务器端将接口函数封装在可串行化的类中并生成.dll文件然后发给源数据发送方,源数据发送方引用该dll文件并通过设置远程对象的工P地址、端口和激活方式来获取远程对象。远程处理框架需要提供必要的基础结构,以便隐藏远程对象调用方法和返回结果的复杂性。所有需要跨越应用程序域的本地对象都必须按数值来传递并且用Serializable属性标记,否则需要继承并实现ISerializable接口。在应用程序域内部,数据类型按数值传递,而所有的对象按引用传递。MarshalByRefObject是通过使用代理进行消息通讯从而跨越应用程序域边界的对象的基类。没有从MarshalByRefObject继承的对象会以隐式方式按值封送。在Remoting中能够传递的远程对象可以是各种类型,包括复杂的DataSet对象。通过继承MarshalByRefObject可以使任意对象变为远程对象。当客户端激活远程对象时,将接收到该远程对象的代理。对该代理的所有操作都将重新定向,使远程处理基础结构能够正确截取和转发调用。远程对象定义如下:

//允许运行库串行化一个对象

[Serializable]

//远程对象必须继承MarshalByRefObject

public class Message:MarshalByRefObject

{//为源系统提供的接口

public bool GetMsgFromOrigin(byte[]identify,string oriSystem,string operatorName,string transType,string xmlStr)

{

//实例化业务逻辑层对象

MSDS.BizFacade.Message message=new MSDS.BizFacade.Message();

//调用业务逻辑层函数

return message.GetMsgFromOrigin(identify,oriSystem,operatorName,transType,xmlStr);

catch(Exception ex)

//向接口调用方抛出异常信息

throw new Except.ion(ex.Message);

finally

//释放资源

ServicedComponent.Dispose0bject (message);}}

五、结论

在企业信息化发展过程中,建立了大量的信息管理系统,这些系统之间存在一定的关联关系,部分数据在多个系统内都需要被使用。但由于缺乏有关企业信息管理模型方面的标准和规范,造成这些信息系统之间存在兼容性差、数据信息资源难以交流共享等问题,当一个业务系统对其数据库中的某些信息进行更新时,将导致该系统与其它多个系统内数据的不一致性,从而对公司业务的正常运作造成了阻碍。通过对本人所在企业的需求调研,本文设计并实现了用于解决企业数据同步问题的数据同步系统。系统采用Visual Studio 2003的开发环境,使用C语言实现系统开发。实现了在企业范围内多个业务数据库之间的数据交换与同步。系统投入正式运行,并取得了较好的应用效果。

参考文献:

[1]杨柳,蔡英蔚.基于XML格式异构数据同步模型的研究[J].中国电力教育,2008,22

[2]沈敏,许华虎.基于XML的分布式异构数据库数据同步系统的研究[J].计算机工程与应用,2005,41,5:184-186

[3]梁利妓,吴国平.一种基于XML的异构数据源集成方案[J].现代计算机,2004,3:27-29

嵌入式系统C语言 篇4

结构化查询语言 (Structured Query Language, SQL) 是最普遍使用的关系数据库语言, 它具有表达能力强, 功能丰富, 语言简洁, 使用灵活等特点, 在许多数据库系统环境中, 它作为独立语言由用户在交互环境下使用。

由于SQL语言是一种面向集合运算的描述性语言, 本身不具有过程性结构, 而许多实际事物处理应用都是过程性的, 需要根据不同的条件来执行不同的任务, 因此单纯用SQL语言在交互式环境中执行很难满足应用的需求。为了解决这一问题, 将SQL语言嵌入到某种高级语言中使用, 利用高级语言的过程性结构来弥补SQL语言实现复杂应用方面的不足, 相辅相成, 发挥各自优势。这种方式下使用的SQL语言称为嵌入式SQL, 而嵌入SQL的高级语言称为主语言或宿主语言。

(二) 基于C语言和SQL Server2000的嵌入式SQL的形式

对于嵌入式SQL语句, 数据库管理系统可采用两种方法处理:一种是预编译方法;另一种是修改和扩充主语言使其能识别处理SQL语句。本文采用的是SQL Server2000预编译方法, 由DBMS的预编译器 (NSQLPREP文件) 扫描识别处理源程序中的SQL语句, 把SQL语句转换成主语言 (C语言) 调用语句, 以使主语言编译程序 (这里采用VC++编译程序) 能识别它并将整个源程序编译成目标代码, 连接后形成可执行文件。

为了在嵌入式SQL中区别SQL语句与主语言语句, 须在所有的SQL语句前加前缀EXEC SQL, 而SQL语句的结束标志随宿主语言的不同而不同, C语言中以分号结束, 一般形式为“EXEC SQL;”。例如一条交互形式的SQL语句“SELECT sno, cno, grade FROM course;”, 嵌入到C程序中, 应写作“EXEC SQL SELECT sno, cno, grade FROM course;”

嵌入式SQL语句分为可执行语句和说明性语句, 可执行语句可出现在主语言中任何允许高级语言的执行语句出现的地方, 它完成在交互式环境下的SQL语句能完成的任务, 包括数据定义、数据控制和数据操纵三种语句。说明性语句用于声明通信区和SQL变量等。位于主语言中任何允许出现说明性的语句的地方。

(三) 嵌入式SQL语句与C宿主语言之间的通信

C语言是一种过程性的、与运行环境有关的语言, SQL语言是面向集合的描述性、非过程性语言, 将两者混合编程, 目的在于发挥各自的优势, SQL语句负责操纵SQL Server2000数据库, C语言负责控制程序流程。程序执行过程中, 两者之间需要进行通信, 过程如下:SQL语句将执行状态信息传给C语言;C语言给SQL语句提供一些变量参数;将SQL语句查询结果返回给C语言做进一步处理。

1. SQL通信区

SQL Server数据库管理系统提供了一个通信区SQLCA, 作为SQL Server2000和应用程序的一个接口, 该结构变量是为诊断错误和事件处理而设置的。SQL语句执行后, 系统将当前工作状态和运行环境的各种参数送到通信区SQLCA中, 主语言的应用程序从SQLCA中取出这些状态信息以决定其语句的执行。在C语言中定义SQL通信区的语句为:

EXEC SQL INCLUDE SQLCA;

2. 变量的说明与引用

嵌入式SQL中有两种变量:主变量和指示变量。SQL语句中使用的主语言程序定义的变量称为主变量, 主要完成嵌入式SQL语句的数据输入与输出。指示变量是与主语言相关联的一类SQL变量, 被用于监督和管理与其相关联的主变量。每个主变量都可以定义一个指示器变量。指示其变量的具体作用是:向数据库表列输入NULL值, 检查从数据库表列中选取的数据是否是NULL值或者是否发生截断问题。

SQL变量在引用之前要先说明, 在说明段内使用C语言的类型说明语句为每个SQL变量指定一个SQL Server能支持的C数据类型。如:

在SQL语句中使用SQL变量时, 必须在其之前加一个冒号以与字段名相区别, 但是在C语句中引用时, 不需加冒号。指示器变量引用时必须附在其相关联的主变量之后。例如:

3. 连接SQL Server数据库

C程序的主函数中应包含一条登录语句, 向预编译程序提供用户名和口令, 以与SQL Server数据库管理系统建立连接, 其命令语法为:

EXEC SQL CONNECT TO服务器名.数据库名AS连接名USER用户名.口令

(四) 程序结构

嵌入式SQL语句在C语言中的编程结构一般分为以下四步:

1. 定义通信区域。

2. 定义主变量。

3. 连接所要访问的数据库。

4. 访问数据库。

(五) 实例说明

1. 软件安装及环境设置

安装SQL Server2000时, 使用客户自定义模式, 选中“头文件和库文件、MAC、SDK、备份/还原API和调试程序界面”进行安装。

在VC++6.0中新建名为STU的WIN32 Console Application工程文件。在“工具”菜单项下选择“选择”, 再选择“目录”以设置工作区的的运行环境。

(1) 在“S显示目录为”下拉框中选择“Include files”, 在路径编辑框中输入SQL Server开发工具的头文件路径“C:PROGRAM FILESMICROSOFT SQL SERVER80TOOLSDEVTOOLSINCLUDE”;同理, 新增“Library files”的路径“C:PROGRAM FILESMICROSOFT SQL SERVER80TOOLSDEVTOOLSLIB”和“Executable files”的路径“C:PROGRAMFILESMICROSOFT SQL SERVERMSSQLBINN”。

(2) 在STU工程的源文件目录下创建并添加文件student.sqc, 编写嵌入式SQL的C源程序, 程序部分代码见 (5) 。

(3) 在student.sqc文件上单击右键, 选择settings, 在命令编辑框中输入“NSQLPREP student.sqc”, 在输出编辑框中输入“student.c”。编译student.sqc, 将其预编译成student.c。再将student.c加到源文件目录下, 将其编译成目标文件。

(4) 单击“工程”菜单项下的“设置”命令, 在link页下的object/library modules中加入“caw32.lib和sqlakw32.lib”两个库, 并将“MICROSOFT SQL SERVERMSSQLBINN”下的sqlakw.32.dll复制到当前目录或工程目录中, 并保证windows的system目录下有Ntwdblib.dll和Dbnmpntw.dll, 则可连接成功。

2. 数据库表结构

本文设计了一个包含数据插入、删除、更新和查询的例子。在SQL Server2000 DBMS中设计了一个学生信息数据库student, 用户名和密码均为“ww”, 其中的学生基本信息表S的结构如图1所示。

3. 程序模块结构

该C程序主要由一个MAIN函数及四个子函数构成, 通过对四个子函数的调用来完成对学生基本信息表的操作, 其模块结构如图2所示。

4. 部分程序清单

(1) 主程序模块

(2) 插入模块

摘要:文章旨在研究用嵌入式SQL语言开发SQL Server数据库应用的方法。首先介绍了C语言与SQL Server2000的嵌入式SQL的形式, 然后给出嵌入式SQL语句与C宿主语言之间的通信方式及程序结构, 最后给出了代码实例。

关键词:嵌入式SQL,宿主语言,SQL Server2000数据库

参考文献

[1]陶宏才.数据库原理及设计[M].北京:清华大学出版社, 2004, 2.

[2]丁宝康, 董健全.数据库实用教程[M].北京:清华大学出版社, 2001, 9.

嵌入式系统C语言 篇5

摘要:详细介绍使用VisualDSP开发工具进行ADSP21XX的C语言编程的方法;分析其C语言运行库的结构,并且结合实例介绍C语言工具的使用方法,包括C语言与汇编语言混合编程的方法,从C运行库提取代码用于自己的汇编语言程序的方法、修改运行库的源代码以适应自己开发需要的方法等。

关键词:DSPVisualDSP嵌入式C语言汇编语言

引言

长期以来,在DSP系统开发中,一直把汇编语言作为主要的开发工具;但汇编语言与自然语言差距很大,不易常,而且汇编语言是依赖于处理器的,不利于软件的可重复利用和系统的稳定性,程序不易移植,给开发工作带来了很大的困难。随着嵌入式系统复杂程度的不断提高,用汇编语言编写一个巨大的程度将是困难,甚至是不可能的。为此,AD公司推出了针对ADSP21XX系列DSP的嵌入式C和C++语言集成开发工具,分别是VisualDSP和VisualDSP++系列,这些开发工具提供了C语言和C++语音的开发功能。以下就以笔者在实际开发中的一些经验,结合VisualDSP6.1版本,介绍用C语言开发VisualDSP6.1版本,介绍用C语言开发ADSP21XX的方法。VisualDSP提供了一个开放源码软件组织GNU的C编译器,和一套成熟稳定的C运行时间库(CRuntimeLibrary)等。GNU的编译器一向以编译效率高著称,在编译后的代码长度和运行速度方面非常优秀;C运行时间库则把很多重复性的工作,如浮点运行、三角函数、FFT等作为C语言的库函数,提供给用户,大大提高了用户的开发效率和程序的稳定性,降低了开发难度,另外,由于把这些库函数的源代码提供给了用户,还提高了C语言与汇编语言之间的透明性,使用户开发的程序兼具两者的优点。

1VisualDSP简介

VisualDSP是AD公司的DSP开发工具,主要由可执行文件、库文件和各种帮助文档组成。6.1版本还带有一个基于图形界面,针对21XX系列DSP的软件仿真和调试工具。

VisualDSP的可执行文件包括汇编、编译、链接工具以及可执行文件重新格式化工具等,见表1。

表1VisualDSP的可执行文件及用途

可执行文件名

用途

Asmpp.exe*汇编预处理程序Asm2.exe*21XX系列汇编程序的汇编程序Asm21.exe21XX系列命令行汇编程序Ld21.exe21XX系列链接工具G21.exe基于GNU的21XX系列C编译器Bld21.exe系统编译工具,产生相应于不同硬件体系的.ACH文件Lib21.exe21XX系列的库管理工具Hspl21.exe把21XX系列可执行文件变成HIP口可加载的格式Spl21.exe把21XX系列可执行文件变成PROM可烧写的格式

注:“*”代表该程序一般不单独使用,而昌由G21.exe或Asm21.exe调用。

VisualDSP套件中的软件仿真调试工具DEBUGAPP,采用Windows图形界面,使用方便。它的主要特点是:可以仿真调试从ADSP2101~2189全系列的DSP;支持断点、单步、全速运行等各种常见调试方法;可以随时查询和修改DSP的程序RAM(PM)、数据RAM(DM)和各寄存器的内容;可以仿真中断,进行可执行程序性能评估(Profile),因此可以进行时序仿真。DEBUGAPP是调试程序和验证复杂算法的极好工具。

VisualDSP6.1还提供了丰富的帮助文档,包括21XX系列的用户手册、汇编和C语言工具以及仿真调试程序的使用手册;还有C运行库的参考手册,列出了所有可用的C库函数。用C语言开发DSP的典型流程如图1所示。

2C语言运行库结构

C语言运行时间库是位于LIB目录下的*.a文件,是整个C开发工具的核心之一,提供了大量的可以直接调用的库函数。这些库函数的函数原型包含在INCLUDE目录下的头文件中。这些头文件有的还包含一些宏定义。另外,VisualDSP还把这些库函数的汇编语言源代码提供给出了用户,方便了用户从中提取有用的代码,甚至修改源代码,生成新的库,来适应自己的要求。利用LIB21程序,还可以把自己的常用汇编子程序做成库,或是将实时性要求较高的代码用汇编语言来写,做成库,供C语言程序调用。

VisualDSP的C语言运行库由两部分组成:应用程序框架和预定义的各种库函数。

不同的DSP型号有不同的硬件结构、中断向量表,所以对应的应用程序框架库也不同,相应的文件是21*_HDR.DSP.其中*代表不同的DSP型号。应用程序框架的主体是中断向量处理部分,把中断向量引到合适的地址。其中最重要的.是对系统复位(RESET_VECTOR)的中断向量的处理:

_Reset_vector:CALL_lib_setup_everything;

CALLmain_;

JUMP_lib_prog_term;

NOP;

第一条指令是调用C库函数中的__lib_setup_everything函数作程序启动时的初始化工作。接下来,调用C语言程序中的main_函数,进入C程序的主体,也就是进入用户自己程序,开始正常工作。主程序结束后,再调用_lib_prog_term函数,作程序退出时的结尾工作。由于嵌入式系统的特性,系统绝大多数都在主程序运行时被继电了,所以_lib_prog_term得到执行的机会很小。

其它的中断向量由C运行库来管理,汇编指令如下:

_Interrupt2:JUMP_lib_int2_ctrl;NOP;NOP;NOP;

其中的_lib_int2_crtl就是C语言库中控制INT2的函数。如果用户要使用该中断,应先把中断服务程序用一个C库函数Interrupt把服务函数指针设定好,并打开相应的中断允许位,当该中断发生时,_lib_int2_ctr1函数就会控制DSP跳转到相应的指针位置。

VisualDSP预定义的C语言库函数包括数学函数、FFT函数、ANSI标准内存管理和字符串管理函数的一个子集。所有的函数列表可参考VisualDSP的联机文档。这些库函数以二进制代码的形式,打包集合在lib*.a文件中,用户的C语言程序可以像使用自己的子程序一样方便地调用这些库函数。下面是调用库函数的一个例子。

#include//包含所需的头文件

……

floata,b,c;//定义所需的变量

……

c=a*sin(b);//数学运算

编译后产生的汇编源代码中有callsin_指令,就是调用sin库函数的汇编语言指令语句。

从嵌入式开发的角度讲,VisualDSP的C语言工具已经提供了一个操作系统雏形的功能。在AD公司的ADMC系列DSP中,已经把这些库函数和一些电机控制专用的函数,以及程序加载功能,集成在了DSP的片内ROM中。

3C语言与汇编语言混合编程方法

用C语言开发的缺点是不能精确控制程序运行的时间,对于实时性要求较高的应用,必须用汇编语言。VisualDSP为用户提供了两种与汇编语言的接口方法:用ASM方法,直接嵌入汇编语言语句;用汇编语言编写子程序,供C语言程序调用。为了支持C语言与汇编程序程序的接口,VisualDSP预定义了诸如FUNCTION_ENTRY、EXIT、SAVE_REG、RESTORE_REG等13个宏。限于篇幅,不详细介绍其功能。使用这些宏以前,要包含asm_sprt.h头文件。

3.1使用ASM()嵌入行的方法

使用这一方法时,一定要注意各寄存器和堆栈当前的状态,以免破坏程序运行的环境,产生错误的结果。VisualDSP保留了一些内部寄存器供用户的汇编代码使用。用户可以自由地修改其内容,而不会对程序造成破坏。这些寄存器包括AR、AF、AY1、M5、11、16、MF、MR0等18个。如果不够用,可以用系统定义的宏save_reg和restore_reg保护现场,得到另外11个可用寄存器。另外要注意的是,在汇编语言中操作C语言中定义的变量时,要在变量名后加下划线。下面是一个嵌套汇编语言的例子:

intimg228;//定义C语言变量

asm(“ax0=0x5c;”)

asm(“dm(ing228_)=ax0”);//用汇编语言赋值要将Img228变成Img228_

img228=0x5c;//直接用C语言赋值

编译后的汇编语言代码是

ax0=0x5c;

dm(img228_)=ax0

my1=92;

dm(img228_)=my1;

注意前者可能会破坏程序结构,因为它使用了未经保护的寄存器AX0;而由C语言产生的汇编代码,则会自动选择合适的临时寄存器MY1。

3.2使用汇编子程序的方法

使用汇编子程序是C语言程序与汇编语言接口的另一种方法。用户定义的子程序放在单独的汇编文件中,或是做成二进制的库文件,并将子程序的定义用GLOBEL输出,汇编后就可以供C语言程序调用。下面是一个不需要参数的子程序的例子:

.MODULE/RAM_delay_;

.externaldel_cycle;//声明del_cycle是外部变量

.globaldelay;//声明delay为全局函数

delay_:

runction_entry;//子程序开始标志,必须要的

ar=dm(del_cycle_);

cntr=ar;

dod_loopuntilce;

d_loop:nop;

exit;//子程序结束标志,必须要的

.ENDMOD;

如果汇编语言子程序中用到了参数,情况就复杂些。子程序中的入口参数前两个一定要保存在AR、AY1中。如果参数多于两个就要把其余的放在堆栈中。所有子程序的第一个返回值放在AR中。如果返回值不止一个,就要用到变量型参数或者指针来获得取所有的返回值了。下面是一个有5个输入参数、1个返回值的子程序例子。

add5_:

function_entry;

ar=ar+ay1;//前面的两个变量放在AR、AY1中

readsfirst(ay1);//从程序堆栈中读取第三个变量

ar=ar+ay1;

ay1=readsnext;//从程序堆栈中读取第四个变量

ar=ar+ay1;

ay1=readsnext;//从程序堆栈中读取第五个变量

ar=ar+ay1;//返回值放在AR中

exit;

注意其中的readsfirst和readsnext都是汇编语言接口宏。其功能是从堆栈中读取所有的参数。

4C运行库的汇编源代码

如果只用C语言来开发21XX程序,只要有C运行库的二进制版就够了。幸运的是,AD公司把所有C运行库的汇编源代码随VisualDSP提供给了用户,所以对那些用汇编语言开发的工程师来说,这些源代码也提供了很大的帮助。因此这代表很多功能的子程序不需要自己去编码、调试,用到某功能时只要把相应的汇编代码链接进自己的程序就可以。C运行库的源代码是扩展名为DSP的文本文件。基本上一个库函数对应一个文件,文件名就是函数名。比如说sin.dsp是正弦、余弦查找、使用都很方便,但是对于其中的交叉调用要注意。

反过来,用户也可以把自己已经调试、验证过的汇编子程序,做成二进制库文件,供C程序调用,这样可以大大提高软件的可重复利用率。要制作二进制库文件,只要用lib21.exe工具处理就行了。注意,生成的二制库文件的名字必须以.a作为文件扩展名。

笔者在实际的开发中,遇到这样的情况,自制的2181目标板上有一个自己开忍气吞声驻留程序,通过软件模拟的异步串口与PC通信,加载程序。但是这个驻留程序占据了0~0x500的空间,用户开发的程序只能加载到从0x500开始的空间内,而用C语言开发的程序起始地址都是从0开始的。为了解决这个问题,只能自己修改2181_hdr.dsp源文件。首先把第一行的.MODULE/ABS=0改成.MODULE/ABS=0x500,然后汇编成obj文件,代替原来的文件。另外,在自己的程序中定义一个从0开始0x500大小的PM区域,并初始化成0,就可以防止编译器在该区域内分配别的变量或程序代码,这样编译后的可执行文件的0~0x500空间都是0,加载时把它剔除,而其它有用的指令代码都在0x500之后,解决了这一个问题。

5总结

嵌入式系统C语言 篇6

NANDFlash具有存储密度高、成本低等优点,非常适合于数据存储。现在许多需要存储大量数据的系统都使用NAND Flash作为存储介质。在数据量比较大的情况下,使用FAT文件系统进行管理是非常有效的方式,也容易实现与PC通讯中的文件传输。下面以东芝的TC58512FT为例,说明使用SEP4020的系统是如何在NANDFlash中建立FAT文件系统的。

2 TC58512FT的技术原理

TC58512FT[1]是东芝公司出产的64M字节(Byte)NAND Flash芯片。其存储空间分为4个区(Plane)共4096个块(Block),每个块分为32页(Page),每页为528字节,其中16字节是用来形成NAND结构的,实际存储数据使用512字节。擦除至少是对一块操作,读写可以对页进行操作。要对某页进行写操作前,必须先进行擦除操作,而一次除擦的最少空间是一个块,如果该块中其他页已经存在数据,必须先备份起来,然后在擦完该块后,再一起写到指定区域。

3 在SEP4020上实现嵌入式文件系统μC/FS

Micrium公司的μC/FS[2]是高度可移植、可固化的嵌入式FAT文件系统。μC/FS的设备驱动结构非常简单,只需要读写扇区的底层函数。对于未格式化的设备,还需要提供格式化参数。

3.1 格式化文件系统

FAT文件系统[3]由4部分组成,这些基本区域如下顺序排列:保留区(Reserved Region);FAT区(FAT Region);根目录区(Root Directory Region,FAT32无此域);文件和目录数据区(File and Directory Data Region)。

BPB(BIOS Parameter Block)是FAT文件系统的重要数据结构,它位于FAT卷的第一个扇区,同时属于FAT文件系统的保留区,这个扇区也叫启动扇区。在总共512字节的引导记录中,引导程序占了其中的前446个字节(偏移0H~偏移1BDH),随后的64个字节(偏移1BEH~偏移1FDH)为硬盘分区表,最后的两个字节“55 AA”(偏移1FEH~偏移1FFH)是分区有效结束标志。从偏移36开始FAT12/FAT16的内容开始区别于FAT32。BPB的前36字节包含了格式化的重要参数,具体结构如表1所示。

文件系统的数据存储就是根据以上所列参数来查找表1 BPB结构存放数据的位置,因此这些参数的确定非常重要。

3.2 底层设备驱动

设备驱动的就是要实现物理设备的驱动程序挂接到文件系统中,文件系统通过物理设备的驱动程序和底层设备交互数据。按照从上到下的编写模式,首先编写设备驱动所需要的接口函数,然后细化到对具体地址的操作。设备驱动分为flash_drv.c和flash_X_HW.c两个文件,flash_drv.c提供上层的接口和对低层的调用,设备驱动结构体FS__flashdevice_driver在该文件中定义;而flash_X_HW.c提供低层的调用,完成对flash的具体操作。

3.2.1 设备驱动结构

uc/fs以宏定义的形式来管理设备,flash设备的定义如下:

FS_DEVINFO_DEVFLASH就定义了uc/fs操作一个设备所需要的各种信息。"flash"表示设备名称;&FS__fat_functable是一个指向一组函数指针的指针,该组函数指针指向fat的一些操作函数,如fopen,fclose等;&FS__flashdevice_driver指向flash设备的驱动,提供对flash设备的读写,设备状态以及各种IO命令控制函数,这些函数需要自己创建,这也是移植工作的核心内容;FS_CACHEINFO_FLASH_DRIVER 0定义flash读数据缓冲区的信息,由于flash读取速度很快,可以像一般内存一样线性读取,所以没有必要加一个读缓冲区,故将其值设为0。

3.2.2 flash_drv.c的编写

定义FS__flashdevice_driver结构如下:

"Flash device"是设备驱动名称,这个名称在uc/fs内部使用,而上面提到的"flash"可由用户使用;

_FS_Flash_DevStatus:用来表示设备状态是否改变;

_FS_Flash_DevRead::用于从flash设备中读取一个扇区的数据,这里只提供上层的接口,而对底层flash的读取操作采取调用子函数的方式完成;

_FS_Flash_DevWrite:类似于_FS_Flash_DevRead函数,先检查设备是否可用,然后调用写数据子函数,用于写入一个扇区的数据;

_FS_Flash_DevIoCtl:执行uc/fs发出的对设备进行操作的各种命令,uc/fs提供这样一种机制,如果该命令可以被上层函数识别并执行,则由上层函数执行,如果上层函数没有对这个命令的解析,则用按层次调用底层的函数来执行。

3.2.3 flash_X_HW.c的编写

定义了NANDFlash的读写、擦除、其他控制命令等操作,详见[4]。

4 结论

系统已经实现并通过调试,经过实验证明,能够实现与文件系统实现良好兼容,其功能函数对存储设备能够进行有效管理,经过测试运行可靠稳定,对潜在的存储空间拓展提供了良好的软件架构。

参考文献

[1]TOSHIBA Corporation.TC58512FT datasheet[S].TOSHIBA Corporation,2001.

[2]Micrium Technologies Corporation.μC/FS File System User&Reference manual[S].Micrium Technologies Corporation,2002.

[3]Microsoft Corporation.Microsoft extensible firmware initiative FAT32File system specification[M].Microsoft Corporation,2000.

[4]SEP4020嵌入式微处理器用户手册[S].南京:东南大学国家专用集成电路系统工程技术研究中心,2007.

嵌入式系统C语言 篇7

嵌入式系统具有很高的先进性, 它综合了多种高新技术, 包括计算机技术和电子技术以及半导体技术等, 是多种技术结合的产物。日常生活的点滴都渗透了嵌入式系统, 大大方便了人们的生活、丰富了人们的精神世界。它的应用领域非常广阔, 大到工业、服务业, 小到人们的日常娱乐活动, 并且随着经济的发展, 嵌入式系统的应用范围更加扩大。从专业的角度我们定义嵌入式系统为把计算机作为基础技术, 将应用作为中心, 可裁减软硬件的, 具备应用系统要求的功能、功耗、成本等要求的专用计算机系统。嵌入式系统有三个主要的特征, 分别是较强的专用性、精简的系统和具有较小的内核。嵌入式系统对软件的要求很高, 符合要求的软件必须具有很高的高实时性, 另外软件必须具备高质量和可靠性。我们需要专门的工具和环境对嵌入式系统进行开发[1]。

嵌入式μC/OS的体系结构比较简单, 所以大部分使用的是C语言进行编程, 大部分的友好界面的编译器都能够生成编译的目标代码, 友好的编译器有Borland C、Keil等。嵌入式μC/OS的体系的内核可以很小, 小到几十KB的都有, 所以它在移植时支持体系结构多种多样的微处理器。这样留给用户的工作就很少了, 由于源代码是开放的这就方便了学习。μC/OS-II有几大组成部分, 分别是:核心部分 (OSCore.c) , 这是操作系统的处理核心, 它又包括了多个组成部分, 主要有操作系统初始化、中断进出的前导、任务调度等。任务处理部分 (OSTask.c) 的操作是用来完成任务的, 它又包括了建立任务、删除任务、挂起任务、恢复任务等。时钟部分 (OSTime.c) 主要用来完成延时任务等。

嵌入式系统包括两大部分, 分别是硬件部分和软件部分。嵌入式系统的主要特性如下:

1) 其系统采用的是公开的源代码, 这也是它最大的特点, 在这一点上超越了其它的商业实时内核。源代码开放的好处是为在不同硬件平台上移植操作系统提供了很大的便利。

2) 嵌入式系统的可移植性能非常好, μC OS的嵌入式系统源代码大量采用了ANSI C进行编写, 所以具有很强的可移植性, 另外采用汇编语言编写了和微处理硬件有关的部分, 这样的目的是方面了μC/OS的嵌入式系统的移植, 可以适应8、16、32位等。

3) 嵌入式应用和μC/OS的联系十分紧密, 因为后者是适应前者而设计的, 所以可固化。开发者需要拥有一些固化手段, 包括编译、下载等就可以使μC/OS嵌入到产品中。

4) 可以进行裁减, 对于μC/OS的嵌入式系统中不被需要的东西可以进行裁减, 只选取有用的应用程序, 这样一来μC/OS所需的存储空间就会得到释放。

5) μC/OS的嵌入式系统的另一个特色就是占先式和多任务。级最高的任务在μC/OS的嵌入式系统中是被优先运行的, 不过轮转法的任务调度还是不被支持的, 实时内核是完全占先式的[2]。

6) 其它特性, 包括系统服务、稳定性、可确定性等都是μC/OS的嵌入式系统具有很大吸引力的原因, 对于安全要求很高的系统来说μC/OS的嵌入式系统是一个不错的选择。另外值得一提的是μC/OS中每个任务有独立的栈, 对于任务的独立栈空间是允许的[3]。

2 基于μC/OS的嵌入式系统的平台构建

在嵌入式系统的开发之前我们需要构建一个平台进行开发, μC/OS系统并不提供开发平台, 它提供的只是调度任务的内核。内核的作用是提供软件系统的基础, 如果想开发一个实用完整的操作系统需要首先进行μC/OS的移植, 将其移植到微处理器上之后扩展操作系统, 然后得到一个符合标准的操作系统之后才能对应用程序进行开发。

2.1 μC/OS的移植

微处理器上移植有μC/OS是内核正常运转的前提, 只有内核正常运行起来才能进一步扩展。μC/OS进行移植的例子不少了, 所以可修改现有的这些移植代码, 这需要结合自己选择的微处理器。微处理器需要满足一定条件才能够进行μC/OS的移植, 例如C编译器可产生重入编码、允许打开和中断C编译器等。

本文中的例子是S a m s u n g公司的ARM7TDMI, 通过它来进行μC/OS的移植, 其中移植主要是对OS-CPU.H.OS、OS-CPU-A.ASM和OS-CPU-C.C这三个文件的数据和参数进行改写, 目的就是进行移植。

2.1.1 对OS-CPU-C.C进行修改

所有和移植有关联的C函数都在OS-CPU-C.C中, 和操作系统相关的6个函数编写语言为C语言。这6个函数分别是5个钩子函数和一个堆栈初始化, 后者是必要的函数, 剩下的5个函数需要声明, 不过任何代码可以省略。

2.1.2 对OS-CPU-A.ASM的修改

OS-CPU-A.ASM中的4个关联处理器的函数由汇编语言编写, 这4个函数是OSStart High Rdy () 、OSCtx Sw () 、OSTick ISR () 、OSInit Ctx Sw () 。这4个函数各有分工, 例如可以运行优先级别的最高级的任务的函数是OSStart High Rdy () ;当前任务TCB的地址可以由LDRr4.addr-OSTCBCur.获得;LDRsp[r5]可以切换到新堆栈。再编写几个相关函数就完成了OS-CPU-A.ASM的移植工作。

2.1.3 修改OS-CPU.H

设置OS-CPU.H代码和ARM具有相关性, 并设置数据类型和编译器保持相关性。

对ARM中的数据类型进行定义:

#defi ne unsigned char BOOLEAN;

#defi ne unsigned char INT8U/*8位无符号整数*

#defi ne signed char INT8S/*8位有符号整数*/

#defi ne unsigned char INT16U/*16位无符号整数*/

#defi ne signed int INT8S/*16位有符号整数*/

#defi ne unsigned long INT32U/*32位无符号整数*/

#defi ne signed long INT32S/*32位有符号整数*/

#defi ne fl oat FP32/*单精度浮点数*/

#defi ne double FP64/*双精度浮点数*/

定义16位的ARM的数据类型为typed unsigned int OS-STK。

μC/OS只有完成了以上三个方面的移植才能够在ARM的微处理器上运行正常。完成移植工作后需要划分系统任务、配置存储的空间和实现任务的调度[4]。

2.2 扩展μC/OS

μC/OS是一个内核, 它可以执行实时多任务, 但是仅仅有μC/OS还是不够的, 不能实现完整的嵌入式系统, 如果想拥有完整实用的操作系统还需要进行除了移植以外的扩展工作。扩展指的是文件系统的建立和建立外部设备驱动、对有关的API函数进行规范化、GUI函数的创建等等。

μC/OS系统是没有文件系统的, 而嵌入式系统是需要使用文件系统的, 这就意味着我们要建立一个文件系统。文件系统的建立过程是首先对文件系统进行初始化, 接下来打开一个系统的指定文件, 然后对文件进行读取和写入, 最后关闭文件, 将缓冲释放, 这就是实现文件系统的过程。实现文件系统的过程中必须要首先用int OSFile () 函数来对系统文件进行初始化, 这样做的目的是分配合理的文件结构空间。系统的文件打开采用Open OSFile () 来打开, 对打开模式进行指定然后进行FILE结构的创建, 分配文件读取的缓冲区。文件的缓冲区数据由Read OSFile () 来直接进行读取, 如果数据为空那么就对FAT进行访问, 在文件缓冲区进行下一个簇的读取。Write OSFile () 负责在指定的文件中写入缓冲区[5]。

3 结束语

μC/OS是目前流行的、十分优秀的嵌入式操作系统, 它有众多的优点, 比如实时性好并且内存的需求很小、具有较好的移植性等。这些优点都能够使开发的周期减少, 对于开发嵌入式系统的应用程序是十分有利的。在新世纪嵌入式系统的发展尤为迅速, 随着嵌入式系统的快速发展μC/OS的应用前景也会越来越广阔[6]。

参考文献

[1]陈渝, 李明, 杨晔.源码开放的嵌入式系统软件分析与实践—基于SkyEye和ARM开发平台[M].中国电力出版社.2004.

[2]Bruce Powel Douglass, 柳翔.嵌入式与实时系统开发[M].中国电力出版社.2005.

[3]毛德操, 胡希明.嵌入式系统—采用公开源代码和StrongARM/Xscale处理器[M].清华大学出版社, 2003.

[4]王田苗.嵌入式系统设计与实例开发[M].清华大学出版社, 2002.

[5]杨柳, 卢清萍.嵌入式系统与Nios[J].安徽工程科技学院学报 (自然科学版) ;2005, (02) .

嵌入式系统C语言 篇8

1 硬件架构

根据实际使用需要,无线点菜机的硬件系统由FLASH、SDRAM、NAND-FLASH,数字键盘,通信模块和液晶屏六大模块组成,其硬件组成框图如图1所示。

FLASH用来存放操作系统和在系统掉电后需要保存的用户数据,如Bootloader启动代码。SDRAM由于执行速度比较快,通常作为系统运行的主要区域,但是由于SDRAM不支持掉电后的数据保护,一旦系统断电,存储在里面的数据就会丢失,所以每当系统启动时,就必须把FLASH中的内容重新调入到SDRAM中,这个工作就是由引导程序BootLoader来完成。顾客通过LCD液晶屏和数字小键盘来控制点餐过程。

2 软件系统

2.1 μC/OS-II嵌入式操作系统以及μC/GUI图形用户界面系统

μC/OS-II是源码公开的实时内核,结构小巧,具有可剥夺实时性。其内核提供任务的调度与管理,时间管理,任务间同步与通信,内存管理和中断服务等功能。基于μC/OS-II平台的GUI中用的最多的是μC/GUI,μC/GUI是一种基于嵌入式系统的图形界面支持系统,可以用于任何使用LCD图形显示的应用,提供高效的独立于处理器及LCD控制器的图形用户接口,可以在单任务或是多任务系统上运行,并适用于任意LCD控制器和CPU下任何尺寸的真实显示或虚拟显示。

2.2 μC/OS-II和μC/GUI的移植

μC/OS-II的移植条件:

1)处理器的C编译器能产生可重入代码;

2)用C语言就可以开/关中断;

3)处理器支持中断,且能产生定时中断(通常为10-100 Hz);

4)处理器支持能够容纳一定量的数据(可能是几千字节)的硬件堆栈;

5)处理器有将寄存器的内容和堆栈指针读出,并存储到堆栈或内存中去的指令。

μC/OS-II在S3C2410上的移植主要包括两个部分的代码配置或者编写。第一部分与应用相关的配置,体现在对OS_CFG.H和INCLUDES.H配置上;第二部分与特定处理器(S3C2410)相关的代码编写,体现在OS_CPU.H,OSCUP_A.ASM,OS_CPU_C.C编写上。还要编写目标板初始化引导程序,初始化引导程序主要实现硬件初始化,内存映射,中断向量初始化,系统堆栈空间的分配等功能,从而引导μC/OS-II的正确运行。移植μC/GUI的时候,首先实现液晶屏控制器初始化,然后在ADS1.2开发环境下,添加μC/GUI的源代码,修改其源代码中的几个文件,即LCDConfig.h,GUIConfig.h和LCD-Driver.c。

2.3 系统的总体设计方案

系统的层次图如图2所示。

本设计将点菜系统分为3个任务,每个任务完成一个界面,首先建立一个按键邮箱用来发送按键中断时对系统的控制,又建了三个任务邮箱实现3个任务间的协调,其中在任务2中实现选菜,合计和删菜的功能,并有一个发送按钮将所选择的菜发送出去。

主函数实现的任务是初始化键盘端口,初始化时钟频率,由Key_Port_Init()函数完成,通过调用Lcd_Tft_240X320_Init()来实现对液晶屏的初始化,再调用InitTimers()初始化系统时钟,最后初始化μC/GUI,并创建任务和邮箱(用来实现任务间的通讯)启动操作开始任务调度。

3 结束语

μC/OS-II操作系统使点餐系统具有很好的实时性,嵌入式图形用户界面软件μC/GUI使点餐的界面更加丰富美观,整个系统稳定可靠并且直观,顾客容易上手操作。因此本系统实用性很强,也符合餐饮业逐渐走向信息化的趋势。

摘要:该文介绍了一个面向顾客的电子点餐系统,提出了以ARM9为硬件平台,使用μC/OS-Ⅱ嵌入式操作系统以及μC/GUI图形用户界面系统来开发电子点餐系统的设计方法,外围硬件LCD用于给顾客显示各个界面图像。该系统稳定可靠,有很强的实用性。

关键词:μC/OS-Ⅱ,μC/GUI,嵌入式

参考文献

[1]周立功.ARM嵌入式MiniGUI初步与应用开发范例[M].北京:北京航空航天大学出版社,2006:6-8.

[2]魏春杰.嵌入式实时操作系统UCOS-Ⅱ应用技术研究[J].国外电子元器件,2005(5).

[3]田泽.嵌入式系统开发与应用实现教程[M].北京:北京航空航天大学出版社,2005:46-50.

[4]JEAN J L.μC/OS-II源码公开的实时嵌入式操作系统[M].邵贝贝,译.北京:中国电力出版社,2001.

[5]魏忠.嵌入式开发详解[M].北京:电子工业出版社,2003:56-60.

[6]王涛,刘建辉.基于ARM微处理器的μC/OS-II的移植研究[J].微计算机信息,2005(7).

嵌入式系统C语言 篇9

关键词:车载免提,蓝牙,μC/OS-Ⅱ,ARM

引言

随着汽车技术的发展, 汽车的安全性和便捷性越来越受到关注, 而蓝牙技术的不断进步使这两方面得以实现, 从而使蓝牙免提系统在汽车领域得到了广泛的应用。目前车载蓝牙免提系统已经成为安全驾驶的重要部分, 传统的车载免提是跟用户的手机配套的, 即一款手机对应一款车载免提, 如果换手机就需重新安装车载免提系统, 蓝牙技术成功的解决了这一问题, 蓝牙的初衷在于电缆的替代, 它可以使不同接口通过统一的无线连接方式方便的通信。只要汽车制造商留出统一的接口, 就可以直接安装蓝牙免提, 并且使用蓝牙技术, 手机和免提可以同时工作。

基于蓝牙免提系统的高稳定性和实时性的要求, 基于NXP公司的ARM7[1]系列芯片, 设计了嵌入式车载蓝牙免提系统, 着重介绍系统在嵌入μC/OS-II[2]实时操作系统下的软件设计, 该设计方案对嵌入式蓝牙系统的设计具有借鉴意义。

1 系统实现的功能介绍

该嵌入式车载蓝牙免提系统作为一个终端设备, 具有完备的功能。系统的主要功能是:自动辨识移动电话, 不需要电缆或电话托架便可与手机联机;使用者不需要触碰手机, 直接通过蓝牙免提系统上的按键便可控制手机, 从而实现接听或拨打电话等系统的功能;使用者可以通过车上的音响进行通话, 当有来电或拨打电话时, 车上音响会自动静音, 通过音响的扬声器和免提系统上的麦克来进行话音的传输;该系统还可以实时的播报来电人的姓名和手机接收到的短消息的内容, 从而实现了车载蓝牙免提系统的自然、安全和便捷的人机交互。

2 系统总体硬件设计

这里所介绍的基于语音合成技术和蓝牙技术的车载免提系统是以微处理器LPC2138为核心, 采用闻强GOC-MD-102[3]蓝牙模块作为通信模块, 采用XF-S3011芯片作为语音合成单元, 采用专用的语音处理芯片ATH3101作为免提语音处理单元, 使用XC6209E系列电源芯片构成高效稳定的电源系统, 其总体系统框图如图1所示:

该系统的蓝牙模块负责与音频网关 (蓝牙手机) 之间进行无线通信, 并将语音信号传入免提语音单元进行降噪、消除回音、消除侧音处理, TTS语音合成单元负责文本到语音数据的转换, 由基于ARM7内核的主控MCU芯片LPC2138来协调整个系统各部分之间的运转情况:与蓝牙模块和TTS语音合成单元进行串口通信, 与蓝牙免提语音单元进行IIC通信, 最后通过按键来响应执行各个功能。

3 系统总体软件设计和任务规划

该系统采用的微处理器为LPC2138芯片, 通过嵌入μC/OS-II操作系统来把程序分成多个任务, 根据不同的优先级来对各个任务进行调度, 使得高优先级的任务得以运行, 从而提高了系统的实时性。μC/OS-II具有免费、公开源代码、使用简单、可靠性高、实时性好、可移植性强等优点。

该系统将程序分成七个任务, 分别是初始化任务、按键扫描任务、按键处理任务、蓝牙发送任务、蓝牙接收任务、语音发送任务和语音接收任务。系统的任务接口框图如图2所示。

结束语

该系统针对目前车载蓝牙免提系统的稳定性和实时性, 提出了嵌入式车载蓝牙免提系统的软件设计方案, 在主控芯片LPC2138上嵌入μC/OS-II操作系统, 把程序分成多个任务, 根据不同的优先级来对各个任务进行调度, 使得高优先级的任务得以运行, 从而提高了系统的实时性。实践证明, 系统不仅功耗小、成本低、操作方便, 而且稳定可靠, 实时性强。

基于μC/OS-II的嵌入式车载蓝牙免提系统还可广泛应用于导航系统、车载调度和车载监控等应用领域。

参考文献

[1]David Sea1.ARM Architecture Reference Manua1.EditionPears0n Education Limited (Ad-dison-Wesley) , 2006.

[2]Jean J.Labrosse.μC/OS-II The Real-Time Kernel Second Edition.CMP Books, USA, 2003.

嵌入式系统C语言 篇10

嵌入式系统是在原来简单的单片机系统上发展起来的, 以应用为中心, 软、硬件可剪裁的专用计算机系统, 适用于对功能、可靠性、成本、体积、功耗要求严格的场合。嵌入式系统具有系统精简、实时性强、专用性强等特点, 特别适合具有实时性能要求的机电控制系统。

传统的基于单片机的简易机械润滑控制系统, 虽然造价低, 但功能不足, 而基于专用控制系统机械润滑控制系统等性能较好, 但造价太高。因此采用高性能嵌入式微处理器和实时操作系统的嵌入式系统设计, 将克服以上不足, 具有很高的性价比, 是未来机械润滑控制系统的发展方向。

2 系统硬件设计

2.1 微处理器及其硬件资源分配

本设计采用三星公司S3C44B0X, 是一款专为手持设备和一般应用提供的高性价比、高性能的16/32位RISC型嵌入式微处理器。集成了ARM7TDMI核, 并在ARM7TDMI核基本功能的基础上集成了8KB Cache (数据或指令) 、内部SRAM、外部存储器控制器、LCD控制器、4个DMA通道、带自动握手的2通道UART、1个多主I2C总线控制器、1个I2S总线控制器、5通道PWM定时器、1个看门狗定时器、71个通用I/O口、8个外部中断源、具有日历功能的实时RTC、8通道10位A/D转换器、1个SIO接口以及PLL (锁相环) 时钟发生器等丰富的外围功能模块。

机械润滑控制系统输入输出及其分配见表1:

2.2 存储器的扩展

根据系统需要, 必须扩展程序存储器和S D R A M数据存储器。

程序存储器采用一片SST39VF160, 其存储容量为2MB, 并将其配置为存储器的Bank0, 其地址范围是0x00000000~0x001FFFFF。

SDRAM数据存储器使用HY57V651620B构建16位SDRAM存储器系统, 配置为存储器的B A N K 6, 其存储容量为4组×1 6 M位 (8MB) , 其地址范围是0x0C000000~0x0C7FFFFF。

2.3 键盘与显示电路

系统用于参数设置和控制的键盘采用矩阵式键盘, 并选用中断扫描工作方式。

系统需要显示的基本信息包括加油速度、加油量、润滑油温及其他参数、工作状态指示 (加润滑油、正常润滑、润滑故障灯) 和控制方式指示 (自动、半自动、调校) 等, 以及其他为了操作和控制的方便, 显示的其他有关的操作信息和控制界面。本系统选用LCD液晶显示器进行显示。

2.4 电机驱动控制模块电路

润滑控制系统需要执行电机进行润滑驱动, 系统选用交流伺服电机, 润滑油控制采用交流伺服电机的位置控制。系统中采用S3C44B0X所具有的脉冲宽度调制PWM方式的输出进行控制, 可对润滑加载速度和总量进行精确控制。

2.5 通信模块电路

主要是R S-2 3 2 C接口、U S B接口以及J T A G接口。其中R S-223322CC接接口口用用于于直直接接从从PPCC机机接接收收有有关关信信息息数数据据, , UUSSBB接接口用于接收U盘等USB移动设备存储的有关信息数据, JTAG接口则供系统交叉调试使用。需要注意的是S3C44B0X中只集成了JTAG信号, 因此其他接口都需要外部扩展。

2.6 温度检测模块电路

采用简单可靠的PT100传感器来获取温度信息, 将获取的信息放大后传给处理器进行A D处理。

篇幅所限, 完整硬件电路略去。

3 系统软件设计

3.1 μC/OS-Ⅱ操作系统的移植

所谓μC/OS-Ⅱ的移植, 实际上就是对μC/OS-Ⅱ中与处理器有关的代码进行重写或修改。

移植μC/O S-Ⅱ内核主要步骤:

(1) 用#define设置一个常量的值;

(2) 用#define分别声明3个宏和10个与编译器相关的数据类型 (在OS_CPU.H中) ;

(3) 用C语言编写6个与操作系统相关的函数 (在OS_CPU_C.C中) ;

(4) 用汇编语言编写4个与处理器相关的函数 (在O S_C P U_A.ASM中) 。

3.2 硬件驱动层扩展

计算机使用外部硬件, 都必须有驱动程序。μC/OS-Ⅱ系统没有给驱动程序提供统一的标准接口, 在系统中实现硬件管理的程序都称之为驱动程序。底层驱动程序通常采用汇编或C语言编写, 主要实现初始化硬件和释放硬件, 把数据从内核传到硬件和从硬件读取数据, 检测和处理设备出现的错误和故障。同时, 还必须将对某个硬件进行的某项操作的代码封装成函数, 供上层的程序调用。

本系统中, 主要完成通信接口、电机驱动控制、LCD显示等外设驱动函数的编写。限于篇幅, 驱动程序的编写就不详细介绍了。

3.3 应用程序代码的编写

(1) main主函数的编写。多任务的启动是通过在主函数main中调用OSStart () 来实现的。调用OSStart () 后, 从任务就绪表中找到优先级最高的任务控制块, 启动高优先级任务启动函数OSStart High Rdy () 然后再启动多任务内核。编写主程序m a i n () 中需要做的是调用OSInit () 对有关变量初始化, 创建任务, 调用OSStart () 进入实时多任务环境, 同时启动时间节拍定时器, 调度任务就绪表中优先级最高的任务转入运行。

(2) 中断函数的编写。中断函数的编写, 在中断服务程序中, 要在固定的两个位置增加两个函数OSInt Enter () 和OSInt Exit () , 并在系统初始化时挂接在中断向量表中。

(3) 用户任务的编写。基于μC/OS-Ⅱ操作系统内核的应用代码编程, 主要就是对各个任务的编程。本系统中OSTask Create () 创建了10个用户任务:作业控制、U盘读写、键盘输入、代码翻译、插补运算、电机控制、液晶显示、温度检测及报警、电源管理、时钟任务, 同时还包括空闲任务和统计任务等两个系统任务。其中时钟任务优先级最高, 它是一个超级任务, 用来对其他任务进行超时监控, 以避免程序“跑飞”或陷入死循环。优先级最高的是数据采集层, 包括U盘读写、键盘输入等任务, 主要是准确无误地读取信息并传递给数据处理层;

数据处理层是核心层, 包括代码翻译、插补运算等任务, 它根据数据采集层提供的信息, 选择相应的控制策略, 进行有关数据处理, 发出相应的控制指令;控制执行层包括电机控制、液晶显示等任务, 根据数据处理层的期望值作为控制量, 驱动相应的电机, 显示有关信息;辅助管理层包括电源管理、检测报警等任务, 优先级最低, 主要完成一些电源管理和系统诊断等辅助功能。各层内的任务优先级可以根据具体应用进行合理的设定。任务间的通信可以通过邮箱、消息队列等IPC机制来实现。限于篇幅, 下面仅介绍电机控制任务的程序设计。 (见图1)

4 结语

本设计经过实验室模型验证, 效果良好, 系统以S3C44B0X为控制器, 以μC/OS-Ⅱ为操作系统, 具有控制精度高、成本低、体积小、易于扩展和升级等特点, 是传统机械润滑控制系统改造和经济型智能润滑控制系统开发的首选, 具有良好的社会应用价值。

参考文献

[1]张一斌, 余建坤.单片机原理及应用课程设计指导.中南大学出版社, 2009.10.

[2]闫丽娟, 高剑钊, 李西红, 何涛.徐州重型机械有限公司.专利:工程机械集中润滑系统自动控制装置, 公开 (公告) 号:CN200946747, 2007.09.12.

上一篇:电池新材料下一篇:地质人员