这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 国产MCU » 【STCAi8051U】Ai8051U的IO口中断的测试程序

共1条 1/1 1 跳转至

【STCAi8051U】Ai8051U的IO口中断的测试程序

专家
2026-01-30 22:51:32     打赏

测试程序设计为同时测试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的输出来模拟高低电平的变化,以及产生上升沿和下降沿。

实际上串口输出日志:

图片1.png

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

如果把代码

        OUT2 = 0;
        delay(1);
        OUT2 = 1;
        delay(1);

改为

        OUT2 = 0;
        OUT2 = 1;

结果测试的输出日志

图片2.png

就一直没出现过低电平中断的处理。不知道是不是P1.2低电平出现的时间太短,导致P2.2的低电平中断没有来得及铺捉到。

不过总体上,这个程序已经把四种中断都测试到了。




关键词: 懒猫的学习笔记     Ai8051U     IO口中断    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]