写在前面
这篇博客介绍下用定时器来产生占空比不同的方波,完成了呼吸灯的效果,同时可以实现多个led灯同时呼吸形成类似流水的效果。
主要用到定时器0来形成一个1ms的中断,每次进入中断服务程序会让小灯当前处于的周期加1,用这个周期与设定的亮x个周期对比,这样就可以让小灯占空比改变,让这个x改变就可以让小灯形成呼吸效果。
MCU:STC12C5A60S2 平台:普中HC6800-ES V2.0
所有代码如下:
/**************************************************************************************
* 流动呼吸灯 *
实现现象:上电之后,每个LED小灯都在以不同的占空比在呼吸,每个小灯的占空比差是10%
注意事项:
***************************************************************************************/
#include <reg52.h>
typedef unsigned char uint8;
typedef unsigned int uint16;
//************************************************端口声明
sbit led1 = P2^0;
sbit led2 = P2^1;
sbit led3 = P2^2;
sbit led4 = P2^3;
sbit led5 = P2^4;
sbit led6 = P2^5;
sbit led7 = P2^6;
sbit led8 = P2^7;
//************************************************变量
uint8 all_round,change_time;
uint8 duty=1,duty1=2,duty2=3,duty3=4,duty4=5,duty5=6,duty6=7,duty7=8;
bit flag,flag1,flag2,flag3,flag4,flag5,flag6,flag7;
//************************************************初始化中断、中断服务函数
void timer0_init(){
EA = 0; //关闭总中断
TR0 = 0; //关闭定时器
TMOD = 0X01;
TH0 = 0XFC; //1MS中断一次
TL0 = 0X67;
ET0 = 1; //允许定时器0中断
EA = 1; //开总中断
TR0 = 1; //开定时器
}
void isr_timer0 () interrupt 1 using 0{
TMOD = 0X01;
TH0 = 0XFC; //1MS中断一次
if(++all_round > 10){
all_round = 0; //LED当前的周期,1MS自增1,到10清零,共10个周期
}
if(++change_time > 80){ //80MS改变一次占空比
change_time = 0;
if(!flag) { //flag=0 从暗变亮
if(++duty > 10) { //duty每10个周期改变flag的值
flag = 1;
}
}
else{
if(--duty < 2){ //flag=1 从亮变暗
flag = 0; //duty如果等与0,小灯会灭,即0%占空比,所以这里让duty=1时就改变方向
}
}
//******************************************************************//
if(!flag1) { //同flag
if(++duty1 > 10) {
flag1 = 1;
}
}
else{
if(--duty1 < 2){
flag1 = 0;
}
}
//******************************************************************//
if(!flag2) {
if(++duty2 > 10) {
flag2 = 1;
}
}
else{
if(--duty2 < 2){
flag2 = 0;
}
}
//******************************************************************//
if(!flag3) {
if(++duty3 > 10) {
flag3 = 1;
}
}
else{
if(--duty3 < 2){
flag3 = 0;
}
}
//******************************************************************//
if(!flag4) {
if(++duty4 > 10) {
flag4 = 1;
}
}
else{
if(--duty4 < 2){
flag4 = 0;
}
}
//******************************************************************//
if(!flag5) {
if(++duty5 > 10) {
flag5 = 1;
}
}
else{
if(--duty5 < 2){
flag5 = 0;
}
}
//******************************************************************//
if(!flag6) {
if(++duty6 > 10) {
flag6 = 1;
}
}
else{
if(--duty6 < 2){
flag6 = 0;
}
}
//******************************************************************//
if(!flag7) {
if(++duty7 > 10) {
flag7 = 1;
}
}
else{
if(--duty7 < 2){
flag7 = 0;
}
}
}
}
/*******************************************************************************
* 函数名 : display()
* 函数功能 :
* 输入 : 无
* 输出 : 无
* 备注 :
*******************************************************************************/
void display(){
if(all_round < duty){ //让当前周期与设定的占空比比较
led1 = 0; //当前周期小于设定的占空比就让小灯亮
}
else{
led1 = 1;
}
//******************************************************************//
if(all_round < duty1){ //同led1,但是duty1比duty多1
led2 = 0; //
}
else{
led2 = 1;
}
//******************************************************************//
if(all_round < duty2){
led3 = 0;
}
else{
led3 = 1;
}
//******************************************************************//
if(all_round < duty3){
led4 = 0;
}
else{
led4 = 1;
}
//******************************************************************//
if(all_round < duty4){
led5 = 0;
}
else{
led5 = 1;
}
//******************************************************************//
if(all_round < duty5){
led6 = 0;
}
else{
led6 = 1;
}
//******************************************************************//
if(all_round < duty6){
led7 = 0;
}
else{
led7 = 1;
}
//******************************************************************//
if(all_round < duty7){
led8 = 0;
}
else{
led8 = 1;
}
}
void main(){
timer0_init();
while(1){
display();
}
}
all_round代表当前处于的周期,duty代表设定的占空比高电平的值。初始状态duty-duty7分别是1-8,all_round每1ms加1,则初始时led1会亮1ms,灭9ms,占空比就是10%。保持60ms相同的占空比运行之后,duty会加1,led1的占空比就会变成20%。以此类推,当duty增加到10的时候,led1的占空比就变为了100%。然后duty会开始递减,灯的占空比也相应递减,当duty减到1的时候又会重新把flag清零进入递增的程序。
其他led的情况跟led1类似,只不过初始给这些led赋的初始占空比都相邻递增,所以当中断开起来之后,duty-duty7是同步递增的,这些灯的相邻占空比也一直保持10%的差距,形成了流水的效果。