定时器0控制LED流水灯方向调转及定时器时钟

本文详细介绍了如何使用STM8单片机的定时器0控制LED灯以1s为周期闪烁,并处理了与外设I/O口的冲突问题。随后扩展至定时器控制流水灯方向和实现基本时钟显示功能。
摘要由CSDN通过智能技术生成

一、定时器以一秒为单位计数

上篇文章写到:12.00MHz的晶振分频之后,就是1MHz振动一百万次,也就是1ms.

如果使用STC-ISP进行操作,可以直接从软件里面获取想要的定时器配置:

那么我们怎么样才能知道单片机定时器是否以1s钟为单位进行计数?我们只需要在中断里面加入一个判断,脉冲信号以1MHz为单位发出,也就是1ms,那么我们只需要接受1000次,就是1s。如何进行检测是不是成功了?

——通过实现定时器控制LED灯1s闪烁一次进行观察

代码如下:

#include <REGX52.H>

void time0_init(void)
{
	TMOD|=0X01;//选择为定时器0模式,工作方式1
	TH0=0XFC;	//给定时器赋初值,定时1ms
	TL0=0X18;	
	ET0=1;//打开定时器0中断允许
	EA=1;//打开总中断
	TR0=1;//打开定时器		
}

void main()
{
		Timer0_Init();
		while(1)
		{
		
		
		}
}

void Timer0_Routine()   interrupt 1
{ 
   static	unsigned int T0count = 0;
	T0count++;    //进入一次中断就+1,意味着过了1ms
	TH0=0XFC;	//重新开始,就像一个沙漏一样,这个沙漏流完刚好是1ms,我得给它倒过来,重新开始1ms
	TL0=0X18;
	
	if(T0count == 1000) //当T0count数量达到1000次,也就是1ms过去了1000次(即1s)
	{ 
		P1_0 =~ P1_0;   //我就开始闪烁一次
		T0count = 0;   //然后再把1s归0,重新开始计数,这样子循环,灯就实现了以1s为周期闪烁
	}

}

在实现这个功能的时候遇到了以下问题原先的代码运行后,出现灯常亮的情况

后面经过调试,修改了if语句里面的命令,让一个灯灭和另外一个灯亮,结果发现两个灯都保持常亮,也就是说无论我给高电平还是低电平我的灯都亮,如果把LCD1602拔下才能正常实现功能。

也就是说:我们在运行的时候,要注意其他外设所用到的I/O口和你所设置的I/O口是否冲突,否则就会出现我这样的情况。

二、定时器0控制LED流水灯方向调转

我想要实现:

LED正常流水灯的情况下,按下按键1,调转方向,如果再次按下键1就再次调转方向

代码如下:

1、首先先看流水灯如何实现

#include "TIMER0.H"
#include "Key.h"
#include <INTRINS.H>

unsigned char KeyNumber,LEDMODE; //均默认为0

void main()
{
	  P3 = 0xFE;    //1111 1110 先让第一个小灯点亮
		Timer0_Init(); //定时器0初始化
		while(1)
		{
		  KeyNumber = Key();  
			if(KeyNumber != 0)  //如果有按键按下(我们先讲不按下按键流水灯怎么实现,忽略不看)
			{
			  if(KeyNumber == 1)
				{
				   LEDMODE++;
					if(LEDMODE >= 2)
					{
					   LEDMODE = 0;
					}
				}			
			}
		}
}

void Timer0_Routine()   interrupt 1    //因为没有按键按下,所以我们来到中断系统
{ 
   static	unsigned int T0count = 0; 
	TL0 = 0x18;		//设置定时初值		
	TH0 = 0xFC;	   
	T0count++;     //T0count计数
	
	if(T0count >= 1000) // 达到1s后
	{ 
		T0count = 0;   
		if(LEDMODE == 0)  //如果LEDMODE等于0
		{
		  P3 =_crol_(P3,1) ;  //P3口左移一位,也就是第二个灯点亮,一开始的第一个灯熄灭,就是这样子实现流水灯
		}
 
	}
}

2、通过按键控制:(完整代码)

#include "TIMER0.H"
#include "Key.h"
#include <INTRINS.H>

unsigned char KeyNumber,LEDMODE;

void main()
{
	  P3 = 0xFE;
		Timer0_Init();
		while(1)
		{
		  KeyNumber = Key();
			if(KeyNumber != 0)   //如果按键按下
			{
			  if(KeyNumber == 1)  //且按下按键1
				{
				   LEDMODE++;     //LEDMODE = 1;
					if(LEDMODE >= 2)  //如大于等于2,就为0,也就是说我确保LEDMODE只能为0或1
					{
					   LEDMODE = 0;
					}
				}			
			}
		}
}

void Timer0_Routine()   interrupt 1
{ 
   static	unsigned int T0count = 0;
	TL0 = 0x18;				
	TH0 = 0xFC;	
	T0count++;
	
	if(T0count >= 1000)
	{ 
		T0count = 0;
		if(LEDMODE == 0)    //LEDMODE是0,就左移
		{
		  P3 =_crol_(P3,1) ;
		}
		if(LEDMODE == 1)  //LEDMODE是1,就右移
		{
		  P3 = _cror_(P3,1);
		}
 
	}
}

三、定时器时钟

理解了上面两个程序,这个就更好理解了

想要实现下面这样:

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "Timer0.h"

unsigned char Sec,Min,Hour;

void main()
{
	LCD_Init();
	Timer0Init();
	
	LCD_ShowString(1,1,"Clock:");	//上电显示静态字符串
	LCD_ShowString(2,1,"  :  :");
	
	while(1)
	{
		LCD_ShowNum(2,1,Hour,2);	//显示时分秒
		LCD_ShowNum(2,4,Min,2);
		LCD_ShowNum(2,7,Sec,2);
	}
}

void Timer0_Routine() interrupt 1
{
	static unsigned int T0Count;
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	T0Count++;
	if(T0Count>=1000)	//定时器分频,1s
	{
		T0Count=0;
		Sec++;			//1秒到,Sec自增
		if(Sec>=60)
		{
			Sec=0;		//60秒到,Sec清0,Min自增
			Min++;
			if(Min>=60)
			{
				Min=0;	//60分钟到,Min清0,Hour自增
				Hour++;
				if(Hour>=24)
				{
					Hour=0;	//24小时到,Hour清0
				}
			}
		}
	}
}
  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值