2014-08-06 01:11:42 Leytton 阅读数 2034
  • 定时器和计数-第1季第10部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第10个课程,主要内容是51单片机的定时器和计数器,本课程的学习目标是对定时器的作用和意义有深入理解,掌握通过操作寄存器来操作硬件的思路和方法。

    1965 人正在学习 去看看 朱有鹏

【转载请注明出处:http://blog.csdn.net/leytton/article/details/38393699


/*******************************************************************************
*	
* 软件功能:	 定时器中断实验
* 
*******************************************************************************/
#include "stm32f10x.h"
#include "delay.h"


void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void TIM3_Configuration(u16 arr,u16 psc);

/*************************************************
函数: int main(void)
功能: main主函数
参数: 无
返回: 无
**************************************************/
int main(void)
{
  RCC_Configuration();
  GPIO_Configuration();
  NVIC_Configuration();
  TIM3_Configuration(4999,7199);//10Khz的计数频率,计数到5000为500ms  
  //delay_init(72);
  GPIO_ResetBits(GPIOB,GPIO_Pin_0); 
  while(1);   
}


/*************************************************
函数: void RCC_Configuration(void)
功能: 复位和时钟控制 配置
参数: 无
返回: 无
**************************************************/
void RCC_Configuration(void)
{
  ErrorStatus HSEStartUpStatus;                    //定义外部高速晶体启动状态枚举变量
  RCC_DeInit();                                    //复位RCC外部设备寄存器到默认值
  RCC_HSEConfig(RCC_HSE_ON);                       //打开外部高速晶振
  HSEStartUpStatus = RCC_WaitForHSEStartUp();      //等待外部高速时钟准备好
  if(HSEStartUpStatus == SUCCESS)                  //外部高速时钟已经准别好
  {
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //开启FLASH预读缓冲功能,加速FLASH的读取。所有程序中必须的用法.位置:RCC初始化子函数里面,时钟起振之后
    FLASH_SetLatency(FLASH_Latency_2);                    //flash操作的延时
      	
    RCC_HCLKConfig(RCC_SYSCLK_Div1);               //配置AHB(HCLK)时钟等于==SYSCLK
    RCC_PCLK2Config(RCC_HCLK_Div1);                //配置APB2(PCLK2)钟==AHB时钟
    RCC_PCLK1Config(RCC_HCLK_Div2);                //配置APB1(PCLK1)钟==AHB1/2时钟
         
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);  //配置PLL时钟 == 外部高速晶体时钟 * 9 = 72MHz
    RCC_PLLCmd(ENABLE);                                   //使能PLL时钟
   
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)    //等待PLL时钟就绪
    {
    }
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);            //配置系统时钟 = PLL时钟
    while(RCC_GetSYSCLKSource() != 0x08)                  //检查PLL时钟是否作为系统时钟
    {
    }
  }
  
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);  //允许 GPIOB、AFIO时钟
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

}

/*************************************************
函数: void GPIO_Configuration(void)
功能: GPIO配置
参数: 无
返回: 无
**************************************************/
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;        //定义GPIO初始化结构体

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; 
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
  GPIO_Init(GPIOB, &GPIO_InitStructure); 	   //PB用于输出控制LED灯

}


void NVIC_Configuration(void)	 //中断分组和优先级配置	 详见《STM32的函数说明(中文).pdf》P165
{
    NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器
}

void TIM3_Configuration(u16 arr,u16 psc)	  //TIM3定时器配置   
{
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
 	/*((1+7199[TIM_Prescaler] )/72M)*(1+4999[TIM_Period] )=500,000us=500ms */ 

	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
	TIM_Cmd(TIM3, ENABLE);  //使能TIMx
}

//定时器3中断服务程序
void TIM3_IRQHandler(void)   //TIM3中断
{
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
		{
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx更新中断标志 
		if(!GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)) 	GPIO_SetBits(GPIOB,GPIO_Pin_0); 
		else   GPIO_ResetBits(GPIOB,GPIO_Pin_0); 
	}
}


