松翰C语言编程指导CProgramGuide_第1页
松翰C语言编程指导CProgramGuide_第2页
松翰C语言编程指导CProgramGuide_第3页
松翰C语言编程指导CProgramGuide_第4页
松翰C语言编程指导CProgramGuide_第5页
已阅读5页,还剩52页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、如何用c来完成sn8系列芯片的程序设计松翰易爱华松翰科技(深圳)有限公司sonix technology co.,ltd.内容概览一、c 与 assembly 简述二、sn8 c studio的安装与使用2 sn8 c studio的安装2.2 sn8 c studio 应用实例三、数据类型与运算3.1专有数据类型3.2常量与变量3.3数据的存储类型与存储结构四、程序流程控制4顺序结构4.2分支判断结构4.3循环控制结构五、函数5.1函数的定义5.2函数参数传递与返回值5.3函数参数与全局变量六、结构体、联合在sn8c程序屮的应用6结构体6.2联合七、中断7中断断数的定义7.2屮断过程的分析7

2、.3中断函数的结构八、位操作&1位的定义8.2位的运算8.3位比较在程序流程控制屮的应用九、内嵌汇编9.1如何内嵌汇编9.2内嵌汇编时变量的传递十、程序结构10主函数与了函数10.2构建可复用文件10.3构建具有实用性的程序一、c 与 assembly 简述assembly (汇编)的历史己经有半个多世纪了,从计算机的发明那天开始,汇编就注定要 与其结缘,它作为第-种真正意义上的编程语言,在计算机的发展过程小具有无可替代的地位。汇编具有少机器语言一一对应的高效率,就是由于汇编的高效率,和其紧贴硬件的特性, 使其在半个世纪z后的今天依然是目前开发单片机程序的主流工具z。但是由于编写汇编代

3、 码的工作量和难度都比较高,并且耍求程序员对硬件必须有较深刻的了解,其入门就相对较难。 而汇编的写法各异,不同的程序员编写的代码有着巨大的差异,这就带來了学习的难度,可读 性差也成为了其推广的瓶颈,程序的维护更加艰难。随着程序复杂性的增加,开发团队的形成, 应用而牛的高级语言就逐渐取代了其位置。c就是高级语言中针对硬件操作最优秀的一利,c也是基于汇编的,其和互关系如图所示。 随着人们不断的对c进行改善,使c的效率得到了很大的提升,其编译效率逐渐的逼近汇编。 而c以其模块化的编程模式,简洁的代码,良好的可读性和可维护性,成为了另一种单片机开 发的主流开发工具,相比汇编而言,其具有无可比拟的优异性

