聲明:本文來自網絡,在此分享僅供學習參考
本書簡介
本書基于Keil μVision程序設計平臺和Proteus硬件仿真平臺,精心編寫了100余個8051單片機C語言程
序設計案例。
全書基礎設計類案例貫穿8051單片機最基本的端口編程、定時/計數器應用、中斷和串口通信;硬
件應用類案例涵蓋常用外部存儲器擴展、接口擴展、譯碼、編碼、驅動、光機、機電、A/D與
D/A轉換等內容;綜合設計類案例涉及大量消費類電子產品、儀器儀表及智能控制設備的相關技術
。
本書可作為大專院校學生學習實踐單片機c語言程序設計的教材或參考書,也可作為電子工程技術
人員或單片機技術愛好者的參考資料。
目錄
第1章 8051單片機C語言程序設計概述
1.1 8051單片機引腳
1.2 數據與程序內存
1.3 特殊功能寄存器
1.4 外部中斷、定時/計數器及串口應用
1.5 有符號與無符號數應用、數位分解、位操作
1.6 變量、存儲類型與存儲模式
1.7 數組、字符串與指針
1.8 流程控制
1.9 可重入函數和中斷函數
1.10 C語言在單片機系統開發中的優勢
第2章 Proteus操作基礎
2.1 Proteus操作界面簡介
2.2 仿真電路原理圖設計
2.3 元件選擇
2.4 調試仿真
2.5 Proteus與V3的聯合調試
第3章 基礎程序設計
3.1 閃爍的LED
3.2 從左到右的流水燈
3.3 左右來回循環的流水燈
3.4 花樣流水燈
3.5 LED模擬交通燈
3.6 單只數碼管循環顯示0~9
3.7 8只數碼管滾動顯示單個數字
3.8 8只數碼管顯示多個不同字符
3.9 數碼管閃爍顯示
3.10 8只數碼管滾動顯示數字串
3.11 K1~K4控制LED移位
3.12 K1~K4按鍵狀態顯示
3.13 K1~K4分組控制LED
3.14 K1~K4控制數碼管移位顯示
3.15 K1~K4控制數碼管加減演示
3.16 4×4鍵盤矩陣控制條形LED顯示
3.17 數碼管顯示4×4鍵盤矩陣按鍵
3.18 開關控制LED
3.19 繼電器控制照明設備
3.20 數碼管顯示撥碼開關編碼
3.21 開關控制報警器
3.22 按鍵發音
3.23 播放音樂
3.24 INT0中斷計數
3.25 INT0中斷控制LED
3.26 INT0及INT1中斷計數
3.27 TIMER0控制單只LED閃爍
3.28 TIMER0控制流水燈
3.29 TIMER0控制4只LED滾動閃爍
3.30 T0控制LED實現二進制計數
3.31 TIMER0與TIMER1控制條形LED
3.32 10s的秒表
3.33 用計數器中斷實現100以內的按鍵計數
3.34 10 000s以內的計時程序
3.35 定時器控制數碼管動態顯示
3.36 8×8 LED點陣屏顯示數字
3.37 按鍵控制8×8 LED點陣屏顯示圖形
3.38 用定時器設計的門鈴
3.39 演奏音階
3.40 按鍵控制定時器選播多段音樂
3.41 定時器控制交通指示燈
3.42 報警器與旋轉燈
3.43 串行數據轉換為并行數據
3.44 并行數據轉換為串行數據
3.45 甲機通過串口控制乙機LED閃爍
3.46 單片機之間雙向通信
3.47 單片機向主機發送字符串
3.48 單片機與PC串口通信仿真
第4章 硬件應用
4.1 74LS138譯碼器應用
4.2 74HC154譯碼器應用
4.3 74HC595串入并出芯片應用
4.4 用74LS148擴展中斷
4.5 I2C-24C04與蜂鳴器
4.6 I2C-24C04與數碼管
4.7 用6264擴展內存
4.8 用8255實現接口擴展
……
第5章 綜合設計
參考文獻
下載后 點擊此處查看更多內容
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
1
上海師范大學信息與機電工程學院—倪繼鋒
《單片機C語言程序設計實訓100 例—基于8051+Proteus 仿真》案例
第 01 篇 基礎程序設計
01 閃爍的LED
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit LED=P1^0;
// 延時
void DelayMS(uint x)
{
uchar i;
while(x--)
{
for(i=0;i<120;i++);
}
}
// 主程序
void main()
{
while(1)
{
LED=~LED;
DelayMS(150);
}
}
02 從左到右的流水燈
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
2
上海師范大學信息與機電工程學院—倪繼鋒
// 延時
void DelayMS(uint x)
{
uchar i;
while(x--)
{
for(i=0;i<120;i++);
}
}
// 主程序
void main()
{
P0=0xfe;
while(1)
{
P0=_crol_(P0,1); //P0的值向左循環移動
DelayMS(150);
}
}
03 8 只LED左右來回點亮
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
// 延時
void DelayMS(uint x)
{
uchar i;
while(x--)
{
for(i=0;i<120;i++);
}
}
// 主程序
void main()
{
uchar i;
P2=0x01;
while(1)
{
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
3
上海師范大學信息與機電工程學院—倪繼鋒
for(i=0;i<7;i++)
{
P2=_crol_(P2,1);//P2的值向左循環移動
DelayMS(150);
}
for(i=0;i<7;i++)
{
P2=_cror_(P2,1);//P2的值向右循環移動
DelayMS(150);
}
}
}
04 花樣流水燈
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
uchar code Pattern_P0[]=
{
0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xe7,0xdb,0xbd,0x7e,0xbd,0xdb,0xe7,0xff,0xe7,0xc3,0x81,0x00,0x81,0xc3,0xe7,0xff,
0xaa,0x55,0x18,0xff,0xf0,0x0f,0x00,0xff,0xf8,0xf1,0xe3,0xc7,0x8f,0x1f,0x3f,0x7f,
0x7f,0x3f,0x1f,0x8f,0xc7,0xe3,0xf1,0xf8,0xff,0x00,0x00,0xff,0xff,0x0f,0xf0,0xff,
0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe,
0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,
0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff
};
uchar code Pattern_P2[]=
{
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f,0xff,
0xe7,0xdb,0xbd,0x7e,0xbd,0xdb,0xe7,0xff,0xe7,0xc3,0x81,0x00,0x81,0xc3,0xe7,0xff,
0xaa,0x55,0x18,0xff,0xf0,0x0f,0x00,0xff,0xf8,0xf1,0xe3,0xc7,0x8f,0x1f,0x3f,0x7f,
0x7f,0x3f,0x1f,0x8f,0xc7,0xe3,0xf1,0xf8,0xff,0x00,0x00,0xff,0xff,0x0f,0xf0,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,
0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00,
0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
4
上海師范大學信息與機電工程學院—倪繼鋒
0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff
};
// 延時
void DelayMS(uint x)
{
uchar i;
while(x--)
{
for(i=0;i<120;i++);
}
}
// 主程序
void main()
{
uchar i;
while(1)
{ //從數組中讀取數據送至 P0和P2口顯示
for(i=0;i<136;i++)
{
P0=Pattern_P0[i];
P2=Pattern_P2[i];
DelayMS(100);
}
}
}
05 LED模擬交通燈
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbitRED_A=P0^0; //東西向燈
sbit YELLOW_A=P0^1;
sbit GREEN_A=P0^2;
sbitRED_B=P0^3; //南北向燈
sbit YELLOW_B=P0^4;
sbit GREEN_B=P0^5;
uchar Flash_Count=0,Operation_Type=1; // 閃爍次數,操作類型變量
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
5
上海師范大學信息與機電工程學院—倪繼鋒
// 延時
void DelayMS(uint x)
{
uchar i;
while(x--)for(i=0;i<120;i++);
}
// 交通燈切換
void Traffic_Light()
{
switch(Operation_Type)
{
case 1: //東西向綠燈與南北向紅燈亮
RED_A=1;YELLOW_A=1;GREEN_A=0;
RED_B=0;YELLOW_B=1;GREEN_B=1;
DelayMS(2000);
Operation_Type=2;
break;
case 2: //東西向黃燈閃爍,綠燈關閉
DelayMS(300);
YELLOW_A=~YELLOW_A;GREEN_A=1;
if(++Flash_Count!=10) return; //閃爍5 次
Flash_Count=0;
Operation_Type=3;
break;
case 3: //東西向紅燈,南北向綠燈亮
RED_A=0;YELLOW_A=1;GREEN_A=1;
RED_B=1;YELLOW_B=1;GREEN_B=0;
DelayMS(2000);
Operation_Type=4;
break;
case 4: //南北向黃燈閃爍 5 次
DelayMS(300);
YELLOW_B=~YELLOW_B;GREEN_B=1;
if(++Flash_Count!=10) return;
Flash_Count=0;
Operation_Type=1;
}
}
// 主程序
void main()
{
while(1) Traffic_Light();
}
06 單只數碼管循環顯示0~9
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
6
上海師范大學信息與機電工程學院—倪繼鋒
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar codeDSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
// 延時
void DelayMS(uint x)
{
uchar t;
while(x--)for(t=0;t<120;t++);
}
// 主程序
void main()
{
uchar i=0;
P0=0x00;
while(1)
{
P0=~DSY_CODE[i];
i=(i+1);
DelayMS(300);
}
}
07 8 只數碼管滾動顯示單個數字
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar codeDSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
// 延時
void DelayMS(uint x)
{
uchar t;
while(x--)for(t=0;t<120;t++);
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
7
上海師范大學信息與機電工程學院—倪繼鋒
}
// 主程序
void main()
{
uchar i,wei=0x80;
while(1)
{
for(i=0;i<8;i++)
{
P2=0xff; //關閉顯示
wei=_crol_(wei,1);
P0=DSY_CODE[i]; //發送數字段碼
P2=wei; //發送位碼
DelayMS(300);
}
}
}
08 8 只數碼管動態顯示多個不同字符
電路如上圖
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar codeDSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
// 延時
void DelayMS(uint x)
{
uchar t;
while(x--)for(t=0;t<120;t++);
}
// 主程序
void main()
{
uchar i,wei=0x80;
while(1)
{
for(i=0;i<8;i++)
{
P0=0xff;
P0=DSY_CODE[i]; //發送段碼
wei=_crol_(wei,1);
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
8
上海師范大學信息與機電工程學院—倪繼鋒
P2=wei; //發送位碼
DelayMS(2);
}
}
}
09 8 只數碼管閃爍顯示數字串
電路如上圖
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
// 段碼表
uchar codeDSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
// 位碼表
uchar codeDSY_IDX[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
// 延時
void DelayMS(uint x)
{
uchar t;
while(x--)for(t=0;t<120;t++);
}
// 主程序
void main()
{
uchar i,j;
while(1)
{
for(i=0;i<30;i++)
{
for(j=0;j<8;j++)
{
P0=0xff;
P0=DSY_CODE[j]; //發送段碼
P2=DSY_IDX[j]; //發送位碼
DelayMS(2);
}
}
P2=0x00; //關閉所有數碼管并延時
DelayMS(1000);
}
}
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
9
上海師范大學信息與機電工程學院—倪繼鋒
10 8 只數碼管滾動顯示數字串
電路如上圖
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
// 段碼表
uchar codeDSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
// 下面數組看作環形隊列,顯示從某個數開始的 8 個數(10 表示黑屏)
uchar Num[]={10,10,10,10,10,10,10,10,2,9,8};
// 延時
void DelayMS(uint x)
{
uchar t;
while(x--)for(t=0;t<120;t++);
}
// 主程序
void main()
{
uchar i,j,k=0,m=0x80;
while(1)
{ //刷新若干次,保持一段時間的穩定顯示
for(i=0;i<15;i++)
{
for(j=0;j<8;j++)
{ //發送段碼,采用環形取法,從第 k 個開始取第j個
P0=0xff;
P0=DSY_CODE[Num[(k+j)]];
m=_crol_(m,1);
P2=m; //發送位碼
DelayMS(2);
}
}
k=(k+1); //環形隊列首支針 k 遞增,Num下標范圍0~10,故對 11取余
}
}
11 K1-K4 控制LED移位
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
// 延時
void DelayMS(uint x)
{
uchar i;
while(x--)
for(i=0;i<120;i++);
}
// 根據P1 口的按鍵移動
LED
void Move_LED()
{
if ((P1&0x10)==0) P0=_cror_(P0,1); //K1
else if((P1&0x20)==0)P0=_crol_(P0,1); //K2
else if((P1&0x40)==0)P2=_cror_(P2,1); //K3
else if((P1&0x80)==0)P2=_crol_(P2,1); //K4
}
// 主程序
void main()
{
uchar Recent_Key; //最近按鍵
P0=0xfe;
P2=0xfe;
P1=0xff;
Recent_Key=0xff;
while(1)
{
if(Recent_Key!=P1)
{
Recent_Key=P1; //保存最近按鍵
Move_LED();
DelayMS(10);
}
}
}
12 K1-K4 按鍵狀態顯示
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
11
上海師范大學信息與機電工程學院—倪繼鋒
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit LED1=P0^0;
sbit LED2=P0^1;
sbit LED3=P0^2;
sbit LED4=P0^3;
sbit K1=P1^0;
sbit K2=P1^1;
sbit K3=P1^2;
sbit K4=P1^3;
// 延時
void DelayMS(uint x)
{
uchar i;
while(x--)for(i=0;i<120;i++);
}
// 主程序
void main()
{
P0=0xff;
P1=0xff;
while(1)
{
LED1=K1;
LED2=K2;
if(K3==0)
{
while(K3==0);
LED3=~LED3;
}
if(K4==0)
{
while(K4==0);
LED4=~LED4;
}
DelayMS(10);
}
}
13 K1-K4 分組控制LED
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
12
上海師范大學信息與機電工程學院—倪繼鋒
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
// 延時
void DelayMS(uint x)
{
uchar i;
while(x--)for(i=0;i<120;i++);
}
// 主程序
void main()
{
uchar k,t,Key_State;
P0=0xff;
P1=0xff;
while(1)
{
t=P1;
if(t!=0xff)
{
DelayMS(10);
if(t!=P1) continue;
//取得4 位按鍵值,由模式 XXXX1111(X中有一位為0 ,其他均為 1)
//變為模式0000XXXX(X中有一位為1,其他均為0)
Key_State=~t>>4;
k=0;
//檢查1 所在位置,累加獲取按鍵號 k
while(Key_State!=0)
{
k++;
Key_State>>=1;
}
//根據按鍵號k 進行4 種處理
switch(k)
{
case 1:if(P0==0x00) P0=0xff;
P0<<=1;
DelayMS(200);
break;
case 2:P0=0xf0;break;
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
13
上海師范大學信息與機電工程學院—倪繼鋒
case 3:P0=0x0f;break;
case 4:P0=0xff;
}
}
}
}
14 K1-K4 控制數碼管移位顯示
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
// 段碼
uchar codeDSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
// 位碼
uchar codeDSY_Index[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
// 待顯示到各數碼管的數字緩沖(開始僅在 0 位顯示 0 ,其他黑屏)
uchar Display_Buffer[]={0,10,10,10,10,10,10,10};
// 延時
void DelayMS(uint x)
{
uchar i;
while(x--)for(i=0;i<120;i++);
}
void Show_Count_ON_DSY()
{
uchar i;
for(i=0;i<8;i++)
{
P0=0xff;
P0=DSY_CODE[Display_Buffer[i]];
P2=DSY_Index[i];
DelayMS(2);
}
}
// 主程序
void main()
{
uchar i,Key_NO,Key_Counts=0;
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
14
上海師范大學信息與機電工程學院—倪繼鋒
P0=0xff;
P1=0xff;
P2=0x00;
while(1)
{
Show_Count_ON_DSY();
P1=0xff;
Key_NO=P1;
//P1口按鍵狀態分別為 K1-0xfe,K2-0xfd,K3-0xfb
switch(Key_NO)
{
case 0xfe: Key_Counts++;
if(Key_Counts>8) Key_Counts=8;
Display_Buffer[Key_Counts-1]=Key_Counts;
break;
case 0xfd:if(Key_Counts>0)Display_Buffer[--Key_Counts]=10;
break;
case 0xfb:Display_Buffer[0]=0;
for(i=1;i<8;i++) Display_Buffer[i]=10;
Key_Counts=0;
}
//若鍵未釋放則僅刷新顯示,不進行鍵掃描
while(P1!=0xff) Show_Count_ON_DSY();
}
}
15 K1-K4 控制數碼管加減演示
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
// 段碼
uchar codeDSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
// 待顯示的3 位緩沖
uchar Num_Buffer[]={0,0,0};
// 按鍵代碼,按鍵計數
uchar Key_Code,Key_Counts=0;
// 延時
void DelayMS(uint x)
{
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
15
上海師范大學信息與機電工程學院—倪繼鋒
uchar i;
while(x--)for(i=0;i<120;i++);
}
// 顯示函數
void Show_Counts_ON_DSY()
{
uchar i,j=0x01;
Num_Buffer[2]=Key_Counts/100;
Num_Buffer[1]=Key_Counts/10;
Num_Buffer[0]=Key_Counts;
for(i=0;i<3;i++)
{
j=_cror_(j,1);
P0=0xff;
P0=DSY_CODE[Num_Buffer[i]];
P2=j;
DelayMS(1);
}
}
// 主程序
void main()
{
uchar i;
P0=0xff;
P1=0xff;
P2=0x00;
Key_Code=0xff;
while(1)
{
Show_Counts_ON_DSY();
P1=0xff;
Key_Code=P1;
//有鍵按下時,數碼管刷新顯示 30 次,該行代碼同時起到延時作用
if(Key_Code!=0xff)
for(i=0;i<30;i++)Show_Counts_ON_DSY();
switch(Key_Code)
{
case 0xfe:if(Key_Counts<255) Key_Counts++;
break;
case 0xfd:if(Key_Counts>0) Key_Counts--;
break;
case 0xfb: Key_Counts=0;
}
Key_Code=0xff;
}
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
16
上海師范大學信息與機電工程學院—倪繼鋒
}
16 4X4 矩陣鍵盤控制條
形LED顯示
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
// 矩陣鍵盤按鍵特征碼表
uchar code KeyCodeTable[]={0x11,0x12,0x14,0x18,0x21,
0x22,0x24,0x28,0x41,0x42,0x44,0x48,0x81,0x82,0x84,0x88};
// 延時
void DelayMS(uint x)
{
uchar i;
while(x--)for(i=0;i<120;i++);
}
// 鍵盤掃描
uchar Keys_Scan()
{
uchar sCode,kCode,i,k;
//低4 位置0,放入4 行
P1=0xf0;
//若高4 位出現 0 ,則有鍵按下
if((P1&0xf0)!=0xf0)
{
DelayMS(2);
if((P1&0xf0)!=0xf0)
{
sCode=0xfe; //行掃描碼初值
for(k=0;k<4;k++) //對4 行分別進行掃描
{
P1=sCode;
if((P1&0xf0)!=0xf0)
{
kCode=~P1;
for(i=0;i<16;i++) //查表得到按鍵序號并返回
if(kCode==KeyCodeTable[i])
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
17
上海師范大學信息與機電工程學院—倪繼鋒
return(i);
}
else
sCode=_crol_(sCode,1);
}
}
}
return(-1);
}
// 主程序
void main()
{
uchar i,P2_LED,P3_LED;
uchar KeyNo=-1; //按鍵序號,-1表示無按鍵
while(1)
{
KeyNo=Keys_Scan(); //掃描鍵盤獲取按鍵序號 KeyNo
if(KeyNo!=-1)
{
P2_LED=0xff;
P3_LED=0xff;
for(i=0;i<=KeyNo;i++) //鍵值越大,點亮的 LED 越多
{
if(i<8)
P3_LED>>=1;
else
P2_LED>>=1;
}
P3=P3_LED; //點亮條形LED
P2=P2_LED;
}
}
}
17 數碼管顯示4X4 矩陣鍵盤按
鍵號
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
18
上海師范大學信息與機電工程學院—倪繼鋒
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
// 段碼
uchar codeDSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x83,0xc6,0xa1,0x86,0x8e,0x00};
sbit BEEP=P3^7;
// 上次按鍵和當前按鍵的序號,該矩陣中序號范圍 0~15,16表示無按鍵
uchar Pre_KeyNo=16,KeyNo=16;
// 延時
void DelayMS(uint x)
{
uchar i;
while(x--)for(i=0;i<120;i++);
}
// 矩陣鍵盤掃描
void Keys_Scan()
{
uchar Tmp;
P1=0x0f; //高4 位置0,放入4 行
DelayMS(1);
Tmp=P1^0x0f;//按鍵后0f 變成0000XXXX ,X 中一個為0 ,3 個仍為 1,通過異或把 3 個1 變為0 ,唯
一的0 變為1
switch(Tmp) //判斷按鍵發生于 0~3 列的哪一列
{
case 1: KeyNo=0;break;
case 2: KeyNo=1;break;
case 4: KeyNo=2;break;
case 8: KeyNo=3;break;
default:KeyNo=16; //無鍵按下
}
P1=0xf0; //低4 位置0 ,放入 4 列
DelayMS(1);
Tmp=P1>>4^0x0f;//按鍵后f0 變成XXXX0000 ,X 中有1 個為 0 ,三個仍為 1 ;高 4 位轉移到低 4 位并
異或得到改變的值
switch(Tmp) //對0~3 行分別附加起始值 0 ,4 ,8 ,12
{
case 1: KeyNo+=0;break;
case 2: KeyNo+=4;break;
case 4: KeyNo+=8;break;
case 8: KeyNo+=12;
}
}
// 蜂鳴器
void Beep()
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
19
上海師范大學信息與機電工程學院—倪繼鋒
{
uchar i;
for(i=0;i<100;i++)
{
DelayMS(1);
BEEP=~BEEP;
}
BEEP=0;
}
// 主程序
void main()
{
P0=0x00;
BEEP=0;
while(1)
{
P1=0xf0;
if(P1!=0xf0) Keys_Scan(); //獲取鍵序號
if(Pre_KeyNo!=KeyNo)
{
P0=~DSY_CODE[KeyNo];
Beep();
Pre_KeyNo=KeyNo;
}
DelayMS(100);
}
}
18 開關控制LED
#include<reg51.h>
sbit S1=P1^0;
sbit S2=P1^1;
sbit LED1=P0^0;
sbit LED2=P0^1;
// 主程序
void main()
{
while(1)
{
LED1=S1;
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
20
上海師范大學信息與機電工程學院—倪繼鋒
LED2=S2;
}
}
19 繼電器控制照明設備
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit K1=P1^0;
sbit RELAY=P2^4;
// 延時
void DelayMS(uint ms)
{
uchar t;
while(ms--)for(t=0;t<120;t++);
}
// 主程序
void main()
{
P1=0xff;
RELAY=1;
while(1)
{
if(K1==0)
{
while(K1==0);
RELAY=~RELAY;
DelayMS(20);
}
}
}
20 數碼管顯示撥碼開關編碼
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
21
上海師范大學信息與機電工程學院—倪繼鋒
#define uint unsigned int
// 各數字的數碼管段碼(共陰)
uchar codeDSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
// 顯示緩沖
uchar DSY_Buffer[3]={0,0,0};
// 延時
void DelayMS(uint ms)
{
uchar t;
while(ms--)for(t=0;t<120;t++);
}
// 主程序
void main()
{
uchar i,m,Num;
P0=0xff;
P2=0xff;
while(1)
{
m=0xfe;
Num=P1; //讀取撥碼開關的值
DSY_Buffer[0]=Num/100;
DSY_Buffer[1]=Num/10;
DSY_Buffer[2]=Num;
for(i=0;i<3;i++)//刷新顯示在數碼管上
{
m=_crol_(m,1);
P2=m;
P0=DSY_CODE[DSY_Buffer[i]];
DelayMS(10);
}
}
}
21 開關控制報警器
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit SPK=P1^0;
sbit K1=P1^7;
// 發聲函數
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
22
上海師范大學信息與機電工程學院—倪繼鋒
void Alarm(uchar t)
{
uchar i,j;
for(i=0;i<200;i++)
{
SPK=~SPK;
for(j=0;j<t;j++); //由參數t行成不同的頻率
}
}
void main()
{
SPK=0;
while(1)
{
if(K1==1)
{
Alarm(90);
Alarm(120);
}
}
}
22 按鍵發音
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit BEEP=P3^7;
sbit K1=P1^4;
sbit K2=P1^5;
sbit K3=P1^6;
sbit K4=P1^7;
// 延時
void DelayMS(uint x)
{
uchar t;
while(x--)for(t=0;t<120;t++);
}
// 按周期t 發音
void Play(uchar t)
{
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
23
上海師范大學信息與機電工程學院—倪繼鋒
uchar i;
for(i=0;i<100;i++)
{
BEEP=~BEEP;
DelayMS(t);
}
BEEP=0;
}
void main()
{
P1=0xff;
BEEP=0;
while(1)
{
if(K1==0) Play(1);
if(K2==0) Play(2);
if(K3==0) Play(3);
if(K4==0) Play(4);
}
}
23 播放音樂
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit BEEP=P3^7;
// 生日快樂歌的音符頻率表,不同頻率由不同的延時來決定
uchar codeSONG_TONE[]={212,212,190,212,159,169,212,212,190,212,142,159,
212,212,106,126,159,169,190,119,119,126,159,142,159,0};
// 生日快樂歌節拍表,節拍決定每個音符的演奏長短
uchar code SONG_LONG[]={9,3,12,12,12,24,9,3,12,12,12,24,
9,3,12,12,12,12,12,9,3,12,12,12,24,0};
// 延時
void DelayMS(uint x)
{
uchar t;
while(x--)for(t=0;t<120;t++);
}
// 播放函數
void PlayMusic()
{
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
24
上海師范大學信息與機電工程學院—倪繼鋒
uint i=0,j,k;
while(SONG_LONG[i]!=0||SONG_TONE[i]!=0)
{ //播放各個音符,SONG_LONG 為拍子長度
for(j=0;j<SONG_LONG[i]*20;j++)
{
BEEP=~BEEP;
//SONG_TONE延時表決定了每個音符的頻率
for(k=0;k<SONG_TONE[i]/3;k++);
}
DelayMS(10);
i++;
}
}
void main()
{
BEEP=0;
while(1)
{
PlayMusic(); //播放生日快樂
DelayMS(500); //播放完后暫停一段時間
}
}
24 INT0 中斷計數
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
//0~9 的段碼
uchar codeDSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};
// 計數值分解后各個待顯示的數位
uchar DSY_Buffer[]={0,0,0};
uchar Count=0;
sbit Clear_Key=P3^6;
// 數碼管上顯示計數值
void Show_Count_ON_DSY()
{
DSY_Buffer[2]=Count/100; //獲取3 個數
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
25
上海師范大學信息與機電工程學院—倪繼鋒
DSY_Buffer[1]=Count0/10;
DSY_Buffer[0]=Count;
if(DSY_Buffer[2]==0) //高位為0時不顯示
{
DSY_Buffer[2]=0x0a;
if(DSY_Buffer[1]==0) //高位為0,若第二位為 0 同樣不顯示
DSY_Buffer[1]=0x0a;
}
P0=DSY_CODE[DSY_Buffer[0]];
P1=DSY_CODE[DSY_Buffer[1]];
P2=DSY_CODE[DSY_Buffer[2]];
}
// 主程序
void main()
{
P0=0x00;
P1=0x00;
P2=0x00;
IE=0x81; //允許INT0 中斷
IT0=1; //下降沿觸發
while(1)
{
if(Clear_Key==0) Count=0; //清0
Show_Count_ON_DSY();
}
}
//INT0 中斷函數
void EX_INT0() interrupt 0
{
Count++; //計數值遞增
}
25 外部INT0中斷控制LED
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit LED=P0^0;
// 主程序
void main()
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
26
上海師范大學信息與機電工程學院—倪繼鋒
{
LED=1;
EA=1;
EX0=1;
IT0=1;
while(1);
}
//INT0 中斷函數
void EX_INT0() interrupt 0
{
LED=~LED; //控制LED 亮滅
}
26 INT0 及INT1 中斷計數
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit K3=P3^4; //2個清零鍵
sbit K4=P3^5;
// 數碼管段碼與位碼
uchar codeDSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
uchar code DSY_Scan_Bits[]={0x20,0x10,0x08,0x04,0x02,0x01};
//2 組計數的顯示緩沖,前 3 位一組,后 3 位一組
uchar data Buffer_Counts[]={0,0,0,0,0,0};
uint Count_A,Count_B=0;
// 延時
void DelayMS(uint x)
{
uchar t;
while(x--)for(t=0;t<120;t++);
}
// 數據顯示
void Show_Counts()
{
uchar i;
Buffer_Counts[2]=Count_A/100;
Buffer_Counts[1]=Count_A0/10;
Buffer_Counts[0]=Count_A;
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
27
上海師范大學信息與機電工程學院—倪繼鋒
if( Buffer_Counts[2]==0)
{
Buffer_Counts[2]=0x0a;
if( Buffer_Counts[1]==0)
Buffer_Counts[1]=0x0a;
}
Buffer_Counts[5]=Count_B/100;
Buffer_Counts[4]=Count_B0/10;
Buffer_Counts[3]=Count_B;
if( Buffer_Counts[5]==0)
{
Buffer_Counts[5]=0x0a;
if( Buffer_Counts[4]==0)
Buffer_Counts[4]=0x0a;
}
for(i=0;i<6;i++)
{
P2=DSY_Scan_Bits[i];
P1=DSY_CODE[Buffer_Counts[i]];
DelayMS(1);
}
}
// 主程序
void main()
{
IE=0x85;
PX0=1; //中斷優先
IT0=1;
IT1=1;
while(1)
{
if(K3==0) Count_A=0;
if(K4==0) Count_B=0;
Show_Counts();
}
}
//INT0 中斷函數
void EX_INT0() interrupt 0
{
Count_A++;
}
//INT1 中斷函數
void EX_INT1() interrupt 2
{
Count_B++;
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
28
上海師范大學信息與機電工程學院—倪繼鋒
}
27 定時器控制單只LED
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit LED=P0^0;
uchar T_Count=0;
// 主程序
void main()
{
TMOD=0x00; //定時器0 工作方式 0
TH0=(8192-5000)/32; //5ms定時
TL0=(8192-5000)2;
IE=0x82; //允許T0中斷
TR0=1;
while(1);
}
//T0 中斷函數
void LED_Flash() interrupt 1
{
TH0=(8192-5000)/32; //恢復初值
TL0=(8192-5000)2;
if(++T_Count==100) //0.5s開關一次 LED
{
LED=~LED;
T_Count=0;
}
}
28 TIMER0 控制流水燈
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
29
上海師范大學信息與機電工程學院—倪繼鋒
// 主程序
void main()
{
uchar T_Count=0;
P0=0xfe;
P2=0xfe;
TMOD=0x01; //定時器0 工作方式 1
TH0=(65536-40000)/256; //40ms定時
TL0=(65536-40000)%6;
TR0=1; //啟動定時器
while(1)
{
if(TF0==1)
{
TF0=0;
TH0=(65536-40000)/256;//恢復初值
TL0=(65536-40000)%6;
if(++T_Count==5)
{
P0=_crol_(P0,1);
P2=_crol_(P2,1);
T_Count=0;
}
}
}
}
29 定時器控制4 個LED滾動閃爍
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit B1=P0^0;
sbit G1=P0^1;
sbit R1=P0^2;
sbit Y1=P0^3;
uint i,j,k;
// 主程序
void main()
{
i=j=k=0;
P0=0xff;
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
30
上海師范大學信息與機電工程學院—倪繼鋒
TMOD=0x02; //定時器0 工作方式 2
TH0=256-200; //200us定時
TL0=256-200;
IE=0x82;
TR0=1; //啟動定時器
while(1);
}
//T0 中斷函數
void LED_Flash_and_Scroll() interrupt 1
{
if(++k<35) return; //定時中斷若干次后執行閃爍
k=0;
switch(i)
{
case 0: B1=~B1;break;
case 1: G1=~G1;break;
case 2: R1=~R1;break;
case 3: Y1=~Y1;break;
default:i=0;
}
if(++j<300)return; // 每次閃爍持續一段時間
j=0;
P0=0xff; //關閉顯示
i++; //切換到下一個 LED
}
30 T0控制LED實現二進制計數
#include<reg51.h>
// 主程序
void main()
{
TMOD=0x05; //定時器0 為計數器,工作方式 1 ,最大計數值 65535
TH0=0; //初值為0
TL0=0;
TR0=1; //啟動定時器
while(1)
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
31
上海師范大學信息與機電工程學院—倪繼鋒
{
P1=TH0;
P2=TL0;
}
}
31 TIMER0 與TIMER1 控制條形LED
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar tc0=0,tc1=0;
// 主程序
void main()
{
P0=0xfe;
P2=0xfe;
TMOD=0x11; //定時器0 、定時器
1 均工作于方式 1
TH0=(65536-15000)/256; //定時器0:15ms
TL0=(65536-15000)%6;
TH1=(65536-50000)/256; //定時器1:50ms
TL1=(65536-50000)%6;
IE=0x8a;
TR0=1; //啟動定時器
TR1=1;
while(1);
}
//T0 中斷函數
void Time0() interrupt 1
{
TH0=(65536-15000)/256; //恢復定時器0初值
TL0=(65536-15000)%6;
if(++tc0==10) //150ms轉換狀態
{
tc0=0;
P0=_crol_(P0,1);
}
}
//T1 中斷函數
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
32
上海師范大學信息與機電工程學院—倪繼鋒
void Time1() interrupt 3
{
TH0=(65536-50000)/256; //恢復定時器1初值
TL0=(65536-50000)%6;
if(++tc1==10) //500ms轉換狀態
{
tc1=0;
P2=_crol_(P2,1);
}
}
32 10s 的秒表
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit K1=P3^7;
uchar
i,Second_Counts,Key_Flag_Idx;
bit Key_State;
uchar
DSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
// 延時
void DelayMS(uint ms)
{
uchar t;
while(ms--)for(t=0;t<120;t++);
}
// 處理按鍵事件
void Key_Event_Handle()
{
if(Key_State==0)
{
Key_Flag_Idx=(Key_Flag_Idx+1)%3;
switch(Key_Flag_Idx)
{
case 1:EA=1;ET0=1;TR0=1;break;
case 2:EA=0;ET0=0;TR0=0;break;
case 0:P0=0x3f;P2=0x3f;i=0;Second_Counts=0;
}
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
33
上海師范大學信息與機電工程學院—倪繼鋒
}
}
// 主程序
void main()
{
P0=0x3f; //顯示00
P2=0x3f;
i=0;
Second_Counts=0;
Key_Flag_Idx=0; //按鍵次數(取值 0 ,1 ,2,3 )
Key_State=1; //按鍵狀態
TMOD=0x01; //定時器0 方式 1
TH0=(65536-50000)/256; //定時器0:15ms
TL0=(65536-50000)%6;
while(1)
{
if(Key_State!=K1)
{
DelayMS(10);
Key_State=K1;
Key_Event_Handle();
}
}
}
//T0 中斷函數
void DSY_Refresh() interrupt 1
{
TH0=(65536-50000)/256; //恢復定時器0初值
TL0=(65536-50000)%6;
if(++i==2) //50ms*2=0.1s轉換狀態
{
i=0;
Second_Counts++;
P0=DSY_CODE[Second_Counts/10];
P2=DSY_CODE[Second_Counts];
if(Second_Counts==100) Second_Counts=0;//滿100(10s)后顯示00
}
}
33 用計數器中斷實現100 以內的按鍵計數
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
// 段碼
uchar code
DSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};
uchar Count=0;
// 主程序
void main()
{
P0=0x00;
P2=0x00;
TMOD=0x06; //計數器T0方式2
TH0=TL0=256-1; //計數值為1
ET0=1; //允許T0中斷
EX0=1; //允許INT0 中斷
EA=1; //允許CPU 中斷
IP=0x02; //設置優先級,T0高于INT0
IT0=1; //INT0中斷觸發方式為下降沿觸發
TR0=1; //啟動T0
while(1)
{
P0=DSY_CODE[Count/10];
P2=DSY_CODE[Count];
}
}
//T0 計數器中斷函數
void Key_Counter() interrupt 1
{
Count=(Count+1)0; //因為只有兩位數碼管,計數控制在 100 以內(00~99)
}
//INT0 中斷函數
void Clear_Counter() interrupt 0
{
Count=0;
}
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
35
上海師范大學信息與機電工程學院—倪繼鋒
34 100 000s 以內的計時程序
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
// 段碼
uchar code
DSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//6 只數碼管上顯示的數字
uchar Digits_of_6DSY[]={0,0,0,0,0,0};
uchar Count;
sbit Dot=P0^7;
// 延時
void DelayMS(uint ms)
{
uchar t;
while(ms--)for(t=0;t<120;t++);
}
// 主程序
void main()
{
uchar i,j;
P0=0x00;
P3=0xff;
Count=0;
TMOD=0x01; //計數器T0方式1
TH0=(65536-50000)/256; //50ms定時
TL0=(65536-50000)%6;
IE=0x82;
TR0=1; //啟動T0
while(1)
{
j=0x7f;
//顯示Digits_of_6DSY[5]~Digits_of_6DSY[0]的內容
//前面高位,后面低位,循環中 i!=-1亦可寫成i!=0xff
for(i=5;i!=-1;i--)
{
j=_crol_(j,1);
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
36
上海師范大學信息與機電工程學院—倪繼鋒
P3=j;
P0=DSY_CODE[Digits_of_6DSY[i]];
if(i==1)Dot=1; //加小數點
DelayMS(2);
}
}
}
//T0 中斷函數
void Timer0() interrupt 1
{
uchar i;
TH0=(65536-50000)/256; //恢復初值
TL0=(65536-50000)%6;
if(++Count!=2) return;
Count=0;
Digits_of_6DSY[0]++; //0.1s位累加
for(i=0;i<=5;i++) //進位處理
{
if(Digits_of_6DSY[i]==10)
{
Digits_of_6DSY[i]=0;
if(i!=5)Digits_of_6DSY[i+1]++; //如果0~4位則分別向高一位進位
}
else break; //若某低位沒有進位,怎循環提前結束
}
}
35 定時器控制數碼管動態顯示
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
// 段碼, 最后一位是“-”的段碼
uchar code
DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};
// 待顯示的數據:09-12-25 與23-59-58 (分兩組顯示)
uchar codeTable_of_Digits[][8]={{0,9,10,1,2,10,2,5},{2,3,10,5,9,10,5,8}};
uchar i,j=0;
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
37
上海師范大學信息與機電工程學院—倪繼鋒
uint t=0;
// 主程序
void main()
{
P3=0x80; //位碼初值
TMOD=0x00; //計數器T0方式0
TH0=(8192-4000)/32; //4ms定時
TL0=(8192-4000)2;
IE=0x82;
TR0=1; //啟動T0
while(1);
}
//T0 中斷函數控制數碼管刷新顯示
void DSY_Show() interrupt 1
{
TH0=(8192-4000)/32; //恢復初值
TL0=(8192-4000)2;
P0=0xff; //輸出位碼和段碼
P0=DSY_CODE[Table_of_Digits[i][j]];
P3=_crol_(P3,1);
j=(j+1)%8; //數組第i 行的下一字節索引
if(++t!=350) return; //保持刷新一段時間
t=0;
i=(i+1)%2; //數組行i=0 時顯示年月日,i=1 時顯示時分秒
}
36 8X8LED 點陣顯示數字
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar code Table_of_Digits[]=
{
0x00,0x3e,0x41,0x41,0x41,0x3e,0x00,0x00, //0
0x00,0x00,0x00,0x21,0x7f,0x01,0x00,0x00, //1
0x00,0x27,0x45,0x45,0x45,0x39,0x00,0x00,//2
0x00,0x22,0x49,0x49,0x49,0x36,0x00,0x00,//3
0x00,0x0c,0x14,0x24,0x7f,0x04,0x00,0x00, //4
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
38
上海師范大學信息與機電工程學院—倪繼鋒
0x00,0x72,0x51,0x51,0x51,0x4e,0x00,0x00, //5
0x00,0x3e,0x49,0x49,0x49,0x26,0x00,0x00, //6
0x00,0x40,0x40,0x40,0x4f,0x70,0x00,0x00, //7
0x00,0x36,0x49,0x49,0x49,0x36,0x00,0x00,//8
0x00,0x32,0x49,0x49,0x49,0x3e,0x00,0x00 //9
};
uchar i=0,t=0,Num_Index;
// 主程序
void main()
{
P3=0x80;
Num_Index=0; //從0 開始顯示
TMOD=0x00; //T0方式0
TH0=(8192-2000)/32; //2ms定時
TL0=(8192-2000)2;
IE=0x82;
TR0=1; //啟動T0
while(1);
}
//T0 中斷函數
void LED_Screen_Display() interrupt 1
{
TH0=(8192-2000)/32; //恢復初值
TL0=(8192-2000)2;
P0=0xff; //輸出位碼和段碼
P0=~Table_of_Digits[Num_Index*8+i];
P3=_crol_(P3,1);
if(++i==8)i=0; //每屏一個數字由 8 個字節構成
if(++t==250) //每個數字刷新顯示一段時間
{
t=0;
if(++Num_Index==10) Num_Index=0; //顯示下一個數字
}
}
37 按鍵控制8X8LED 點陣屏顯示圖形
#include<reg51.h>
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
39
上海師范大學信息與機電工程學院—倪繼鋒
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
// 待顯示圖形編碼
uchar code M[][8]=
{
{0x00,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x00}, //圖1
{0x00,0x38,0x44,0x54,0x44,0x38,0x00,0x00}, //圖2
{0x00,0x20,0x30,0x38,0x3c,0x3e,0x00,0x00} //圖3
};
uchar i,j;
// 主程序
void main()
{
P0=0xff;
P1=0xff;
TMOD=0x01; //T0方式1
TH0=(65536-2000)/256; //2ms定時
TL0=(65536-2000)%6;
IT0=1; //下降沿觸發
IE=0x83; //允許定時器0 、外部0 中斷
i=0xff; //i的初值設為 0xff ,加1 后將從0 開始
while(1);
}
//T0 中斷控制點陣屏顯示
void Show_Dot_Matrix() interrupt 1
{
TH0=(65536-2000)/256; //恢復初值
TL0=(65536-2000)%6;
P0=0xff; //輸出位碼和段碼
P0=~M[i][j];
P1=_crol_(P1,1);
j=(j+1)%8;
}
//INT0 中斷(定時器由鍵盤中斷啟動)
void Key_Down() interrupt 0
{
P0=0xff;
P1=0x80;
j=0;
i=(i+1)%3; //i在0 ,1 ,2 中取值,因為只要 3 個圖形
TR0=1;
}
38 用定時器設計的門鈴
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
40
上海師范大學信息與機電工程學院—倪繼鋒
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit Key=P1^7;
sbit DoorBell=P3^0;
uint p=0;
// 主程序
void main()
{
DoorBell=0;
TMOD=0x00; //T0方式0
TH0=(8192-700)/32; //700us定時
TL0=(8192-700)2;
IE=0x82;
while(1)
{
if(Key==0) //按下按鍵啟動定時器
{
TR0=1;
while(Key==0);
}
}
}
//T0 中斷控制點陣屏顯示
void Timer0() interrupt 1
{
DoorBell=~DoorBell;
p++;
if(p<400) //若需要拖長聲音,可以調整 400 和800
{
TH0=(8192-700)/32; //700us定時
TL0=(8192-700)2;
}
else if(p<800)
{
TH0=(8192-1000)/32; //1ms定時
TL0=(8192-1000)2;
}
else
{
TR0=0;
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
41
上海師范大學信息與機電工程學院—倪繼鋒
p=0;
}
}
39 演奏音階
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit K1=P1^0;
sbit SPK=P3^4;
uint i=0; //音符索引
//14 個音符放在方式 2 下的定時寄存器
(TH0,TL0 )
uchar codeHI_LIST[]={0,226,229,232,233,236,238,240,241,242,244,245,246,247,248};
uchar code LO_LIST[]={0,4,13,10,20,3,8,6,2,23,5,26,1,4,3};
// 定時器0 中斷函數
void T0_INT() interrupt 1
{
TL0=LO_LIST[i];
TH0=HI_LIST[i];
SPK=~SPK;
}
// 延時
void DelayMS(uint ms)
{
uchar t;
while(ms--)for(t=0;t<120;t++);
}
// 主程序
void main()
{
TMOD=0x00; //T0方式0
IE=0x82;
SPK=0;
while(1)
{
while(K1==1); //未按鍵等待
while(K1==0); //等待釋放
for(i=1;i<15;i++)
{
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
42
上海師范大學信息與機電工程學院—倪繼鋒
TR0=1; //播放一個音符
DelayMS(500); //播放延時
TR0=0;
DelayMS(50);
}
}
}
40 按鍵控制定時器選播多段音樂
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit K1=P1^0; // 播放和停止鍵
sbit SPK=P3^7; // 蜂鳴器
uchar Song_Index=0,Tone_Index=0; //當前音樂段索引,音符索引
// 數碼管段碼表
uchar codeDSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
// 標準音符頻率對應的延時表
uchar codeHI_LIST[]={0,226,229,232,233,236,238,240,241,242,244,245,246,247,248};
uchar code LO_LIST[]={0,4,13,10,20,3,8,6,2,23,5,26,1,4,3};
// 三段音樂的音符
uchar code Song[][50]=
{
{1,2,3,1,1,2,3,1,3,4,5,3,4,5,5,6,5,3,5,6,5,3,5,3,2,1,2,1,-1},
{3,3,3,4,5,5,5,5,6,5,3,5,3,2,1,5,6,53,3,2,1,1,-1},
{3,2,1,3,2,1,1,2,3,1,1,2,3,1,3,4,5,3,4,5,5,6,5,3,5,3,2,1,3,2,1,1,-1}
};
// 三段音樂的節拍
uchar code Len[][50]=
{
{1,1,1,1,1,1,1,1,1,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,2,-1},
{1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,2,-1},
{1,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,2,1,1,1,1,1,1,1,2,1,1,2,2,-1}
};
// 外部中斷0
void EX0_INT() interrupt 0
{
TR0=0; //播放結束或者播放中途切換歌曲時停止播放
Song_Index=(Song_Index+1)%3; //跳到下一首的開頭
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
43
上海師范大學信息與機電工程學院—倪繼鋒
Tone_Index=0;
P2=DSY_CODE[Song_Index]; //數碼管顯示當前音樂段號
}
// 定時器0 中斷函數
void T0_INT() interrupt 1
{
TL0=LO_LIST[Song[Song_Index][Tone_Index]];
TH0=HI_LIST[Song[Song_Index][Tone_Index]];
SPK=~SPK;
}
// 延時
void DelayMS(uint ms)
{
uchar t;
while(ms--)for(t=0;t<120;t++);
}
// 主程序
void main()
{
P2=0xc0;
SPK=0;
TMOD=0x00; //T0方式0
IE=0x83;
IT0=1;
IP=0x02;
while(1)
{
while(K1==1); //未按鍵等待
while(K1==0); //等待釋放
TR0=1; //開始播放
Tone_Index=0; //從第0個音符開始
//播放過程中按下 K1可提前停止播放(K1=0)。
//若切換音樂段會觸發外部中斷,導致 TR0=0 ,播放也會停止
while(Song[Song_Index][Tone_Index]!=-1&&K1==1&&TR0==1)
{
DelayMS(300*Len[Song_Index][Tone_Index]); //播放延時(節拍)
Tone_Index++; //當前音樂段的下一音符索引
}
TR0=0; //停止播放
while(K1==0); //若提前停止播放,按鍵未釋放時等待
}
}
41 定時器控制交通指示燈
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
44
上海師范大學信息與機電工程學院—倪繼鋒
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit RED_A=P0^0; // 東西向指示燈
sbit YELLOW_A=P0^1;
sbit GREEN_A=P0^2;
sbit RED_B=P0^3; // 南北向指示燈
sbit YELLOW_B=P0^4;
sbit GREEN_B=P0^5;
// 延時倍數,閃爍次數,操作類型
變量
uchar Time_Count=0,Flash_Count=0,Operation_Type=1;
// 定時器0 中斷函數
void T0_INT() interrupt 1
{
TL0=-50000/256;
TH0=-50000%6;
switch(Operation_Type)
{
case 1: //東西向綠燈與南北向紅燈亮 5s
RED_A=0;YELLOW_A=0;GREEN_A=1;
RED_B=1;YELLOW_B=0;GREEN_B=0;
if(++Time_Count!=100) return; //5s(100*50ms)切換
Time_Count=0;
Operation_Type=2;
break;
case 2: //東西向黃燈開始閃爍,綠燈關閉
if(++Time_Count!=8) return;
Time_Count=0;
YELLOW_A=~YELLOW_A;GREEN_A=0;
if(++Flash_Count!=10) return; //閃爍
Flash_Count=0;
Operation_Type=3;
break;
case 3: //東西向紅燈與南北向綠燈亮 5s
RED_A=1;YELLOW_A=0;GREEN_A=0;
RED_B=0;YELLOW_B=0;GREEN_B=1;
if(++Time_Count!=100) return; //5s(100*50ms)切換
Time_Count=0;
Operation_Type=4;
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
45
上海師范大學信息與機電工程學院—倪繼鋒
break;
case 4: //南北向黃燈開始閃爍,綠燈關閉
if(++Time_Count!=8) return;
Time_Count=0;
YELLOW_B=~YELLOW_B;GREEN_A=0;
if(++Flash_Count!=10) return; //閃爍
Flash_Count=0;
Operation_Type=1;
break;
}
}
// 主程序
void main()
{
TMOD=0x01; //T0方式1
IE=0x82;
TR0=1;
while(1);
}
42 報警與旋轉燈
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit SPK=P3^7;
uchar FRQ=0x00;
// 延時
void DelayMS(uint ms)
{
uchar i;
while(ms--)for(i=0;i<120;i++);
}
//INT0 中斷函數
void EX0_INT() interrupt 0
{
TR0=~TR0; //開啟或停止兩定時器,分別控制報警器的聲音和 LED 旋轉
TR1=~TR1;
if(P2==0x00)
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
46
上海師范大學信息與機電工程學院—倪繼鋒
P2=0xe0; //開3 個旋轉燈
else
P2=0x00;//關閉所有LED
}
// 定時器0 中斷
void T0_INT() interrupt 1
{
TH0=0xfe;
TL0=FRQ;
SPK=~SPK;
}
// 定時器1 中斷
void T1_INT() interrupt 3
{
TH1=-45000/256;
TL1=-45000%6;
P2=_crol_(P2,1);
}
// 主程序
void main()
{
P2=0x00;
SPK=0x00;
TMOD=0x11; //T0、T1方式 1
TH0=0x00;
TL0=0xff;
IT0=1;
IE=0x8b; //開啟0 ,1 ,3 號中斷
IP=0x01; //INT0設為最高優先
TR0=0;
TR1=0; //定時器啟停由 INT0 控制,初始關閉
while(1)
{
FRQ++;
DelayMS(1);
}
}
43 串行數據轉換為并行數據
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
47
上海師范大學信息與機電工程學院—倪繼鋒
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit SPK=P3^7;
uchar FRQ=0x00;
// 延時
void DelayMS(uint ms)
{
uchar i;
while(ms--)for(i=0;i<120;i++);
}
// 主程序
void main()
{
uchar c=0x80;
SCON=0x00; //串口模式0,即移位寄存器輸入/輸出方式
TI=1;
while(1)
{
c=_crol_(c,1);
SBUF=c;
while(TI==0); //等待發送結束
TI=0; //TI軟件置位
DelayMS(400);
}
}
44 并行數據轉換為串行數據
#include<reg51.h>
#include<intrins.h>
#include<stdio.h>
#define uchar unsigned char
#define uint unsigned int
sbitSPL=P2^5; //shift/load
// 延時
void DelayMS(uint ms)
{
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
48
上海師范大學信息與機電工程學院—倪繼鋒
uchar i;
while(ms--)for(i=0;i<120;i++);
}
// 主程序
void main()
{
SCON=0x10; //串口模式0,允許串口接收
while(1)
{
SPL=0; //置數(load) ,讀入并行輸入口的8位數據
SPL=1; //移位(shift),并口輸入被封鎖,串行轉換開始
while(RI==0); //未接收1 字節時等待
RI=0; //RI軟件置位
P0=SBUF; //接收到的數據顯示在P0口,顯示撥碼開關的值
DelayMS(20);
}
}
45 甲機通過串口控制乙機LED
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbitLED1=P0^0;
sbit LED2=P0^3;
sbit K1=P1^0;
// 延時
void DelayMS(uint ms)
{
uchar i;
while(ms--)for(i=0;i<120;i++);
}
// 向串口發送字符
void Putc_to_SerialPort(uchar c)
{
SBUF=c;
while(TI==0);
TI=0;
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
49
上海師范大學信息與機電工程學院—倪繼鋒
}
// 主程序
void main()
{
uchar Operation_No=0;
SCON=0x40; //串口模式1
TMOD=0x20; //T1工作模式 2
PCON=0x00; //波特率不倍增
TH1=0xfd;
TL1=0xfd;
TI=0;
TR1=1;
while(1)
{
if(K1==0) //按下K1時選擇操作代碼 0 ,1 ,2 ,3
{
while(K1==0);
Operation_No=(Operation_No+1)%4;
}
switch(Operation_No) //根據操作代碼發送 A/B/C或停止發送
{
case 0: LED1=LED2=1;
break;
case 1:Putc_to_SerialPort('A');
LED1=~LED1;LED2=1;
break;
case 2:Putc_to_SerialPort('B');
LED2=~LED2;LED1=1;
break;
case 3:Putc_to_SerialPort('C');
LED1=~LED1;LED2=LED1;
break;
}
DelayMS(100);
}
}
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbitLED1=P0^0;
sbit LED2=P0^3;
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
50
上海師范大學信息與機電工程學院—倪繼鋒
// 延時
void DelayMS(uint ms)
{
uchar i;
while(ms--)for(i=0;i<120;i++);
}
// 主程序
void main()
{
SCON=0x50; //串口模式1,允許接收
TMOD=0x20; //T1工作模式 2
PCON=0x00; //波特率不倍增
TH1=0xfd; //波特率9600
TL1=0xfd;
RI=0;
TR1=1;
LED1=LED2=1;
while(1)
{
if(RI) //如收到則LED 閃爍
{
RI=0;
switch(SBUF)//根據所收到的不同命令字符完成不同動作
{
case 'A':LED1=~LED1;LED2=1;break; //LED1閃爍
case 'B':LED2=~LED2;LED1=1;break; //LED2閃爍
case 'C':LED1=~LED1;LED2=LED1; //雙閃爍
}
}
elseLED1=LED2=1; //關閉LED
DelayMS(100);
}
}
46 單片機之間雙向通信
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbitLED1=P1^0;
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
51
上海師范大學信息與機電工程學院—倪繼鋒
sbit LED2=P1^3;
sbit K1=P1^7;
uchar Operation_No=0; // 操作代碼
// 數碼管代碼
uchar codeDSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
// 延時
void DelayMS(uint ms)
{
uchar i;
while(ms--)for(i=0;i<120;i++);
}
// 向串口發送字符
void Putc_to_SerialPort(uchar c)
{
SBUF=c;
while(TI==0);
TI=0;
}
// 主程序
void main()
{
LED1=LED2=1;
P0=0x00;
SCON=0x50; //串口模式1,允許接收
TMOD=0x20; //T1工作模式 2
PCON=0x00; //波特率不倍增
TH1=0xfd;
TL1=0xfd;
TI=RI=0;
TR1=1;
IE=0x90; //允許串口中斷
while(1)
{
DelayMS(100);
if(K1==0) //按下K1時選擇操作代碼 0 ,1 ,2 ,3
{
while(K1==0);
Operation_No=(Operation_No+1)%4;
switch(Operation_No)//根據操作代碼發送 A/B/C 或停止發送
{
case 0:Putc_to_SerialPort('X');
LED1=LED2=1;
break;
case 1:Putc_to_SerialPort('A');
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
52
上海師范大學信息與機電工程學院—倪繼鋒
LED1=~LED1;LED2=1;
break;
case 2:Putc_to_SerialPort('B');
LED2=~LED2;LED1=1;
break;
case 3:Putc_to_SerialPort('C');
LED1=~LED1;LED2=LED1;
break;
}
}
}
}
// 甲機串口接收中斷函數
void Serial_INT() interrupt 4
{
if(RI)
{
RI=0;
if(SBUF>=0&&SBUF<=9)P0=DSY_CODE[SBUF];
else P0=0x00;
}
}
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbitLED1=P1^0;
sbit LED2=P1^3;
sbit K2=P1^7;
uchar NumX=-1;
// 延時
void DelayMS(uint ms)
{
uchar i;
while(ms--)for(i=0;i<120;i++);
}
// 主程序
void main()
{
LED1=LED2=1;
SCON=0x50; //串口模式1,允許接收
TMOD=0x20; //T1工作模式 2
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
53
上海師范大學信息與機電工程學院—倪繼鋒
TH1=0xfd; //波特率9600
TL1=0xfd;
PCON=0x00; //波特率不倍增
RI=TI=0;
TR1=1;
IE=0x90;
while(1)
{
DelayMS(100);
if(K2==0)
{
while(K2==0);
NumX=++NumX;//產生0~10范圍內的數字,其中10 表示關閉
SBUF=NumX;
while(TI==0);
TI=0;
}
}
}
void Serial_INT() interrupt 4
{
if(RI) //如收到則LED 則動作
{
RI=0;
switch(SBUF) //根據所收到的不同命令字符完成不同動作
{
case 'X':LED1=LED2=1;break; //全滅
case 'A': LED1=0;LED2=1;break;//LED1亮
case 'B': LED2=0;LED1=1;break;//LED2亮
case 'C':LED1=LED2=0; //全亮
}
}
}
47 單片機向主機發送字符串
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
// 延時
void DelayMS(uint ms)
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
54
上海師范大學信息與機電工程學院—倪繼鋒
{
uchar i;
while(ms--)for(i=0;i<120;i++);
}
// 向串口發送字符
void Putc_to_SerialPort(uchar c)
{
SBUF=c;
while(TI==0);
TI=0;
}
// 向串口發送字符串
void Puts_to_SerialPort(uchar *s)
{
while(*s!='\0')
{
Putc_to_SerialPort(*s);
s++;
DelayMS(5);
}
}
// 主程序
void main()
{
uchar c=0;
SCON=0x40; //串口模式1
TMOD=0x20; //T1工作模式 2
TH1=0xfd; //波特率9600
TL1=0xfd;
PCON=0x00; //波特率不倍增
TI=0;
TR1=1;
DelayMS(200);
//向主機發送數據
Puts_to_SerialPort("Receiving From8051...\r\n");
Puts_to_SerialPort("-------------------------------\r\n");
DelayMS(50);
while(1)
{
Putc_to_SerialPort(c+'A');
DelayMS(100);
Putc_to_SerialPort(' ');
DelayMS(100);
if(c==25) //每輸出一遍后加橫線
{
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
55
上海師范大學信息與機電工程學院—倪繼鋒
Puts_to_SerialPort("\r\n-------------------------------\r\n");
DelayMS(100);
}
c=(c+1)&
if(c==0) //每輸出10個字符后換行
{
Puts_to_SerialPort("\r\n");
DelayMS(100);
}
}
}
48 單片機與PC通信
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
ucharReceive_Buffer[101]; // 接收緩沖
ucharBuf_Index=0; // 緩沖空間索引
// 數碼管編碼
uchar codeDSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};
// 延時
void DelayMS(uint ms)
{
uchar i;
while(ms--)for(i=0;i<120;i++);
}
// 主程序
void main()
{
uchar i;
P0=0x00;
Receive_Buffer[0]=-1;
SCON=0x50; //串口模式1,允許接收
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
56
上海師范大學信息與機電工程學院—倪繼鋒
TMOD=0x20; //T1工作模式 2
TH1=0xfd; //波特率9600
TL1=0xfd;
PCON=0x00; //波特率不倍增
EA=1;EX0=1;IT0=1;
ES=1;IP=0x01;
TR1=1;
while(1)
{
for(i=0;i<100;i++)
{ //收到-1 為一次顯示結束
if(Receive_Buffer[i]==-1)break;
P0=DSY_CODE[Receive_Buffer[i]];
DelayMS(200);
}
DelayMS(200);
}
}
// 串口接收中斷函數
void Serial_INT() interrupt 4
{
uchar c;
if(RI==0) return;
ES=0; //關閉串口中斷
RI=0; //清接收中斷標志
c=SBUF;
if(c>='0'&&c<='9')
{ //緩存新接收的每個字符,并在其后放-1 為結束標志
Receive_Buffer[Buf_Index]=c-'0';
Receive_Buffer[Buf_Index+1]=-1;
Buf_Index=(Buf_Index+1)0;
}
ES=1;
}
void EX_INT0() interrupt0 //外部中斷0
{
uchar *s="這是由 8051 發送的字符串!\r\n";
uchar i=0;
while(s[i]!='\0')
{
SBUF=s[i];
while(TI==0);
TI=0;
i++;
}
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
57
上海師范大學信息與機電工程學院—倪繼鋒
}
第02篇 硬件應用
19 用ADC0808控制PWM 輸出
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbitCLK=P2^4; //時鐘信號
sbit ST=P2^5; // 啟動信號
sbitEOC=P2^6; //轉換結束信號
sbit OE=P2^7; // 輸出使能
sbitPWM=P3^0; //PWM 輸出
// 延時
void DelayMS(uint ms)
{
uchar i;
while(ms--)for(i=0;i<40;i++);
}
// 主程序
void main()
{
uchar Val;
TMOD=0x02; //T1工作模式 2
TH0=0x14;
TL0=0x00;
IE=0x82;
TR0=1;
while(1)
{
ST=0;ST=1;ST=0; //啟動A/D轉換
while(!EOC); //等待轉換完成
OE=1;
Val=P1; //讀轉換值
OE=0;
if(Val==0) //PWM輸出(占空比為 0%)
{
PWM=0;
DelayMS(0xff);
continue;
《單片機 語言程序設計實訓 例 基于 和 仿真》案例 C 100 --- 8051PROTEUS
58
上海師范大學信息與機電工程學院—倪繼鋒
}
if(Val==0xff) //PWM輸出(占空比為100%)
{
PWM=1;
DelayMS(0xff);
continue;
}
PWM=1; //PWM輸出(占空比為 0%~100%)
DelayMS(Val);
PWM=0;
DelayMS(0xff-Val);
}
}
//T0 定時器中斷給 ADC0808提供時鐘信號
void Timer0_INT() interrupt 1
{
CLK=~CLK;
}
20 ADC0809數模轉換與顯示
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
// 各數字的數碼管段碼(共陰)
uchar codeDSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
sbitCLK=P1^3; //時鐘信號
sbit ST=P1^2; // 啟動信號
sbitEOC=P1^1; //轉換結束信號
sbit OE=P1^0; // 輸出使能
// 延時
void DelayMS(uint ms)
{
uchar i;
while(ms--)for(i=0;i<120;i++);
}
// 顯示轉換結果
void Display_Result(uchar d)
{
P2=0xf7; //第4 個數碼管顯示個位數
P0=DSY_CODE[d];
《單片機C 語言程序設計實訓100 例--- 基于8051和PROTEUS 仿真》案例
59
上海師范大學信息與機電工程學院—倪繼鋒
DelayMS(5);
P2=0xfb; //第3 個數碼管顯示十位數
P0=DSY_CODE[d0/10];
DelayMS(5);
P2=0xfd; //第2 個數碼管顯示百位數
P0=DSY_CODE[d/100];
DelayMS(5);
}
// 主程序
void main()
{
TMOD=0x02; //T1工作模式 2
TH0=0x14;
TL0=0x00;
IE=0x82;
TR0=1;
P1=0x3f; //選擇ADC0809的通道3(0111)(P1.4~P1.6)
while(1)
{
ST=0;ST=1;ST=0; //啟動A/D轉換
while(EOC==0); //等待轉換完成
OE=1;
Display_Result(P3);
OE=0;
}
}
//T0 定時器中斷給 ADC0808提供時鐘信號
void Timer0_INT() interrupt 1
{
CLK=~CLK;
}
|