单片机C语言程序设计实训100例—基于8051+Proteus仿真
更新时间:2024-06-06 19:29:01 阅读量: 综合文库 文档下载
《基于8051+Proteus仿真》案例
第 01 篇 基础程序设计
01 闪烁的LED
/* 名称:闪烁的LED 说明:LED按设定的时间间隔闪烁
*/
#include
#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 从左到右的流水灯
/* 名称:从左到右的流水灯 说明:接在P0口的8个LED从左到右循环依次点亮,产生走马灯效果 */
#include
#define uchar unsigned char #define uint unsigned int
1
//延时
void DelayMS(uint x) {
uchar i;
while(x--) { for(i=0;i<120;i++); }
}
//主程序 void main() { P0=0xfe; }
03 8只LED左右来回点亮
/* 名称:8只LED左右来回点亮 说明:程序利用循环移位函数_crol_和_cror_形成来回滚动的效果 */
#include
#define uchar unsigned char #define uint unsigned int //延时
void DelayMS(uint x) { uchar i;
while(x--) { }
for(i=0;i<120;i++);
while(1) { P0=_crol_(P0,1); //P0的值向左循环移动 DelayMS(150); }
}
//主程序 void main() {
uchar i; P2=0x01; while(1) {
2
}
}
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 花样流水灯
/* 名称:花样流水灯 说明:16只LED分两组按预设的多种花样变换显示 */
#include
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,
3
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模拟交通灯
/* 名称:LED模拟交通灯 说明:东西向绿灯亮若干秒,黄灯闪烁5次后红灯亮, 红灯亮后,南北向由红灯变为绿灯,若干秒后南北向黄灯闪烁5此后变红灯,东西向变绿灯,如此重复。 */
#include
#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 Flash_Count=0,Operation_Type=1; //闪烁次数,操作类型变量
4
//延时
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
5
/* 名称:单只数码管循环显示0~9 */
#include
#define uchar unsigned char #define uint unsigned int
uchar code DSY_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) {
/*
说明:主程序中的循环语句反复将0~9的段码送至P0口,使数字0~9循环显示
for(;i<11;i++){ P0=~DSY_CODE[i]; DelayMS(300);} //注:另一方案 */ }
07 8只数码管滚动显示单个数字
/* 名称:8只数码管滚动显示单个数字 说明:数码管从左到右依次滚动显示0~7,程序通过每次仅循环选通一只数码管 */
#include
#define uchar unsigned char
#define uint unsigned int
uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //延时
void DelayMS(uint x) {
6
}
P0=~DSY_CODE[i]; i=(i+1); DelayMS(300);
uchar t;
while(x--) for(t=0;t<120;t++);
}
//主程序
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只数码管动态显示多个不同字符
电路如上图
/* 名称:8只数码管动态显示多个不同字符 说明:数码管动态扫描显示0~7。 */
#include
#define uchar unsigned char #define uint unsigned int
uchar code DSY_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++) {
P2=0xff;
7
}
}
}
P0=DSY_CODE[i]; //发送段码 wei=_crol_(wei,1); P2=wei; //发送位码 DelayMS(2);
09 8只数码管闪烁显示数字串
电路如上图
/* 名称:8只数码管闪烁显示数字串
说明:数码管闪烁显示由0~7构成的一串数字
本例用动态刷新法显示一串数字,在停止刷新时所有数字显示消失。*/
#include
uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //位码表
uchar code DSY_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);
8
}
}
10 8只数码管滚动显示数字串
电路如上图
/* 名称:8只数码管滚动显示数字串 说明:数码管向左滚动显示3个字符构成的数字串 */
#include
uchar code DSY_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移位
9
/* 名称:K1-K4 控制LED移位 说明:按下K1时,P0口LED上移一位;
按下K2时,P0口LED下移一位; 按下K3时,P2口LED上移一位; 按下K4时,P2口LED下移一位;
*/
#include
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
//K4
else if((P1&0x80)==0) P2=_crol_(P2,1); }
//主程序 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);
10
12 K1-K4 按键状态显示
/* 名称:K1-K4 按键状态显示 说明:K1、K2按下时LED点亮,松开时熄灭,
K3、K4按下并释放时LED点亮,再次按下并释放时熄灭;
*/
#include
void DelayMS(uint x) {
uchar i;
while(x--) for(i=0;i<120;i++);
} //主程序 void main() { P0=0xff; P1=0xff; }
11
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
/* 名称:K1-K4 分组控制LED */
#include
void DelayMS(uint x) {
uchar i;
while(x--) for(i=0;i<120;i++);
说明:每次按下K1时递增点亮一只LED,全亮时再次按下则再次循环开始, K2按下后点亮上面4只LED,K3按下后点亮下面4只LED,K4按下后关闭所有LED
} //主程序 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);
12
}
}
}
}
case 2: case 3: case 4:
break;
P0=0xf0;break; P0=0x0f;break; P0=0xff;
14 K1-K4 控制数码管移位显示
/* 名称:K1-K4 控制数码管移位显示
说明:按下K1时加1计数并增加显示位,
按下K2时减1计数并减少显示位, 按下K3时清零。
*/
#include
uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //位码
uchar code DSY_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() {
P0=DSY_CODE[Display_Buffer[i]]; P2=DSY_Index[i]; }
DelayMS(2); uchar i;
for(i=0;i<8;i++) {
P0=0xff;
}
//主程序 void main()
13
{ }
uchar i,Key_NO,Key_Counts=0; 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;
if(Key_Counts>0)Display_Buffer[--Key_Counts]=10; break;
Display_Buffer[0]=0;
for(i=1;i<8;i++) Display_Buffer[i]=10; Key_Counts=0;
case 0xfd: case 0xfb:
}
//若键未释放则仅刷新显示,不进行键扫描 while(P1!=0xff) Show_Count_ON_DSY();
15 K1-K4 控制数码管加减演示
/* 名称:K1-K4 控制数码管加减演示 说明:按下K1后加1计数,按下K2后减1计数,按下K3后清零。 */
#include
#define uchar unsigned char #define uint unsigned int //段码
uchar code DSY_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; //延时
14
void DelayMS(uint x) { 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;
}
15
}
}
Key_Code=0xff;
16 4X4矩阵键盘控制条形LED显示
/* 名称:4X4矩阵键盘控制条形LED显示 说明:运行本例时,按下的按键值越大点亮的LED越多。 */
#include
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;
16
}
}
}
}
for(i=0;i<16;i++) //查表得到按键序号并返回
if(kCode==KeyCodeTable[i])
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;
//点亮条形LED
}
P3=P3_LED; P2=P2_LED;
17 数码管显示4X4矩阵键盘按键号
/* 名称:数码管显示4X4矩阵键盘按键号 说明:按下任意键时,数码管都会显示其键的序号,扫描程序首先判断按键发生在哪一列,然后根据所发生的行附加不同的
17
值,从而得到按键的序号。 */
#include
#define uchar unsigned char #define uint unsigned int //段码
uchar code DSY_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: case 2:
KeyNo=0;break; 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位并异或得到改变的值 }
18
switch(Tmp) //对0~3行分别附加起始值0,4,8,12 { }
case 1: case 2: case 4: case 8:
KeyNo+=0;break; KeyNo+=4;break; KeyNo+=8;break; KeyNo+=12;
//蜂鸣器 void Beep() {
uchar i;
for(i=0;i<100;i++) { DelayMS(1); } BEEP=0;
BEEP=~BEEP;
}
//主程序 void main() { }
18 开关控制LED
/* 名称:开关控制LED 说明:开关S1和S2分别控制LED1和LED2。 */
#include
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);
while(1)
19
{ }
LED1=S1; LED2=S2;
}
19 继电器控制照明设备
/* 名称:继电器控制照明设备 说明:按下K1灯点亮,再次按下时灯熄灭 */
#include
sbit RELAY=P2^4; //延时
void DelayMS(uint ms) {
uchar t;
while(ms--)for(t=0;t<120;t++);
}
//主程序 void main() { P1=0xff; RELAY=1; }
20 数码管显示拨码开关编码
/* 名称:数码管显示拨码开关编码 */
#include
20
while(1) { }
if(K1==0) { while(K1==0); }
RELAY=~RELAY; DelayMS(20);
说明:系统显示拨码开关所设置的编码000~255
#include
#define uchar unsigned char #define uint unsigned int
//各数字的数码管段码(共阴)
uchar code DSY_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 开关控制报警器
/* 名称:开关控制报警器 说明:用K1开关控制报警器,程序控制P1.0输出两种不同频率的声音,模拟很逼真的报警效果 */
#include
21
sbit K1=P1^7; //发声函数 void Alarm(uchar t) {
uchar i,j;
for(i=0;i<200;i++) { }
SPK=~SPK; for(j=0;j //由参数t行成不同的频率 } void main() { } 22 按键发音 /* 名称:按键发音 说明:按下不同的按键会是SOUNDER发出不同频率的声音。本例使用延时函数实现不同频率的声音输出,以后也可使用定时器 */ #include #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; SPK=0; while(1) { } if(K1==1) { } Alarm(90); Alarm(120); while(x--) for(t=0;t<120;t++); } //按周期t发音 22 void Play(uchar t) { 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 #define uchar unsigned char #define uint unsigned int sbit BEEP=P3^7; //生日快乐歌的音符频率表,不同频率由不同的延时来决定 uchar code SONG_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++); } //播放函数 23 void PlayMusic() { } uint i=0,j,k; while(SONG_LONG[i]!=0||SONG_TONE[i]!=0) { //播放各个音符,SONG_LONG为拍子长度 } for(j=0;j BEEP=~BEEP; //SONG_TONE延时表决定了每个音符的频率 for(k=0;k } DelayMS(10); i++; void main() { } BEEP=0; while(1) { } PlayMusic(); //播放生日快乐 DelayMS(500); //播放完后暂停一段时间 24 INT0中断计数 /* 名称:INT0中断计数 说明:每次按下计数键时触发INT0中断,中断程序累加计数, 计数值显示在3只数码管上,按下清零键时数码管清零 */ #include uchar code DSY_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() 24 { DSY_Buffer[2]=Count/100; //获取3个数 DSY_Buffer[1]=Count0/10; DSY_Buffer[0]=Count; if(DSY_Buffer[2]==0) //高位为0时不显示 { } P0=DSY_CODE[DSY_Buffer[0]]; P1=DSY_CODE[DSY_Buffer[1]]; P2=DSY_CODE[DSY_Buffer[2]]; DSY_Buffer[2]=0x0a; if(DSY_Buffer[1]==0) //高位为0,若第二位为0同样不显示 DSY_Buffer[1]=0x0a; } //主程序 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 /* 名称:外部INT0中断控制LED 说明:每次按键都会触发INT0中断,中断发生时将LED状态取反,产生LED状态由按键控制的效果 */ #include 25 //主程序 void main() { LED=1; EA=1; EX0=1; IT0=1; while(1); } //INT0中断函数 void EX_INT0() interrupt 0 { LED=~LED; //控制LED亮灭 } 26 INT0及INT1中断计数 /* 名称:INT0及INT1中断计数 说明:每次按下第1个计数键时,第1组计数值累加并显示在右边3只数 码管上, 每次按下第2个计数键时,第 2组计数值累加并显示在左边3只数码管上,后两个按键分别清零。 */ #include //数码管段码与位码 uchar code DSY_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; 26 Buffer_Counts[1]=Count_A0/10; Buffer_Counts[0]=Count_A; 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 27 { } Count_B++; 27 定时器控制单只LED /* 名称:定时器控制单只LED 说明:LED在定时器的中断例程控制下不断闪烁。 */ #include 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控制流水灯 /* 名称:TIMER0控制流水灯 说明:定时器控制P0、P2口的LED滚动显示,本例未使用中断函数。 */ #include 28 #define uchar unsigned char #define uint unsigned int //主程序 void main() { } 29 定时器控制4个LED滚动闪烁 /* 名称:定时器控制4个LED滚动闪烁 说明:4只LED在定时器控制下滚动闪烁。 */ #include 29 uchar T_Count=0; P0=0xfe; P2=0xfe; TMOD=0x01; TH0=(65536-40000)/256; //定时器0工作方式1 //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; //恢复初值 i=j=k=0; P0=0xff; TMOD=0x02; TH0=256-200; TL0=256-200; IE=0x82; TR0=1; while(1); //定时器0工作方式2 //200us定时 //启动定时器 } //T0中断函数 void LED_Flash_and_Scroll() interrupt 1 { if(++k<35) return; //定时中断若干次后执行闪烁 } 30 T0控制LED实现二进制计数 /* 名称:T0控制LED实现二进制计数 说明:本例对按键的计数没有使用查询法,没有使用外部中断函数,没有使用定时或计数中断函数。而是启用了计数器,连接在T0引脚的按键每次按下时,会使计数寄存器的值递增,其值通过LED以二进制形式显示 */ #include void main() { TMOD=0x05; //定时器0为计数器,工作方式1,最大计数值65535 TH0=0; //初值为0 k=0; switch(i) { case 0: case 1: case 2: case 3: B1=~B1;break; G1=~G1;break; R1=~R1;break; Y1=~Y1;break; default:i=0; } if(++j<300) return; //每次闪烁持续一段时间 j=0; P0=0xff; //关闭显示 i++; //切换到下一个LED TL0=0; 30 } TR0=1; while(1) { } P1=TH0; P2=TL0; //启动定时器 31 TIMER0与TIMER1控制条形LED /* 名称:TIMER0与TIMER1控制条形LED 说明:定时器T0定时控制上一组条形LED,滚动速度较快 定时器T1定时控制下一组条形LED,滚动速度较慢 */ #include #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转换状态 { } 31 tc0=0; P0=_crol_(P0,1); } //T1中断函数 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的秒表 /* 名称:10s的秒表 说明:首次按键计时开始,再次按键暂停,第三次按键清零。 */ #include 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: case 2: EA=1;ET0=1;TR0=1;break; EA=0;ET0=0;TR0=0;break; 32 case 0: P0=0x3f;P2=0x3f;i=0;Second_Counts=0; } } } //主程序 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以内的按键计数 /* 名称:用计数器中断实现100以内的按键计数 说明:本例用T0计数器中断实现按键技术,由于计数寄存器初值为1,因此 33 P3.4引脚的每次负跳变都会触发T0中断,实现计数值累加。 计数器的清零用外部中断0控制。 */ #include code DSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00}; uchar Count=0; //主程序 void main() { P0=0x00; //计数器T0方式2 //计数值为1 //允许T0中断 //允许INT0中断 //允许CPU中断 P2=0x00; TMOD=0x06; TH0=TL0=256-1; ET0=1; EX0=1; EA=1; IP=0x02; IT0=1; TR0=1; while(1) { P0=DSY_CODE[Count/10]; P2=DSY_CODE[Count]; //设置优先级,T0高于INT0 //INT0中断触发方式为下降沿触发 //启动T0 } } //T0计数器中断函数 void Key_Counter() interrupt 1 { Count=(Count+1)0; //因为只有两位数码管,计数控制在100以内(00~99) } //INT0中断函数 void Clear_Counter() interrupt 0 { 34 } Count=0; 34 100 000s以内的计时程序 /* 名称:100 000s以内的计时程序 说明:在6只数码管上完成0~99 999.9s。 */ #include 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; TH0=(65536-50000)/256; //计数器T0方式1 //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--) 35 } { } j=_crol_(j,1); 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; } 35 定时器控制数码管动态显示 /* 名称:定时器控制数码管动态显示 说明:8个数码管上分两组动态显示年月日与时分秒,本例的 位显示延时用定时器实现。 */ #include #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(分两组显示) 36 //恢复初值 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; uchar code Table_of_Digits[][8]={{0,9,10,1,2,10,2,5},{2,3,10,5,9,10,5,8}}; uchar i,j=0; uint t=0; //主程序 void main() { P3=0x80; TMOD=0x00; //位码初值 //计数器T0方式0 TH0=(8192-4000)/32; //4ms定时 TL0=(8192-4000)2; IE=0x82; TR0=1; while(1); //启动T0 } //T0中断函数控制数码管刷新显示 void DSY_Show() interrupt 1 { TH0=(8192-4000)/32; } 36 8X8LED点阵显示数字 /* 名称:8X8LED点阵显示数字 说明:8X8LED点阵屏循环显示数字0~9,刷新过程由定时器中断完成。 */ #include uchar code Table_of_Digits[]= { //恢复初值 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时显示时分秒 0x00,0x3e,0x41,0x41,0x41,0x3e,0x00,0x00, 0x00,0x00,0x00,0x21,0x7f,0x01,0x00,0x00, 0x00,0x27,0x45,0x45,0x45,0x39,0x00,0x00, 0x00,0x22,0x49,0x49,0x49,0x36,0x00,0x00, //0 //1 //2 //3 37 0x00,0x0c,0x14,0x24,0x7f,0x04,0x00,0x00, 0x00,0x72,0x51,0x51,0x51,0x4e,0x00,0x00, 0x00,0x3e,0x49,0x49,0x49,0x26,0x00,0x00, 0x00,0x40,0x40,0x40,0x4f,0x70,0x00,0x00, //4 //5 //6 //7 //8 //9 0x00,0x36,0x49,0x49,0x49,0x36,0x00,0x00, 0x00,0x32,0x49,0x49,0x49,0x3e,0x00,0x00 }; uchar i=0,t=0,Num_Index; //主程序 void main() { P3=0x80; Num_Index=0; //从0开始显示 //T0方式0 //2ms定时 TMOD=0x00; TH0=(8192-2000)/32; TL0=(8192-2000)2; IE=0x82; TR0=1; while(1); //启动T0 } //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点阵屏显示图形 /* 名称:按键控制8X8LED点阵屏显示图形 说明:每次按下K1时,会使8X8LED点阵屏循环显示不同图形。 本例同时使用外部中断和定时中断。 */ 38 #include 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; } 39 38 用定时器设计的门铃 /* 名称:用定时器设计的门铃 说明:按下按键时蜂鸣器发出叮咚的门铃声。 */ #include #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; TH0=(8192-700)/32; TL0=(8192-700)2; IE=0x82; while(1) { if(Key==0) { TR0=1; //按下按键启动定时器 //T0方式0 //700us定时 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定时 } else { 40 TL0=(8192-1000)2;
正在阅读:
单片机C语言程序设计实训100例—基于8051+Proteus仿真06-06
旅游管理专业实习报告范文05-06
员工薪酬管理制度12-12
2018年完整版慢性阻塞性肺疾病(COPD)的护理诊断和措施方案10-22
教师师德个人研修计划03-23
IBM System X服务器产品培训03-19
2014届高考历史15种热考题型1材料主旨类选择题Word版含答案03-11
小学生资料作文06-15
实验二 离散时间信号的表示及运算12-25
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 单片机
- 程序设计
- 仿真
- 基于
- Proteus
- 语言
- 8051
- 100
- 第七讲追及问题
- 浮动车的技术
- 【精校版】2018年江苏省扬州市中考生物试卷以及答案(word解析版)
- 述职报告- 丽水学院
- 6S管理方案
- PolymerCompositionandSubstrateInfluencesontheAdhesive Bondin
- 技术标
- 浙江省绍兴市2015-2016学年高一化学下册期末考试题
- 浅谈中职合并升高职后的校园文化融合
- 云南电网有限责任公司营销安规考试题库
- EDA课程设计--八位全加器 - 图文
- 棉纱英文质量标准翻译
- 《足球:踢墙式“二过一”战术》教案
- 《入菩萨行论释善说海》思考题第二品-智悲佛网(精)
- 关于绿色建筑设计要素及其在工程中应用的探讨
- 幼儿园社会教育领域活动教学策略
- 民俗文化交流协会章程(1)
- 三菱电机重庆售后电话报修查询防坑必看攻略 - 图文
- 统计学案例
- 徐文长从小就善于动脑筋思考