《MC9S12的C语言与标准C语言的区别》由会员分享,可在线阅读,更多相关《MC9S12的C语言与标准C语言的区别(45页珍藏版)》请在金锄头文库上搜索。
1、MC9S12MC9S12的的C C语言与标准语言与标准C C语语言的区别言的区别控制科学与工程学院控制科学与工程学院1、建立汇编语言工程建立一个汇编语言程序并完成LED点亮选择“File”“New”选择向导,输入工程名“LED”,设置工程目录欢迎屏幕选择单片机“MC9S12DG128B”选择开发语言“Assembly”选择“RelocatableAssembly”选择编译目标完成建立汇编语言工程选择编译目标为TBDML,插好PCB板在“CLI”后写上执行一次的代码:movb#$ff,DDRBmovb#$55,PORTB这两句代码只执行一次,可以看到静态花灯的效果程序进入大循环,花灯状态不变2、
2、建立C语言工程建立一个C语言程序并完成LED花灯闪亮选择“File”“New”选择向导,输入工程名“LED”,设置工程目录欢迎屏幕选择单片机“MC9S12DG128B”选择开发语言“Assembly”和“C”选择不使用ProcessorExpert选择不使用PC-Lint选择ANSIStartupcode选择浮点数支持为NONE建立C语言工程MemoryModule选择banked编译目标选择上TBDML完成初始化方向寄存器和初始显示DDRB=0xff;PORTB=0x55;在无限for循环里写PORTB=PORTB;编写延时函数delay1()建立C语言工程voiddelay1()unsig
3、nedinti=60000;while(i-);在“PORTB=PORTB;”后调用该函数delay1();观看演示效果,典型的无限循环程序C语言程序结构voidmain(void)EnableInterrupts;/开中断asm_main();/初始化硬件/设置单片机I/O口的数据方向for(;)/无限循环/循环执行的程序/花灯循环显示开机执行一次循环执行到断电为止3、Codewarrior4.6程序调试软件仿真调试选择编译目标为FullChipSimulation调试:全速执行、断点、执行到光标、单步等子窗口:source、data、register、assembly、memory、com
4、mand等Codewarrior4.6程序调试BDM调试安装BDM驱动拨码开关1提供供电方式选择编译目标TBDML进入调试界面需要进行相关设置,如晶振频率、MCU型号等等单步全速调试与仿真基本相同,不同的是这个属于在线调试,必须有MCU连接。Lecture5Page11微控制器开发技术FileprocesstreeC源文件源文件汇编源文件汇编源文件库文件库文件目标文件目标文件C编译器汇编编译器链接器执行文件执行文件映射文件映射文件列表文件列表文件汇编汇编反编译文件反编译文件反编译器链接配链接配置文件置文件*.h*.c*.c+*.asm*.inc*.prm*.lib*.obj*.lst*.map
5、*.sx*.abs4、S格式文件将程序和数据用ASCII码表示,包含了基本协议,包括出错校验功能。程序编译完成后,在bin文件夹生成“xxx.abs.s19”文件。行-S记录,由记录类型、记录长度、存储地址、程序/数据校验和构成。记录类型(S0、S1、S9)S0:包含本S文件的名字,在PC上有意义。如P167,S0表示记录类型,18为记录长度(0X18),最后一个字节80为校验码。S1:S1后接记录长度,接装载地址,32个机器码字节,最后为校验码。S格式文件S9:最后一个记录,表示文件传送结束。S记录类型S0:S格式文件的起始记录S1:地址为2字节的程序数据记录S2:地址为3字节的程序数据记录
6、(64K)S3:地址为4字节的程序数据记录(16M)S5:标记本文件的S1、S2或S3记录个数(可选)S7:S3格式,用S7记录结束S8:S2格式,用S8记录结束S9:S1格式,用S9记录结束S0510000433A5C446F63756D656E747320616E642053657474696E67735C41646D696E6973747261746F725C4D7920446F63756D656E74735C50726F6A6563745F335C62696E5C50726F6A6563742E616273BDS123C000CF050010EF180BFF0003180B550001
7、CE00017E0500070E7C0502FE0500088E0028S119C0201826EF20EACD0000CC000104050719EEB7C60435F93D32S105FFFEC0003DS9030000FC2、MC9S12的的C编程与标准编程与标准C的不同的不同9S12C语言的不同变量资源映射用C语言处理中断(中断向量表64)标准C库C语言入口程序链接与定位变量的不同基本数据类型的定义P185特有类型的变量volatile更加特殊的constvolatile2.1变量各种类型的数据占的字节数,在不同的系统中有所不同各种类型的数据占的字节数,在不同的系统中有所不同自定义Co
8、deWarrior数据类型在CodeWarrior环境下按ALT+F7打开工程的通用设置,选择“CompilerforHC12”面板然后点按钮“TypeSizes”。CodeWarrior编译器标准类型设置建议不要随意更改数据类型的设置16位微控制器内部的数据长度是16位(2字节),所以首选的数据类型是“int”。16位机处理16位数据比8位数据的效率更高。对于9S12单片机来说,16位数据类型效率最高,因此在使用中,尽量选择int类型数据。若可能,选用无符号类型。数据类型的真相存储类修饰符以下关键字用于声明变量,以指定特定需要或内存中变量存储的相关条件。static(静态变量)volatil
9、e(可变变量)const(只读变量)Constvolatile可变(volatile)变量volatile的本意是“易变的”,就是该变量会以编译器无法预知的方式发生变化.所有的编译器的优化均假设编译器知道变量的变化规律,请编译器不要做优化。也就是说是其值在正常程序流程以外可能改变的变量。在嵌入式系统中,这种情况通过两种主要途径发生:一是中断服务程序,二是硬件动作。例子staticinti=0;intmain(void).while(1)if(i)dosomething();/*Interruptserviceroutine.*/voidISR_2(void)i=1;程序的本意是希望ISR_2中
10、断产生时,在main当中调用dosomething函数,但是,由于编译器判断在main函数里面没有修改过i,因此可能只执行一次对从i到某寄存器的读操作,然后每次if判断都只使用这个寄存器里面的“i副本”,导致dosomething永远也不会被调用。如果将变量加上volatile修饰,则编译器保证对此变量的读写操作都不会被优化(肯定执行)。此例中i也应该如此说明。Lecture5Page24微控制器开发技术volatile(2)volatile用在如下的几个地方中断服务程序中修改的供其它程序检测的变量需要加volatile;存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写
11、都可能由不同意义const关键字“const”,并不表示恒量,而是代表“只读”。Const声明可用于任何变量,它告诉编译器将其存储在ROM区。编译器保留了那个位置程序存储器地址。由于位于ROM中,其值不能改变。const unsigned short a;unsigned short const a;const unsigned short *a;unsigned short * const a;Constvolatile变量只读变量这个修饰符应该用于能出乎意料地改变的任何存储器位置,因此需要volatile限定语,由于const该变量是只读的。最明显的例子是硬件状态寄存器,像SCI状态寄存器
12、SCS1。这个寄存器包含信号状态标志,如发送空、发送完成、接收满以及其它。这是一个可变寄存器由于这些标志的改变依赖于串行通信的状态;这也是只读,由于标志不能被程序直接改写,它们只对模块的状态作出响应。这个状态寄存器最佳声明方法是:constvolatileunsignedcharSCS10x00162.2资源的映射访问固定的内存位置访问I/O寄存器访问固定内存位置访问固定内存位置在某个项目中需要将绝对地址0x2FFA处整型变量的值设为0xAA55。完成这个任务的代码是:与PC机不同,嵌入式系统通常的特点是需要编程者访问一个指定的存储器位置。int*ptr;ptr=(int*)0x2FFA;*p
13、tr=0xAA55;访问固定内存位置访问固定内存位置在某个项目中需要将绝对地址0x2FFA处整型变量的值设为0xAA55。完成这个任务的代码是:(2)unsignedintptr0x2FFA;intptr0x2FFA;ptr=0xAA55;访问I/O寄存器一个方法是使用如下的#define指示:#define PortA ( * ( volatile unsigned char * ) 0x0000 )这种情况下,PortA为地址0x0000处字符型变量。在codewarrior中的头文件中已经给出了寄存器的宏定义。例如:mc9s12dg128.hunsignedcharpta;pta=POR
14、TA;或 PORTA=pta;另一种方法是在变量声明中使用符号“”:constvolatileunsignedcharSCS10x00162.3C语言的中断ANSIC里并没有定义如何用C写中断服务程序表达式以interrupt关键字开始,接着是中断向量号,最后是函数原型。以下定义了中断向量号为7的实时中断interrupt7voidRTI_ISR(void)/*RTI_ISRFunctionCodes*/9S12中断源有55个,中断向量号越小,优先级越大。见课本64页。在codewarrior环境下,中断向量号在头文件中,例如mc9s12dg28.h2.4标准C库标准库如stdio.h通常包含
15、在大部分输入输出函数,大部分可以直接使用。#includevoidmain(void)Printf(“HelloWorld!n”)标准C语言与硬件无关,I/O的输入输出并不是标准C语言的一部分。在标准C语言中,I/O操作是通过操作系统实现的。在标准C中,printf()缺省的控制台是显示器,但9S12没有显示器作为片外外设。在嵌入式编程中,如果需要使用这个功能,则需要修改基础库函数才能正确输出。凡是需要显示在显示终端的,可以使用SCI(异步串行通信)发送到PC机的超级终端显示。2.5C语言入口在MC9S12的C程序中,程序的入口在什么地方?程序是怎样起动的呢?开机进入0号复位中断初始化(堆栈、
16、硬件初始化、看门狗等等)调用main函数Codewarrior中的Start12.c程序员可以自己编写启动代码,可以将应用程序中的硬件初始化程序都放在启动代码里面,这样就可以比较专注地在应用程序中做要做的事情。void _Startup() asm LDS 0x1000 JSR HardInit JSR main 一个启动代码的例子一个启动代码的例子2.6程序的链接与定位对于MC9S12单片机来说,由于RAM,EEPROM,寄存器可以重新映射,而且不同型号的单片机内部FLASH大小也不一样,这样程序编译后存放在什么位置,成了我们必须告诉链接器的内容,因为链接器不知道你用的单片机RAM放在什么地
17、方,ROM放在什么地方。为了方便管理,CodeWarrior自动生成一个.prm文件,用于定义目标代码的装载地址。详见课本192页。C语言与汇编语言的混合编程在绝大多数场合采用C语言编程可完成预期的目的,但是对一些特殊情况进行编程时要结合汇编语言。汇编语言具有直接和硬件打交道、执行代码的效率高等特点,可以做到C语言所不能做到的一些事情:1.一个程序中的关键部分对执行速度有很高要求,实时性强。用汇编编程可以更有效的利用用汇编编程可以更有效的利用CPU的寄存器和指令集,的寄存器和指令集,用其产生的代码比用编译器产生的代码运行更快。2.对特定硬件接口的访问。例如对I/O端口的访问,或者用于禁止、启用
18、中断系统。#defineEnableInterrupts_asmCLI;#defineDisableInterrupts_asmSEI;C中使用汇编C语言中嵌入汇编语句:n_asmCLI;nasm(CLI);nasmCLInasm_main()例1对从RAM中0x1000地址开始的10个无符号字节型数进行由小到大排序程序分析:可以使用C语言把一个unsignedchar类型的数组存储到从0x1000开始的内存空间中,数组的大小为10个字节,内容由程序员自定义。由小到大的排序使用冒泡法完成。unsignedchardata100x1000=0x22,i,j,temp; /*定义数组*/voidmain(void)for(i=0;i10;i+)/*初始化数组*/datai=20-i;for(i=0;i9;i+)/*使用冒泡法排序*/for(j=0;jdataj+1)temp=dataj;dataj=dataj+1;dataj+1=temp;for(;)注:若在函数内定义变量,须在函数体开始处注:若在函数内定义变量,须在函数体开始处定义定义谢谢!谢谢!