目录
根据单片机100案例所做,适合初学者进一步学习单片机的案例.
单片机案例11
结合proteus和keil
11 INT0中断计数器
原理图
程序
/*
名称:INT0中断计数
说明:按下计数键K1触发中断,中断程序累加计数
计数值显示在三个数码管上,按下清零键K2数码管清零
*/
#include<reg51.h>
#include<intrins.h>
#define INT8U unsigned char
#define INT16U unsigned int
//共阳极0-9的数码管段码表
code INT8U CA_Table[]=
{
0xC0,0xF9,
0xA4,0xB0,
0x99,0x92,
0x82,0xF8,
0x80,0x90,
0xFF//黑屏
};
//计数器值分解后的给位
INT8U show_buffer[]={0,0,0};
INT16U count=0;
sbit clear_key=P3^6;
//延时
void delay_ms(INT16U x)
{
INT8U t;
while(x--)
{
for(t=0;t<120;t++);
}
}
//数码管显示计数值
void refresh_show()
{
//获取三个数位
show_buffer[0]=count/100;
show_buffer[1]=count%100/10;
show_buffer[2]=count%10;
if(show_buffer[0]==0)//高位为0时不显示
{
show_buffer[0]=10;
//高位为0时,第二位为0,也不显示
if(show_buffer[1]==0)
show_buffer[1]=10;
}
P0=CA_Table[show_buffer[0]];
P1=CA_Table[show_buffer[1]];
P2=CA_Table[show_buffer[2]];
}
void main()
{
//初始化显示端口
P0=0xFF;
P1=0xFF;
P2=0xFF;
IE=0x81;//允许INT0中断
IT0=1;//下降沿触发
while(1)
{
if(clear_key==0)//清零
count=0;
refresh_show();//持续则刷新显示
}
}
//INT0中断函数
void ex_int0() interrupt 0
{
EA=0;//禁止中断
delay_ms(10);//消抖
count++;//计数值递增
EA=1;//开中断
}
单片机案例12
结合proteus和keil
12 INT0与INT1中断计数
原理图
程序
/*
名称:INT0和INT1中断计数
说明:按下计数键K1计数值显示在右边数码管上,
按下计数键K2计数值显示在左边数码管上,
按下清零键K3,K4数码管清零
*/
#include<reg51.h>
#include<intrins.h>
#define INT8U unsigned char
#define INT16U unsigned int
sbit K3=P3^4;//清零
sbit K4=P3^5;
//共阳极0-9的数码管段码表
code INT8U CA_Table[]=
{
0xC0,0xF9,
0xA4,0xB0,
0x99,0x92,
0x82,0xF8,
0x80,0x90,
0xFF//黑屏
};
code INT8U scan_bits[]=
{
0x20,0x10,
0x08,0x04,
0x02,0x01
};
//两组计数的显示缓冲,前3为一组,后3一组
INT8U show_buffer[]=
{
0,0,0,
0,0,0
};
INT16U count_a=0;
INT16U count_b=0;
//延时
void delay_ms(INT16U x)
{
INT8U t;
while(x--)
{
for(t=0;t<120;t++);
}
}
//数码管显示计数值
void refresh_show()
{
INT8U i;
//分解count_a
show_buffer[5]=count_a/100;
show_buffer[4]=count_a%100/10;
show_buffer[3]=count_a%10;
if(show_buffer[5]==0)//高位为0时不显示
{
show_buffer[5]=10;
//高位为0时,第二位为0,也不显示
if(show_buffer[4]==0)
show_buffer[4]=10;
}
//分解count_b
show_buffer[2]=count_b/100;
show_buffer[1]=count_b%100/10;
show_buffer[0]=count_b%10;
if(show_buffer[2]==0)//高位为0时不显示
{
show_buffer[2]=10;
//高位为0时,第二位为0,也不显示
if(show_buffer[1]==0)
show_buffer[1]=10;
}
for(i=0;i<6;i++)
{
P0=0xFF;//暂时关闭段码
P2=scan_bits[i];//位码
P0=CA_Table[show_buffer[i]];//段码
delay_ms(1);
}
}
void main()
{
IT0=1;//下降沿触发
IT1=1;
PX0=1;//设置优先级
IE=0x85;//允许INT0,INT1中断
while(1)
{
if(!K3)//清零
count_a=0;
if(!K4)//清零
count_b=0;
refresh_show();//持续则刷新显示
}
}
//INT0中断函数
void ex_int0() interrupt 0
{
EA=0;//禁止中断
delay_ms(10);//消抖
count_a++;//计数值递增
EA=1;//开中断
}
//INT1中断函数
void ex_int1() interrupt 2
{
EA=0;//禁止中断
delay_ms(10);//消抖
count_b++;//计数值递增
EA=1;//开中断
}
单片机案例13
结合proteus和keil
13 TIMER0控制单只LED闪烁
原理图
程序
/*
名称:定时器控制单只LED闪烁
说明:TIMER0控制LED闪烁
*/
#include<reg51.h>
#define INT8U unsigned char
#define INT16U unsigned int
INT16U count=0;
//主程序
void main()
{
TMOD=0x00;//T0工作于模式0(13位模式)
//5ms定时
TH0=(8192-5000)>>5;//等同于:TH0=(8192-5000)/32;
TL0=(8192-5000)&0x1F;//等同于:TH0=(8192-5000)%32;
IE=0x82;//允许T0中断
TR0=1;//启动T0
while(1);
}
//T0中断函数
void led_flash() interrupt 1
{
TH0=(8192-5000)>>5;
TL0=(8192-5000)&0x1F;
if(++count==50)//累加形成5ms*50=250ms定时开关LED
{
P0=~P0;//P0端口的LED整体闪烁
count=0;
}
}
单片机案例14
结合proteus和keil
14 定时器控制数码管显示
原理图
程序
/*
名称:TIMER0控制数码管动态显示
说明:数码管显示:年月日时分秒
使用定时器实现
*/
#include<reg51.h>
#include<intrins.h>
#define INT8U unsigned char
#define INT16U unsigned int
#define METHOD1 1
//共阳极0-9的数码管段码表
code INT8U CA_Table[]=
{
0xC0,0xF9,
0xA4,0xB0,
0x99,0x92,
0x82,0xF8,
0x80,0x90,
0xBF//'-'的段码,索引为10
};
//待显示数据
code INT8U show_date[][8]=
{
{2,2,10,0,2,10,1,4},
{2,3,10,5,9,10,5,9}
};
INT8U i=0;
INT8U j=0;
INT16U t=0;
#if METHOD1
//主程序:使用方法1,使用定时器中断控制数码管刷新显示
void main()
{
TMOD=0x01;//T0工作于模式1(16位模式)
//4ms定时
TH0=(65536-5000)>>8;
TL0=(65536-5000)&0xFF;
IE=0x82;//允许T0中断
TR0=1;//启动T0
while(1);
}
#else
//方法2:不使用定时器中断控制,不需要中断函数
void main()
{
TMOD=0x01;//T0工作于模式1(16位模式)
//4ms定时
TH0=(65536-5000)>>8;
TL0=(65536-5000)&0xFF;
IE=0x82;//允许T0中断
TR0=1;//启动T0
while(1)
{
if(TF0)
{
TF0=0;
TH0=(65536-5000)>>8;
TL0=(65536-5000)&0xFF;
P0=0xFF;//先暂时关闭段码
P2=~(1<<j);//输出位码
P0=CA_Table[show_date[i][j]];//输出段码
j=(j+1)%8;//数组第i行的下一数字索引
if(++t!=350)//每组的8个字符位保持刷新一段时间
continue;
t=0;
//刷新若干遍后切换
i=(i+1)%2;//数组行i=0时,显示年月日,i=1时显示时分秒
}
}
}
#endif
//T0中断函数
void seg_show() interrupt 1
{
TH0=(65536-5000)>>8;
TL0=(65536-5000)&0xFF;
P0=0xFF;//先暂时关闭段码
P2=~(1<<j);//输出位码
P0=CA_Table[show_date[i][j]];//输出段码
j=(j+1)%8;//数组第i行的下一数字索引
if(++t!=350)//每组的8个字符位保持刷新一段时间
return;
t=0;
//刷新若干遍后切换
i=(i+1)%2;//数组行i=0时,显示年月日,i=1时显示时分秒
}
单片机案例15
结合proteus和keil
15 定时器控制8乘8点阵显示
原理图
程序
/*
名称:TIMER0控制8*8点阵显示数字
说明:点阵屏显示:0-9
使用T0定时器溢出中断实现
*/
#include<reg51.h>
#include<intrins.h>
#define INT8U unsigned char
#define INT16U unsigned int
//数字点阵
INT8U code DotMatrix[] =
{
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
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
};
//主程序
void main()
{
TMOD=0x00;//T0工作于模式0(13位模式)
//2ms定时
TH0=(8192-2000)>>5;
TL0=(8192-2000)&0x1F;
TR0=1;//启动T0
IE=0x82;//允许T0中断
while(1);
}
//T0中断函数
void seg_show() interrupt 1
{
static INT8U i=0;
static INT8U num_idx=0;
static INT8U t=0;
TH0=(8192-2000)>>5;
TL0=(8192-2000)&0x1F;
P2=0xFF;//先暂时关闭段码
P3=1<<i;//输出列码(列共阳)
P2=~DotMatrix[num_idx*8+i];//输出行码
if(++i==8)//每屏一个数字点阵由8个字节构成
i=0;
if(++t==200)//每个数字刷新显示一段时间
{
t=0x00;
if(++num_idx==10)
num_idx=0;//显示下一个数字
}
}
单片机案例16
结合proteus和keil
16 TIMER0控制蜂鸣器发出门铃声
原理图
程序
/*
名称:TIMER0控制门铃声输出
说明:按下按键时,蜂鸣器发出叮咚的门铃声
*/
#include<reg51.h>
#include<intrins.h>
#define INT8U unsigned char
#define INT16U unsigned int
sbit key=P1^7;
sbit doorBell=P3^0;
INT16U p=0;
//延时函数
void delay_ms(INT16U x)
{
INT8U t;
while(x--);
for(t=0;t<120;t++);
}
//主程序
void main()
{
IE=0x82;//允许T0中断
TMOD=0x00;//T0工作于模式0(13位模式)
//初始定时700us
TH0=(8192-1000)/32;
TL0=(8192-1000)%32;
while(1)
{
if(key==0)//按下K1时,启动定时器
{
delay_ms(10);//消抖
if(key==0)//按键释放后启动T1
{
while(!key);
TR0=1;
}
}
}
while(1);
}
//T0中断函数
void timer0() interrupt 1
{
doorBell=~doorBell;
p++;
//调整400和800,将声音拖长
//高音
if(p<400)
{
TH0=(8192-700)/32;
TL0=(8192-700)%32;
}
else if(p<800)//低音
{
TH0=(8192-1000)/32;
TL0=(8192-1000)%32;
}
else//关闭
{
TR0=0;
p=0;
}
}
单片机案例17
结合proteus和keil
17 TIMER0控制交通指示灯
原理图
程序
/*
名称:TIMER0控制交通指示灯
说明:绿灯黄灯红灯根据设置循环闪烁
*/
#include<reg52.h>
#define INT8U unsigned char
#define INT16U unsigned int
sbit RED_EW=P0^0;//东西方向
sbit YELLOW_EW=P0^1;
sbit GREEN_EW=P0^2;
sbit RED_SN=P0^3;//南北方向
sbit YELLOW_SN=P0^4;
sbit GREEN_SN=P0^5;
//延时倍数
INT8U Time_Count=0;
//闪烁次数
INT8U Flash_Count=0;
//灯闪烁方式
INT8U type=1;
//T0中断
void Timer0() interrupt 1
{
TH0=-50000/256;
TL0=-50000%256;
switch(type)
{
case 1:
{
//东西方向绿灯亮
RED_EW=0;
YELLOW_EW=0;
GREEN_EW=1;
//南北方向红灯亮
RED_SN=1;
YELLOW_SN=0;
GREEN_SN=0;
//5s
if(++Time_Count!=100)
return;
Time_Count=0;
type=2;//切换变化方式
break;
}
case 2:
{
if(++Time_Count!=8)
return;
Time_Count=0;
//关闭绿灯
GREEN_EW=0;
//东西方向黄灯闪烁
YELLOW_EW=~YELLOW_EW;
if(++Flash_Count!=10)
return;
Flash_Count=0;
type=3;
break;
}
case 3:
{
//东西方向红灯亮
RED_EW=1;
YELLOW_EW=0;
GREEN_EW=0;
//南北方向绿灯亮
RED_SN=0;
YELLOW_SN=0;
GREEN_SN=1;
if(++Time_Count!=100)
return;
Time_Count=0;
type=4;
break;
}
case 4:
{
if(++Time_Count!=8)
return;
Time_Count=0;
//南北方向黄灯闪烁
YELLOW_SN=~YELLOW_SN;
GREEN_SN=0;
if(++Flash_Count!=10)
return;
Flash_Count=0;
type=1;//循环
}
}
}
//主程序
void main()
{
TMOD=0x01;//定时器0工作在方式1
IE=0x82;//允许定时器0中断
TR0=1;//启动定时器0
while(1);
}
单片机案例18
结合proteus和keil
18 TIMER1控制音阶演奏
原理图
程序
/*
名称:TIMER1控制音阶演奏
说明:使用定时器中断控制演奏一段音阶,K1控制播放
*/
#include<reg52.h>
#include<intrins.h>
#define INT8U unsigned char
#define INT16U unsigned int
INT8U i=0;//音符索引
sbit SPK=P2^0;//扬声器输出引脚
sbit K1=P3^6;//按键输入引脚
//14个音符在TIMER1模式0下的定时/计数寄存器初值表
code INT8U hight_list[]=
{
0,226,229,232,234,
236,238,240,241,243,
244,245,246,247,248
};
code INT8U lower_list[]=
{
0,4,12,9,20,
2,8,6,2,22,
5,26,1,4,2
};
//延时
void delay_ms(INT16U x)
{
INT8U t;
while(x--)
{
for(t=0;t<120;t++);
}
}
//T1中断
void Timer1() interrupt 3
{
SPK=!SPK;//音频脉冲输出
TH1=hight_list[i];//加载第i个音符的延时初值
TL1=lower_list[i];
}
//主程序
void main()
{
IE=0x88;//T1中断
TMOD=0x00;//模式0
while(1)
{
if(!K1)
{
delay_ms(10);//消抖
if(!K1)
{
for(i=1;i<15;i++)//输出14个音符
{
TR1=1;
delay_ms(500);//播放一个音符
TR1=0;
delay_ms(50);//播放停顿50ms
}
}
}
}
}
单片机案例19
结合proteus和keil
19 T0T1T2实现外部计数二进制显示
原理图
程序
/*
名称:TIMER0,TIMER1,TIMER2实现外部信号计数与显示
说明:T0,T1均工作于计数器方式,T2工作于16位自动重装方式
均实现了对外部输入信号的计数功能
计数值最大均为65535,即:0xFFFF
*/
#include<reg52.h>
sfr T2MOD =0xC9;//reg52.h中没定义,在此添加sfr定义
sbit SW1=P1^5;
sbit SW2=P1^6;
sbit SW3=P1^7;
//主程序
void main()
{
//设置T/C0,T/C1为计数器,工作于方式1(16位)
TMOD=0x55;
//设置T2引脚计数时钟输入,默认为递增计数
T2MOD=0x00;
//设置TIMER2为计数器
C_T2=1;
//T2工作于自动重装模式(上溢时重装0x0000)
RCAP2H=0x00;
RCAP2L=0x00;
//三者初值均为0x00
TH0=0x00;
TL0=0x00;
TH1=0x00;
TL1=0x00;
TH2=0x00;
TL2=0x00;
//启动三个定时器/计数器
TR0=1;
TR1=1;
TR2=1;
while(1)
{
if(!SW1)//通过P2,P0端口显示T0二进制计数值
{
P2=~TH0;
P0=~TL0;
}
else if(!SW2)//通过P2,P0端口显示T1二进制计数值
{
P2=~TH1;
P0=~TL1;
}
else if(!SW3)//通过P2,P0端口显示T2二进制计数值
{
P2=~TH2;
P0=~TL2;
}
}
}
单片机案例20
结合proteus和keil
20 T0T1INT0中断控制报警器与旋转灯
原理图
程序
/*
名称:TIMER0,TIMER1,INT0中断控制报警器与旋转灯
说明:定时器控制报警灯旋转显示,并发出警报声
*/
#include<reg52.h>
#include<intrins.h>
#define INT8U unsigned char
#define INT16U unsigned int
sbit SPK=P3^7;
INT8U FRQ=0x00;
//延时
void delay_ms(INT16U x)
{
INT8U t;
while(x--)
{
for(t=0;t<120;t++);
}
}
//主程序
void main()
{
P2=0x00;//关闭所有LED
TMOD=0x11;//两个定时器均工作在模式1
TH0=0xFE;//定时器初值为0xFE00
TL0=0x00;
IT0=1;//下降沿触发INT0中断
IE=0x8B;//开启0,1,3号中断(INT0,T0,T1)
IP=0x01;//INT0设为高优先级
TR0=0;//定时器启停由INT0中断控制,初始为关闭
TR1=0;
while(1)//循环过程中递增频率,溢出后再次递增
{
FRQ++;
delay_ms(1);
}
}
//INT0中断
void ex0_int() interrupt 0
{
TR0=!TR0;//开启或停止两个定时器,分别控制报警声和LED旋转
TR1=!TR1;
if(P2==0x00)
P2=0xE0;//开启三个灯旋转(0xE0即1110 0000)
else
P2=0x00;//关闭所有LED
}
//TIMER0中断
void Timer0() interrupt 1
{
TH0=0xFE;
TL0=FRQ;
SPK=~SPK;
}
//TIEMR1中断
void Timer1() interrupt 3
{
TH1=-45000>>8;
TL1=-45000&0x1F;
P2=_crol_(P2,1);
}
如果觉得对你有帮助的话,不妨点个赞呗^_^