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

(1)中断的基本概念

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

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

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

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

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

(3)中断的处理流程

中断的处理流程

二、定时器

(1)定时器

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

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

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

(2)计数器

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

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

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

三、程序实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//加入包含文件
#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