|
數據類型 | | | | 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基本數據類型
unsigned char data *p=0x00; 訪問內部RAMunsigned char xdata *q=0x01; 訪問外部RAMunsigned char code *x=0x02; 訪問ROM
C51程序設計實例
例1:把存放在程序存儲區3800H-3805H單元中的6個常數讀到內部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個帶符號數,要求統計出大于0、小于0和等于0的個數并存放在單片機內部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:將片外數據存儲器中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口接八個共陰極發光二極管,試編寫程序令發光二極管循環點亮。
#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); 左循環,左移
delay(250); 延時250ms,代表n
}
}
例2:電路如下圖。8051的P1.0、P1.1、P1.2、P1.3分別接入四支發光二極管VD0、VD1、VD2、VD3,P3.0、P3.1、P3.2、P3.4分別接入四支開關S0、S1、S2、S3。
開關斷開,對應的發光二極管亮。
開關閉合,對應的發光二極管滅。
#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; //設為下降沿觸發
EX0=1; //開外部中斷0
EA=1;//開總中斷
}
void main(void)
{
init();
While(1);
}
void ex0() interrupt 0 //中斷子函數
{
P1=0xff;
IE1=0;
}
例:通過/INT0的下降沿實現數碼管增計數,/INT1的下降沿實現數碼管減計數。計數范圍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 允許中斷后執行interrupt程序,當為/INT0中斷時,對應向量0,選擇該程序進行;若為……
{
if(i<9)
{
P0=LED[++i];
}
else;
}
voidex1() interrupt 2
{
if(i>0)
{
P0=LED[--i];
}
else;
}
中斷與查詢相結合的方式進行外部中斷
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; //低電平觸發中斷
}
定時器
方式0
例:應用定時器T0產生1ms定時,并使P1.0輸出周期為2ms的方波,方式0。已知晶振震蕩頻率為6MHz。
TH0=(213-500)/25 (初值的計算與寫入)
TL0=(213-500)%25
#include<reg51.h>
sbitled=P1^0;(定義接口P1.0,使C51單片機識別接口為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產生25Hz方波,由P1.0輸出,采用查詢方式進行控制,方式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,實現一個發光二極管以1s亮滅閃爍。12MHz晶振。
(使用中斷的方式,定時時間超過單片機所允許的時間)
#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計數,要求每計滿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)
例:應用T0方式3,分別設定200μs和400μs定時并使P1.0和P1.1分別產生周期為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:請編寫在數碼管上循環顯示0-9這10個數字的程序。串行通信方式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:根據電路圖,編寫從16位擴展口讀入10個字節數據,并把它們轉存到內部RAM的20H~29H中。S/L=0并行置入16位數據;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); //等待數據接收完成
*p++=SBUF; //將數據緩存區中接收到的數據給了20H
RI=0; //響應中斷后該標志位必須及時清零,為下一次做準備
}
}
}
第一個for循環是為了分5次接收字節,每次接收16位數,也就是2個字節;第二個for循環是將一次接收的2個字節轉存RAM
先讓P1.0=0,是為了置入16位數;置入后讓P1.0=1,是為了允許串行移位輸出
C51拓展
存儲器拓展
例,下圖采用的是譯碼法還是片(線)選法?74LS139、74LS373起到什么作用?2#芯片的尋址范圍是什么?執行unsigned char xdata *r22= 0x4000;語句后,r22變量中的值將存儲于哪一個芯片中?
下圖采用的是譯碼法。
74LS139作用是地址譯碼。
2000H~3FFFH。
存儲于3#芯片中。
38譯碼器,數電中的知識點,eg. CBA—001—Y1口,從而對應2#芯片
010—Y2口,從而對應3#芯片
P2.7P2.6 P2.5
只有這三種選法,因為外部RAM使能必須保證/CE為低電平
外部
I/O拓展
例題:利用74LS244作為輸入口接8路開關,讀取開關狀態,并將讀取狀態通過74LS273驅動發光二極管顯示出來。
#include <reg51.h>
unsignedchar xdata *p=0xbfff;(分析)
unsignedchar xdata *q=0x7fff;
unsignedchar buffer;
voidmain(void)
{
buffer=*p;
*q=buffer;
}
輸入緩沖,輸出鎖存
常用作輸入拓展的芯片:74LS244、74LS373
注:74LS244是8位三態門,當/1G、/2G均為低電平時,允許輸入數據;否則,為高阻態。
74LS373的/E=0時才允許輸入
常用作輸出拓展的芯片:74LS377、74LS273
注:74LS377的E=0時才可將數據打入鎖存器
74LS273的CLK=0時才可將數據打入鎖存器
(具體講解想見課本)
A/D拓展
1111 1110 1111 1***
P2.0 P0.2 P0.1 P0.0
例題:設有一個8路模擬量輸入的巡回檢測系統,采樣數據依次存放在外部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;
}
|
-
-
單片機程序例題.docx
2020-4-5 11:34 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
2.32 MB, 下載次數: 8, 下載積分: 黑幣 -5
|