2019-01-27 20:38:23 cax1165 阅读数 316
  • 定时器和计数-第1季第10部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第10个课程,主要内容是51单片机的定时器和计数器,本课程的学习目标是对定时器的作用和意义有深入理解,掌握通过操作寄存器来操作硬件的思路和方法。

    1965 人正在学习 去看看 朱有鹏

目的:通过定时器中断控制延时,使第一盏led的状态反转

开发板muc与led模块电路图如下:

关于定时器和计数器的要点请参考:https://blog.csdn.net/cax1165/article/details/86659302

关于中断的要点请参考:https://blog.csdn.net/cax1165/article/details/86633086

#include<reg52.h>
#define uc unsigned char
sbit led=P2^0;
void timeint0()
{
	TMOD=0X01;//工作方式
	TH0=0XFC;//定时1ms
	TL0=0X18;//定时1ms
	TR0=1;//控制
	ET0=1;//定时器0中断请求
	EA=1;//总中断
}
void time0int () interrupt 1//注意中断号
{
	static int i=0;//注意静态变量的使用!
	TH0=0XFC;//定时器复位
	TL0=0X18;//定时器复位
	i++;
	if(i==1000)//1000个1ms,构成1s
	{
		i=0;
		led=~led;//led状态反转
	}
}
void main()
{
	timeint0();
	while(1);
}

 

2015-11-26 21:28:29 chengdong1314 阅读数 1044
  • 定时器和计数-第1季第10部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第10个课程,主要内容是51单片机的定时器和计数器,本课程的学习目标是对定时器的作用和意义有深入理解,掌握通过操作寄存器来操作硬件的思路和方法。

    1965 人正在学习 去看看 朱有鹏

这篇文章讲51芯片内部各个模块的汇编程序,这里不做实验,只贴代码:

定时器模块程序:

中断地址,中断调用:

  ;-----------------------------------------------
  ORG 0000H  ;伪指令 告诉编译器从0000H开始
  LJMP MAIN  ;64KB无条件跳转 跳转到main处执行
  ORG 0003H     ;外部中断0中断入口
  LJMP exter0
  ORG 000BH     ;T0溢出中断入口
  LJMP time_0  
  ORG 0013H     ;外部中断1中断入口
  LJMP exter1  
  ORG 001BH     ;T1溢出中断入口
  LJMP time_1
  ORG 0100H  ;虽然这里是伪指令 但是确实有标明地址的作用
  ;-----------------------------------------------



主函数 main:

MAIN:
  MOV SP,#3FH   ;设置栈低为5FH
  MOV num,#00H
  MOV wei,#07H
  MOV TMOD,#11H
  MOV TH0,#4CH
  MOV TL0,#00H
  MOV TH1,#4CH
  MOV TL1,#00H
  SETB ET0   ;开定时中断
  CLR PT0    ;设置定时器0的中断优先级为低
  SETB TR0   ;开启定时器
  SETB ET1
  SETB PT1
  SETB TR1
  SETB EA      ;开总中断
  MOV num1,#00H  ;初始化数据
  MOV num2,#00H
  MOV LEDTEMP,#0FEH
  LCALL led_Static_display  ;数码管初始化
  ;********************死循环**********************



中断函数:

  ;================================================
  ;定时器0中断函数
  ;================================================
time_0:       
  PUSH DPH
  PUSH DPL
  PUSH PSW
  PUSH ACC
  MOV TH0,#4CH
  MOV TL0,#00H
  INC num1
  MOV A,num1
  CJNE A,#020, OVERtime_0
  INC num
  MOV A,num
  CJNE A,#010H,rigthnumtime_0
  MOV num,#00H
  rigthnumtime_0:
  LCALL led_Static_display
  MOV num1,#00H
  OVERtime_0:
  POP ACC
  POP PSW
  POP DPL
  POP DPH
  RETI        ;中断结束返回
  ;================================================
  ;定时器1中断函数
  ;================================================
