MC9S12的C语言与标准C语言的区别.ppt

上传人:牧羊曲112 文档编号:5439609 上传时间:2023-07-07 格式:PPT 页数:45 大小:318.50KB
返回 下载 相关 举报
MC9S12的C语言与标准C语言的区别.ppt_第1页
第1页 / 共45页
MC9S12的C语言与标准C语言的区别.ppt_第2页
第2页 / 共45页
MC9S12的C语言与标准C语言的区别.ppt_第3页
第3页 / 共45页
MC9S12的C语言与标准C语言的区别.ppt_第4页
第4页 / 共45页
MC9S12的C语言与标准C语言的区别.ppt_第5页
第5页 / 共45页
点击查看更多>>
资源描述

《MC9S12的C语言与标准C语言的区别.ppt》由会员分享,可在线阅读,更多相关《MC9S12的C语言与标准C语言的区别.ppt(45页珍藏版)》请在三一办公上搜索。

1、MC9S12的C语言与标准C语言的区别,控制科学与工程学院,1、建立汇编语言工程,建立一个汇编语言程序并完成LED点亮选择“File”“New”选择向导,输入工程名“LED”,设置工程目录欢迎屏幕选择单片机“MC9S12DG128B”选择开发语言“Assembly”选择“Relocatable Assembly”选择编译目标完成,建立汇编语言工程,选择编译目标为TBDML,插好PCB板在“CLI”后写上执行一次的代码:movb#$ff,DDRB movb#$55,PORTB这两句代码只执行一次,可以看到静态花灯的效果程序进入大循环,花灯状态不变,2、建立C语言工程,建立一个C语言程序并完成LE

2、D花灯闪亮选择“File”“New”选择向导,输入工程名“LED”,设置工程目录欢迎屏幕选择单片机“MC9S12DG128B”选择开发语言“Assembly”和“C”选择不使用Processor Expert选择不使用PC-Lint选择ANSI Startup code选择浮点数支持为NONE,建立C语言工程,Memory Module 选择banked编译目标选择上TBDML完成初始化方向寄存器和初始显示DDRB=0 xff;PORTB=0 x55;在无限for循环里写PORTB=PORTB;编写延时函数delay1(),建立C语言工程,void delay1()unsigned int i

3、=60000;while(i-);在“PORTB=PORTB;”后调用该函数delay1();观看演示效果,典型的无限循环程序,C语言程序结构,void main(void)EnableInterrupts;/开中断asm_main();/初始化硬件/设置单片机I/O口的数据方向for(;)/无限循环/循环执行的程序/花灯循环显示,开机执行一次,循环执行到断电为止,3、Codewarrior 4.6 程序调试,软件仿真调试选择编译目标为Full Chip Simulation调试:全速执行、断点、执行到光标、单步等子窗口:source、data、register、assembly、memory

4、、command等,Codewarrior 4.6 程序调试,BDM调试安装BDM驱动拨码开关1提供供电方式选择编译目标TBDML进入调试界面需要进行相关设置,如晶振频率、MCU型号等等单步全速调试与仿真基本相同,不同的是这个属于在线调试,必须有MCU连接。,Lecture5 Page 11,微控制器开发技术,File process tree,C源文件,汇编源文件,库文件,目标文件,C编译器,汇编编译器,链接器,执行文件,映射文件,列表文件,汇编反编译文件,反编译器,链接配置文件,*.h*.c*.c+,*.asm*.inc,*.prm,*.lib,*.obj,*.lst,*.map,*.sx

5、*.abs,4、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记录结束,S0510000433A5C446F63756D656E747320616E642053657474696E67735C41646D696E6973747261746F725C4D7920446F63756D656E74735C50726F6A6563745F335C62696E5C50726F6A6563742E616273BD S123C000CF050010EF180BFF0003180B5500

7、01CE00017E0500070E7C0502FE0500088E0028 S119C0201826EF20EACD0000CC000104050719EEB7C60435F93D32 S105FFFEC0003D S9030000FC,2、MC9S12的C编程与标准C的不同,9S12 C语言的不同变量资源映射用C语言处理中断(中断向量表64)标准C库C语言入口程序链接与定位,变量的不同基本数据类型的定义P185特有类型的变量volatile更加特殊的const volatile,2.1 变量,各种类型的数据占的字节数,在不同的系统中有所不同,自定义CodeWarrior数据类型,在Code

8、Warrior环境下按ALT+F7打开工程的通用设置,选择“Compiler for HC12”面板然后点按钮“Type Sizes”。,CodeWarrior编译器标准类型设置建议不要随意更改数据类型的设置,16位微控制器内部的数据长度是16位(2字节),所以首选的数据类型是“int”。16位机处理16位数据比8位数据的效率更高。对于9S12单片机来说,16位数据类型效率最高,因此在使用中,尽量选择int类型数据。若可能,选用无符号类型。,数据类型的真相,存储类修饰符,以下关键字用于声明变量,以指定特定需要或内存中变量存储的相关条件。static(静态变量)volatile(可变变量)con

