|
|
| 數(shù)據(jù)類型 | | | | | sbit | |
| | | signed char | | | | | unsigned char | | | | | signed short | | | | | unsigned short | | | | | signed int | | | | | unsigned int | | | | | signed long | | | | | unsigned long | | | | | float | | | 0.175494E-38~0.402823E+38 | | sfr | | | | | sfr16 | | | |
51基本數(shù)據(jù)類型
unsigned char data *p=0x00; 訪問內(nèi)部RAMunsigned char xdata *q=0x01; 訪問外部RAMunsigned char code *x=0x02; 訪問ROM
C51程序設(shè)計實例
例1:把存放在程序存儲區(qū)3800H-3805H單元中的6個常數(shù)讀到內(nèi)部RAM的20H開始的單元。
#include<reg51.h>
unsignedchar code *p=0x3800;
unsignedchar data *q=0x20;
voidmain (void)
{
unsigned char i;
for(i=0;i<6;i++)
{
*(q+i)=*(p+i);
}
}
例2:從20H單元開始存放32個帶符號數(shù),要求統(tǒng)計出大于0、小于0和等于0的個數(shù)并存放在單片機(jī)內(nèi)部RAM的60H,61H,62H單元中。
#include<reg51.h>
chardata *p=0x20;
unsignedchar data *q=0x60;
voidmain(void)
{
for(i=0;i<32;i++)
{
if(*(p+i)>0)
{
*q=*q+1;
}
else if (*(p+i)<0)
{
*(q+1)=*(q+1)+1;
}
else
{
*(q+2)=*(q+2)+1;
}
}
}
例3:將片外數(shù)據(jù)存儲器中7000H-70FFH單元全部清零。
#include<reg51.h>
unsignedchar xdata *p=0x7000;
voidmain (void)
{
unsigned char i;
for(i=0;i<256;i++)
{
*(p+i)=0;
}
}
例1:P1口接八個共陰極發(fā)光二極管,試編寫程序令發(fā)光二極管循環(huán)點亮。
#include<reg51.h>
voiddelay(unsigned int n) 延時n(ms)
{
unsigned int i,j;
for(i=0;i<n;i++)
for(j=0;j<120;j++);
}
voidmain (void)
{
unsigned char i;
for(i=0;i<8;i++)
{
P1=(1<<i); 左循環(huán),左移
delay(250); 延時250ms,代表n
}
}
例2:電路如下圖。8051的P1.0、P1.1、P1.2、P1.3分別接入四支發(fā)光二極管VD0、VD1、VD2、VD3,P3.0、P3.1、P3.2、P3.4分別接入四支開關(guān)S0、S1、S2、S3。
開關(guān)斷開,對應(yīng)的發(fā)光二極管亮。
開關(guān)閉合,對應(yīng)的發(fā)光二極管滅。
#include<reg51.h> (見課本)
voidmain (void)
{
while(1)
{
switch(P3&0x0f)
{
case 0x01: P1=P1|0x01;break;
case 0x02: P1=P1|0x02;break;
case 0x04: P1=P1|0x04;break;
case 0x08: P1=P1|0x08;break;
default:;
}
}
}
中斷
#include<reg51.h>
void init(void)//中斷初始化
{
IT0=1; //設(shè)為下降沿觸發(fā)
EX0=1; //開外部中斷0
EA=1;//開總中斷
}
void main(void)
{
init();
While(1);
}
void ex0() interrupt 0 //中斷子函數(shù)
{
P1=0xff;
IE1=0;
}
例:通過/INT0的下降沿實現(xiàn)數(shù)碼管增計數(shù),/INT1的下降沿實現(xiàn)數(shù)碼管減計數(shù)。計數(shù)范圍0-9
#include<reg51.h>
unsignedchar LED[10]={0x3f,0x06,....};
unsignedchar i;
voidmain(void)
{
IT0=1;IT1=1;
EX0=1;EX1=1;EA=1; (固定套路)
while(1);
}
voidex0() interrupt 0 允許中斷后執(zhí)行interrupt程序,當(dāng)為/INT0中斷時,對應(yīng)向量0,選擇該程序進(jìn)行;若為……
{
if(i<9)
{
P0=LED[++i];
}
else;
}
voidex1() interrupt 2
{
if(i>0)
{
P0=LED[--i];
}
else;
}
中斷與查詢相結(jié)合的方式進(jìn)行外部中斷
voidex0() interrupt 0
{
switch(P1&0x0f)
{
case 0x01: DV1();break;
case 0x02: DV2();break;
case 0x04: DV3();break;
case 0x08: DV4();break;
default:;
}
IE0=0; //低電平觸發(fā)中斷
}
定時器
方式0
例:應(yīng)用定時器T0產(chǎn)生1ms定時,并使P1.0輸出周期為2ms的方波,方式0。已知晶振震蕩頻率為6MHz。
TH0=(213-500)/25 (初值的計算與寫入)
TL0=(213-500)%25
#include<reg51.h>
sbitled=P1^0;(定義接口P1.0,使C51單片機(jī)識別接口為P1.0)
voidmain (void)
{
TMOD=0x00;
TH0=(213-500)/25;
TL0=(213-500)%25;
TR0=1;
while(1)
{
if(TF0==1)
{
led=~led;
TH0=(213-500)/25;
TL0=(213-500)%25; 四句話
TF0=0;
}
else;
}
}
方式1
例:用定時器T1產(chǎn)生25Hz方波,由P1.0輸出,采用查詢方式進(jìn)行控制,方式1。已知晶振震蕩頻率為12MHz。
#include<reg51.h>
sbitled=P1^0;
voidmain(void)
{
TMOD=0x10;
TH1=(216-20000)/28;
TL1=(216-20000)%28;
TR1=1;
while(1)
{
if(TF1==1)
{
led=~led;
TH1=(216-20000)/28;
TL1=(216-20000)%28;
TF1=0;
}
else;
}
}
例:利用定時器T0工作方式1,實現(xiàn)一個發(fā)光二極管以1s亮滅閃爍。12MHz晶振。
(使用中斷的方式,定時時間超過單片機(jī)所允許的時間)
#include<reg51.h>
sbitled=P1^0;
unsignedchar num;
voidmain(void)
{
TMOD=0x01;
TH0=(216-50000)/28;
TL0=(216-50000)%28; 六句話
ET0=1;EA=1;TR0=1;
while(1)
{
if(num==20)
{
led=~led;
num=0;
}
}
}
voidT0() interrupt 1
{
num++;
TH0=(216-50000)/28;
TL0=(216-50000)%28;
}
方式2
例:用定時器T1,工作方式2計數(shù),要求每計滿156次,將P1.7取反。
#include<reg51.h>
sbitled=P1^7;
voidmain(void)
{
TMOD=0x60;
TH1=28-156;
TL1=28-156;
TR1=1;
while(1)
{
if(TF1==1)
{
led=~led;
TF1=0;
}
}
}
(見課本,方式0、1、2的綜合)
方式3(只適用于T0)
例:應(yīng)用T0方式3,分別設(shè)定200μs和400μs定時并使P1.0和P1.1分別產(chǎn)生周期為400μs和800μs方波。晶振6MHz。采用中斷控制方式。
#include<reg51.h>
sbitled1=P1^0;
sbitled2=P1^1;
voidmain(void)
{
TMOD=0x03;
TH0=28-100; //200μs
TL0=28-200; // 400μs
ET0=1;ET1=1;EA=1;
TR0=1;TR1=1;
while(1);
}
voidtime0() interrupt 1
{
TL0=28-200;
led2=~led2;
TF0=0;
}
void time1() interrupt 3
{
TH0=28-100;
led1=~led1;
TF1=0;
}
串行口
例1:請編寫在數(shù)碼管上循環(huán)顯示0-9這10個數(shù)字的程序。串行通信方式0,定時器間隔1s。
#include<reg51.h>
unsignedchar led[10]={0x03,….};
unsignedchar num,I;
voidmain(void)
{
TMOD=0x01;
TH0=(216-50000)/28;
TL0=(216-50000)%28;
TR0=1;
ET0=1;
EA=1;
SCON=0x00;
while(1)
{
if(num==20)
{
num=0;
SBUF=led[i++];
if(i==10)
{
i=0;
}
}
}
}
voidT0() interrupt 1
{
num++;
TH0=(216-50000)/28;
TL0=(216-50000)%28;
TF0=0;
}
例2:根據(jù)電路圖,編寫從16位擴(kuò)展口讀入10個字節(jié)數(shù)據(jù),并把它們轉(zhuǎn)存到內(nèi)部RAM的20H~29H中。S/L=0并行置入16位數(shù)據(jù);S/L=1允許串行移位輸出
#include<reg51.h>
unsignedchar data *p=0x20;
unsignedchar i,j;
void main(void)
{
SCON=0x10; //方式0
for(i=0;i<5;i++)
{
P1&=0xfe; //P1.0置0
P1|=0x01; //P1.0置1
for(j=0;j<2;j++)
{
while(!RI); //等待數(shù)據(jù)接收完成
*p++=SBUF; //將數(shù)據(jù)緩存區(qū)中接收到的數(shù)據(jù)給了20H
RI=0; //響應(yīng)中斷后該標(biāo)志位必須及時清零,為下一次做準(zhǔn)備
}
}
}
第一個for循環(huán)是為了分5次接收字節(jié),每次接收16位數(shù),也就是2個字節(jié);第二個for循環(huán)是將一次接收的2個字節(jié)轉(zhuǎn)存RAM
先讓P1.0=0,是為了置入16位數(shù);置入后讓P1.0=1,是為了允許串行移位輸出
C51拓展
存儲器拓展
例,下圖采用的是譯碼法還是片(線)選法?74LS139、74LS373起到什么作用?2#芯片的尋址范圍是什么?執(zhí)行unsigned char xdata *r22= 0x4000;語句后,r22變量中的值將存儲于哪一個芯片中?
下圖采用的是譯碼法。
74LS139作用是地址譯碼。
2000H~3FFFH。
存儲于3#芯片中。
38譯碼器,數(shù)電中的知識點,eg. CBA—001—Y1口,從而對應(yīng)2#芯片
010—Y2口,從而對應(yīng)3#芯片
P2.7P2.6 P2.5
只有這三種選法,因為外部RAM使能必須保證/CE為低電平
外部
I/O拓展
例題:利用74LS244作為輸入口接8路開關(guān),讀取開關(guān)狀態(tài),并將讀取狀態(tài)通過74LS273驅(qū)動發(fā)光二極管顯示出來。
#include <reg51.h>
unsignedchar xdata *p=0xbfff;(分析)
unsignedchar xdata *q=0x7fff;
unsignedchar buffer;
voidmain(void)
{
buffer=*p;
*q=buffer;
}
輸入緩沖,輸出鎖存
常用作輸入拓展的芯片:74LS244、74LS373
注:74LS244是8位三態(tài)門,當(dāng)/1G、/2G均為低電平時,允許輸入數(shù)據(jù);否則,為高阻態(tài)。
74LS373的/E=0時才允許輸入
常用作輸出拓展的芯片:74LS377、74LS273
注:74LS377的E=0時才可將數(shù)據(jù)打入鎖存器
74LS273的CLK=0時才可將數(shù)據(jù)打入鎖存器
(具體講解想見課本)
A/D拓展
1111 1110 1111 1***
P2.0 P0.2 P0.1 P0.0
例題:設(shè)有一個8路模擬量輸入的巡回檢測系統(tǒng),采樣數(shù)據(jù)依次存放在外部RAM 2000H-2007H單元中,要求采用中斷方式。
#include <reg51.h>
unsignedchar xdata *p=0xfef8; //一定要寫正確,對通道的選擇
unsignedchar xdata *q=0x2000;
unsignedchar num=1;
voidmain(void)
{
IT0=0;
EX0=1;
EA=1;
*p=0x00; //寫什么都行,需要送出地址
while(1);
}
voidad() interrupt 0
{
*q=*p;
p++;
q++;
num++;
if(num==8)
{
EX0=0;
EA=0;
}
*p=0x00; //寫什么都行,需要送出地址
IE0=0;
}
|
-
-
單片機(jī)程序例題.docx
2020-4-5 11:34 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
2.32 MB, 下載次數(shù): 8, 下載積分: 黑幣 -5
|