time_1:       
  PUSH DPH
  PUSH DPL
  PUSH PSW
  PUSH ACC
  MOV TH1,#4CH
  MOV TL1,#00H
  INC num2
  MOV A,num2
  CJNE A,#02H, OVERtime_1
  MOV A,LEDTEMP
  RR A
  MOV LEDTEMP,A
  MOV LED_P,LEDTEMP
  MOV num2,#00H
  OVERtime_1:
  POP ACC
  POP PSW
  POP DPL
  POP DPH
  RETI        ;中断结束返回
  ;================================================
  ;数码管静态显示函数
  ;================================================



整个程序的代码:

  ;-----------------------数码管脚功能定义---------------------------   
  LED_wei EQU P2
  LED138_0 EQU P2.0
  LED138_1 EQU P2.1
  LED138_2 EQU P2.2
  LED_duan EQU P0
  LED_P EQU P1
  ;-------------------- 数码要显示的位、数据---------------------------
  wei EQU 30H    ;数码管位选
  num EQU 31H    ;数码管段选
  num1 EQU 32H    ;定时器0进中断数
  num2 EQU 33H    ;定时器1进中断数
  LEDTEMP EQU 34H    ;小灯数据暂存
  ;-----------------------------------------------
  ORG 0000H  ;伪指令 告诉编译器从0000H开始
  LJMP MAIN  ;64KB无条件跳转 跳转到main处执行
  ORG 0003H     ;外部中断0中断入口
  LJMP exter0
  ORG 000BH     ;T0溢出中断入口
  LJMP time_0  
  ORG 0013H     ;外部中断1中断入口
  LJMP exter1  
  ORG 001BH     ;T1溢出中断入口
  LJMP time_1
  ORG 0100H  ;虽然这里是伪指令 但是确实有标明地址的作用
  ;-----------------------------------------------
MAIN:
  MOV SP,#3FH   ;设置栈低为5FH
  MOV num,#00H
  MOV wei,#07H
  MOV TMOD,#11H
  MOV TH0,#4CH
  MOV TL0,#00H
  MOV TH1,#4CH
  MOV TL1,#00H
  SETB ET0   ;开定时中断
  CLR PT0    ;设置定时器0的中断优先级为低
  SETB TR0   ;开启定时器
  SETB ET1
  SETB PT1
  SETB TR1
  SETB EA      ;开总中断
  MOV num1,#00H  ;初始化数据
  MOV num2,#00H
  MOV LEDTEMP,#0FEH
  LCALL led_Static_display  ;数码管初始化
  ;********************死循环**********************
while1:
  LJMP while1
  ;================================================
  ;外部中断0函数
  ;================================================
exter0:    
  RETI        ;中断结束返回
  ;================================================
  ;外部中断1函数
  ;================================================
exter1:    
  RETI        ;中断结束返回
  ;================================================
  ;定时器0中断函数
  ;================================================
time_0:       
  PUSH DPH
  PUSH DPL
  PUSH PSW
  PUSH ACC
  MOV TH0,#4CH
  MOV TL0,#00H
  INC num1
  MOV A,num1
  CJNE A,#020, OVERtime_0
  INC num
  MOV A,num
  CJNE A,#010H,rigthnumtime_0
  MOV num,#00H
  rigthnumtime_0:
  LCALL led_Static_display
  MOV num1,#00H
  OVERtime_0:
  POP ACC
  POP PSW
  POP DPL
  POP DPH
  RETI        ;中断结束返回
  ;================================================
  ;定时器1中断函数
  ;================================================
time_1:       
  PUSH DPH
  PUSH DPL
  PUSH PSW
  PUSH ACC
  MOV TH1,#4CH
  MOV TL1,#00H
  INC num2
  MOV A,num2
  CJNE A,#02H, OVERtime_1
  MOV A,LEDTEMP
  RR A
  MOV LEDTEMP,A
  MOV LED_P,LEDTEMP
  MOV num2,#00H
  OVERtime_1:
  POP ACC
  POP PSW
  POP DPL
  POP DPH
  RETI        ;中断结束返回
  ;================================================
  ;数码管静态显示函数
  ;================================================
