版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1/30单片微型计算机原理及接口技术(11)内容提纲一单片机C语言程序中的常用运算二C51对ANSIC的扩展三STC8H单片机C51程序框架2/30单片机C语言程序中的常用运算一3/301.关系运算符关系运算符用于比较两个常数或者表达式的大小。关系运算的结果只能是0或1。关系运算符的值为真时,结果值为1;关系运算符的值为假时,结果值为0。C语言提供6种关系运算符。运
算
符名
称示
例功
能<小于a<ba小于b时返回真;否则返回假<=小于等于a<=ba小于等于b时返回真;否则返回假>大于a>ba大于b时返回真;否则返回假>=大于等于a>=ba大于等于b时返回真;否则返回假=
=等于a=
=ba等于b时返回真;否则返回假!=不等于a!=ba不等于b时返回真;否则返回假特别注意,判断两个常数或者表达式相等时,使用“=
=”,不要使用单个的“=”。否则,判断两个数是否相等就变成了赋值语句,编译时不会提示错误或警告,但执行结果一般是不正确的。4/30逻辑运算符包括与(&&)、或(||)、非(!)三种,用于对包含关系运算符的表达式进行合并或取非。对于使用逻辑运算符的表达式,返回0表示“假”,返回1表示“真”。与运算符(&&)表示两个条件同时满足时(即两个条件都为真时),返回结果才为真。例如,假设一个程序在同时满足条件a<100和b<=40时,必须执行某些操作,应使用关系运算符和逻辑与运算符(&&)来写这个条件的代码:(a<100)&&(b<=40)。类似地,或运算符(||)用于检查两个条件中是否有一个为真的运算符,只要有一个条件为真,运算结果就为真。如果上例改为如果任一语句为真,程序需执行某些操作,则条件代码为:(a<100)||(b<=40)。逻辑非运算符(!)表示对表达式的真值取反。例如,如果检测变量s不大于10,程序需执行某些操作,则条件代码:(!(s>10))。其实,该条件码相当于(s<=10)。2.逻辑运算符5/303.位运算符很多应用程序常要求在位(bit)一级进行运算或处理。C语言提供了位运算的功能,这使得C语言也能像汇编语言一样用来编写系统程序。C语言提供了六种位运算符,分别为按位与(&)、按位或(|)、按位异或(^)、取反(~)、左移(<<)和右移(>>)。按位运算的数据长度与参与运算的变量类型有关。(1)按位与运算按位与运算符“&”是双目运算符。其功能是参与运算的两个数或变量对应的二进位相与。只有对应的两个二进位均为1时,结果位才为1,否则为0。例如:
unsignedchara=9,b=5,c;
c=a&b; //执行后c=1。9&5可写算式为00001001&00000101=00000001按位与运算通常用来对某些位清0或保留某些位。例如把无符号整型变量a的高八位清0,保留低八位,可作a&255运算(255的二进制数为0000000011111111)。6/30(2)按位或运算按位或运算符“|”是双目运算符。其功能是参与运算的两个数或变量对应的二进位相或。只要对应的两个二进位有一个为1时,结果位就为1。例如:unsignedchara=9,b=5,c;c=a|b;//执行后c=13。9|5的算式为00001001|00000101=00001101(十进制为13)(3)按位异或运算按位异或运算符“^”是双目运算符。其功能是参与运算的两个数或变量对应的二进位相异或。当两个对应的二进位相异时,结果为1。例如:
unsignedchara=9,b=5,c;
c=a^b; //执行后c=12。9^5的算式为00001001^00000101=00001100(十进制为12)(4)求反运算求反运算符“~”为单目运算符。其功能是对参与运算的数的各二进位按位求反。例如:unsignedinta=9,c;c=~a; //执行后c=65526。~9的算式为~(0000000000001001)=11111111111101107/30(5)左移运算左移运算符“<<”是双目运算符。其功能是把“<<”左边的运算数的各二进位全部左移若干位,由“<<”右边的数指定移动的位数,高位丢弃,低位补0。例如:
unsignedchara=3,c;
c=a<<4;//执行后c=48。a=00000011(十进制3),左移4位后为00110000(十进制48)。(6)右移运算右移运算符“>>”是双目运算符。其功能是把“>>”左边的运算数的各二进位全部右移若干位,“>>”右边的数指定移动的位数。例如:
unsignedchara=15,c;c=a>>2; //执行后c=3。a=000001111(十进制15),右移2位后为00000011(十进制3)。对于有符号数,在右移时,符号位将随同移动。当为正数时,最高位补0,而为负数时,符号位为1。8/30C51对ANSIC的扩展二9/301.
C51扩展的关键字
C51有以下19个扩展关键字:_at_、sbit、sfr、bit、sfr16、idata、bdata、xdata、pdata、data、code、alien、small、compact、large、using、reentrant、interrupt、_task_。10/30(1)变量或数据类型C51编译器支持的数据类型见表5-1。表5-1C51支持的数据类型数据类型含义位数/bit字节数/B取值范围bit*位型11/80或1signedchar带符号字符型81-128~127unsignedchar无符号字符型810~255enum
8/161或2-128~127或-32768~32,767signedshort带符号短型162-32,768~32,767unsignedshort无符号短型1620~65,535signedint带符号整型162-32,768~32,767unsignedint无符号整型1620~65,53511/30表5-1C51支持的数据类型(续)数据类型含义位数/bit字节数/B取值范围signedlong带符号长整型324-2,147,483,648~2,147,483,647unsignedlong无符号长整型3240~429,4967,295float浮点型324+1.175,494,E38~3.402,823,E+38sbit*11/80~1sfr*810x80-0xffsfr16*1620x80~0xff注:带*部分为C51所特别支持的变量类型(扩展的数据类型),它们不属于ANSIC,不能用指针对它们存取。包括: l
bit:位变量,值为0或1。 l
sbit:从字节中定义的位变量(0或1)。 l
sfr:sfr字节地址(0x80~0xff)。 l
sfr16:sfr字地址(0x80~0xff,其实是占用两个连续的地址)。
其余的数据类型如char、enum、short、int、long、float等与ANSIC相同。12/30①bit型变量bit型变量可用于变量类型和函数声明、函数返回值等,存储于内部RAM的20H~2FH单元中。需要注意:
1)位不能声明为一个指针。如bit*bit_poiter;是错误的。
2)不能有bit数组如bitarr[5];是错误的。②可位寻址区说明使用sbit声明可独立访问可位寻址对象的位。sbit声明要求基址对象的存储器类型为“bdata”,否则只有绝对的位声明方法是合法的。位的位置(‘^’操作符号后的数字)的最大值依赖于指定的基类型,对于char/unsignedchar而言是0~7,对于int/unsignedint/short/unsignedshort而言是0~15,对于long/unsignedlong而言是0~31。例如:
intbdatabittest_at_0x20; //也可以省略“_at_0x20”
sbitbit0=bittest^0; //0x20单元的第0位
sbitbit15=bittest^15; //0x21单元的第7位可位寻址对象的位的声明只能放到main函数的外部作为全局变量使用,否则编译出错。13/30③特殊功能寄存器(SFR)STC8H8K64U单片机的特殊功能寄存器(SFR)寻址区,用来控制定时/计数器、串口、I/O及其他部件。为了支持SFR及其可寻址位的声明,引入了sfr、sbit等关键词,具体如下:
sfr:字节寻址。语法如下:
sfrsfr_name=int_constant;
“=”后为常数,并且这个常数就是特殊功能寄存器的对应地址。如:
sfrP0=0x80; //0x80为P0口的地址。
sfr16:字寻址,如:
sfr16DPTR=0x82;//指定DPTR的地址DPL=0x82,DPH=0x83
sbit:位寻址。用于声明可位寻址的特殊功能寄存器的位变量。声明方法如下:
sbitbitname=sfr_name^bit_number;
其中,sfr_name必须是已定义的SFR的名字,bit_number是位号(0~7)。如:
sbitCY=PSW^7;//定义CY为PSW的第7位附录F中提供了STC8H8K64U单片机的头文件stc8h.h的内容,编程时包含这个文件即可。14/30(2)内存区域的指定①程序存储器code关键字表示将变量保存到程序存储区。可以使用code定义表格常数,这样可以节省内部RAM的使用。例如,可以使用下面的代码保存共阴极数码LED的显示字模:
unsignedcharcode
led_buf[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};②内部RAM
内部数据存储器用以下关键字说明:
data:直接寻址区,内部RAM的低128字节,地址范围为00H~7FH。在用户程序中声明变量时,默认都保存在该区域。
idata:间接寻址区,包括整个内部RAM区256字节,地址范围为00H~0FFH。
bdata:可位寻址区,地址范围为20H~2FH。15/30③外部数据存储器
外部RAM视使用情况可由以下关键字标识:
xdata:可指定多达64KB的外部直接寻址区,地址范围0000H~0FFFFH。在用户程序中,需要声明较大的数组时,可以使用xdata关键字将变量数组保存到扩展RAM中。例如:
unsignedcharxdataarr[300][2];
pdata:能访问1页(256B)的外部RAM(很少用)。16/30(3)KeilC51指针KeilC51支持一般指针(GenericPointer)和存储器指针(MemorySpecificPointer)。一般指针的声明和使用均与标准C相同,同时还可以说明指针的存储类型。例如,下面的语句都声明pt为指向保存在外部RAM中unsignedchar数据的指针,但pt本身的保存位置却不同: unsignedcharxdata*pt;
//pt本身依存储模式存放 unsignedcharxdata*datapt;//pt被保存在内部RAM中 unsignedcharxdata*xdatapt;
//pt被保存在外部RAM中
基于存储器的指针,说明时即指定了存储类型,例如: chardata*str;
//str指向data区中char型数据 intxdata*pow; //pow指向外部RAM的int型整数
17/30(3)KeilC51指针
除了和标准C语言一样使用指针外,指针还可以用来访问外部并行扩展的器件。例如,为了方便地访问外部存储器及I/O端口,在C51中的absacc.h头文件做了如下定义,利用这些定义可以方便地访问外部I/O端口。 #defineCBYTE((unsignedcharvolatilecode*)0) #defineDBYTE((unsignedcharvolatiledata*)0) #definePBYTE((unsignedcharvolatilepdata*)0) #defineXBYTE((unsignedcharvolatilexdata*)0)其中,volatile影响编译器编译的结果,volatile告诉编译器变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错。这样,如果变量是一个寄存器变量或者表示一个端口,使用volatile可以保证对特殊地址的稳定访问,不会出错。在stc8h.h文件中,对于位于扩展RAM区域的特殊功能寄存器的声明就使用了这样的方法。例如P0口上拉电阻控制寄存器的声明如下: #defineP0PU(*(unsignedcharvolatilexdata*)0xfe10)18/30C51不仅仅支持ANSIC的标准函数,而且扩展了函数的声明,下面具体介绍。①中断函数声明中断函数通过使用interrupt关键字和中断号来声明。中断号告诉编译器中断服务程序的入口地址。例如,串行口1的中断函数可以声明如下: voidUART1_ISR(void)interrupt4 { /*中断服务程序的代码
*/ }上述代码声明了串行口1中断服务函数。其中,interrupt4说明是串行口1的中断。中断函数具体是哪个中断的函数,与中断号有关,而与函数名无关。为了便于使用,在stc8h.h文件中,将各个中断号进行了宏定义,如:voidUART1_ISR(void)interruptUART1_VECTOR完整的STC8H8K64U单片机的中断号及相关内容请参见第6章。19/30(4)C51对函数的扩展②指定工作寄存器区当需要指定函数中使用的工作寄存器区时,使用关键字using后跟一个0~3的数,对应着工作寄存器0~3区。例如,在下面的函数中使用了工作寄存器1区(相当于PSW.4=0,PSW.3=1): unsignedcharGetKey(void)using1 { /*用户程序代码*/ }③指定存储模式用户可以使用small、compact及large说明存储模式。例如: voiddisp_data(void)small { /*用户程序代码*/ } small说明的函数内部变量全部使用内部RAM。关键的、经常性的、耗时的地方可以这样声明,以提高运行速度。20/30STC8H8K64U单片机C51程序框架三21/30为了便于学习,下面给出一个通用的STC8H8K64U单片机的C51程序框架。读者可以在适当的地方根据设计任务需要填入代码,便可构成较完整的C语言程序。没有用到的中断函数可以不写到程序中。 #include“stc8h.h”//stc8h.h为单片机寄存器定义头文件,具体内容参见附录F voiddelay(longdelaytime);//声明子函数,子函数可以有返回值 voidmain(void) { //此处可存放应用系统的初始化代码
while(1)//主程序循环
{ //根据需要填入适当的内容
delay(100);//可以调用用户自定义的子函数
} }//---------各个子函数的声明----------- voiddelay(longdelaytime) { while(delaytime>0) delaytime--;//子函数的实现代码 }22/30//---------各个中断函数的实现----------voidINT0_ISR(void)interruptINT0_VECTOR
//外部中断0服务函数{//根据需要填入程序代码}voidINT1_ISR(void)interruptINT1_VECTOR
//外部中断1服务函数{//根据需要填入程序代码}voidINT2_ISR(void)interruptINT2_VECTOR //外部中断2服务函数{//根据需要填入程序代码}voidINT3_ISR(void)interruptINT3_VECTOR //外部中断3服务函数{//根据需要填入程序代码}voidINT4_ISR(void)interruptINT4_VECTOR //外部中断4服务函数{//根据需要填入程序代码}23/30voidT0_ISR(void)interruptT0_VECTOR //定时器0中断服务函数{//根据需要填入程序代码}voidT1_ISR(void)interruptT1_VECTOR //定时器1中断服务函数{//根据需要填入程序代码}voidT2_ISR(void)interruptT2_VECTOR //定时器2中断服务函数{//根据需要填入程序代码}voidT3_ISR(void)interruptT3_VECTOR //定时器3中断服务函数{//根据需要填入程序代码}voidT4_ISR(void)interruptT4_VECTOR //定时器4中断服务函数{//根据需要填入程序代码}24/30voidUART1_ISR(void)interruptUART1_VECTOR//串口1中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidUART2_ISR(void)interruptUART2_VECTOR//串口2中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidUART3_ISR(void)interruptUART3_VECTOR//串口3中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidUART4_ISR(void)interruptUART4_VECTOR//串口4中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidSPI_ISR(void)interruptSPI_VECTOR//SPI中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidI2C_ISR(void)interruptI2C_VECTOR//I2C中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidUSB_ISR(void)interruptUSB_VECTOR//USB中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}25/30voidADC_ISR(void)interruptADC_VECTOR//ADC模块中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidLVD_ISR(void)interruptLVD_VECTOR//低电压检测中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidCMP_ISR(void)interruptCMP_VECTOR//比较器模块中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidPCA_ISR(void)interruptPCA_VECTOR//PCA中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidPWMA_ISR(void)interruptPWMA_VECTOR//PWMA模块中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidPWMB_ISR(void)interruptPWMB_VECTOR//PWMB模块中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}26/30voidP0_ISR(void)interruptP0_VECTOR//P0中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidP1_ISR(void)interruptP1_VECTOR//P1中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidP2_ISR(void)interruptP2_VECTOR//P2中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidP3_ISR(void)interruptP3_VECTOR//P3中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidP4_ISR(void)interruptP4_VECTOR//P4中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidP5_ISR(void)interruptP5_VECTOR//P5中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidP6_ISR(void)interruptP6_VECTOR//P6中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidP7_ISR(void)interruptP7_VECTOR//P7中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}27/30voidDMA_M2M_ISR(void)interruptDMA_M2M_VECTOR//DMA_M2M中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidDMA_ADC_ISR(void)interruptDMA_ADC_VECTOR//DMA_ADC中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidDMA_SPI_ISR(void)interruptDMA_SPI_VECTOR//DMA_SPI中断服务函数{//根据需要填入程序代码,注意中断请求标志的清0}voidDMA_UR1T_ISR(void)interruptDMA_UR1T_VECTOR
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年护士职业资格(高级)临床护理技能备考试题及参考答案
- 2026年急诊病历书写规范试题及答案
- 2026年临床执业医师精神神经专项模拟试卷及答案
- 2026年煤矿培训考核模拟试题附参考答案详解(A卷)
- 2026年青海(公务员)行测考试真题试卷
- 2026年全国高压电工证考试练习题库(含答案)
- 2026年人教版高二数学下册第 2 单元测试卷 (含答案及解析)
- 一线调研第173期:中卫市精细化工产业发展现状、问题与建议
- 2026年校招:浙商银行真题及答案
- 2026年校招:中国广核真题及答案
- 初中音乐八年级下册《阳关三叠》教学设计
- 伦敦美甲行业调研分析报告
- 招标人主体责任履行指引
- 2025年自考《犯罪学13144》真题和答案
- 美发店分红权合同范本
- 药事法规和药学知识培训课件
- 《管理学基础(第3版)》高职全套教学课件
- 快速换型SMED教学课件
- 保安大门岗培训
- 石油化工安装工程概算指标说明(2019版)
- 雨季安全案例分享会
评论
0/150
提交评论