Prouteus 定时中断 控制流水灯的实现

Prouteus 定时中断 控制流水灯的实现

我们一般51单片机使用的流水灯–跑马灯绝大多多数都是通过–软件Delay延时实现,但是这样会非常占用MCU时间,MCU就没有太多时间来处理其他的事情了!!

那如何避免这种情况的发生呢?

答案当然有–我们可以使用单片机的定时中断来实现!

以下是我在Ptroteus仿真环境下,两个按键控制流水灯不同模式的实现


实验电路:
在这里插入图片描述


实验现象:

按键没有按下时,LED按每1s时间从上往下亮下来,当按键1按下后,LED按相反方向-每1s时间从下往上依次亮灭,当按键2按下时,LED加快从上往下亮下来的速度(大约200ms左右)

实验程序:

/*
* 	本次实验的系统主频率为11.0592MHZ
*/
#include <REGX52.H>
#include <intrins.h>

typedef signed char sint8_t;
typedef signed short int sint16_t;
typedef signed long int sint32_t;

typedef unsigned char  uint8_t;
typedef unsigned short int  uint16_t;
typedef unsigned long int uint32_t;

uint8_t LED_Number[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

#define LED P1
#define NoKeyProcess 0
#define Key2_Press 	 2

uint8_t T0RH=0;
uint8_t T0RL=0;
bit Time_1s_Flag=0;
bit IT0_Flag=0;
sbit Key2=P3^4;

void Delayxms(uint16_t xms)		//@11.0592MHz
{
	unsigned char i, j;
	while(xms--)
	{
		_nop_();
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
	}
}



void TimerConfiger(unsigned int xms)
{
	unsigned  long temp;
	temp=11059200/12;
	temp=(temp*xms)/1000;
	temp=65536-temp; //定时器重载值
	TMOD&=0XF0;
	TMOD|=0X01; //定时器模式1 16位定时器
	T0RH=(uint8_t)(temp>>8);
	T0RL=(uint8_t)temp;
	TH0=T0RH;
	TL0=T0RL;
	ET0=1; //T0中断打开
	TR0=1; //T0定时器打开
}

/*按键处理函数*/
void Key_Process(uint8_t key_value)
{
	uint8_t i=0;
	switch(key_value)
	{
		case Key2_Press:
			for(i=0;i<8;i++)
			{
				LED=~(LED_Number[i]);
				Delayxms(200); //流水灯速度加快
			}
			break;
			default:break; //关闭LED
	}
}

/*Key2 Key3  按键状态机扫描函数 --10ms定时器中扫描*/
void vKey_Scan(){
	static uint8_t Key_Value=0,Key_status=0,priv_key_val =0;
	Key_Value|=(Key2==1)? NoKeyProcess:Key2_Press;
	switch(Key_status)
	{
		case 0: //Key pressed
			if(Key_Value)
			{
				priv_key_val=Key_Value;
				Key_status++;
			}
		break;
		case 1: //Confirm key pressed
			if(priv_key_val==Key_Value)
			{
				Key_status++;
				Key_Process(priv_key_val); //按键处理函数
			}
			else
				Key_status=0;
			break;
		case 2:// Wait to release
			if(Key_Value =!=priv_key_val)
			{
				Key_status = 0;
				
			}
				break;
		default:break;
	}
}

void SystemInit()
{
		EA=1;  //中断总开关
		IT0=1; //下降沿触发Interrput 0中断
		EX0=1; //Interrput 0中断控制位
}

void main()
{
	uint8_t i=0;
	SystemInit();
	/*Interrupt0 下降沿触发*/
	TimerConfiger(10);
	while(1)
	{
		if(Time_1s_Flag)
		{
			Time_1s_Flag=0;
			LED=~(LED_Number[i]);
			i++;
			if(i==8)
				i=0;
		}
		if(IT0_Flag) //Interrupt 0中断发生标志位
		{
			IT0_Flag=0;
			i--;
			for(i;i>0;i--)
			{
				LED=~(LED_Number[i]);
				Delayxms(1000); //流水灯速度加快
			}
		}
	}
}

void Timer0_ISR() interrupt 1 //TIM0 中断服务函数
{
	 static uint8_t timer_1s=0;
		TH0=T0RH;
		TL0=T0RL;
		if(++timer_1s>=100)
		{
			timer_1s=0;
			Time_1s_Flag=1;
		}
		vKey_Scan();
}

void IT0_ISR() interrupt 0  //Interrput 0 中断服务函数
{
	IT0_Flag=1;
}

实验总结:

本次实验使用了Interrupt 0中断控制 P32引脚下降沿(从高电平到低电平触发Interrupt 0中断)和TImer0 定时中断 定时10ms(经典滤波时间!) --并在10ms定时中完成按键检测 --按键检测采用状态机的编程思想

  • 6
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为你提供思路和代码示例。流水是一个非常简单的电路,它的原理是利用单片机的GPIO口依次控制LED的亮灭,从而实现LED的流动效果。在中断控制下,我们可以让流水更加精确地控制闪烁的频率和节奏。 以下是一个基于C51单片机的流水程序,使用了定时中断实现控制: ```c #include <reg51.h> sbit led1 = P1^0; //LED1连接到P1.0口 sbit led2 = P1^1; //LED2连接到P1.1口 sbit led3 = P1^2; //LED3连接到P1.2口 sbit led4 = P1^3; //LED4连接到P1.3口 unsigned char led_state = 0; //当前LED状态 unsigned char timer_count = 0; //定时器计数器 //定时中断服务程序 void timer0_isr() interrupt 1 { TH0 = 0xfc; //重置计数器高位 TL0 = 0x67; //重置计数器低位 timer_count++; //计数器加1 if(timer_count == 50) //50个中断周期之后,改变LED状态 { timer_count = 0; //重置计数器 led_state++; //改变LED状态 if(led_state > 0x0f) //超过四个LED,重置状态 { led_state = 0; } P1 = ~led_state; //输出LED状态 } } void main() { TMOD = 0x01; //定时器0工作在模式1下 TH0 = 0xfc; //重置计数器高位 TL0 = 0x67; //重置计数器低位 ET0 = 1; //打开定时器0中断 EA = 1; //打开总中断 TR0 = 1; //启动定时器0 while(1); //程序死循环 } ``` 在这个程序中,我们使用了定时器0来产生一个中断,每50个中断周期之后改变LED的亮灭状态,从而实现流水的效果。定时器0的计数值是65536-5000=60536,这样可以让定时器每1ms产生一个中断。在中断服务程序中,我们使用了一个计数器timer_count来计算中断周期,并利用led_state变量来表示当前的LED状态,最后通过P1口输出LED状态。 你可以根据需要修改程序中的定时器计数值和LED状态,来实现不同的流水效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值