led_Static_display:
  ANL wei, #07H
  ANL LED_wei,#0F8H
  MOV A,wei
  ORL LED_wei,A
  MOV A,num  
  MOV DPTR,#numtab
  MOVC A,@A+DPTR  ;查表取数据
  MOV LED_duan,A
  RET
  ;================================================
  ;各种参数的延时子函数
  ;================================================
DELAY100us:     ;100us  
  MOV R6,#06H
  DEL11: MOV R7,#08H
  DEL12: DJNZ R7,DEL12
  DJNZ R6,DEL11
  RET

DELAY500us:    ;500us
  MOV R6,#0CH   ;288
  DEL21: MOV R7,#18H
  DEL22: DJNZ R7,DEL22
  DJNZ R6,DEL21
  RET
 
DELAY1ms:    ;1ms
  MOV R6,#18H   
  DEL61: MOV R7,#18H
  DEL62: DJNZ R7,DEL62
  DJNZ R6,DEL61
  RET

DELAY40ms:    ;延时40ms  500得1ms
  MOV R6,#100
  DEL41: MOV R7,#200
  DEL42: DJNZ R7,DEL42
  DJNZ R6,DEL41
  RET

DELAY256ms:        ;延时256ms
  MOV R5,#05H
  DEL51: MOV R6,#100
  DEL52: MOV R7,#0FFH
  DEL53: DJNZ R7,DEL53
  DJNZ R6,DEL52
  DJNZ R5,DEL51
  RET
 
DELAY500ms:        ;延时256ms
  MOV R5,#0AH
  DEL81: MOV R6,#100
  DEL82: MOV R7,#0FFH
  DEL83: DJNZ R7,DEL83
  DJNZ R6,DEL82
  DJNZ R5,DEL81
  RET
 
DELAY1s:    ;1秒
  MOV R5,#16H
  DEL31: MOV R6,#100
  DEL32: MOV R7,#0FFH
  DEL33: DJNZ R7,DEL33
  DJNZ R6,DEL32
  DJNZ R5,DEL31
  RET
 
DELAY10s:    ;10秒
  MOV R5,#0DCH
  DEL71: MOV R6,#100
  DEL72: MOV R7,#0FFH
  DEL73: DJNZ R7,DEL73
  DJNZ R6,DEL72
  DJNZ R5,DEL71
  RET
numtab: DB  03FH,006H,05BH,04FH,066H,06DH,07DH,007H,07FH,06FH,077H,07CH,039H,05EH,079H,071H,000H
end

keil工程整体源码:

keil工程整体源码:

51汇编之双定时器数码管流水灯-汇编

http://download.csdn.net/detail/chengdong1314/9303613

2016-10-13 12:14:48 phenixyf 阅读数 6723
  • 定时器和计数-第1季第10部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第10个课程,主要内容是51单片机的定时器和计数器,本课程的学习目标是对定时器的作用和意义有深入理解,掌握通过操作寄存器来操作硬件的思路和方法。

    1965 人正在学习 去看看 朱有鹏

程序运行开始,A灯先亮5秒,然后灭了到B灯亮5秒,B再灭再到C灯亮5秒,C灭,程序结束,不再运行。这程序该怎么写?用定时器精确定时……晶振11.092MHZ。

#include "REG52.H"

/*
*
*/
sbit      	LED_A	= P1^0;
sbit      	LED_B	= P1^1;
sbit      	LED_C	= P1^2;

unsigned char TIME_BASE;
unsigned char MACT_ENDB;
unsigned char Rece_Errp;

/*
*    定时器初始化
*/
void SystemInit(void)
{
	TMOD = 0x01;
	TH0 = (65536 - 45872) / 256;	 // 定时50ms  //晶振:11.0592MHZ
	TL0 = (65536 - 45872) % 256;
	ET0 = 1;
	TR0 = 1;
	EA  = 1;
}

