一、51呼吸灯
1.先在proteus中绘制原理图
a.51单片机最小系统包含电源电路、晶振电路、复位电路
b.使用的器件:AT89C51 、 BUTTONCAP、CAP-POL、CRYSTAL、LED-RED、LED-YELLOW、RES、RESPACK-8
c.注意:R2为限流电阻,将它的阻值调低一点,灯会亮的更明显,但不能低于一定值,否则会烧坏单片机
2、在keil中写程序
#include <REG51.h>//此文件中定义了有关51单片机的一些特殊功能寄存器
sbit LED1=P2^0;//位地址的声明。LED1接的I/O口的引脚是P2.0;P要大写,sbit小写
void delay(unsigned int i)//延时函数
{
unsigned int time;
for(;i>0;i--);//i的初始值在传参过来时,就知道了
}
void main(void)
{
while(1)
{
unsigned int t,j;
for(t=0;t<100;t++)//每经过一次循环,小灯的亮度程度就会发生改变。
{//暗到亮。每一次循环,通过改变灯亮和灯灭的延时时间,使灯处于不同状态(不同亮度)
for(j=0;j<20;j++)//让每一个状态(灯所处亮度)停留久一点
{
LED1=0;//发光
delay(t);
LED1=1;//灯灭
delay(100-t);
}
}
for(t=100;t>0;t--)
{//灯由亮到暗
for(j=0;j<20;j++)
{
LED1=0;
delay(t);
LED1=1;
delay(100-t);
}
}
}
}
注意:为了保证周期是恒定的,不随占空比的变化而变化,所以一般会保证亮的delay中的数值(第18行)和灭的delay中的数值(第20行)加起来是一个固定值(100),那么它的PWM的周期就是一个固定值。
3、将程序烧录到proteus,运行得到效果
二、51时钟
1、先在proteus中绘制原理图
2、在keil中写程序
#include<reg51.h> //单独控制某个引脚的电平不能直接写P3^0=1,必须先定义引脚 sbit key0 = P3^0 ; sbit key1 = P3^1 ; sbit key2 = P3^2 ; unsigned char s[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //共阴数码管0~9(此处作时钟用,只需显示0~9) unsigned char a = 0 , hour = 0, min = 0 , sec = 0 ; unsigned char b = 0 , c = 0 , d = 0;//用于key函数中的条件判断 //定时器0中断服务函数 void time0() interrupt 1 // interrupt是中断特有的关键字,后面接1表示定时器中断0 {//晶振为11.0592MHZ,则时钟周期为1/11059200,机器周期为12/11059200,给T0赋初值0x4c00,定时50ms TH0 = 0x4c ; //TH0:存储定时器0的计数值的高字节(65536-50000)/256 TL0 = 0x00 ; //存储定时器0的计数值的低字节(65536-50000)%256 a++; //中断次数计数值加1 if(a == 20) //20 * 50 = 1000ms = 1s 即每隔1s“秒”加1 { a = 0 ; sec = sec + 1 ; } if(sec == 60) //sec=60时清空,“分”加1 { min = min + 1 ; sec = 0 ; } if(min == 60) //min=60时清空,“时”加1 { hour = hour + 1 ; min = 0 ; } if(hour == 24) //hour=24时清空 { hour = 0 ; } } void init_t0() //初始化 { TMOD = 0x01 ; //TMOD控制定时器的工作模式,此刻采用TH0和TL0组成的16位定时器 TH0 = 0x4C ; //定时,0.05s,要经过x个机器周期的到0.05s ,计算的x=46080,16位定时器的溢出值为65536. TL0 = 0x00 ; // 先给TH0、TL0赋初值,让它们经过46080个机器周期后刚好溢出 EA = 1 ; //总中断开关,相当于电闸 ET0 = 1 ; //使能定时器0中断 , TR0 = 1 ; //定时器0启动控制 } void delay(unsigned int n) //延时函数(运行空项目以达到延迟时间的效果) { unsigned int i; while(n--) { for(i = 0 ; i < 120 ; i ++); } } void display1() //在数码管上显示 { unsigned char t0 = 0 ,t1 = 0 , t2 = 0 , t3 = 0 , t4 = 0 , t5 = 0 ; t0 = hour / 10 ; //t0表示"时"的十位 t1 = hour % 10 ; //t1表示"时"的个位 t2 = min / 10 ; //t2表示"分"的十位 t3 = min % 10 ; //t3表示"分"的个位 t4 = sec / 10 ; //t4表示"秒"的十位 t5 = sec % 10 ; //t5表示"秒"的个位 P2 = 0x7f ; //P2^7低电平 0111 1111 控制第一个数码管 。因为是共阴的接法,所以低电平有效 P0 = s[t0] ; //用来显示“时”的十位 delay(1) ; //延时大约1ms P2 = 0xbf ; //P2^6低电平 1011 1111 控制第二个数码管 P0 = s[t1] ; //用来显示“时”的个位 delay(1) ; P2 = 0xdf ; //P2^5低电平 1101 1111 控制第三个数码管 P0 = 0x40 ; //显示“—”来分割“时”与“分” delay(1) ; P2 = 0xef ; //P2^4低电平 1110 1111 控制第四个数码管 P0 = s[t2] ; //用来显示“分”的十位 delay(1) ; P2 = 0xf7 ; //P2^3低电平 1111 0111 控制第五个数码管 P0 = s[t3] ; //用来显示“分”的个位 delay(1) ; P2 = 0xfb ; //P2^2低电平 1111 1011 控制第六个数码管 P0 = 0x40 ; //显示“—”来分割“分”与“秒” delay(1) ; P2 = 0xfd ; //P2^1低电平 1111 1101 控制第七个数码管 P0 = s[t4] ; //用来显示“秒”的十位 delay(1) ; P2 = 0xfe ; //P2^0低电平 1111 1110 控制第八个数码管 P0 = s[t5] ; //用来显示“秒”的个位 delay(1) ; } void KEY0() //此处KEY函数的作用:手动(按按键)改变hour、min、sec的值。开关0控制“时”加1。 { if(key0 == 0 && c == 0) { c = 1 ; } if(key0 == 1 && c == 1) { c = 0 ; hour = hour + 1 ; } } void KEY1() //开关1控制“分”加1 { if(key1 == 0 && d == 0) { d = 1 ; } if(key1 == 1 && d == 1) { d = 0 ; min = min + 1 ; } } void KEY2() //开关2控制“秒”加1 { if(key2 == 0 && b == 0) { b = 1 ; } if(key2 == 1 && b == 1)//按下按键后key2就等于1了,松开后key2就是0了 { b = 0 ; sec = sec + 1 ; } } void main() //主函数 { init_t0(); while(1) { KEY0(); KEY1(); KEY2(); display1(); } }
3、烧录、运行
a.时钟周期T是最小的时间单位,是晶振频率的倒数。
b.机器周期是单片机完成一个操作的最短时间。51单片机中,一个机器周期等于12个时钟周期。
c.此处用到了定时器中断,其程序有固定格式
感想:在通过视频学习后,我对这两个软件稍微了解了些。以我现在的水平还无法完全独立写出程序,所以上述代码都参考了很多别人的代码,在稍微理解后,做了些修改使其更满足自己的需要。多看、多练、多查资料。如果有理解错的地方请指教。现在我还有很多不足,但也算迈出了第一步。