4、。图1、c与汇编的关系sn8c是基于标准(2而乂加入sonix sn8系列芯片特征的专用c,它而对的是sonix sn8系列芯片程序开发,它能产生非常简洁的能直接运行于sn8系列芯片的优化代码。具冇 良好的兼容性,易学易用,既方便客八开发,乂继承了原有汇编的卓越性能。在木文当中,我们将结合汇编来讲述c开发的各方面知识,以期通过对比来加深对芯片 的编程应用的了解,同吋,对熟悉c的程序员來说,可以更加深入了解芯片;而对于熟悉汇编 的程序员来说,我们可以从对比中找到从汇编到c的转换方法。二、sn8 c studio的安装与使用sonix sn8系列的芯片是risc内核的高性能芯片。h前,由sonix

5、提供的sn8 assembly 仅有59条指令,是一种高效的汇编语言,有s8asm和m2asm编译器分别支持其1系和2系 芯片。在此:基础上的sn8 c studio整合了汇编和c的编译器,1 1、 sn8 c studio 的安装在得到sn8 c studio的安装包后,按照标准的windows程序安装方法安装就可以将软件 安装到机器上。12、sn8 c studio应用实例、创建一个工作区与vc类似,我们的工程管理模式是以工作区方式來管理,在你准备一个项目的时候, 你首先创建一个属于这个项目的工作区:1、打开ids-文件新建,单击出现如下界面:a 2-1新建对话框2单击workspace图

6、标,进入workspace创建窗口,单击location编辑框后的按钮,选择你 需要的匚作目录,然后输入新建workspace的name,在这里如f:图2-2 新建workspace对话框3、单击0k, ids的界血生成了工作区的工作界面,出现了 workspace窗口和output窗口。同 时,打开目标文件夹,你会发现在你选定的文件夹下面,牛成了一个以workspace name命名 的新文件夹,打开文件夹你可以看到一个新生成的.wsp文件,这就是新生成的workspace的配 置文件:5n8c1ex.wspm/sp爻件$i图2-3新生成的workspace配置文件二、新建一个工程(proj

7、ect)在我们成功创建一个工作区后,你会发现我们的workspace窗口中的projiect数目为0,接 看我们就要依据项目所用的芯片母体來创建一个工程项目了,跟创建workspace相同,打开菜 单中的文件新建,单击出现新建窗口,此时默认为新建projecto在右边的project list窗口 中选择你要使用的芯片母体和要创建的工程类型(一般为普通项冃),此时的h标路径location 中已经显示为你刚才建立的workspace冃录,建议将工程保存在这个口录下,不修改默认路径。 给新建工程取一个有意义的name,在框中输入。这里我们収与workspace相同的名称,新建 一个2700系列芯

8、片的普通项口工程,设迸如f图所示:1、单击文件新建,选择合适的选项:newnewrroject list副workspaces阳厢阳n8阳厢阳阳阳厢阳1t81t8n82700a rroject2600 project2500 project1900 project1800 project1700 project1600 project2700a sreies static library project260025001900180017001600static static static static static staticlibrary library library library

9、library libraryproject proj ect project project project projectokcancel i图 2-4 新建 project2、单击ok。3、新工程选项配置,在确认建立工程后,出现project setting对话框,左边的project列表 中默认选中我们刚刚建立的工程,在这里我们只修改chip和code option项目下的选项,如图 所示:图 2-5 project setting 对话框4、选择正确的芯片:在chip页屮,definition文木框屮显示系统依据你选定的芯片母体系列而确定的需要调用 的芯片定义文件。chip list

10、表列出了当前版木的ids所支持的这一系列的各个芯片,选中其中 你需要使用的芯片母体,selected文本框和description sc本框和应会口动改变。如图:图2-6选择芯片5、设置正确的code option选项和ice mode:ice mode的设置在sn8plxxx芯片中是用丁选择是否是ice仿真模式,在code option 列表中自动显示选定芯片母体的code option选项,在option value项的默认值上单击,出现 一个下拉列表,单击选择合适的选项。如图:图2-7设置止确的code option6、单击ok,系统牛成一个没有文件的工程,在workspace管理窗口中

11、我们可以看见当 前牛成的工程为working project,正处被激活状态(工程名称为加粗字休):workspace - sn8c_ex : 1 projec白鶯 sm8c_ex 口 source header图2-8新建project的状态被激活 打开相应的文件夹,我们会发现系统生成了很多个新的文件,其屮的.pij文件即为工程文 件,其他的文件为根据我们刚才的设置和不同的芯片生成的配置文件及头文件。三、新建文件完成项目的新建后,我们发现项目管理器source文件夹下是空的,没有任何文件,文件 就是我们编程的主要工作了 !1、打开文件-新建菜单,单击出现我们前面看过很多次的new对话框,不过

12、比前面多了一个选项files,选择new列表中的files选项,单击按钮,对话框如图所示:图2-9新建文件对话框2在file list 'i1选屮需要创建的文件类型,这里我们创建一个c source file,给文件命 名从name编辑框屮输入,存放的地点为刚才的设定位置,默认不做修改。3、单击0k按钮,ids打开一个编辑窗口,最大化,显示为刚刚建立的文件名的页,系 统允许我们在这里进行程序的编写。四、编写程序在新建一个文件后,系统自动打开编辑器,并打开一个由用户命名的空文档,它与普通文 档相比较没有什么不同的z处,只不过它可以对c的关键字进行高亮显示。在新的文档里编辑 程序。c本身就

13、是一种模块化的编程语言,sn8c的编程保持c语言的编程风格。 sn8c所具有的nonansi c的特性请参看其他章节,在此不再做描述。 下面是一个简单的c程序举例。例2:* file name : sn8c_ex.c* post by : dragon.yi* date : 2005/09/23* test history : vi.00.220 describe:test 2708 interrupt住丄 2丄.丄丄丄“ ”“ ”丄 “丄.“/<t>p ppp pppppp /#includc <sn8p2708a.h> struct wordunsigned fin

14、t: 1; unsigned :7;jintword;unsigned int tc0cvaluc=0x64;unsigned int accbuf = 0x00; unsigned int pflagbuf = 0;/the data will auto store!interrupt intserv(void)_bclr(&intrq,5); tc0c = tcocvalue; intword.fint = 1;void initlo(void); void initlnt(void);void main(void)stkp=0x07;initio();initint();whil

15、e(l)if(intword.fint!=0) pl=0x00;p2=0x00;p3=()x()();p4=0x00;p5=0x00;po=oxoo;elsepo=oxff;pl=oxff;p2=0xff;p3=0xff;p4=0xff;p5=0xff;void initlo(void)p0m=0xff;plm=()xff;p2m=0xff;p3m 二 oxff;p4m=0xff;p5m=0xff;void initlnt(void)intrq=0x00;inten=0x00;tc()m=()x()();tc0m=0x20;tc0c=0x64;_bclr(&intrq,5); _bse

16、t(&inten,5);_bset(&tc0m,7); _bset(&stkp,7);注:程序只作为程序架构提供参考!五、调试程序在完成代码编辑后,想要马上顺利运行基本上是不可能的,每一个程序都有经过调试的 过程,程序的调试在ids屮非常方便,ids有全而的可视化的调试工具。你可以在程序屮设置 断点,在程序中按自己的需求来运行。可以根据不同的需求来进行调试。1、compile 和 build完成代码的编辑后,首先要进行compile,在菜单build->compile current file单击或在工具栏屮单击compile按钮和单击快捷键ctrl+f7均以启动

17、系统的compile程序。compile程 序会检杏代码屮存在的语法错谋和软件设置错込 然示在ompih窗口表列岀来,用户可以根据 表列出来的提示,对程序进行修改。若是语法错误,在列表中双击选项,系统会自动将光标移 动到相对应的代码行,方便你的检查和修改。compile通过后,进行build,同样有3种方式可 以启动build程序,build程序生成运行所需要的一些文件,同时检查硬件配置和连接错误,用 户必须根据提示对程序进行修改才能顺利通过。2、选择仿真方式单击进入projcct->sctting, !l|jw我们前面已经熟悉的project setting对话框,当前就示的是 gen

18、eral页,在primary setting组下面找到复选项use simulateo如果选屮该选项,则程序就在系 统提供的虚拟仿真器上仿真并显示相应结果;若不选中该选项,则程序必须在相应系列的仿真 器上进行程序调试仿真。这里我们先选择它。3、进入调试模式完成compile和build z后,进入菜单dcbug->bcgin debug,单击菜单项或直接按快捷键f5或在图标选项中选择按 曾钮单击都可进入调试模式,进入调试模式后,系统界面变成如下图:d e r 0尙 g >> t£? vi % 冷档谀体ii 4)卩.£ .茫? *.q h f »r

