📄 第三章 keil c51 vs 标准c.htm
字号:
lang=EN-US>(1) 用#pragma
disable说明函数和用“usign”指定的函数,不能返回bit值。</SPAN></P>
<P class=MsoBodyTextIndent style="MARGIN-LEFT: 36.75pt"><SPAN
lang=EN-US>(2) 一个bit变量不能声明为指针,如bit *ptr;是错误的</SPAN></P>
<P class=MsoBodyTextIndent style="MARGIN-LEFT: 36.75pt"><SPAN
lang=EN-US>(3) 不能有bit数组如:bit arr[5];错误。</SPAN></P>
<H3 style="MARGIN-LEFT: 0cm; TEXT-INDENT: 0cm"><A
name=_Toc475103169><SPAN lang=EN-US style="FONT-SIZE: 15pt">2.
</SPAN>可位寻址区说明<SPAN lang=EN-US>20H-2FH</SPAN></A><SPAN
style="mso-bookmark: _Toc475103169"></SPAN><SPAN lang=EN-US
style="FONT-SIZE: 12pt"><O:P></O:P></SPAN></H3>
<P class=MsoBodyTextFirstIndent>可作如下定义:</P>
<P class=MsoBodyTextIndent style="MARGIN-LEFT: 36.75pt"><SPAN
lang=EN-US>int bdata i;</SPAN></P>
<P class=MsoBodyTextIndent style="MARGIN-LEFT: 36.75pt"><SPAN
lang=EN-US>char bdata arr[3],</SPAN></P>
<P class=MsoBodyTextFirstIndent>然后:</P>
<P class=MsoBodyTextIndent style="MARGIN-LEFT: 36.75pt"><SPAN
lang=EN-US>sbit<SPAN style="mso-spacerun: yes">
</SPAN>bito=in0;sbit bit15=I^15;</SPAN></P>
<P class=MsoBodyTextIndent style="MARGIN-LEFT: 36.75pt"><SPAN
lang=EN-US>sbit arr07=arr[0]^7;sbit arr15=arr[i]^7;</SPAN></P>
<H2 style="MARGIN-LEFT: 0cm; TEXT-INDENT: 0cm"><A
name=_Toc475103170><SPAN lang=EN-US
style="FONT-SIZE: 16pt">第七节 </SPAN><SPAN lang=EN-US>Keil
C51指针</SPAN></A></H2>
<P class=MsoBodyTextFirstIndent><SPAN
lang=EN-US>C51支持一般指针(Generic Pointer)和存储器指针(Memory_Specific
Pointer).</SPAN></P>
<H3 style="MARGIN-LEFT: 0cm; TEXT-INDENT: 0cm"><A
name=_Toc475103171><SPAN lang=EN-US style="FONT-SIZE: 15pt">1.
</SPAN>一般指针</A><SPAN
style="mso-bookmark: _Toc475103171"></SPAN><SPAN lang=EN-US
style="FONT-SIZE: 12pt"><O:P></O:P></SPAN></H3>
<P class=MsoBodyTextFirstIndent>一般指针的声明和使用均与标准<SPAN
lang=EN-US>C相同,不过同时还可以说明指针的存储类型,例如:</SPAN></P>
<P class=MsoBodyTextIndent style="MARGIN-LEFT: 36.75pt"><SPAN
lang=EN-US>long *
state;为一个指向long型整数的指针,而state本身则依存储模式存放。</SPAN></P>
<P class=MsoBodyTextIndent style="MARGIN-LEFT: 36.75pt"><SPAN
lang=EN-US>char * xdata
ptr;ptr为一个指向char数据的指针,而ptr本身放于外部RAM区,以上的long,char等指针指向的数据可存放于任何存储器中。</SPAN></P>
<P class=MsoBodyTextIndent
style="MARGIN-LEFT: 36.75pt">一般指针本身用<SPAN
lang=EN-US>3个字节存放,分别为存储器类型,高位偏移,低位偏移量。</SPAN></P>
<H3 style="MARGIN-LEFT: 0cm; TEXT-INDENT: 0cm"><A
name=_Toc475103172><SPAN lang=EN-US style="FONT-SIZE: 15pt">2.
</SPAN>存储器指针</A><SPAN
style="mso-bookmark: _Toc475103172"></SPAN><SPAN lang=EN-US
style="FONT-SIZE: 12pt"><O:P></O:P></SPAN></H3>
<P class=MsoBodyTextFirstIndent>基于存储器的指针说明时即指定了存贮类型,例如:</P>
<P class=MsoBodyTextIndent style="MARGIN-LEFT: 36.75pt"><SPAN
lang=EN-US>char data * str;str指向data区中char型数据</SPAN></P>
<P class=MsoBodyTextIndent style="MARGIN-LEFT: 36.75pt"><SPAN
lang=EN-US>int xdata * pow; pow指向外部RAM的int型整数。</SPAN></P>
<P class=MsoBodyTextFirstIndent>这种指针存放时,只需一个字节或<SPAN
lang=EN-US>2个字节就够了,因为只需存放偏移量。</SPAN></P>
<H3 style="MARGIN-LEFT: 0cm; TEXT-INDENT: 0cm"><A
name=_Toc475103173><SPAN lang=EN-US style="FONT-SIZE: 15pt">3.
</SPAN>指针转换</A><SPAN
style="mso-bookmark: _Toc475103173"></SPAN><SPAN lang=EN-US
style="FONT-SIZE: 12pt"><O:P></O:P></SPAN></H3>
<P class=MsoBodyTextFirstIndent>即指针在上两种类型之间转化:</P>
<P class=MsoBodyTextIndent
style="MARGIN-LEFT: 57.75pt; TEXT-INDENT: -21pt; tab-stops: 45.0pt list 57.75pt left 63.0pt 117.0pt 180.0pt 243.0pt 297.0pt 378.0pt; mso-list: l30 level1 lfo165"><SPAN
lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN
style="FONT: 7pt 'Times New Roman'">
</SPAN></SPAN>当基于存储器的指针作为一个实参传递给需要一般指针的函数时,指针自动转化。</P>
<P class=MsoBodyTextIndent
style="MARGIN-LEFT: 57.75pt; TEXT-INDENT: -21pt; tab-stops: 45.0pt list 57.75pt left 63.0pt 117.0pt 180.0pt 243.0pt 297.0pt 378.0pt; mso-list: l30 level1 lfo165"><SPAN
lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN
style="FONT: 7pt 'Times New Roman'">
</SPAN></SPAN>如果不说明外部函数原形,基于存储器的指针自动转化为一般指针,导致错误,因而请用“#<SPAN
lang=EN-US>include”说明所有函数原形。</SPAN></P>
<P class=MsoBodyTextIndent
style="MARGIN-LEFT: 57.75pt; TEXT-INDENT: -21pt; tab-stops: 45.0pt list 57.75pt left 63.0pt 117.0pt 180.0pt 243.0pt 297.0pt 378.0pt; mso-list: l30 level1 lfo165"><SPAN
lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN
style="FONT: 7pt 'Times New Roman'">
</SPAN></SPAN>可以强行改变指针类型。</P>
<H2 style="MARGIN-LEFT: 0cm; TEXT-INDENT: 0cm"><A
name=_Toc475103174><SPAN lang=EN-US
style="FONT-SIZE: 16pt">第八节 </SPAN><SPAN lang=EN-US>Keil
C51函数</SPAN></A></H2>
<P class=MsoBodyTextFirstIndent><SPAN lang=EN-US>C51函数声明对ANSI
C作了扩展,具体包括:</SPAN></P>
<H3 style="MARGIN-LEFT: 0cm; TEXT-INDENT: 0cm"><A
name=_Toc475103175><SPAN lang=EN-US style="FONT-SIZE: 15pt">1.
</SPAN>中断函数声明:</A><SPAN
style="mso-bookmark: _Toc475103175"></SPAN><SPAN lang=EN-US
style="FONT-SIZE: 12pt"><O:P></O:P></SPAN></H3>
<P class=MsoBodyTextFirstIndent>中断声明方法如下:</P>
<P class=MsoBodyTextFirstIndent
style="TEXT-INDENT: 21.25pt"><SPAN lang=EN-US
style="mso-hansi-font-family: 宋体">void serial_ISR () interrupt
4 [using 1]<O:P></O:P></SPAN></P>
<P class=MsoBodyTextFirstIndent
style="TEXT-INDENT: 21.25pt"><SPAN lang=EN-US
style="mso-hansi-font-family: 宋体">{<O:P></O:P></SPAN></P>
<P class=MsoBodyTextFirstIndent
style="MARGIN-LEFT: 21.25pt; TEXT-INDENT: 21.25pt"><SPAN
lang=EN-US style="mso-hansi-font-family: 宋体">/* ISR
*/<O:P></O:P></SPAN></P>
<P class=MsoBodyTextFirstIndent
style="TEXT-INDENT: 21.25pt"><SPAN lang=EN-US
style="mso-hansi-font-family: 宋体">}<O:P></O:P></SPAN></P>
<P class=MsoBodyTextFirstIndent>为提高代码的容错能力,在没用到的中断入口处生成<SPAN
lang=EN-US>iret语句,定义没用到的中断。</SPAN></P>
<P class=MsoBodyTextFirstIndent style="TEXT-INDENT: 0cm"><SPAN
lang=EN-US style="mso-hansi-font-family: 宋体">/* define not
used interrupt, so generate "IRET" in their entrance
*/<O:P></O:P></SPAN></P>
<P class=MsoBodyTextFirstIndent><SPAN lang=EN-US
style="mso-hansi-font-family: 宋体">void extern0_ISR() interrupt
0{}<SPAN style="mso-spacerun: yes">
</SPAN>/* not used */<O:P></O:P></SPAN></P>
<P class=MsoBodyTextFirstIndent><SPAN lang=EN-US
style="mso-hansi-font-family: 宋体">void timer0_ISR () interrupt
1{}<SPAN style="mso-spacerun: yes">
</SPAN>/* not used */<O:P></O:P></SPAN></P>
<P class=MsoBodyTextFirstIndent><SPAN lang=EN-US
style="mso-hansi-font-family: 宋体">void extern1_ISR() interrupt
2{}<SPAN style="mso-spacerun: yes">
</SPAN>/* not used */<O:P></O:P></SPAN></P>
<P class=MsoBodyTextFirstIndent><SPAN lang=EN-US
style="mso-hansi-font-family: 宋体">void timer1_ISR () interrupt
3{}<SPAN style="mso-spacerun: yes">
</SPAN>/* not used */<O:P></O:P></SPAN></P>
<P class=MsoBodyTextFirstIndent><SPAN lang=EN-US
style="mso-hansi-font-family: 宋体">void serial_ISR () interrupt
4{}<SPAN style="mso-spacerun: yes">
</SPAN>/* not used */<O:P></O:P></SPAN></P>
<H3 style="MARGIN-LEFT: 0cm; TEXT-INDENT: 0cm"><A
name=_Toc475103176><SPAN lang=EN-US style="FONT-SIZE: 15pt">2.
</SPAN>通用存储工作区</A></H3>
<H3 style="MARGIN-LEFT: 0cm; TEXT-INDENT: 0cm"><A
name=_Toc475103177><SPAN lang=EN-US style="FONT-SIZE: 15pt">3.
</SPAN>选通用存储工作区由<SPAN lang=EN-US>using
x声明,见上例。</SPAN></A></H3>
<H3 style="MARGIN-LEFT: 0cm; TEXT-INDENT: 0cm"><A
name=_Toc475103178><SPAN lang=EN-US style="FONT-SIZE: 15pt">4.
</SPAN>指定存储模式</A><SPAN
style="mso-bookmark: _Toc475103178"></SPAN><SPAN lang=EN-US
style="FONT-SIZE: 12pt"><O:P></O:P></SPAN></H3>
<P class=MsoBodyTextFirstIndent>由<SPAN lang=EN-US>small
compact 及large说明,例如:</SPAN></P>
<P class=MsoBodyTextIndent style="MARGIN-LEFT: 36.75pt"><SPAN
lang=EN-US>void fun1(void) small {<SPAN
style="mso-spacerun: yes"> </SPAN>}</SPAN></P>
<P class=MsoBodyTextFirstIndent>提示:<SPAN
lang=EN-US>small说明的函数内部变量全部使用内部RAM。关键的经常性的耗时的地方可以这样声明,以提高运行速度。</SPAN></P>
<H3 style="MARGIN-LEFT: 0cm; TEXT-INDENT: 0cm"><A
name=_Toc475103179><SPAN lang=EN-US style="FONT-SIZE: 15pt">5.
</SPAN><SPAN lang=EN-US>#pragma disable</SPAN></A></H3>
<P
class=MsoBodyTextFirstIndent>在函数前声明,只对一个函数有效。该函数调用过程中将不可被中断。</P>
<H3 style="MARGIN-LEFT: 0cm; TEXT-INDENT: 0cm"><A
name=_Toc475103180><SPAN lang=EN-US style="FONT-SIZE: 15pt">6.
</SPAN>递归或可重入函数指定</A></H3>
<P class=MsoBodyTextFirstIndent>在主程序和中断中都可调用的函数,容易产生问题。因为<SPAN
lang=EN-US>51和PC不同,PC使用堆栈传递参数,且静态变量以外的内部变量都在堆栈中;而51一般使用寄存器传递参数,内部变量一般在RAM中,函数重入时会破坏上次调用的数据。可以用以下两种方法解决函数重入:</SPAN></P>
<P class=MsoBodyTextIndent style="MARGIN-LEFT: 36.75pt"><SPAN
lang=EN-US>a、在相应的函数前使用前述“#pragma
disable”声明,即只允许主程序或中断之一调用该函数;</SPAN></P>
<P class=MsoBodyTextIndent style="MARGIN-LEFT: 36.75pt"><SPAN
lang=EN-US>b、将该函数说明为可重入的。如下:</SPAN></P>
<P class=MsoBodyTextIndent style="MARGIN-LEFT: 36.75pt"><SPAN
lang=EN-US>void func(param...) reentrant;</SPAN></P>
<P class=MsoBodyTextFirstIndent><SPAN
lang=EN-US>KeilC51编译后将生成一个可重入变量堆栈,然后就可以模拟通过堆栈传递变量的方法。</SPAN></P>
<P
class=MsoBodyTextFirstIndent>由于一般可重入函数由主程序和中断调用,所以通常中断使用与主程序不同的<SPAN
lang=EN-US>R寄存器组。</SPAN></P>
<P class=MsoBodyTextFirstIndent>另外,对可重入函数,在相应的函数前面加上开关“<SPAN
lang=EN-US>#pragma
noaregs”,以禁止编译器使用绝对寄存器寻址,可生成不依赖于寄存器组的代码。</SPAN></P>
<H3 style="MARGIN-LEFT: 0cm; TEXT-INDENT: 0cm"><A
name=_Toc475103181><SPAN lang=EN-US style="FONT-SIZE: 15pt">7.
</SPAN>指定<SPAN lang=EN-US>PL/M-51函数</SPAN></A></H3>
<P class=MsoBodyTextFirstIndent>由<SPAN
lang=EN-US>alien指定。</SPAN></P></TD></TR>
<TR>
<TD width="100%"><!-- 广告位 -->
<TABLE cellSpacing=0 cellPadding=0 width="99%" align=center
background="" border=0>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -