测试程序设计为同时测试IO口的中断。但实际测试中发现有如下问题:
在默认弱双向口状态下,没有外围电路的配置时,IO口默认是高电平状态,因此常态下高电平中断会不断产生。实际测试时,通过输出日志也证实了这一点,所以取消了对高电平中断的测试。
代码如下:
/*---------------------------------------------------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/*---------------------------------------------------------------------*/
/************* 功能说明 **************
本例程基于AI8051U为主控芯片的实验箱进行编写测试。
使用Keil C251编译器,Memory Model推荐设置XSmall模式,默认定义变量在edata,单时钟存取访问速度快。
edata建议保留1K给堆栈使用,空间不够时可将大数组、不常用变量加xdata关键字定义到xdata空间。
通过添加MDU32库文件实现AI8051U硬件乘除法,替换标准算法库算法
串口1(115200,N,8,1)打印计算结果
可通过屏蔽"STC32_MDU32_V1.x.LIB"文件,用示波器测量IO口低电平时间,来对比AI8051U硬件乘除法单元与标准算法库的计算效率
测量计算时间时可将串口打印指令屏蔽,方便查看每条公式的计算时间
下载时, 默认时钟 24MHz (用户可自行修改频率).
******************************************/
#include "AI8051U.h"
#include "intrins.h"
#include "stdio.h"
#include "math.h"
#define MAIN_Fosc 24000000UL
/*****************************************************************************/
sbit OUT0 = P1^0;
sbit OUT1 = P1^1;
sbit OUT2 = P1^2;
sbit OUT3 = P1^3;
/*****************************************************************************/
#define Baudrate 115200L
#define TM (65536 -(MAIN_Fosc/Baudrate/4))
#define PrintUart 1 //1:printf 使用 UART1; 2:printf 使用 UART2
/******************** 串口打印函数 ********************/
void UartInit(void) {
S1_S1 = 0; //UART1 switch to, 0x00: P3.0 P3.1, 0x01: P3.6 P3.7, 0x10: P1.6 P1.7, 0x11: P4.3 P4.4
S1_S0 = 1;
SCON = (SCON & 0x3f) | 0x40;
T1x12 = 1; //定时器时钟1T模式
S1BRT = 0; //串口1选择定时器1为波特率发生器
TL1 = TM;
TH1 = TM>>8;
TR1 = 1; //定时器1开始计时
}
void UartPutc(unsigned char dat) {
SBUF = dat;
while(TI==0);
TI = 0;
}
char putchar(char c) {
UartPutc(c);
return c;
}
void delay(unsigned char ms) {
int p = ms*2000;
while(--p);
}
void PLL_Init() {
CLKSEL |= 0x80; //选择PLL的144M(*12)作为PLL的输出时钟
USBCLK &= ~0x60;
USBCLK |= 0x40; //PLL输入时钟为48M则选择4分频
USBCLK |= 0x80; //启动PLL
delay(1000); //等待PLL锁频,建议50us以上
HSCLKDIV = 0; //高速外设时钟源不分频
TFPU_CLKDIV = 0; //TFPU时钟源不分频
CLKSEL |= 0x40; //选择PLL时钟作为高速外设时钟源
}
// 测试P2口的IO中断,因为P2口焊接有LED
void P2Init(void) {
//P2IM1 00001100 = P2IM1.3=1, P2IM1.2=1, P2IM1.1=0, P2IM1.0=0,
//P2IM0 00001010 = P2IM0.3=1, P2IM0.2=0, P2IM0.1=1, P2IM0.0=0,
// 高电平 低电平 上升沿 下降沿
P2IM0 = 0x0A; // P2.0下降沿中断,P2.1上升沿中断,P2.2低电平中断,P2.3高电平中断,其它IO口为下降沿中断
P2IM1 = 0x0C; // 00001100 P2IM1.3=1, P2IM1.2=1, P2IM1.1=0, P2IM1.0=0,
// 因为常态下IO口为高电平,所以这里禁止P2.3的中断
P2INTE = 0x07; // 使能 P2 口中断,只允许P2.0, P2.1, P2.2
//P2INTE = 0x0F; // 使能 P2 口中断,只允许P2.0, P2.1, P2.2, P2.3
}
/*****************************************************************************/
void main(void) {
unsigned char val = 0;
WTST = 0; //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0x00; //设置为准双向口
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
UartInit();
PLL_Init();
DMAIR = 0x3f; //TFPU使用高速外设时钟作为时钟源
//*** 必须设置此句,TFPU才能使用高速时钟作为时钟源 ***
// 初始化P2口中断
P2Init();
EA = 1;
printf("main......\r\n");
while(1) {
OUT0 = 0;
delay(1000);
OUT0 = 1;
delay(1000);
OUT1 = 0;
delay(1000);
OUT1 = 1;
delay(1000);
OUT2 = 0;
delay(1);
OUT2 = 1;
delay(1);
}
}
/*****************************************************************************/
// 由于中断向量大于 31 ,在 KEIL 中无法直接编译
// 必须借用第 13 号中断入口地址
// P2中断处理成由ASM程序处理,处理中由JMP处理导向13号中断处理程序的入口,所以此处的C程序使用13号中断
void common_isr() interrupt 13 {
unsigned char val = 0;
unsigned char intf;
val = P2;
intf = P2INTF;
if (intf) {
// 清除标志位
P2INTF = 0x00;
printf("value = %2x\r\n", val);
if (intf & 0x01) {
//P2.0 口中断
printf("ISR:P2.0\r\n");
}
if (intf & 0x02) {
//P2.1 口中断
printf("ISR:P2.1\r\n");
}
if (intf & 0x04) {
//P2.2 口中断
printf("ISR:P2.2\r\n");
}
// if (intf & 0x08) {
// //P2.3 口中断
// printf("ISR:P2.3\r\n");
// }
}
}实际测试时,如果使用按钮测试的话,一定会有抖动发面的问题,所以使用其它IO输出电平的方式,代替高低电平的变化,以及产生上升沿和下降沿。
连接方式如下:
P1.0-P2.0, P1.1-P2.1, P1.2-P2.2
通过控制P1.0、P1.1、P1.2的输出来模拟高低电平的变化,以及产生上升沿和下降沿。
实际上串口输出日志:

通过对输出日志的分析发现,上升沿和下降沿的响应很好,结果也正常。但低电平的测试出了问题,就是当P1.2=0导致低电平的中断响应出现后,这个中断就会不断产生,根本停止不下来,似乎由于delay延时处理中的某个点上被低电平中断不断地打断,而且退不出来了。
如果把代码
OUT2 = 0; delay(1); OUT2 = 1; delay(1);
改为
OUT2 = 0; OUT2 = 1;
结果测试的输出日志

就一直没出现过低电平中断的处理。不知道是不是P1.2低电平出现的时间太短,导致P2.2的低电平中断没有来得及铺捉到。
不过总体上,这个程序已经把四种中断都测试到了。
我要赚赏金
