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

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。

下面是中断服务函数

/************************************************
*  @函数功能:定时器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每次复位默认处于单向量模式,因此需要手动配置。下面介绍如何配置。

配置代码:

/* 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 );
	
}


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

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

在这里插入图片描述
图1.2

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

最后附上参考手册的链接

中文文档链接:http://www.microchip.com.cn/newcommunity/Uploads/Download/Library/60001108h_cn.pdf
英文文档链接:http://ww1.microchip.com/downloads/en/DeviceDoc/60001108H.pdf

第一次写博客,如有大神看到有错误的地方,还请指正!

猜你喜欢

转载自blog.csdn.net/weixin_42952614/article/details/107968615
今日推荐