中断服务程序不要占时太长,应尽快退出中断,在主循环中处理部分中断事件
中断服务程序, 不要占时太长,应尽快退出中断服务程序 !===防止 影响 其他 中断的响应速度
在主循环中处理部分不是特急的中断任务,而不是全部由中断服务程序来完成
中断需服务的事件 分2种:
A, 需立即处理的事件;
B, 可以在中断服务程序中,树立软件标志,
然后在主循环中查询软件标志,再去处理的事件;
1,如部分特急的任务,占时很短,就直接在中断服务程序中处理,如 <【2uS - 20uS】
=====如 只是 读走数据/送数据,改变状态而已 !
=====如STC8H8K64U跑40MHz, 则可以 【大致执行40条指令/uS】
2,如部分不是特急的任务,占时较长,如>【10uS/20uS/30uS/40uS/50uS...】
=====如果占时较长的话,在中断服务程序中,树立软件标志,
然后在主循环中查询处理
需时长,那就只能在主程序中处理需要处理时间较长的事件
正在执行的中断:会屏蔽【低优先级的中断】和【同级的中断/含自己又发生的中断】;
直到执行完并退出,同级的和低优先级的中断才会被执行。
如果STC8H8K64U跑40MHz, 则可以 【大致执行40条指令/uS】
一般中断服务程序都很短,如 <【2uS - 20uS】,
只是读走数据/送数据,改变状态,树立特殊标志位,而已。
如果复杂的话,是树立软件标志后,然后在主循环中查询处理 !
演示程序,见最新 ISP 软件中的 范例程序 部分
深圳国芯人工智能有限公司-工具软件
用 DMA来支持串口发送...
//外部中断INT0和INT1控制点灯并USB仿真
#include <AI8051U.H> //包含AI8051U的头文件
#include "intrins.h" //使用_nop_()函数所必须要包含的头文件,
//否则延时函数中调用的_nop_()函数没有被头文件引用过来,
//会导致编译器找不到这个而函数而报错。
bit int0_flag = 0; //定义1个位变量,INT0事件位变量标志,记录INT0已产生中断
// 供主循环查询INT0是否已产生中断,在主循环中处理INT0的中断事件任务,不堵塞其他中断
bit int1_flag = 0; //定义1个位变量,INT1事件位变量标志,记录INT1已产生中断
// 供主循环查询INT1是否已产生中断,在主循环中处理INT1的中断事件任务,不堵塞其他中断
void main (void)
{
EAXFR = 1; //允许访问扩展的特殊寄存器,XFR
WTST = 0; //设置取程序代码等待时间,赋值为 0 表示不等待,程序以最快速度运行
CKCON = 0; //设置访问片内的 xdata 速度,赋值为 0 表示用最快速度访问,不增加额外的等待时间
P0M0 = 0x00; P0M1 = 0x00;
P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x00; P2M1 = 0x00;
// P3M0 = 0x00; P3M1 = 0x00; //P32、P33设置为准双向口
P3M0 = 0x00; P3M1 = 0xff; //P32、P33设置为高阻输入(需要同步开启上拉电阻)
P4M0 = 0x00; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;
P6M0 = 0x00; P6M1 = 0x00;
P7M0 = 0x00; P7M1 = 0x00;
P3PU = 0x0c; //P32、P33打开上拉电阻
IT0 = 0; //使能 INT0 上升沿和下降沿中断
// IT0 = 1; //使能 INT0 下降沿中断
EX0 = 1; //使能 INT0 中断
// IT1 = 0; //使能 INT1 上升沿和下降沿中断
IT1 = 1; //使能 INT1 下降沿中断
EX1 = 1; //使能 INT1 中断
IE0 = 0; //清INT0中断标志
IE1 = 0; //清INT1中断标志
EA = 1; //打开所有中断
P40 = 0; //打开LED灯供电
int0_flag = 0; //初始化用户标志位
int1_flag = 0; //初始化用户标志位
while(1)
{
if(int0_flag) //主循环中查询,INT0是否已产生中断,是否有需要处理的INT 0事件
{
int0_flag = 0; //清0,INT0事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
if(int1_flag) //主循环中查询,INT1是否已产生中断,是否有需要处理的INT1事件
{
int1_flag = 0; //清0,INT1事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
}
}
void int0_isr(void) interrupt INT0_VECTOR
{
int0_flag = 1; // int0_flag置1是通知主循环处理部分INT0中断事件不需要特急处理的任务
//置1,记录INT0已产生中断,供主循环查询判断有无需处理的INT0任务
if(INT0) //边沿中断,进入后再次判断电平从而判断是什么样的电平
{
P00 = 0; //判断为高电平,则当前为上升沿,点亮P00端口上的LED灯
_nop_(); //可以在这里插入断点进行观察现象
P00 = 1; //关闭LED灯
}
else
{
P07 = 0; //判断为低电平,则当前为下降沿,点亮P07端口上的LED灯
_nop_(); //可以在这里插入断点进行观察现象
P07 = 1; //关闭LED灯
}
}
void int1_isr(void) interrupt INT1_VECTOR
{
int1_flag = 1; // int1_flag置1是通知主循环处理部分INT1中断事件不需要特急处理的任务
//置1,记录INT1已产生中断,供主循环查询判断有无需处理的INT1任务
P04 = 0; //点亮P04端口上的LED灯
_nop_(); //可以在这里插入断点观察现象
P04 = 1; //关闭LED灯
}
#include <AI8051U.H> //AI8051U的通用头文件,头文件不分大小写
#include"ai_usb.h" //USB库和USB虚拟设备的头文件
//由于在USB库函数的代码中已经定义了,不停电ISP下载命令字”@STCISP#”,
//只需要在下载软件的“收到用户命令后复位到ISP监控程序区”选项卡中进行相应的设置,
//即可实现USB不停电ISP下载功能,或串口不停电ISP下载功能。
bit t0_flag = 0; //定义1个位变量,T0事件位变量标志,记录定时器0已产生中断
// 供主循环查询定时器0是否已产生中断,在主循环中处理定时器0的中断事件任务,不堵塞其他中断
bit t1_flag = 0; //定义1个位变量,T1事件位变量标志,记录定时器1已产生中断
// 供主循环查询定时器1是否已产生中断,在主循环中处理定时器1的中断事件任务,不堵塞其他中断
void Timer0_Isr(void) interrupt TMR0_VECTOR //定时器0中断服务程序
{
P00 = ~P00; //P00灯闪烁,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
t0_flag = 1; // t0_flag置1是通知主循环处理部分T0中断事件不需要特急处理的任务
//置1,记录定时器0已产生中断,供主循环查询判断有无需处理的定时器0任务
}
//定时器0中断服务程序,TMR0_VECTOR在AI8051U.H头文件中已宏定义为1
void Timer0_Init(void) //定时器0初始化,2秒@40.000MHz
{
TM0PS = 0x65; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xB1; //设置定时初始值
TH0 = 0x00; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
voidTimer1_Isr(void)interruptTMR1_VECTOR
{
P07 = ~P07; //P07灯闪烁,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
t1_flag = 1; // t1_flag置1是通知主循环处理部分T1中断事件不需要特急处理的任务
//置1,记录定时器1已产生中断,供主循环查询判断有无需处理的定时器1任务
}
//定时器1中断服务程序,TMR1_VECTOR在AI8051U.H头文件中已宏定义为3
void Timer1_Init(void) //定时器1初始化,500毫秒@40.000MHz
{
TM1PS = 0x19; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x99; //设置定时初始值
TH1 = 0x05; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器1中断
}
voidsys_init(void) //系统初始化
{
EAXFR = 1; //允许访问扩展的特殊寄存器,XFR
WTST = 0; //设置取程序代码等待时间,赋值为0表示不等待,程序以最快速度运行
CKCON = 0; //设置访问片内的xdata速度,赋值为0表示用最快速度访问,不增加额外的等待时间
P0M0 = 0x00; P0M1 = 0x00; //设置 P0 口为准双向口模式
P1M0 = 0x00; P1M1 = 0x00; //设置 P1 口为准双向口模式
P2M0 = 0x00; P2M1 = 0x00; //设置 P2 口为准双向口模式
P3M0 = 0x00; P3M1 = 0x00; //设置 P3 口为准双向口模式
P4M0 = 0x00; P4M1 = 0x00; //设置 P4 口为准双向口模式
P5M0 = 0x00; P5M1 = 0x00; //设置 P5 口为准双向口模式
P6M0 = 0x00; P6M1 = 0x00; //设置 P6 口为准双向口模式
P7M0 = 0x00; P7M1 = 0x00; //设置 P7 口为准双向口模式
}
voidmain(void)
{
sys_init(); //调用系统初始化函数
usb_init(); //调用USB初始化函数,不需要立即判断电脑已正确识别到USB从设备
/* USB型单片机从设备,如需要主动向电脑发送数据,
在执行USB_SendData( )函数和printf_usb( )函数时,
这两个函数已增加了判断电脑是否已正确识别到USB从设备的程序。
如果电脑要主动发送数据给USB从设备,电脑自己会主动判断与USB从设备是否已正确连接。
*/
EA = 1; //总中断允许位打开
Timer0_Init(); //调用定时器0初始化函数
Timer1_Init(); //调用定时器1初始化函数
P40 = 0; //给LED灯供电
while(1) //主循环中查询需要处理的各种事件,如T0/T1中断事件,并打印输出状态
{
if(t0_flag) //主循环中查询,定时器0是否已产生中断,是否有需要处理的定时器0事件
{
t0_flag = 0; //清0,T0事件位变量标志
printf_usb("Timer0!\r\n");
//向电脑USB-CDC串口助手输出“Timer0!”字符串,代表主循环在处理T0不急的任务
}
if(t1_flag) //主循环中查询,定时器1是否已产生中断,是否有需要处理的定时器1事件
{
t1_flag = 0; //清0,T1事件位变量标志
printf_usb("Timer1!\r\n");
//向电脑USB-CDC串口助手输出“Timer1!”字符串,代表主循环在处理T1不急的任务
}
}
}
#include <AI8051U.H> //包含AI8051U的头文件
#include"ai_usb.h" //USB库和USB虚拟设备的头文件,需要在项目文件中添加对应的USB库
//由于在USB库函数的代码中已经定义了,不停电ISP下载命令字”@STCISP#”,
//只需要在下载软件的“收到用户命令后复位到ISP监控程序区”选项卡中进行相应的设置,
//即可实现USB不停电ISP下载功能,或串口不停电ISP下载功能。
#include "intrins.h" //使用_nop_()函数所必须要包含的头文件,
//否则延时函数中调用的_nop_()函数没有被头文件引用过来,
//会导致编译器找不到这个而函数而报错。
bit int0_flag = 0; //定义1个位变量,INT0事件位变量标志,记录INT0已产生中断
// 供主循环查询INT0是否已产生中断,在主循环中处理INT0的中断事件任务,不堵塞其他中断
bit int1_flag = 0; //定义1个位变量,INT1事件位变量标志,记录INT1已产生中断
// 供主循环查询INT1是否已产生中断,在主循环中处理INT1的中断事件任务,不堵塞其他中断
bit t0_flag = 0; //定义1个位变量,T0事件位变量标志,记录定时器0已产生中断
// 供主循环查询定时器0是否已产生中断,在主循环中处理定时器0的中断事件任务,不堵塞其他中断
bit t1_flag = 0; //定义1个位变量,T1事件位变量标志,记录定时器1已产生中断
// 供主循环查询定时器1是否已产生中断,在主循环中处理定时器1的中断事件任务,不堵塞其他中断
void Timer0_Init(void) //定时器0初始化,2秒@40.000MHz
{
TM0PS = 0x65; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xB1; //设置定时初始值
TH0 = 0x00; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
void Timer1_Init(void) //定时器1初始化,500毫秒@40.000MHz
{
TM1PS = 0x19; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x99; //设置定时初始值
TH1 = 0x05; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器1中断
}
void main (void)
{
EAXFR = 1; //允许访问扩展的特殊寄存器,XFR
WTST = 0; //设置取程序代码等待时间,赋值为0表示不等待,程序以最快速度运行
CKCON = 0; //设置访问片内的xdata速度,赋值为0表示用最快速度访问,不增加额外的等待时间
P0M0 = 0x00; P0M1 = 0x00; //设置 P0 口为准双向口模式
P1M0 = 0x00; P1M1 = 0x00; //设置 P1 口为准双向口模式
P2M0 = 0x00; P2M1 = 0x00; //设置 P2 口为准双向口模式
//P3M0 = 0x00; P3M1 = 0x00; //设置 P3 口为准双向口模式
P3M0 = 0x00; P3M1 = 0x0c; //P32、P33设置为高阻输入(需要同步开启上拉电阻)
P4M0 = 0x00; P4M1 = 0x00; //设置 P4 口为准双向口模式
P5M0 = 0x00; P5M1 = 0x00; //设置 P5 口为准双向口模式
P6M0 = 0x00; P6M1 = 0x00; //设置 P6 口为准双向口模式
P7M0 = 0x00; P7M1 = 0x00; //设置 P7 口为准双向口模式
P3PU = 0x0c; //P32、P33打开上拉电阻
IT0 = 0; //使能 INT0 上升沿和下降沿中断
// IT0 = 1; //使能 INT0 下降沿中断
EX0 = 1; //使能 INT0 中断
// IT1 = 0; //使能 INT1 上升沿和下降沿中断
IT1 = 1; //使能 INT1 下降沿中断
EX1 = 1; //使能 INT1 中断
IE0 = 0; //清INT0中断标志
IE1 = 0; //清INT1中断标志
int0_flag = 0; //初始化用户标志位
int1_flag = 0; //初始化用户标志位
Timer0_Init(); //调用定时器0初始化函数
Timer1_Init(); //调用定时器1初始化函数
usb_init(); //调用USB初始化函数,不需要立即判断电脑已正确识别到USB从设备
/* USB型单片机从设备,如需要主动向电脑发送数据,
在执行USB_SendData( )函数和printf_usb( )函数时,
这两个函数已增加了判断电脑是否已正确识别到USB从设备的程序。
如果电脑要主动发送数据给USB从设备,电脑自己会主动判断与USB从设备是否已正确连接。
*/
EA = 1; //总中断允许位打开
P40 = 0; //打开LED灯供电
while(1) //主循环中查询需要处理的各种事件,如T0/T1中断事件,并打印输出状态
{
/*本演示程序中,主循环查询各中断有无需要继续处理的事件的次序,
依次是 INT0/INT1/T0/T1, 用户可以自己根据实际情况,
调整查询各中断有无需要继续处理的事件的优先次序*/
if(int0_flag) //主循环中查询,INT0是否已产生中断,是否有需要处理的INT 0事件
{
int0_flag = 0; //清0,INT0事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
if(int1_flag) //主循环中查询,INT1是否已产生中断,是否有需要处理的INT1事件
{
int1_flag = 0; //清0,INT1事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
if(t0_flag) //主循环中查询,定时器0是否已产生中断,是否有需要处理的定时器0事件
{
t0_flag = 0; //清0,T0事件位变量标志
printf_usb("Timer0!\r\n");
//向电脑USB-CDC串口助手输出“Timer0!”字符串,代表主循环在处理T0不急的任务
}
if(t1_flag) //主循环中查询,定时器1是否已产生中断,是否有需要处理的定时器1事件
{
t1_flag = 0; //清0,T1事件位变量标志
printf_usb("Timer1!\r\n");
//向电脑USB-CDC串口助手输出“Timer1!”字符串,代表主循环在处理T1不急的任务
}
}
}
void int0_isr(void) interrupt INT0_VECTOR
{
int0_flag = 1; // int0_flag置1是通知主循环处理部分INT0中断事件不需要特急处理的任务
//置1,记录INT0已产生中断,供主循环查询判断有无需处理的INT0任务
if(INT0) //边沿中断,进入后再次判断电平从而判断是什么样的电平
{
// P01 = 0; //判断为高电平,则当前为上升沿,点亮P01端口上的LED灯
// _nop_(); //可以在这里插入断点进行观察现象
// P01 = 1; //关闭LED灯
P01 = ~P01; //如果用外部按键触发INT0,则需另外添加去抖动处理
}
else
{
// P06 = 0; //判断为低电平,则当前为下降沿,点亮P06端口上的LED灯
// _nop_(); //可以在这里插入断点进行观察现象
// P06 = 1; //关闭LED灯
P06 = ~P06; //如果用外部按键触发INT0,则需另外添加去抖动处理
}
}
//INT0中断服务程序,INT0_VECTOR在AI8051U.H头文件中已宏定义为0
void int1_isr(void) interrupt INT1_VECTOR
{
int1_flag = 1; // int1_flag置1是通知主循环处理部分INT1中断事件不需要特急处理的任务
//置1,记录INT1已产生中断,供主循环查询判断有无需处理的INT1任务
// P02= 0; //点亮P02端口上的LED灯
// _nop_(); //可以在这里插入断点观察现象
// P02 = 1; //关闭LED灯
P02 = ~P02; //如果用外部按键触发INT1,则需另外添加去抖动处理
}
//INT1中断服务程序,INT1_VECTOR在AI8051U.H头文件中已宏定义为2
void Timer0_Isr(void) interrupt TMR0_VECTOR //定时器0中断服务程序
{
P00 = ~P00; //P00灯闪烁,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
t0_flag = 1; // t0_flag置1是通知主循环处理部分T0中断事件不需要特急处理的任务
//置1,记录定时器0已产生中断,供主循环查询判断有无需处理的定时器0任务
}
//定时器0中断服务程序,TMR0_VECTOR在AI8051U.H头文件中已宏定义为1
void Timer1_Isr(void) interrupt TMR1_VECTOR
{
P07 = ~P07; //P07灯闪烁,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
t1_flag = 1; // t1_flag置1是通知主循环处理部分T1中断事件不需要特急处理的任务
//置1,记录定时器1已产生中断,供主循环查询判断有无需处理的定时器1任务
}
//定时器1中断服务程序,TMR1_VECTOR在AI8051U.H头文件中已宏定义为3
#include <AI8051U.H> //包含AI8051U的头文件
#include "intrins.h" //使用_nop_()函数所必须要包含的头文件,
//否则延时函数中调用的_nop_()函数没有被头文件引用过来,
//会导致编译器找不到这个而函数而报错。
unsigned char uart1_txflag = 0; //定义1个位变量,UART1事件位变量标志,记录UART1已产生发送中断
// 供主循环查询UART1是否已产生发送中断,在主循环中处理UART1的中断事件任务,不堵塞其他中断
unsigned char uart1_rxflag = 0; //定义1个位变量,UART1事件位变量标志,记录UART1已产生接收中断
// 供主循环查询UART1是否已产生接收中断,在主循环中处理UART1的中断事件任务,不堵塞其他中断
unsigned char uart2_txflag = 0; //定义1个位变量,UART2事件位变量标志,记录UART2已产生发送中断
// 供主循环查询UART2是否已产生发送中断,在主循环中处理UART2的中断事件任务,不堵塞其他中断
unsigned char uart2_rxflag = 0; //定义1个位变量,UART2事件位变量标志,记录UART2已产生接收中断
// 供主循环查询UART2是否已产生接收中断,在主循环中处理UART2的中断事件任务,不堵塞其他中断
unsigned char uart3_txflag = 0; //定义1个位变量,UART3事件位变量标志,记录UART3已产生发送中断
// 供主循环查询UART3是否已产生发送中断,在主循环中处理UART3的中断事件任务,不堵塞其他中断
unsigned char uart3_rxflag = 0; //定义1个位变量,UART3事件位变量标志,记录UART3已产生接收中断
// 供主循环查询UART3是否已产生接收中断,在主循环中处理UART3的中断事件任务,不堵塞其他中断
unsigned char uart4_txflag = 0; //定义1个位变量,UART4事件位变量标志,记录UART4已产生发送中断
// 供主循环查询UART4是否已产生发送中断,在主循环中处理UART1的中断事件任务,不堵塞其他中断
unsigned char uart4_rxflag = 0; //定义1个位变量,UART4事件位变量标志,记录UART4已产生接收中断
// 供主循环查询UART4是否已产生接收中断,在主循环中处理UART4的中断事件任务,不堵塞其他中断
void Uart1_Init(void) //115200bps@40.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器时钟1T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xA9; //设置定时初始值
TH1 = 0xFF; //设置定时初始值
ET1 = 0; //禁止定时器中断
TR1 = 1; //定时器1开始计时
ES = 1; //使能串口1中断
}
void Uart2_Init(void) //115200bps@40.000MHz
{
S2CON = 0x50; //8位数据,可变波特率
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0xA9; //设置定时初始值
T2H = 0xFF; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
IE2 |= 0x01; //使能串口2中断
}
void Uart3_Init(void) //115200bps@40.000MHz
{
S3CON = 0x10; //8位数据,可变波特率
S3CON |= 0x40; //串口3选择定时器3为波特率发生器
T4T3M |= 0x02; //定时器时钟1T模式
T3L = 0xA9; //设置定时初始值
T3H = 0xFF; //设置定时初始值
T4T3M |= 0x08; //定时器3开始计时
IE2 |= 0x08; //使能串口3中断
}
void Uart4_Init(void) //115200bps@40.000MHz
{
S4CON = 0x10; //8位数据,可变波特率
S4CON |= 0x40; //串口4选择定时器4为波特率发生器
T4T3M |= 0x20; //定时器时钟1T模式
T4L = 0xA9; //设置定时初始值
T4H = 0xFF; //设置定时初始值
T4T3M |= 0x80; //定时器4开始计时
IE2 |= 0x10; //使能串口4中断
}
void main (void)
{
EAXFR = 1; //允许访问扩展的特殊寄存器,XFR
WTST = 0; //设置取程序代码等待时间,赋值为0表示不等待,程序以最快速度运行
CKCON = 0; //设置访问片内的xdata速度,赋值为0表示用最快速度访问,不增加额外的等待时间
P0M0 = 0x00; P0M1 = 0x00; //设置 P0 口为准双向口模式
P1M0 = 0x00; P1M1 = 0x00; //设置 P1 口为准双向口模式
P2M0 = 0x00; P2M1 = 0x00; //设置 P2 口为准双向口模式
P3M0 = 0x00; P3M1 = 0x00; //设置 P3 口为准双向口模式
P3M0 = 0x00; P3M1 = 0x0c; //P32、P33设置为高阻输入(需要同步开启上拉电阻)
P4M0 = 0x00; P4M1 = 0x00; //设置 P4 口为准双向口模式
P5M0 = 0x00; P5M1 = 0x00; //设置 P5 口为准双向口模式
P6M0 = 0x00; P6M1 = 0x00; //设置 P6 口为准双向口模式
P7M0 = 0x00; P7M1 = 0x00; //设置 P7 口为准双向口模式
uart1_txflag = 0; //初始化用户标志位
uart1_rxflag = 0; //初始化用户标志位
uart2_txflag = 0; //初始化用户标志位
uart2_rxflag = 0; //初始化用户标志位
uart3_txflag = 0; //初始化用户标志位
uart3_rxflag = 0; //初始化用户标志位
uart4_txflag = 0; //初始化用户标志位
uart4_rxflag = 0; //初始化用户标志位
Uart1_Init(); //调用UART1初始化函数
Uart2_Init(); //调用UART2初始化函数
Uart3_Init(); //调用UART3初始化函数
Uart4_Init(); //调用UART4初始化函数
EA = 1; //总中断允许位打开
P40 = 0; //打开LED灯供电
while(1) //主循环中查询需要处理的各种事件
{
/*本演示程序中,主循环查询各中断有无需要继续处理的事件的次序,
依次是 UART/UART2/UART3/UART4, 用户可以自己根据实际情况,
调整查询各中断有无需要继续处理的事件的优先次序*/
if(uart1_txflag) //主循环中查询,UART1是否已产生发送中断,是否有需要处理的UART1发送事件
{
uart1_txflag = 0; //清0,UART1发送事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
if(uart1_rxflag) //主循环中查询,UART1是否已产生接收中断,是否有需要处理的UART1接收事件
{
uart1_rxflag = 0; //清0,UART1接收事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
if(uart2_txflag) //主循环中查询,UART2是否已产生发送中断,是否有需要处理的UART2发送事件
{
uart2_txflag = 0; //清0,UART2发送事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
if(uart2_rxflag) //主循环中查询,UART2是否已产生接收中断,是否有需要处理的UART2接收事件
{
uart2_rxflag = 0; //清0,UART2接收事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
if(uart3_txflag) //主循环中查询,UART3是否已产生发送中断,是否有需要处理的UART3发送事件
{
uart3_txflag = 0; //清0,UART3发送事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
if(uart3_rxflag) //主循环中查询,UART3是否已产生接收中断,是否有需要处理的UART3接收事件
{
uart3_rxflag = 0; //清0,UART3接收事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
if(uart4_txflag) //主循环中查询,UART4是否已产生发送中断,是否有需要处理的UART4发送事件
{
uart4_txflag = 0; //清0,UART4发送事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
if(uart4_rxflag) //主循环中查询,UART4是否已产生接收中断,是否有需要处理的UART4接收事件
{
uart4_rxflag = 0; //清0,UART4接收事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
}
}
void Uart1_Isr(void) interrupt UART1_VECTOR
{
if (TI) //检测串口1发送中断
{
TI = 0; //清除串口1发送中断请求位
_nop_(); //特急处理
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
uart1_txflag = 1; // uart1_txflag置1是通知主循环处理部分串口1发送中断事件不需要特急处理的任务
//置1,记录UART1已产生发送中断,供主循环查询判断有无需处理的UART1发送任务
}
if (RI) //检测串口1接收中断
{
RI = 0; //清除串口1接收中断请求位
_nop_(); //特急处理
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
uart1_rxflag = 1; // uart1_rxflag置1是通知主循环处理部分串口1接收中断事件不需要特急处理的任务
//置1,记录UART1已产生接收中断,供主循环查询判断有无需处理的UART1接收任务
}
}
//UART1中断服务程序,UART1_VECTOR在AI8051U.H头文件中已宏定义为4
void Uart2_Isr(void) interrupt UART2_VECTOR
{
if (S2CON & 0x02) //检测串口2发送中断
{
S2CON &= ~0x02; //清除串口2发送中断请求位
_nop_(); //特急处理
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
uart2_txflag = 1; // uart2_txflag置1是通知主循环处理部分串口2发送中断事件不需要特急处理的任务
//置1,记录UART2已产生发送中断,供主循环查询判断有无需处理的UART2发送任务
}
if (S2CON & 0x01) //检测串口2接收中断
{
S2CON &= ~0x01; //清除串口2接收中断请求位
_nop_(); //特急处理
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
uart2_rxflag = 1; // uart2_rxflag置1是通知主循环处理部分串口2接收中断事件不需要特急处理的任务
//置1,记录UART2已产生接收中断,供主循环查询判断有无需处理的UART2接收任务
}
}
//UART2中断服务程序,UART2_VECTOR在AI8051U.H头文件中已宏定义为8
void Uart3_Isr(void) interrupt UART3_VECTOR
{
if (S3CON & 0x02) //检测串口3发送中断
{
S3CON &= ~0x02; //清除串口3发送中断请求位
_nop_(); //特急处理
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
uart3_txflag = 1; // uart3_txflag置1是通知主循环处理部分串口3发送中断事件不需要特急处理的任务
//置1,记录UART3已产生发送中断,供主循环查询判断有无需处理的UART3发送任务
}
if (S3CON & 0x01) //检测串口3接收中断
{
S3CON &= ~0x01; //清除串口3接收中断请求位
_nop_(); //特急处理
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
uart3_rxflag = 1; // uart3_rxflag置1是通知主循环处理部分串口3接收中断事件不需要特急处理的任务
//置1,记录UART3已产生接收中断,供主循环查询判断有无需处理的UART3接收任务
}
}
//UART3中断服务程序,UART3_VECTOR在AI8051U.H头文件中已宏定义为17
void Uart4_Isr(void) interrupt UART4_VECTOR
{
if (S4CON & 0x02) //检测串口4发送中断
{
S4CON &= ~0x02; //清除串口4发送中断请求位
_nop_(); //特急处理
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
uart4_txflag = 1; // uart4_txflag置1是通知主循环处理部分串口4发送中断事件不需要特急处理的任务
//置1,记录UART4已产生发送中断,供主循环查询判断有无需处理的UART4发送任务
}
if (S4CON & 0x01) //检测串口4接收中断
{
S4CON &= ~0x01; //清除串口4接收中断请求位
_nop_(); //特急处理
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
uart4_rxflag = 1; // uart4_rxflag置1是通知主循环处理部分串口4接收中断事件不需要特急处理的任务
//置1,记录UART4已产生接收中断,供主循环查询判断有无需处理的UART4接收任务
}
}
//UART4中断服务程序,UART4_VECTOR在AI8051U.H头文件中已宏定义为18
#include <AI8051U.H> //包含AI8051U的头文件
#include "intrins.h" //使用_nop_()函数所必须要包含的头文件,
//否则延时函数中调用的_nop_()函数没有被头文件引用过来,
//会导致编译器找不到这个而函数而报错。
unsigned char int0_flag = 0; //定义1个位变量,INT0事件位变量标志,记录INT0已产生中断
// 供主循环查询INT0是否已产生中断,在主循环中处理INT0的中断事件任务,不堵塞其他中断
unsigned char int1_flag = 0; //定义1个位变量,INT1事件位变量标志,记录INT1已产生中断
// 供主循环查询INT1是否已产生中断,在主循环中处理INT1的中断事件任务,不堵塞其他中断
unsigned char int2_flag = 0; //定义1个位变量,INT2事件位变量标志,记录INT2已产生中断
// 供主循环查询INT2是否已产生中断,在主循环中处理INT2的中断事件任务,不堵塞其他中断
unsigned char int3_flag = 0; //定义1个位变量,INT3事件位变量标志,记录INT3已产生中断
// 供主循环查询INT3是否已产生中断,在主循环中处理INT3的中断事件任务,不堵塞其他中断
unsigned char t0_flag = 0; //定义1个位变量,T0事件位变量标志,记录定时器0已产生中断
// 供主循环查询定时器0是否已产生中断,在主循环中处理定时器0的中断事件任务,不堵塞其他中断
unsigned char t1_flag = 0; //定义1个位变量,T1事件位变量标志,记录定时器1已产生中断
// 供主循环查询定时器1是否已产生中断,在主循环中处理定时器1的中断事件任务,不堵塞其他中断
unsigned char t3_flag = 0; //定义1个位变量,T3事件位变量标志,记录定时器3已产生中断
// 供主循环查询定时器3是否已产生中断,在主循环中处理定时器3的中断事件任务,不堵塞其他中断
unsigned char t4_flag = 0; //定义1个位变量,T4事件位变量标志,记录定时器4已产生中断
// 供主循环查询定时器4是否已产生中断,在主循环中处理定时器4的中断事件任务,不堵塞其他中断
unsigned char uart1_txflag = 0; //定义1个位变量,UART1事件位变量标志,记录UART1已产生发送中断
// 供主循环查询UART1是否已产生发送中断,在主循环中处理UART1的中断事件任务,不堵塞其他中断
unsigned char uart1_rxflag = 0; //定义1个位变量,UART1事件位变量标志,记录UART1已产生接收中断
// 供主循环查询UART1是否已产生接收中断,在主循环中处理UART1的中断事件任务,不堵塞其他中断
unsigned char uart2_txflag = 0; //定义1个位变量,UART2事件位变量标志,记录UART2已产生发送中断
// 供主循环查询UART2是否已产生发送中断,在主循环中处理UART2的中断事件任务,不堵塞其他中断
unsigned char uart2_rxflag = 0; //定义1个位变量,UART2事件位变量标志,记录UART2已产生接收中断
// 供主循环查询UART2是否已产生接收中断,在主循环中处理UART2的中断事件任务,不堵塞其他中断
unsigned char uart3_txflag = 0; //定义1个位变量,UART3事件位变量标志,记录UART3已产生发送中断
// 供主循环查询UART3是否已产生发送中断,在主循环中处理UART3的中断事件任务,不堵塞其他中断
unsigned char uart3_rxflag = 0; //定义1个位变量,UART3事件位变量标志,记录UART3已产生接收中断
// 供主循环查询UART3是否已产生接收中断,在主循环中处理UART3的中断事件任务,不堵塞其他中断
unsigned char uart4_txflag = 0; //定义1个位变量,UART4事件位变量标志,记录UART4已产生发送中断
// 供主循环查询UART4是否已产生发送中断,在主循环中处理UART1的中断事件任务,不堵塞其他中断
unsigned char uart4_rxflag = 0; //定义1个位变量,UART4事件位变量标志,记录UART4已产生接收中断
// 供主循环查询UART4是否已产生接收中断,在主循环中处理UART4的中断事件任务,不堵塞其他中断
void Timer0_Init(void) //定时器0初始化,2秒@40.000MHz
{
TM0PS = 0x65; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xB1; //设置定时初始值
TH0 = 0x00; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
void Timer1_Init(void) //定时器1初始化,500毫秒@40.000MHz
{
TM1PS = 0x19; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x99; //设置定时初始值
TH1 = 0x05; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器1中断
}
void Timer3_Init(void) //100毫秒@40.000MHz
{
TM3PS = 0x3D; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
T4T3M |= 0x02; //定时器时钟1T模式
T3L = 0xFC; //设置定时初始值
T3H = 0x03; //设置定时初始值
T4T3M |= 0x08; //定时器3开始计时
IE2 |= 0x20; //使能定时器3中断
}
void Timer4_Init(void) //200毫秒@40.000MHz
{
TM4PS = 0x7A; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
T4T3M |= 0x20; //定时器时钟1T模式
T4L = 0xEF; //设置定时初始值
T4H = 0x01; //设置定时初始值
T4T3M |= 0x80; //定时器4开始计时
IE2 |= 0x40; //使能定时器4中断
}
void Uart1_Init(void) //115200bps@40.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0xA9; //设置定时初始值
T2H = 0xFF; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
ES = 1; //使能串口1中断
}
void Uart2_Init(void) //115200bps@40.000MHz
{
S2CON = 0x50; //8位数据,可变波特率
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0xA9; //设置定时初始值
T2H = 0xFF; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
IE2 |= 0x01; //使能串口2中断
}
void Uart3_Init(void) //115200bps@40.000MHz
{
S3CON = 0x10; //8位数据,可变波特率
S3CON &= 0xBF; //串口3选择定时器2为波特率发生器
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0xA9; //设置定时初始值
T2H = 0xFF; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
IE2 |= 0x08; //使能串口3中断
}
void Uart4_Init(void) //115200bps@40.000MHz
{
S4CON = 0x10; //8位数据,可变波特率
S4CON &= 0xBF; //串口4选择定时器2为波特率发生器
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0xA9; //设置定时初始值
T2H = 0xFF; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
IE2 |= 0x10; //使能串口4中断
}
void main (void)
{
EAXFR = 1; //允许访问扩展的特殊寄存器,XFR
WTST = 0; //设置取程序代码等待时间,赋值为0表示不等待,程序以最快速度运行
CKCON = 0; //设置访问片内的xdata速度,赋值为0表示用最快速度访问,不增加额外的等待时间
P0M0 = 0x00; P0M1 = 0x00; //设置 P0 口为准双向口模式
P1M0 = 0x00; P1M1 = 0x00; //设置 P1 口为准双向口模式
P2M0 = 0x00; P2M1 = 0x00; //设置 P2 口为准双向口模式
P3M0 = 0x00; P3M1 = 0x00; //设置 P3 口为准双向口模式
P3M0 = 0x00; P3M1 = 0x0c; //P32、P33设置为高阻输入(需要同步开启上拉电阻)
P4M0 = 0x00; P4M1 = 0x00; //设置 P4 口为准双向口模式
P5M0 = 0x00; P5M1 = 0x00; //设置 P5 口为准双向口模式
P6M0 = 0x00; P6M1 = 0x00; //设置 P6 口为准双向口模式
P7M0 = 0x00; P7M1 = 0x00; //设置 P7 口为准双向口模式
P3PU = 0x0c; //P32、P33打开上拉电阻
int0_flag = 0; //初始化用户标志位
int1_flag = 0; //初始化用户标志位
int2_flag = 0; //初始化用户标志位
int3_flag = 0; //初始化用户标志位
t0_flag = 0; //初始化用户标志位
t1_flag = 0; //初始化用户标志位
t3_flag = 0; //初始化用户标志位
t4_flag = 0; //初始化用户标志位
uart1_txflag = 0; //初始化用户标志位
uart1_rxflag = 0; //初始化用户标志位
uart2_txflag = 0; //初始化用户标志位
uart2_rxflag = 0; //初始化用户标志位
uart3_txflag = 0; //初始化用户标志位
uart3_rxflag = 0; //初始化用户标志位
uart4_txflag = 0; //初始化用户标志位
uart4_rxflag = 0; //初始化用户标志位
IT0 = 0; //使能 INT0 上升沿和下降沿中断
// IT0 = 1; //使能 INT0 下降沿中断
EX0 = 1; //使能 INT0 中断
IE0 = 0; //清INT0中断标志
// IT1 = 0; //使能 INT1 上升沿和下降沿中断
IT1 = 1; //使能 INT1 下降沿中断
EX1 = 1; //使能 INT1 中断
IE1 = 0; //清INT1中断标志
INTCLKO |= 0x10; //使能INT2中断
INTCLKO |= 0x20; //使能INT3中断
Timer0_Init(); //调用定时器0初始化函数
Timer1_Init(); //调用定时器1初始化函数
Timer3_Init(); //调用定时器0初始化函数
Timer4_Init(); //调用定时器1初始化函数
Uart1_Init(); //调用UART1初始化函数
Uart2_Init(); //调用UART2初始化函数
Uart3_Init(); //调用UART3初始化函数
Uart4_Init(); //调用UART4初始化函数
EA = 1; //总中断允许位打开
P40 = 0; //打开LED灯供电
while(1) //主循环中查询需要处理的各种事件
{
/*本演示程序中,主循环查询各中断有无需要继续处理的事件的次序,
依次是 INTx/TIMERx/UARTx, 用户可以自己根据实际情况,
调整查询各中断有无需要继续处理的事件的优先次序*/
//查询外部中断0事件
if(int0_flag) //主循环中查询,INT0是否已产生中断,是否有需要处理的INT 0事件
{
int0_flag = 0; //清0,INT0事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
//查询外部中断1事件
if(int1_flag) //主循环中查询,INT1是否已产生中断,是否有需要处理的INT1事件
{
int1_flag = 0; //清0,INT1事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
//查询外部中断2事件
if(int2_flag) //主循环中查询,INT2是否已产生中断,是否有需要处理的INT2事件
{
int2_flag = 0; //清0,INT2事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
//查询外部中断3事件
if(int3_flag) //主循环中查询,INT3是否已产生中断,是否有需要处理的INT3事件
{
int3_flag = 0; //清0,INT3事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
//查询定时器0中断事件
if(t0_flag) //主循环中查询,定时器0是否已产生中断,是否有需要处理的定时器0事件
{
t0_flag = 0; //清0,T0事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
//查询定时器1中断事件
if(t1_flag) //主循环中查询,定时器1是否已产生中断,是否有需要处理的定时器1事件
{
t1_flag = 0; //清0,T1事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
//查询定时器3中断事件
if(t3_flag) //主循环中查询,定时器3是否已产生中断,是否有需要处理的定时器3事件
{
t3_flag = 0; //清0,T3事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
//查询定时器4中断事件
if(t4_flag) //主循环中查询,定时器4是否已产生中断,是否有需要处理的定时器4事件
{
t4_flag = 0; //清0,T4事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
//查询串口1中断事件
if(uart1_txflag) //主循环中查询,UART1是否已产生发送中断,是否有需要处理的UART1发送事件
{
uart1_txflag = 0; //清0,UART1发送事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
if(uart1_rxflag) //主循环中查询,UART1是否已产生接收中断,是否有需要处理的UART1接收事件
{
uart1_rxflag = 0; //清0,UART1接收事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
//查询串口2中断事件
if(uart2_txflag) //主循环中查询,UART2是否已产生发送中断,是否有需要处理的UART2发送事件
{
uart2_txflag = 0; //清0,UART2发送事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
if(uart2_rxflag) //主循环中查询,UART2是否已产生接收中断,是否有需要处理的UART2接收事件
{
uart2_rxflag = 0; //清0,UART2接收事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
//查询串口3中断事件
if(uart3_txflag) //主循环中查询,UART3是否已产生发送中断,是否有需要处理的UART3发送事件
{
uart3_txflag = 0; //清0,UART3发送事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
if(uart3_rxflag) //主循环中查询,UART3是否已产生接收中断,是否有需要处理的UART3接收事件
{
uart3_rxflag = 0; //清0,UART3接收事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
//查询串口4中断事件
if(uart4_txflag) //主循环中查询,UART4是否已产生发送中断,是否有需要处理的UART4发送事件
{
uart4_txflag = 0; //清0,UART4发送事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
if(uart4_rxflag) //主循环中查询,UART4是否已产生接收中断,是否有需要处理的UART4接收事件
{
uart4_rxflag = 0; //清0,UART4接收事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
}
}
void int0_isr(void) interrupt INT0_VECTOR
{
_nop_(); //特急处理,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
int0_flag = 1; // int0_flag置1是通知主循环处理部分INT0中断事件不需要特急处理的任务
//置1,记录INT0已产生中断,供主循环查询判断有无需处理的INT0任务
if(INT0) //边沿中断,进入后再次判断电平从而判断是什么样的电平
{
_nop_(); //判断为高电平,则当前为上升沿
_nop_(); //可以在这里插入断点进行观察现象
}
else
{
_nop_(); //判断为低电平,则当前为下降沿
_nop_(); //可以在这里插入断点进行观察现象
}
}
//INT0中断服务程序,INT0_VECTOR在AI8051U.H头文件中已宏定义为0
void int1_isr(void) interrupt INT1_VECTOR
{
_nop_(); //特急处理,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
int1_flag = 1; // int1_flag置1是通知主循环处理部分INT1中断事件不需要特急处理的任务
}
//INT1中断服务程序,INT1_VECTOR在AI8051U.H头文件中已宏定义为2
void int2_isr(void) interrupt INT2_VECTOR
{
_nop_(); //特急处理,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
int2_flag = 1; // int2_flag置1是通知主循环处理部分INT2中断事件不需要特急处理的任务
}
//INT2中断服务程序,INT2_VECTOR在AI8051U.H头文件中已宏定义为10
void int3_isr(void) interrupt INT3_VECTOR
{
_nop_(); //特急处理,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
int3_flag = 1; // int3_flag置1是通知主循环处理部分INT3中断事件不需要特急处理的任务
}
//INT3中断服务程序,INT3_VECTOR在AI8051U.H头文件中已宏定义为11
void Timer0_Isr(void) interrupt TMR0_VECTOR //定时器0中断服务程序
{
_nop_(); //特急处理,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
t0_flag = 1; // t0_flag置1是通知主循环处理部分T0中断事件不需要特急处理的任务
//置1,记录定时器0已产生中断,供主循环查询判断有无需处理的定时器0任务
}
//定时器0中断服务程序,TMR0_VECTOR在AI8051U.H头文件中已宏定义为1
void Timer1_Isr(void) interrupt TMR1_VECTOR
{
_nop_(); //特急处理,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
t1_flag = 1; // t1_flag置1是通知主循环处理部分T1中断事件不需要特急处理的任务
//置1,记录定时器1已产生中断,供主循环查询判断有无需处理的定时器1任务
}
//定时器1中断服务程序,TMR1_VECTOR在AI8051U.H头文件中已宏定义为3
void Timer3_Isr(void) interrupt TMR3_VECTOR
{
_nop_(); //特急处理,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
t3_flag = 1; // t3_flag置1是通知主循环处理部分T3中断事件不需要特急处理的任务
//置1,记录定时器3已产生中断,供主循环查询判断有无需处理的定时器1任务
}
//定时器3中断服务程序,TMR3_VECTOR在AI8051U.H头文件中已宏定义为19
void Timer4_Isr(void) interrupt TMR4_VECTOR
{
_nop_(); //特急处理,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
t4_flag = 1; // t1_flag置4是通知主循环处理部分T4中断事件不需要特急处理的任务
//置1,记录定时器4已产生中断,供主循环查询判断有无需处理的定时器1任务
}
//定时器4中断服务程序,TMR4_VECTOR在AI8051U.H头文件中已宏定义为20
void Uart1_Isr(void) interrupt UART1_VECTOR
{
if (TI) //检测串口1发送中断
{
TI = 0; //清除串口1发送中断请求位
_nop_(); //特急处理
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
uart1_txflag = 1; // uart1_txflag置1是通知主循环处理部分串口1发送中断事件不需要特急处理的任务
//置1,记录UART1已产生发送中断,供主循环查询判断有无需处理的UART1发送任务
}
if (RI) //检测串口1接收中断
{
RI = 0; //清除串口1接收中断请求位
_nop_(); //特急处理
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
uart1_rxflag = 1; // uart1_rxflag置1是通知主循环处理部分串口1接收中断事件不需要特急处理的任务
//置1,记录UART1已产生接收中断,供主循环查询判断有无需处理的UART1接收任务
}
}
//UART1中断服务程序,UART1_VECTOR在AI8051U.H头文件中已宏定义为4
void Uart2_Isr(void) interrupt UART2_VECTOR
{
if (S2CON & 0x02) //检测串口2发送中断
{
S2CON &= ~0x02; //清除串口2发送中断请求位
_nop_(); //特急处理
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
uart2_txflag = 1; // uart2_txflag置1是通知主循环处理部分串口2发送中断事件不需要特急处理的任务
//置1,记录UART2已产生发送中断,供主循环查询判断有无需处理的UART2发送任务
}
if (S2CON & 0x01) //检测串口2接收中断
{
S2CON &= ~0x01; //清除串口2接收中断请求位
_nop_(); //特急处理
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
uart2_rxflag = 1; // uart2_rxflag置1是通知主循环处理部分串口2接收中断事件不需要特急处理的任务
//置1,记录UART2已产生接收中断,供主循环查询判断有无需处理的UART2接收任务
}
}
//UART2中断服务程序,UART2_VECTOR在AI8051U.H头文件中已宏定义为8
void Uart3_Isr(void) interrupt UART3_VECTOR
{
if (S3CON & 0x02) //检测串口3发送中断
{
S3CON &= ~0x02; //清除串口3发送中断请求位
_nop_(); //特急处理
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
uart3_txflag = 1; // uart3_txflag置1是通知主循环处理部分串口3发送中断事件不需要特急处理的任务
//置1,记录UART3已产生发送中断,供主循环查询判断有无需处理的UART3发送任务
}
if (S3CON & 0x01) //检测串口3接收中断
{
S3CON &= ~0x01; //清除串口3接收中断请求位
_nop_(); //特急处理
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
uart3_rxflag = 1; // uart3_rxflag置1是通知主循环处理部分串口3接收中断事件不需要特急处理的任务
//置1,记录UART3已产生接收中断,供主循环查询判断有无需处理的UART3接收任务
}
}
//UART3中断服务程序,UART3_VECTOR在AI8051U.H头文件中已宏定义为17
void Uart4_Isr(void) interrupt UART4_VECTOR
{
if (S4CON & 0x02) //检测串口4发送中断
{
S4CON &= ~0x02; //清除串口4发送中断请求位
_nop_(); //特急处理
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
uart4_txflag = 1; // uart4_txflag置1是通知主循环处理部分串口4发送中断事件不需要特急处理的任务
//置1,记录UART4已产生发送中断,供主循环查询判断有无需处理的UART4发送任务
}
if (S4CON & 0x01) //检测串口4接收中断
{
S4CON &= ~0x01; //清除串口4接收中断请求位
_nop_(); //特急处理
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
uart4_rxflag = 1; // uart4_rxflag置1是通知主循环处理部分串口4接收中断事件不需要特急处理的任务
//置1,记录UART4已产生接收中断,供主循环查询判断有无需处理的UART4接收任务
}
}
//UART4中断服务程序,UART4_VECTOR在AI8051U.H头文件中已宏定义为18
我一般把按键扫描、数码管扫描等放入1ms定时中断里
页:
[1]