void NVIC_SetPendingIRQ (IRQn_t IRQn) 关于中断挂起函数
芯片型号:STM32F103RE操作系统:FREERTOS问题描述:
1.编码器计数时,硬件计数器记满一个周期(目前设置为10),会在TIM2中产生一个中断,进行进位
2.实现方式,先获取了硬件定时器中的数,再获取周期中的数,返回两者相加的值。计数值函数如下:
u32CCounter::getCounter_u32()
{
return _counterTotal + TIM_GetCounter((TIM_TypeDef*)_timer->getTimx());//自动截取低32位
}3.存在问题,先获取个位数时(正好是9),再获取十位数时(此时正好产生了一个进位中断),导致十位进一而个位仍然是9,最终该值比期望值小9
解决方案:
1.不使用中断而改用查询的方式(因为这是公司的框架,希望尽量少的改动代码)
2.考虑使用临界区保护。但发现freertos中临界区的优先级比TIM2低,无法挂起中断
3.考虑使用STM32自带的中断挂起函数void NVIC_SetPendingIRQ (IRQn_t IRQn) ,但目前发现该函数操作的寄存器ISPR虽然是32位,但赋值时只能使用16位,无法挂起该中断(TIM2为28)
关于挂起中断,void NVIC_SetPendingIRQ (IRQn_t IRQn)
/**
* @briefSet the pending bit for an external interrupt
*
* @paramIRQn The number of the interrupt for set pending
*
* Set the pending bit for the specified interrupt.
* The interrupt number cannot be a negative value.
*/
static __INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
{
NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */
}关于读取该中断挂起的状态,static __INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
/**
* @briefRead the interrupt pending bit for a device specific interrupt source
*
* @paramIRQn The number of the device specifc interrupt
* @return 1 = interrupt pending, 0 = interrupt not pending
*
* Read the pending register in NVIC and return 1 if its status is pending,
* otherwise it returns 0
*/
static __INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
{
return ((uint32_t) ((NVIC->ISPR & (1 << ((uint32_t)(IRQn) & 0x1F))) ? 1 : 0)); /* Return 1 if pending else 0 */测试代码时,发现只能设置和读取16位以下的数(但TIM2是28),不是官方表示的32位。
希望各位大大帮忙给下建议
萌新上路,希望各位大大出手相助:loveliness: 为什么会先获取个位再获取十位呢?直接一次性全部读出来不可以么?一个32位的数可以表示很大了。 一个32位的数却只有16位的权力,看看你设置的是不是对,看看获取位是不是异常,我觉得还是参数的问题 前来学习,这问题之前也遇过,当时也只能搁着没解决。
之后就忙新的案子去了,也不再捣鼓这问题了!~ :L
修改一下,计数值函数 CCounter::getCounter_u32() 。
在获取硬件读数值后,TIM_GetCounter((TIM_TypeDef*)_timer->getTimx())
对该值做处理,如果<9,数值按正常累加。
如果>9数值先加9,再累加,不就可以了吗?
问题的原因应该是TIM2的中断优先级太低了,其他中断的优先级高于这个TIM2中断。如果不是精度要求,用FreeRTOS的软件中断吧。 有两个解决方法:
1、读取计数之前关中断,读取结束再打开
2、先读取十位,再读取硬件的个位
if (个位 < 5)
{
重新读取一次十位;
}
页:
[1]