任务12:中断与定时器

本系列教程以AVR单片机为对象,介绍单片机的快速开发方法。

参考教材:《单片机技术及应用项目教程》 栾秋平 电子工业出版社 2019.6 第1版

本文介绍中断与定时器。


一、认知单片机中的“中断”

(1)中断的基本概念

在计算机执行程序的过程中,当出现某种情况时,由服务对象向CPU发出请求当前程序中断的信号,要求CPU暂时停止当前程序的执行,而转去执行相应的处理程序,待处理程序执行完毕后,再返回继续执行原来被中断的程序,这样的过程称为中断过程。引起中断的原因或触发中断请求的来源称为中断源。为实现中断而设置的各种硬件和软件称为中断系统。

   (2)采用中断技术的优点

 a、实行分时操作,提高了CPU的利用率。当服务对象向CPU发出中断请求时,才使CPU转向为该对象服务,否则不影响CPU的正常工作。这样,利用中断可以使CPU同时为多个对象服务,从而大大提高了整个单片机系统的工作效率。

b、实现实时处理,及时处理实时信息。在工业现场控制中,常常要求单片机系统对信号进行实时处理。利用中断技术,各服务对象可以根据需要随时向CPU发出中断请求,CPU及时检测并处理各对象的控制要求,已实现实时控制。

 c、对难以预料的情况或故障进行及时处理。在单片机系统工作过程中,有时会出现一些难以预料的情况或故障,如电源掉电、运算溢出、传输错误等,此时可以利用中断进行相应的处理而不必停机。

(3)中断的处理流程

二、定时器

(1)定时器

定时器启动后,开始定时,定时时间到,则置相应的中断标志位,然后向CPU申请中断。定时器的定时功能是以计数的方式来工作的,此时是对单片机内部的脉冲进行加1计数,此脉冲的周期是机器周期分频后得到的,其公式如下:

定时时间 = (溢出值 – 计数初值)× 内部脉冲

定时器可以用来实现很多功能,例如我们可以产生时间;可以在检测系统中,对被检测点进行定时取样;可以在读按键状态时,产生一个消抖时间等等。

   (2)计数器

计数器启动后,对外部输入脉冲进行加1计数,计数器加满溢出时,将中断标志位置位,然后向CPU申请中断,其公式如下:

计数脉冲个数 = 溢出值 – 计数初值

计时器在很多应用场合都发挥着作用;例如在工业生产线上,对零件和产品进行计数;在大桥和高速公路上对车流量进行统计等等。

三、程序实现

//加入包含文件
#include "../include.h"

//定义系统常量

//定义全局变量
uint8 u8g_DisplayString[8];
uint8 u8g_DisplayPoint[8];

//主程序
int main(void)
{
	//定义局部变量
	uint8 i;
	//目标板初始化,该函数会自动初始化相应的外设文件	
	TARGET_Init();
	
	//初始化全局变量	
	for (i = 0; i < 8; i++)
	{
		u8g_DisplayString[i] = 0x00;
		u8g_DisplayPoint[i] = 0x00;
	}
		
	//在上电时,执行的相应操作	
			
	//后台主循环
	while(1)
	{
		/*
		**********************************
		在这里完成自己的项目逻辑
		**********************************
		*/	
		for (i = 0; i < 8; i++)
		{
			u8g_DisplayString[i] = i;
		}
		TARGET_Delayms(500, 1);
		for (i = 0; i < 8; i++)
		{
			u8g_DisplayString[i] = 8 + i;
		}
		TARGET_Delayms(500, 1);					
		/*
		**********************************
		喂狗语句,大部分工程项目都不应去除
		**********************************
		*/	
		#if INTERNAL_PERIPHERAL_WDT_MODE != 0
			TARGET_WatchDogReset();
		#endif
	}
	return 0;	//永不执行
}