int main(void)
{
	SystemInit();

	while(1)
	{
		/* 程序一开始上电Rece_Errp = 0 定时器5秒加一次 */
		if(Rece_Errp == 0)
		{
			LED_A = 0;		// A亮5秒
			LED_B = 1;		// B是灭
			LED_C = 1;		// C是灭
		}
		/* 判断是否5秒时间到 */
		else if(Rece_Errp ==1)
		{
			LED_A = 1;	 // A是灭
			LED_B = 0;	 // B亮5秒
			LED_C = 1;	 // C是灭	
		}
		else if(Rece_Errp == 2)
		{
			LED_A = 1;	// A是灭
			LED_B = 1;	// B是灭
			LED_C = 0;	// C亮5秒		
		}
		else
		{
			LED_A = 1;	 // A是灭
			LED_B = 1;	 // B是灭
			LED_C = 1;	 // C是灭
			while(1);	 // 程序运行到这里停止
		}				
	}
}

void Timer0_IRQ(void) interrupt 1
{
	TH0 = (655365 - 45872) / 256;
	TL0 = (655365 - 45872) % 256;
	/* 进入中断50ms +1次 */
	TIME_BASE++;
	
	if(TIME_BASE == 20)	 //	20ms * 50ms = 刚好等于1000ms 也就是1秒
	{
		TIME_BASE = 0;
		MACT_ENDB++;	// 一秒加一次
		if(MACT_ENDB == 5) // 等于刚好5秒时间到
		{
			MACT_ENDB = 0;
			Rece_Errp++;   // 用来切换LED A、B、C5秒灭
		}
	}	
}





2012-12-01 08:17:45 misskissC 阅读数 5394
  • 定时器和计数-第1季第10部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第10个课程,主要内容是51单片机的定时器和计数器,本课程的学习目标是对定时器的作用和意义有深入理解,掌握通过操作寄存器来操作硬件的思路和方法。

    1965 人正在学习 去看看 朱有鹏

     上篇笔记记录到51单片机的中断允许寄存器定时器/计数器工作方式寄存器(TMOD)、定时器/计数器控制寄存器(TCON)各位的作用。这些寄存器都是用来为编写定时器中断程序编写的初始化部分而服务的。然后今天再这里补填中断函数的编写格式,以后就可以编写定时器中断程序了。

 

1.中断服务程序的写法

C51的中断函数格式如下:

void  函数名()  中断号 using 工作组

{

        中断服务程序内容

}


与一般的C语言程序相比,中断服务程序有一下特点

  • 中断函数不能返回任何值,所以函数名前用void;
  • 函数名随便起,但不能与C51语言中的关键字同名(同C语言函数要求)
  • 中断函数不能带任何参数,故函数名后的括号内为空
  • 中断号是指单片机中的几个中断源的序号,列表如下(红方框内内容)

图1.51单片机中的中断源
        
        此序号是编译器识别不同中断的唯一符号,在程序编写中定要写正确
  • “using 工作组”是指这个中断函数使用单片机内存中4组工作寄存器中的哪一组,C51编译器在编译程序时会自动分配工作组,因此这句话经常被省略不写。

2.定时器1中断程序编写

#include <reg52.h>

#define uint unsigned int


#define MANY_KEY_DELAY  1
#define TOTAL_TIME_NUM  5
#define ONE_SECOND      20

uint num;
uint num1;

uint flag_key;

//流水灯的第一列
sbit led1 = P1^0;
//第一个按钮位
sbit key = P3^1;
//按钮的接地端
sbit h_key6 = P3^6;

//函数申明
void T1_end_AND_change_status();
void delayms(uint xms);
void init_timer();
void data_init();
void key_scan();

void main()
{
        //初始化数据变量
        data_init();

        //初始化T1定时器
        init_timer();

        while(1){

                //不断检测此按钮是否被按下
                key_scan();

                //检测一个大周期定时是否完成
                //使按下按钮后相应的位发生电平反转
                T1_end_AND_change_status();
        }
}