19、» e护f臥 "a口叶 erowet quu qebug loebgp/tho data vill auto stow!5onb< in*egrated development system - (w8_tet604xuruxened urt tc0cvalue»llx64; unsicned mt accbuf = 0x00; imfifmd lnt pflafbuf = 0: .interrupt interv(void) .boruihtrq, 5); tcoc s tcocvalue. intword. fint « 1 3 lorktpa

20、ct - %nfl.ltt<604e) k ib8_1«sim4 a o swc«void a&w(void)uif (intvord. fint l«0)htoo»k00l1ljioiooaddr«*sm gln 31,3 inum16:53 o图211调试程序界面3:void lmt io(void). void lmtlwt(void):stkp«)xo7; mitloo : lnitinto; vhile(l)2 he心oh 轉 cn»wxtkb |sowlnt9r(gpl»0x00; p2=

21、' <00; p>0x00.pchucl5 fit s 口 k”dr二4ryond.fl h 勻 dryondf2 hokoo0«000x000*00 00 (mlm0noisioksiob owoo系统界而出现 ram windowwatch window> variable window> register window> call stack window和disassembly window ,这些窗口都是调试程序要用到的。程序的指针指向程序的入 口处,即main ()函数的第一条语句。4 应用 watch window:在调试过程中如何

22、应用watch window? watch window用在调试工程中对定义的变量进行 监视,将需要进行监视的variable在编辑窗口屮双击,然后拖放到watch window当中,运行 程序就可以在watch window中看到variable的存放地点和值的变化。如图:namelo.addressvalue keycha tramf0x00000010oxft|1 imiv watch 1 x watch 2 入 watch3 /!图 2-12 watch window 窗 fl系统会将产牛了变化的项置成红色。为方便观察,你最多可以将variable分别放到3个watch window当

23、中进行观察,他们的 显示效果是一样的!5、应用 variable windowvariable window显示格式和watch window的显示格式样,但是variable window里面的 项无法自己设定。它是以auto的状态显示当前运行过程中被改变的local variable,同样系统 会将最近改变的量置成红色。6、应用 register window:register window里面显示的项是根据芯片的资源而定的,它显示的是当前母体芯片ram 中0x80oxff空间屮专用存储器在当前运行状态下的值,单击前面的“ + ”号,将扩展项f1展 开,可以得到毎一个bit的当而值。同样,

24、在运行过程中,系统会将刚改变的项的值置为红色 高亮显示,便于我们观察跟踪。由tcorcannot access.spcloxadspch0x00ep00x00白ploxfff fp100x01 fpu0x01fp120x01ofp130x01fp140x01fp150x01 fp160x01fp170x01a3p20x00由i>30x00namevalue图 2-13 register 窗口7、应用 call stack windowcall stack window显示当前运行状态卜,stack的使用状况和入栈的函数,用户可以根据 显示来判断程序的调用状况,进而判断当前的状态是否正确,

25、有没有函数调用岀错。图 2-14 call stack 窗口8、应丿ij memory window:在程序运行当屮,当你想从具体的ram地址而得到它的值的时候,你可以通过memory 窗口中实现,你可以直接在go to后面的编辑框中输入地址,按enter键确认,窗口会自动跳转 到相应的位置显示该位置的值,方便我们在使用过程中的查找。9 应用 disassembly window:如果调试过程屮,你需耍知道程序的直接汇编码,你可以在这个窗口屮观察。1()、设置断点:程序调试的时候,往往需要知道程序运行过程中某个变虽的运行状态,或者想知道某段 程序是否执行,还有执行后的结果;或者,需要知道某段程

26、序的运行过程是否匸确。这吋,就 必须在程序的正确位置设置断点。将光标移到正确位置,在相应的行,单击设置断点的按钮或按快捷键f9或者从菜单项中 设置都可以使该行程序被设置成为断点,被设置成断点后,运行程序,程序就会运行到断点处 停下来,以便于用户控制程序的执行和观察执行的结果。如图:elsep0=0xff;pl=0xff;op2=0xff;p3=0xff;p4=0xff;p5=0xff;图215断点执行状态11、跟踪程序执行:应用系统提供的debug工具,用户可以很方便地对程序的执行效果进行跟踪。你可以单步, 也可越过一段程序往下执行,这要看你的需要!调试工具同样町以以3种方式打开:debug菜

27、 单、工具栏按钮和快捷键。六、程序输出1、仿真程序结果:将仿真器与主机连接好,在project setting中清除use simulate选项的选中状态。将需要仿 真的硬件系统冃标板连接好。单击debug按钮或者按快捷键进入调试状态,就可以在实际硬件 上看到程序运行的结果,对程序进行修改直到得到正确结果。我们就得到一个正确运行的可以 烧录到实际芯片的程序。2、输出烧录文档在完成程序的调试仿真后,我们就需要将程序输出。系统已经在默认目录下生成程序的 烧录档xxx.sns,默认目录为当前工程文件的目录下。数据类型与运算sn8 c支持标准c的所有数据类型。具体有无符号字符(unsigned cha

28、r).有符号字符 (signed char)> 无符号整型(unsigned int)> 有符号整型(signed int)、无符号长型(unsigned long)、 有符号长型(signed long)浮点(float)和指针类型。还支持所有的构造类型。字符型(char)r基本类型整型(int)长整型(long)< 浮点型(float)数据类型j构造类型指针类型数组(any)结构体(struct) 共用体(union) 枚举(enum)图3-1数据类型3.1专有数据类型虽然sn8c支持c的所冇数据类型,但是由于它面对的是8-bit单片机,所以必然会考虑 数据类型的定义方法

29、和长度。在这些方面,sn8 c有它口己的专有的定义特征和数据长度,在 使用时一定要加于区分。请看下表:数据类型size (byte)数据取值范围signed char (short int)1-128 +127unsigned char(shorts int)10-255signed long2-32768+32767unsigned long2065535float、double4pointer2enum1表31、数据类型长度定义表3.2常量与变量在程序设计的过程中,我们有些量可能是参考值,也町能是预设的值。总z,我们希望它 在整个程序中保持不变,并且在程序的任何地方可以提供我们调用,用来比

30、对某些条件是否成对于这样的值,我们可以不去定义它,而直接参考数值,这在汇编编程过程中,经常会有 一些缺乏经验的程序员这样用。但这就需要程序员把程序中的这些值都牢牢记住,并要将他 们的值前后统一,这是一个非常容易出错的过程,而且也会影响了程序的可读性,这样,程序 的修改和维护都非常艰难,必须处处小心翼翼,一处不慎就全盘错误!这是任何人不想看到的 后果。因此,建议对于程序中用到的不会改变的参考值或其他预设的值都进行一个预先的定义, 给它取一个有意义的或与其相关的名字。这个过程就是常最定义,白然,这个不变的量就称为 常量。在标准c中,由于而对的是功能强大的cpu系统和大内存,用户可以不去管它放置的地

31、 方。但是,而对一个单片机系统,它的ram非常小,有吋会显得很紧张。所以系统为了节省空 间会将一些表格等放在系统的rom中。而我们直接命名的常虽,则由编译器自动将其替换为 所需要的值,这些工作就由计算机来完成好了。我们先來看看我们用汇编编写程序时是怎么來定义常量的:如:door_service_cequ#8();80ms去门抖动toint_cequ#224;t0中断时间segment_cequ#3;最多3段烹调注:上面数值前的#号,是sn8asm的符号,用于提示后面的是立即数。上而定义了 3个程序中会用到的参考值,顺便提一下,在定义的时候加上注釋是有必耍的, 要不然时间久了你就乂不知道你定义的

32、到底是什么了。在上而的定义中,用的是汇编equ关键 字,在编译过程中,程序里但凡出现了 equ前面的字段都会被其后面的值直接代替,因此,很 方便地减轻了程序员的工作。我们再來看看用sn8 c是如何定义这些相同的常量的:如:#define door_service_c 80 /80ms 去门抖动#dcfinc toint.c224/t0 中断时间#define segment_c3;最多 3 段烹调上面定义的3个量是与前面汇编当中定义的3个常量是完全和同的。在进行编译预处理时, 这些量就会被数值代替。还有一个特殊的地方,那就是一些数值列表,在汇编当中,查表项都是放在code当中的, 作为code

33、來处理,其实这些值也是常量,只不过他们的处理不同于一般常量而己,并且它们 共用一个入口。下面是一个汇编的表:disp_automenu:;显示菜单用第二数字表格dw oooohdwoaelfh;a-1dw0ae2fhdwoae3thdw0ac4flidwoae5flidw0ae6flidw0ae7fh我们可以看到,汇编的表是用dw关键字定义一个word,它是存放在.code段里面的,通 过表头地址來得到每一个相对应的值。那么在sn8c里面乂如何來处理这些表呢?在讲到表的处理之前,必须先提一提变量定义关键字的问题。sn8c定义一个变量时,可 以指明它所放置的地方(ram或rom),分别用关键字_

34、ram 和rom来指定存放的地点, 如:unsigned int _ram ramveriable;将变量存放在 ram 中ram unsigned int ramveriable2;unsigned int _rom romveriable;将变赧存放在 rom 屮_rom unsigned int romveriable2;我们可以知道,当一个最放到了 rom当屮就没法改变它的值了,其实就是我们说的常最。在c当屮,可以通过一个头名称來访问的变量类型比较多,其屮数组是比较方便的一种, 我们可以通过定义一个数组来存储这些表的数值,然示通过对数纟r的访问来杏询对应的值。如:unsigned lo

35、ng rom disp_automenu=显示菜单用第二数字表格0x0000,oxoae 1 f,0x0ae2f,0x0ae3f,0x0ae4f,0x0ae5f,0x0ae6f,0x0ae7f;这是一个与上面的汇编表完全相同的表,我们将它存放在_rom中,通过调用数组来查 表,这在后面将详细介绍。而在程序中还冇另外一类的虽是会在程序中不断被改变的,比如程序中的计数器,状态寄 存器等等都会随着程序的运行而改变。我们将这一类量称z为变量。我们先來看看汇编的定义变量的方法:.dataorgohtempids1tcmp2ds1temp3ds1temp4ds1led_dpds1stepds1 ;当前状态

36、上面的代码定义了 tempi、temp2、temp3、temp4、led_dp> step6个变量,它们分别占用 一个byte的ram空间,那么程序当屮就可以通过变量名对该变量的空间进行读写。当然在汇 编屮你也可以用一个变蜃名来访问两个或多个ram空间,这类似于杏表的操作,其定义如下:job_modeds 2powcr_modeds 4对上面的job_mode变最对以通过job_mode和job_mode+1来读写定义的两个存储单元, 以此类推power_inode或其他多个ram空间定义的变蜃可以通过相同的方法来定义。可见, sn8asm定义变屋的方法主要是通过ds关键字来申请盂要的变

37、虽空间,空间一旦被申请,就 在整个程序流程里面被占用,也就是说定义一个变量就少一个空间,这对于ram本身就很少 的单片机而言,不能不说是一种浪费°那么sn8c又是如何來定义变量的呢?要说到c的变疑,就不能不提一提变量的有效作用域。我们知道,汇编当中定义的变量都是在整个程序中冇效的,在程序中任何地方都可以改变 变量的值,这样程序员就会经常遇到这样的悄况:在调试程序时发现变量的值有误,却无法判 断变量到底在什么地方被错误赋值或被赋予了错误的值,从而不得不在整个程序中到处设置断 点,运行多次才找出问题的所在。这就是汇编当屮变量定义造成不方便的地方!而c的变量的定义区分了作用域,分为全局变量

38、和局部变量,而区分定义这两种变量的 方法很简单,只是在不同的位置定义就行了,这与标准c所规定的方法是一样的,后面再详细 讨论。卜面是sn8 c定义的儿个变量:unsigned int tempi;unsigned int temp2;unsigned int temp3;unsigned int temp4;unsigned int led_dp;unsigned int step;当前状态unsigned long job_mode;unsigned long power_mode 1;float powervalue;int templ_l;有符号的long temp2_2;从上面的定义可

39、以看到c的变量不仅区分了作用域,还有不同长度的变量类型,这样就 方便了程序员的使用。与面向数学运算的计算机相比,单片机的编程对变量类型或数据类型的选择更具有关键性 意义。sn8系列单片机是8bi(处理器的单片机,只有byie型的数据是处理器肓接支持的。对 于c这样的高级语言,不管使用何种数据类型,虽然某一行程序从字面上看,其操作i 分简单, 然而,实际上系统的c编译器需耍用一系列机器指令对其复朵的变量类型、数据类型的进行处 理。相同的一行语句,变量选择的类型不同,处理时就会产生很大的差别,产牛:的代码更是差 别很多。特别是当使川浮点变量时,将明显地赠加运算时间和程序的长度。当程序必须保证运 算

40、精度时,c编译器将调用相应的了程序库,把它们加到程序屮。然而许多不熟练的程序员, 在编写c程序时往往会使用大量的、不必要的变屋类型。这就导致c编译器相应地增加所调用 的库函数以处理大量增加的变量类型,并最终导致程序变得过于庞大,运行速度减慢,甚至因 此会在link时,出现因程序过大而装不进rom的情况。所以必须特别慎重的选择变量和数据 类型。而对于有符号与无符号的变蜃类型。在编写程序时,如果使用signed和unsigned两种数 据类型,那么就得使用两种格式类型的库函数。这将使得占用的存储空间成倍增长。因此在编 程时,如果只强调程序的运算速度而又不进行负数运算吋,最好采用无符号(unsign

41、ed)格式。note:1、选择数据类型的时候,在能够顺利完成功能的情况下,请尽量选择占空 间少的数据类型,这样不管是在ram空间使用上还是在产生代码效率上 都是有益的!2、能使用无符号数的都使用无符号数,以免处理出错,因为芯片内部是以 无符号数处理的。3、切记! c语言对大小写敏感,在开始定义变量的时候就要注意要有相应 的规范可循,用驼峰式是一个好的选择,这对于习惯于汇编的程序员来 说,可能不大习惯!当然,在标准c编程当中,经常会冇为书写方便,对数据类型进行缩写定义,这在sn8c 也是允许的。如:#define uchar unsigned char#define uint unsigned

42、int这样,在以后的编程中,就可以用uchar代替unsigncd char,用uint代替unsigned int来 定义变量。33数据的存储类型与存储结构在前面分析查表类型数据定义的时候已经提到了数据在单片机里的存储,会分为rom和 ram两部分,我们分别称之为程序存储器(rom)和数据存储器(ram)。它们在我们编写汇 编的时候,会分别用关键字.code和.data来预先声明。通常sn8系列单片机不用扩展存储器,它提供种类丰富的机型,你完全可以根据你的需 求來选择合适的机型。因此,数据只存储在片内,寻址也不存在片内片外的区分。sn8p单片机的数据存储器(ram)的结构如下:bankoba

43、nklooooh007fhoo8ohooffhoo1ooolffhsn8p系列单片机的通用ram区的大小依不同的芯片而不同,但都是按bank來划分, 每一个bank内的地址为00hffh。而所有芯片的banko的80hffh的空间都是留给系统 专用的系统寄存器区。其实我们上面定义的变虽都是放在ram区的数据结构,在定义一个变虽时,我们前面已 经提到可以用_ram和rom关键字来指定存储的地方,而变最定义一般都放在ram当屮, 因而ram关键字是缺省项。看下面的例子:unsigned int temp 1;unsigned int _ram temp2;_ram unsigned int tem

44、p3;unsigned long job_modc;unsigned long ram job_mode2;ram unsigned long job_mode3;float powervalue;float _ram powervalue;_ram float powcrvaluc;int templ_l;冇符号的int ram tempi-2;_ram temp 1-3;long temp2_2;其实上面的定义都是相同的效果,就是定义变量,并将其放置在数据存储区(ram)内。 也就是说,我们在定义一个变量,按我们c常用的方法定义就自动地放到ram里了,缺省项 给我们带來了很大的方便。上面已

45、经说明了,在ram存储区内,80hffh是系统寄存器区。那么我们又是如何来定义系统寄存器区呢?我们先来看看系统寄存器都有哪些内容:0123456789abcdef8lhrzyxpflagrbank9ampmap4con-bdamadmadbadrpedgec-p2m-p4mp5m-intrqintenoscm-wdtrtcorpclpchdp0p2p4p5tomtcomtcoctc1mtc1ctc1rstkpepourp2urp4urp5uryzfstk7lstk7hstk6lstk6hstk5lstk5hstk4lstk4hstk3lstk3hstk2lstk2hstk1lstk1hstko

46、lstkoh表32、sn8p系列单片机系统寄存器列表根据不同的芯片的资源,寄存器的内容会随之改变,但是他们定义的区域都不变。这些寄 存器都分别对应了芯片内部的资源,sn8 c针对这部分的系统资源,对这些寄存器进行了定义,其定义的形式如下:# definel(*(_ram unsigned int*)ox8o)#defineh(*(_ram unsigned int*)ox8l)#definer(*(_ram unsigned int*)ox82)# definez(*(_ram unsigned int*)ox83)# definey(*(_ram unsigned int*)0x84)# d

47、efinex(*(_ram unsigned int*)ox85)#definepflag(*(_ram unsigned int*)ox86)这些定义都被包含在相应芯片的头文档里(h),因此并不需要用户自己去定义寄存器的相应名称,只需要在程序的开头包含相应的头文档就行了。如下所示:#include <sn8p2708a.h>note:这些系统寄存器都是以大写字母进行定义的,在编写程序时要注意这一 占/lit。程序流程控制是程序的精华所在,正确的程序流程/能实现正确的程序功能。安排精巧的 程序流程控制才可能使程序具有高效率。程序流程控制不管是在c还是在汇编中都是程序设计 者最值得思

48、考的地方。41顺序结构顺序结构是程序最基木的流程,其语句顺序执行,pc指针依次下移,是cpu内部处理指 令的初始方法。这也是编程思维的蝕初级方式,也是程序的蝕基本方式和流程。顺序结构流程:图41顺序结构流程其实,其描述的是一个向量方式发展的问题,是所有问题发展和描述的基木方法,具有明 确的方向性和时间性,如图中的a操作的发展方向只冇一个,即接下来就是b操作,中间既没 有反复也没有曲折变化,b 一定发生在a的后面。我们平时可以看到的c语言的实现:(微波炉开机初始化)key_bibi_f = 1;上电响一声menu_disp_h = oxfou;上电显示 0:00menu_disp=();disp

49、5 = oxffu;上述简短的几条语句分别完成一定冃的的初始化,虽然在这星没冇强制要求什么样的顺 序,但是执行过程屮是严格按语旬的先后来开关目标的。sn8asm的实现:bobset key_bibi_f;上电响一声mova,#ofohmovmenu_disp_h,amova,#00hmovmcnu_disp_l,amova,#llllllllbmovdisp5,a;上电显示0:00这是一段功能完全与上面这段c相同的汇编实现,我们可以看见在顺序结构的汇编语句 当中没有任何的跳转和判断,都是按原功能的顺序來描述。从对比当中我们完全可以找到它们的逻辑上的一一对应关系。4.2选择结构事实上,完全顺序结

50、构的流程的程序很少,因为很多事情并不是一帆风顺,顺流而下。很 多情况下,事件的发生都需要具备一定的条件,只冇一定条件下才冇可能实现。这就得使用选 择结构来描述。选择结构流程图:图4-2选择结构流程图简单选择结构只判断一个条件的真假來决定下面的需要执行的操作,这是一个最简单的判 断。c语言实现:(bcd码调整)if(result_buf > oxoa)result_buf = input + 6;rcsult_buf = input;我们看见在c语言当中,我们用判断语句来实现这样一个判断逻辑,不管是什么样的条 件,我们只计算其真假,做出判断。ifelse是一个非常好的判断组合,很容易用它来

51、完 成下列我们用汇编來实现的功能。sn8汇编实现:emprs a,#oah nop bobtso fcjmp $+3 bomov a,ybomov a,yadd a,#6h;调整后的数放在a事实上,在汇编程序中,我们会遇到几种情况的条件选择:一是当条件是一个位变量时,我们可以直接川bobts指令來进行判断。一是当条件是是否满足一个预定的值,我们可以用cmprs指令来进行判断,当然也可以 将英转化为标志位来判断。也可以用减法的方法将其转化成为标志位进行判断,就看需要来安 排了更 7/k o o 0 o 0 oa、串行多分支结构流程:事实上大多数时候,单个的条件无法分析判断复杂的问题,冇时候一个结

52、果的出现需要很 多个条件同吋成立,而每一个条件成立,又都有不同的结果产生,这样就会有一系列的有层次 的判断!图4-3串行多分支结构流程图c用if, else if嵌套來实现:if(key_bibi_f)buzzejtime = d_buzzer_time 1;响声长愆,200msbuzzer_not = d_buzzer_not3;要响儿次,#1else if(end_bibi_f)/buzzer 10buzzejtime = d_buzzer_time2;响声长愆,500msbuzzer_not = d_buzzer_not 1;要响几次,#10else if(segment_bibi_f) /buzzer20buzzejtime = d_buzzer_time2;响声长愆,500msbuzzer_not = d_buzzer_not 1;要响儿次,#4说明:kcy_bibi_f;按键响声请求标志end_bibi_f;烹调结束响声请求标志sgment_bibi_f;段切换响声请求标志按键响声:200ms/l次结束响声:5()()ms/5次段切换响声:500ms/2次问:sn8 asm怎么实现?sn8 asm的实现:

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论