//串口0接收中断服务处理函数,接收到的数据存储在 UDR0 寄存器中
#if INTERNAL_PERIPHERAL_UART0_MODE != 0
ISR(USART__RX_vect)
{
	uint8 u8_UartData;	
		
	u8_UartData = UDR0;	
		
#if PROTOCOL_MINIUART_UART0_MODE !=0	
	miniUART_UartInterrupt(&miniUART_UART0, u8_UartData);	
#endif
}
#endif

//定时器0溢出中断服务处理函数
#if INTERNAL_PERIPHERAL_TIMER0_MODE != 0
ISR(TIMER0_OVF_vect)
{	
#if INTERNAL_PERIPHERAL_TIMER0_MODE == 1
	//在此完成逻辑内容
	static uint8 u8_Number;
	
	u8_Number++;
	if (u8_Number > 7)
	{
		u8_Number = 0;
	}
	NIXIETUBE_SelectLED(u8_Number);
	NIXIETUBE_DrawLED(u8g_DisplayString[u8_Number], u8g_DisplayPoint[u8_Number]);
	
	#if PROTOCOL_MINIUART_UART0_MODE !=0
		miniUART_TimerInterrupt(&miniUART_UART0);
	#endif
	#if PROTOCOL_MINIUART_CH432T_UART0_MODE !=0
		miniUART_TimerInterrupt(&miniUART_CH432T_UART0);
	#endif
	#if PROTOCOL_MINIUART_CH432T_UART1_MODE !=0
		miniUART_TimerInterrupt(&miniUART_CH432T_UART1);
	#endif
	//为了提高运行速度,将此语句写在中断服务处理函数里,用户在使用时,可不理会下列语句
	TCNT0 = TIMER0_TCNT0;
#elif INTERNAL_PERIPHERAL_TIMER0_MODE == 2
	
#endif
}
#endif

//定时器1溢出中断服务处理函数
#if INTERNAL_PERIPHERAL_TIMER1_MODE != 0
ISR(TIMER1_OVF_vect)
{
	//在此完成逻辑内容	
	
	//为了提高运行速度,将此语句写在中断服务处理函数里,用户在使用时,可不理会下列语句
	TCNT1H = TIMER1_TCNT1H;
	TCNT1L = TIMER1_TCNT1L;
}
#endif

//外部中断0中断服务处理函数
#if INTERNAL_PERIPHERAL_INT0_MODE != 0
ISR(INT0_vect)
{
	//如果使用了CH432T,则调用相应的中断处理函数
	#if EXTERNAL_MODULE_CH432T_MODE != 0
		CH432T_INT();
	#endif
}
#endif

//外部中断1中断服务处理函数
#if INTERNAL_PERIPHERAL_INT1_MODE != 0
ISR(INT1_vect)
{
	//如果使用了CH432T,则调用相应的中断处理函数
	#if EXTERNAL_MODULE_CH432T_MODE != 0
		CH432T_INT();
	#endif
}
#endif

//CH432T扩展串口0,接收调用函数
#if EXTERNAL_MODULE_CH432T_MODE != 0
void CH432T_Uart0(uint8 u8_UartData)
{	
	#if PROTOCOL_MINIUART_CH432T_UART0_MODE != 0
		miniUART_UartInterrupt(&miniUART_CH432T_UART0, u8_UartData);
	#endif
}
#endif

//CH432T扩展串口1,接收调用函数
#if EXTERNAL_MODULE_CH432T_MODE != 0
void CH432T_Uart1(uint8 u8_UartData)
{
	#if PROTOCOL_MINIUART_CH432T_UART1_MODE != 0
		miniUART_UartInterrupt(&miniUART_CH432T_UART1, u8_UartData);
	#endif
}
#endif

任何问题,只需在此文章的评论处留言即可,我将尽力解答,不要试图采用其它的联系方式,我一概不理会。

原创性文章,转载请注明出处CSDN:http://blog.csdn.net/qingwufeiyang12346。

发布了413 篇原创文章 · 获赞 1104 · 访问量 81万+

猜你喜欢

转载自blog.csdn.net/qingwufeiyang12346/article/details/103302242