Cx51流程控制共有3種基本結構:順序結構、選擇結構以及循環結構。
一、順序結構
順序結構是最基本、最簡單的編程結構,程序按先后順序執行指令代碼。
下圖是8051單片機的P0口和P1口上分別連接了8個LED,請分別用P0和P1口顯示加法125+34和減法176-98的運算結果
#include
int main(void)
{
unsigned char a=125,b=34,c=176,d=98;
P1=a+b; //加法運算結果送P1端口,P1=159=1001 1111B
P0=c-d; //減法運算結果送P0端口,P0=78=0100 1110B
while(1); //循環等待,防止主程序退出后單片機跑飛
}
二、選擇結構
2.選擇結構
(1)if語句
if語句用于根據條件判定結果決定執行的語句。if語句有三種基本形式:
if(表達式)
{語句組}
說明:如果“表達式”為真,則執行花括號中的語句組,否則跳過花括號執行下面的語句。
if(表達式)
{語句組1}
else
{語句組2}
說明:如果“表達式”真,則執行語句組1,否則執行語句組2。
if(表達式1)
{語句1}
else if(表達式2)
{語句組2 }
else if(表達式3)
{語句組3}
else if(表達式m)
{語句組m}
else
{語句組n}
說明:如果“表達式1”為真,則執行“語句組1”,否則如果“表達式2”為真,則執行“語句組2”…,如果所有的表達式都不滿足,則執行語句組n。
同圖4-2,用if語句根據54/18的計算結果選擇P0口8位LED的狀態。
#include //包含單片機寄存器的頭文件
int main(void)
{
unsigned char a=54,b=18;
if (a/b==1)P0=0xfe; //第一個LED亮
else if (a/b==2) P0=0xfd; //第二個LED亮
else if (a/b==3) P0=0xfb; //第三個LED亮
else if (a/b==4) P0=0xf7; //第四個LED亮
else if (a/b==5) P0=0xef; //第五個LED亮
else if (a/b==6) P0=0xdf; //第八個LED亮
else if (a/b==7) P0=0xbf; //第七個LED亮
else if (a/b==8) P0=0x7f; //第八個LED亮
else P0=0xff; //缺省值,關閉所有LED
while(1);
}
(2)switch/case語句
根據表達式的值決定要執行的語句組,用于實現多中選一,形式如下:
switch(表達式)
{
case常量表達式1://如果1滿足,則執行語句組1
語句組1;
break; //跳出switch結構
case常量表達式2://如果2滿足,則執行語句組2
語句組2;
break; //跳出switch結構
…
default: //條件都不滿足時,執行語句組n
語句組n;
}
同圖4-2,用swtich語句根據54/18的計算結果選擇P0口8位LED的狀態
#include //包含單片機寄存器的頭文件
int main(void)
{
unsigned char a=56,b=18;
switch(a/b) //使用多分支選擇語句
{
case 1: P0=0xfe; break; //第一個LED亮
case 2: P0=0xfd; break; //第二個LED亮
case 3: P0=0xfb; break; //第三個LED亮
case 4: P0=0xf7; break; //第四個LED亮
case 5: P0=0xef; break; //第五個LED亮
case 6:P0=0xdf; break; //第六個LED亮
case 7:P0=0xbf; break; //第七個LED亮
case 8:P0=0x7f; break; //第八個LED亮
default: P0=0xff; //缺省值,關閉所有LED
}
while(1);
}
1、for循環
for 循環結構用于按指定的次數循環執行一組語句,格式如下:
for(表達式1;表達式2;表達式3)
{語句;}
for循環語句執行過程如下:
(1)先執行表達式1,一般是對循環變量賦初值;
(2)執行表達式2,若表達式2結果為真,則執行循環體語句,并求解表達式
3(一般是改變循環變量的值);然后再次執行表達式2;并判斷結果真假
(3)若表達式2結果為假,則退出for循環。
三、循環結構
while循環
while循環語句先判斷條件真假,若表達式為真,則執行花括號內的語句組,否則終止循環,格式如下:
while(表達式)
{語句組}
同圖4-3,用while循環計算7的階乘并送P1和P0口顯示結果。
#include //包含單片機寄存器的頭文件
int main(void)
{
unsigned char i=1;
unsigned int s=1;
while(i<=7)
{
s=s*i;//計算階乘
i++; //i自增運算
}
P1=s/256; //高8位送P1顯示
P0=s%256; //低8位送P0顯示
while(1);
}
do while 循環
先執行花括號內的語句組,然后執行表達式,若結果為真,則重復執行花括號內的語句組,否則終止循環,格式如下:
do
{語句組}
while(表達式);
根據下圖用do while循環計算7的階乘并送P1和P0口顯示結果。
#include //包含單片機寄存器的頭文件
int main(void)
{
unsigned char i=1;
unsigned int s=1;
do
{
s=s*i;//計算階乘
i++; //i自增運算
} while(i<=7);
P1=s/256; //高8位送P1顯示
P0=s%256; //低8位送P0顯示
while(1);
}
四、數組
1.一維數組
(1)一維數組的定義方式為:
數據類型 數組名 [常量表達式];
例如定義有3個元素字符型數組m:
charm[3];
m的3個元素分別是m[0], m[1], m[2]。數組的類型指數組元素的取值類型。對于同一個數組,其所有元素的數據類型都是相同的。
(2)一維數組的初始化
數組初始化是指在數組定義時給數組元素賦予初值。
例如:
int m[3]={ 0,1,2};
相當于a[0]=0,a[1]=1,a[2]=2。
當{ }中值的個數少于元素個數時,只給前面部分元素賦值,其他元素自動賦0值。
例如:
int m[3]={0,1}
(3)一維數組元素的引用
數組必須預先定義才能使用。數組只能逐個地使用各元素,而不能一次引用整個數組。例如,輸出有10個元素的數組必須使用循環語句逐個輸出各下標變量:
for(i=0;i<3; i++)
printf("%d",m[i]);
而不能用一個語句輸出整個數組。因此,下面的寫法是錯誤的:
printf("%d",m);
用一維數組實現流水點亮P0口的8位LED
int main(void) //主函數
{
unsigned char i;
unsigned char code Tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //定義無符號字符型數組
while(1)
{
for(i=0;i<8;i++)
{
P0=Tab[i];//依次引用數組元素,并將其送P0口顯示
delay();//調用延時函數
}
}
}
2.二維數組
二維數組是以行列矩陣的形式存儲數據。
** (1)二維數組定義**
數據類型 數組名[下標1][下標2];
第一個下標代表行,第二個下標代表列。例如語句 int a[2][3] 定義了二維整形數組,共有2行3列6個元素。
(2)二維數組的初始化
可以采用以下兩種方式初始化:
按先行后列的存儲順序整體賦值,例如:
int a[2][3]={0,1,2,3,4,5}
按每行分別賦值,例如:
int a[2][3]={{0,1,2},{3,4,5}};
用二維數組實現流水點亮P0口的8位LED。
int main(void)
{
unsigned char i,j;
unsigned char codeTab[2][4]={{0xfe,0xfd,0xfb,0xf7},{0xef,0xdf,0xbf,0x7f}}; //定義無符 //號字符型數組
while(1)
{
for(i=0;i<2;i++)
for(j=0;j<4;j++)
{
P0=Tab[i][j];//依次引用數組元素,并將其送P0口顯示
delay();//調用延時函數
}
}
}
變量的指針就是變量的地址。在C語言中,允許用一個變量來存放指針,這種變量稱為指針變量。
指針變量是一種特殊的變量,它也和一般變量一樣,具有變量名、類型和值,但它的值就是變量所存放的地址。
通過指針對變量進行操作是間接操作,比直接操作變量更費時間,且不夠直觀,但可以通過靈活運用指針使程序代碼更為簡潔、有效。
四、指針
1、指針變量的定義
指針變量同普通變量一樣,使用之前要進行定義。指針變量定義的一般形式為:
數據類型 *變量名;
其中,數據類型表示本指針變量所指向變量的數據類型,*表示這是一個指針變量。
例如:定義:int*point,表示point指向一個整型變量,但point具體指向哪一個整型變量,取決于point中所存儲的地址。一個指針變量只能指向同類型的變量,如上述point 只能指向整形變量,不能指向一個字符變量。
2、指針變量的引用
指針變量在使用之前必須賦予具體的地址,使用未經賦值的指針變量會引起嚴重后果。指針變量的引用有兩個重要運算符:
&:取地址運算符;
*:指針運算符(或稱“間接訪問” 運算符)。
在指針變量定義中所出現的“ ”是類型說明符,表示其后的變量是指針類型,而指針運算符“ ”則出現在表達式中,用以表示指針指向的變量值。
地址運算符&用來取出變量的地址。其形式為:
&變量名;
?指針運算符*用來取出指針指向變量的值,其形式為:
*指針變量名;
inti,j;
int *point;
point= &i;
j=*point;
表示取出變量i的值賦予變量j,與語句j=i的效果相同。對*point的任何操作與直接對變量i的操作效果相同。
3、數組指針
一個變量有一個地址,一個數組包含若干元素,每個數組元素都在內存中占用存儲單元,它們都有相應的地址。數組的指針是指數組的起始地址,數組元素的指針是數組元素的地址。
一個數組是由連續的一塊內存單元組成的。數組名就是這塊連續內存單元的首地址。一個數組也是由各個數組元素(下標變量)組成的。每個數組元素按其類型不同占有幾個連續的內存單元。一個數組元素的首地址也是指它所占有的幾個內存單元的首地址。
定義一個指向數組元素的指針變量,與定義普通變量的指針相同。例如:
intm[]={1,2,3};4int*p;4p=&m[0];
經上述定義后,p就是數組m的指針。因為數組名代表數組的首地址,也就是第一個元素的地址,因此下面兩個語句等價:
p=&m[0];
p=m;
p指向數組m的首地址后,p+i就是數組的元素m[i]。
例題:用一維數組實現流水點亮P0口的8位LED。
int main(void)
{
unsigned char i;
unsigned char code Tab[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; /*定義無符號字符型數組*/
unsigned char *p;
p=&Tab[0];/*定義指針變量并指向Tab數組,也可寫為unsigned char *p=Tab */
while(1)
{
for(i=0;i<8;i++)
{
P0=*(p+i);//通過指針變量依次引用數組元素,并將其送P0口顯示
delay();//調用延時函數
}
}
}
指向二維數組的指針變量的說明形式為
類型說明符 (*指針變量名)[長度];
“長度”是二維數組的列數。二維數組的每一行都代表一個一維數組,該一維數組的長度就是二維數組的列數。若該指針變量指向二組數組A[m][n]的首地址,則 (指針變量名+i)就是A[i],而A[i]是一維數組A[i][n]的首地址, (*(指針變量名+i)+j)就是A[i][j]的值。
例題:用二維數組實現流水點亮P0口的8位LED。
int main(void)
{
unsigned char i,j;
unsigned char codeTab[2][4]={{0xfe,0xfd,0xfb,0xf7},{0xef,0xdf,0xbf,0x7f}}; //定
//義無符號字符型數組
unsigned char (*p)[4]; //定義二維數組指針
p=Tab;//指向二維數組首地址
while(1)
{
for(i=0;i<2;i++)
for(j=0;j<4;j++)
{
P0=*(*(p+i)+j);//依次引用數組元素,并將其送P0口顯示
delay();//調用延時函數
}
}
}
-
Cx51
+關注
關注
0文章
4瀏覽量
7623 -
循環結構
+關注
關注
0文章
22瀏覽量
7716 -
順序結構
+關注
關注
0文章
8瀏覽量
6557
發布評論請先 登錄
相關推薦
評論