//自定义函数:数据初始化
void data_init()
{
     num        = 1;
     num1       = 1;
     flag_key   = 0;
     h_key6     = 0;   
}

//自定义函数:初始化TMOD、TCON、中断寄存器,并装入计数初值
void init_timer()
{
        //选中定时器1
        TMOD    = 0x10;

        //定时器1的初值
        TH1     = (65536 - 45872) / 256;
        TL1     = (65536 - 45872) % 256;
        
        //开总中断,     
        //定时器1中断
        EA         = 1;
        ET1        = 1;
}

//自定义函数:延迟xms ms
void delayms(uint xms)
{
        uint i, j;

        for(i = xms; i > 0; i--)
                for(j = 110; j > 0; j--);
}

//自定义函数:检测哪一个按键被按下
void key_scan()
{
        if(key == 0){
                //<1>.待按钮被按下后的稳定状态
                delayms(10);
    
                //<2>.操作:
                //开启定时器,由T1时间到达关闭T1定时器
                TR1 = 1;
    
                //记住按钮已被按下
                flag_key    = 1;
    
                //点亮响应的流水灯
                led1        = 0;
    
                //<3>.等待按键的释放
                while(!key);    
        }      
}

void T1_end_AND_change_status()
{
        //T1计时完成
        if(num >= TOTAL_TIME_NUM * ONE_SECOND){
                num     = 0;
                
                //检测有哪些按钮被按下,结束其高低电平的转换
                if(flag_key){
                        flag_key       = 0;

                        //按钮信号以低电平结束
                        led1    = 1;
                                
                        //一旦检测到总的计时时间到则关闭定时功能
                        //当有任何按钮再次被按下时,T1定时器再被开启
                        //需要在按钮被按下的前提下设置此语句,防止没有任何按钮按下时到达定时器时间设置
                        TR1     = 0;
                 }
        }
        
        //按钮的电平反转
        if(num1 >= MANY_KEY_DELAY * ONE_SECOND){
                num1    = 0;
                if(flag_key){
                        led1    = ~led1;
                }
        }
             
}

//中断函数编写
void T1_time() interrupt 3
{
     TH1        = (65536 - 45872) / 256;
     TL1        = (65536 - 45872) % 256; 
     
     num++;
     num1++;    
}

此源程序经编译链接生成可执行文件后,下载到单片机中,按下key对应的按键时,流水灯1就会以1s的高低电平交换显示。照片一张作为纪念:

图2.闪烁的流水灯

3.程序分析

程序从main函数出开始运行。自在main函数中对个寄存器初始化后,待按键按下(TR1=1)时,定时器1开始从当前值开始计时,当计数计满溢出时,TCON的TF1向CPU申请中断从而进入中断函数内执行中断函数内的语句,当把中断函数内的语句执行完毕后,再返回到main函数开始中断处。当在中断函数中重新给定时器赋新值后(若不赋新值,则从0开始计),则将又会过与原来一样长的时间后发生中断。
此程序的中断周期是50ms(晶振频率为11.0592)。此程序随时等待按钮被按下,只有按钮被按下时才开始计时,中断程序才会生效。定时器被启动后,将会以50ms的周期进行中断产生,当计满1s时,流水灯的状态反转一次。当计满5s后定时器再次被关闭。程序重新等待按钮被按下。

4.总结

使用定时器中断的方式可以得到以高低电平反转的方波。在现实生活中我们可以用这种方波做很多事情,如红外遥控器就是采用的此种原理对不同按钮进行编码,经发射电路将此方波发射出去,再由相应的接收电路接受此方波,然后对其进行解码,得到原信号进而可以判断此信号是想要做出什么样的操作。
当然,使用单片机编写程序不再是单纯的写代码,还需要会阅读各种电路图和电器件的特性。

没有更多推荐了,返回首页