9、st(只读变量)Const volatile,可变(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也应该如此说明。,Lecture5 Page 24,微控制器开发技术,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;,Const volatile 变量,只读变量这个修饰符应该用于能出乎意料地改变的任何存储器位置,因此需要volatile限定语,由于const该变量是只读的。,最明显的例子是硬件状态寄存器,像

12、SCI状态寄存器SCS1。这个寄存器包含信号状态标志,如发送空、发送完成、接收满以及其它。这是一个可变寄存器由于这些标志的改变依赖于串行通信的状态;这也是只读,由于标志不能被程序直接改写,它们只对模块的状态作出响应。这个状态寄存器最佳声明方法是:const volatile unsigned char SCS1 0 x0016,2.2 资源的映射,访问固定的内存位置访问I/O寄存器,访问固定内存位置,在某个项目中需要将绝对地址0 x2FFA处整型变量的值设为0 xAA55。完成这个任务的代码是:,与PC机不同,嵌入式系统通常的特点是需要编程者访问一个指定的存储器位置。,int*ptr;ptr=

13、(int*)0 x2FFA;*ptr=0 xAA55;,访问固定内存位置,在某个项目中需要将绝对地址0 x2FFA处整型变量的值设为0 xAA55。完成这个任务的代码是:,(2)unsigned int ptr 0 x2FFA;,int ptr 0 x2FFA;ptr=0 xAA55;,访问I/O寄存器,一个方法是使用如下的#define指示:#define PortA(*(volatile unsigned char*)0 x0000)这种情况下,Port A为地址0 x0000处字符型变量。在codewarrior中的头文件中已经给出了寄存器的宏定义。例如:mc9s12dg128.huns

14、igned char pta;pta=PORTA;或PORTA=pta;,另一种方法是在变量声明中使用符号“”:const volatile unsigned char SCS1 0 x0016,2.3 C语言的中断,ANSI C里并没有定义如何用C写中断服务程序表达式以interrupt关键字开始,接着是中断向量号,最后是函数原型。以下定义了中断向量号为7的实时中断 interrupt 7 void RTI_ISR(void)/*RTI_ISR Function Codes*/,9S12中断源有55个,中断向量号越小,优先级越大。见课本64页。在codewarrior环境下,中断向量号在头文

15、件中,例如mc9s12dg28.h,2.4 标准C库,标准库如stdio.h通常包含在大部分输入输出函数,大部分可以直接使用。#include void main(void)Printf(“Hello World!n”),标准C语言与硬件无关,I/O的输入输出并不是标准C语言的一部分。在标准C语言中,I/O操作是通过操作系统实现的。在标准C中,printf()缺省的控制台是显示器,但9S12没有显示器作为片外外设。在嵌入式编程中,如果需要使用这个功能,则需要修改基础库函数才能正确输出。凡是需要显示在显示终端的,可以使用SCI(异步串行通信)发送到PC机的超级终端显示。,2.5 C语言入口,在M

16、C9S12的C程序中,程序的入口在什么地方?程序是怎样起动的呢?开机进入0号复位中断初始化(堆栈、硬件初始化、看门狗等等)调用main函数Codewarrior中的Start12.c程序员可以自己编写启动代码,可以将应用程序中的硬件初始化程序都放在启动代码里面,这样就可以比较专注地在应用程序中做要做的事情。,void _Startup()asm LDS 0 x1000 JSR HardInit JSR main,一个启动代码的例子,2.6 程序的链接与定位,对于MC9S12单片机来说,由于RAM,EEPROM,寄存器可以重新映射,而且不同型号的单片机内部FLASH大小也不一样,这样程序编译后存

17、放在什么位置,成了我们必须告诉链接器的内容,因为链接器不知道你用的单片机RAM放在什么地方,ROM放在什么地方。为了方便管理,CodeWarrior自动生成一个.prm文件,用于定义目标代码的装载地址。详见课本192页。,C语言与汇编语言的混合编程,在绝大多数场合采用C语言编程可完成预期的目的,但是对一些特殊情况进行编程时要结合汇编语言。汇编语言具有直接和硬件打交道、执行代码的效率高等特点,可以做到C语言所不能做到的一些事情:一个程序中的关键部分对执行速度有很高要求,实时性强。用汇编编程可以更有效的利用CPU的寄存器和指令集,用其产生的代码比用编译器产生的代码运行更快。对特定硬件接口的访问。例

18、如对I/O端口的访问,或者用于禁止、启用中断系统。#define EnableInterrupts _asm CLI;#define DisableInterrupts _asm SEI;,C中使用汇编,C语言中嵌入汇编语句:_asm CLI;asm(CLI);asm CLIasm_main(),例1,对从RAM中0 x1000地址开始的10个无符号字节型数进行由小到大排序 程序分析:可以使用C语言把一个unsigned char类型的数组存储到从0 x1000开始的内存空间中,数组的大小为10个字节,内容由程序员自定义。由小到大的排序使用冒泡法完成。unsigned char data10 0 x1000=0 x22,i,j,temp;/*定义数组*/void main(void)for(i=0;idataj+1)temp=dataj;dataj=dataj+1;dataj+1=temp;for(;)注:若在函数内定义变量,须在函数体开始处定义,谢谢!,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号