打印
[PIC®/AVR®/dsPIC®产品]

PIC32MX单片机无法进入中断问题--解决方法

[复制链接]
1237|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wiba|  楼主 | 2021-6-6 10:49 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
Hello,小伙伴们大家好,最近从STM32平台转战到PIC平台,一开始不是特别的顺手。首先资料不如32那么详尽,其次相关的论坛比较少,遇到问题只能去看官方手册和百度。今天按照官方的寄存器手册,调用<plb.h>函数库,在编写完定时器的配置后,发现无法进入中断,经过一番苦苦寻找,终于找到了问题所在。我会把源码以及解决方案放在下面。

平台:PIC32MX795F512L单片机,主频80MHz,定时器时钟频率为40MHz。采用外部4M晶振,通过PLL倍频器20倍频得到80MHz主时钟,外设时钟2分频,得到40MHz。

下面是我的初始化代码:

/************************************************
*  @函数功能:定时器2初始化
*  @参    数:无
*  @返    回:无
*  @说    明:定时时间为1ms  外设时钟为40M
*************************************************/
void Tim2_Init()
{
        //定时器2初始化
        OpenTimer2(T2_ON             /* 打开定时器 */
                   |T2_IDLE_CON       /* 空闲模式继续 */
                      |T2_PS_1_64,       /* 64分频 */
                  625);             /* 定时周期设置 1ms */
        TMR2 = 0; /* 清除计数 */
        ConfigIntTimer2(T2_INT_ON|T2_INT_PRIOR_4);/* 定时器中断配置 */
}



定时器2采用外设时钟,时钟周期为40MHz,设置64分频,所以1s的计数值为 40000000/64 = 625000,所以定时1ms的重装值为625.
公式:预设值 = 主频 / 分频系数 / 1000 * n,n为定时周期,单位为ms。


使用特权

评论回复
沙发
wiba|  楼主 | 2021-6-6 10:50 | 只看该作者
下面是中断服务函数

/************************************************
*  @函数功能:定时器2中断服务函数
*  @参    数:无
*  @返    回:无
*************************************************/
void __ISR(_TIMER_2_VECTOR, ipl4auto) IsrTIM2Handler(void)
{
        delay_count++;
        INTClearFlag(INT_T2);/* 清除中断标志位 */
}


其中 “_TIMER_2_VECTOR”为定时器2的向量地址,ipl4auto表示定时器2的中断优先级为4。

问题来了,确定配置没问题后,调试发现竟然无法进入中断,在网上一顿乱找,最后终于找到了。

PIC32MX没有所谓的总中断控制位,但是CPU有两种中断方式,中断单向量模式和多向量模式。意思就是如果工作在单向量模式,CPU只会进入同一个中断向量地址(没用过,故不多介绍)。我们主要关心多向量模式,就是根据不同的中断地址进入不同的中断函数。但是PIC32MX每次复位默认处于单向量模式,因此需要手动配置。下面介绍如何配置。


使用特权

评论回复
板凳
wiba|  楼主 | 2021-6-6 10:51 | 只看该作者
配置代码:

/* CPU工作多中断向量模式配置 */
#define hwGLOBAL_INTERRUPT_BIT           ( 0x01UL )
#define hwBEV_BIT                       ( 0x00400000 )
#define hwEXL_BIT                       ( 0x00000002 )
#define hwIV_BIT                               ( 0x00800000 )
/************************************************
*  @函数功能:设置CPU工作于多向量模式
*  @参    数:无
*  @返    回:无
*  @说    明:定时时间为1ms  外设时钟为40M
*************************************************/
void vHardwareUseMultiVectoredInterrupts( void )
{
        unsigned long ulStatus, ulCause;
        extern unsigned long _ebase_address[];
        /* 获取当前状态 */
        ulStatus = _CP0_GET_STATUS();
        /* 禁止中断 */
        ulStatus &= ~hwGLOBAL_INTERRUPT_BIT;
        /* 设置 BEV */
        ulStatus |= hwBEV_BIT;
        /* 写状态返回 */
        _CP0_SET_STATUS( ulStatus );
        /* 设置 Ebase */
        _CP0_SET_EBASE( ( unsigned long ) _ebase_address );
        /* 0x20字节空间向量 */
        _CP0_XCH_INTCTL( 0x20 );
        /* 设置 CAUSE寄存器的 IV位 */
        ulCause = _CP0_GET_CAUSE();
        ulCause |= hwIV_BIT;
         _CP0_SET_CAUSE( ulCause );
        /* 清除 BEV和 EXL */
        ulStatus &= ~( hwBEV_BIT | hwEXL_BIT );
         _CP0_SET_STATUS( ulStatus );

        /* 设置MVEC */
        INTCONbits.MVEC = 1;       
       
        /* 使能中断 */
        ulStatus |= hwGLOBAL_INTERRUPT_BIT;
         _CP0_SET_STATUS( ulStatus );
       
}



使用特权

评论回复
地板
wiba|  楼主 | 2021-6-6 10:53 | 只看该作者

为啥要这样配置呢,我也不知道,但是有参考,可以在microchip的官网找到相应的手册。如下图1.1


图1.1

可能有的朋友看英文比较费劲(比如像我),因此特地找到了中文版的,如下图1.2所示。


图1.2

把多向量配置函数放在man()函数的开头就行了,到此解决!


使用特权

评论回复
5
xinpian101| | 2021-6-6 22:03 | 只看该作者
现在不支持代码模式贴代码了吗

使用特权

评论回复
6
pzsh| | 2021-8-16 19:27 | 只看该作者
分享的好,避免以后踩坑

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

77

主题

3305

帖子

3

粉丝