【STM32F103疑问】定时器1比较输出产生2路脉冲
找到原因了。但是没有全部解决。对于我之前提出的问题,原因是:当产生了CC2中断,且正要进入程序段2时,此时发生了CC1中断。由于CC2IF是1,则TIM1_CC的中断悬停位不会被置一,此情况如下图所示:
然而当程序段2执行后,CC2IF标志被清除,则此时来了CC1中断后,TIM1_CC的中断悬停位会被再次置一。这也是为什么从来不会进入test=5的断点。
参见我的程序:
void TIM1_CC_IRQHandler(void)
{
vu8 test=1;
//程序段1
if (TIM1_CC1IF)
{
TIM1_CC1IF = 0;
CCR_Mask_x += CCR_Acc_x;
TIM1->CCR1 = CCR_Mask_x;
}
//程序段2:
if (TIM1_CC2IF)
{
TIM1_CC2IF = 0;
CCR_Mask_y += CCR_Acc_y;
TIM1->CCR2 = CCR_Mask_y;
}
//程序段3:
if (1==TIM1_CC1IF)//6clk
{
if (NVIC_GetPendingIRQ(TIM1_CC_IRQn))
{
test = 2; //说明发生了CC1中断,且硬件自动置1了Pending位。这个断点有40%的机会进入//3clk
}
if (!NVIC_GetPendingIRQ(TIM1_CC_IRQn))//22clk
{
test = 3; //说明发生了CC1中断,但是硬件没有置一Pending位。这个断点也有40%的机会进入
}
}
//程序段4:
if (test==1 && TIM1_CC1IF==1)
{
if (NVIC_GetPendingIRQ(TIM1_CC_IRQn))
{
test = 4; //说明发生了CC1中断,且硬件置1了Pending位。这个断点有20%的机会进入
}
if (!NVIC_GetPendingIRQ(TIM1_CC_IRQn))
{
test = 5; //★令人同样奇怪的是,这个断点不会进入★
}
}
}
因此,需要采取的措施是:在进入中断,对各个CCxIF做判断之前,必须一次性把TIM1->SR读取到内存变量,然后清零SR,然后根据内存变量来判断。
于是产生了新的问题:
ISR中,第一步先要读取寄存器SR到内存变量,第二步写SR为0,其间仍然有可能硬件改变SR,即:
于是我采用了流水线指令隔离ISB + 互斥访问LDREX/STREX来保护:
void TIM1_CC_ISR(void)
{
vu8 test=0;
u32 TIM1_SR_mask;
__TRY_:
TIM1_SR_mask = __LDREXH(&(TIM1->SR));
__asm("isb");
TIM1->SR = 1;
if (__STREXH(0,&(TIM1->SR)))
{
goto __TRY_;
}
于是出现的新问题是:即使我在LDREX和STREX之间手动添加一个测试语句TIM1->SR = 1;,STREX的执行总是成功的。
是我使用LDREX和STREX有误吗?
各位大虾求指点啊。。
=============================分割线,以下是之前发的问题,上面的问题解决的当前进度=========================
遇到一个很诡异的问题
问题描述:
芯片:STM32F103 ZET6
工程中使用TIM1的CCR1和CCR2作为输出比较模式(在TIM1_CNT和TIM1_CCRx匹配时翻转电平,并触发TIM1_CC_IRQHandler中断进行处理,即使用TIM1来输出两路不同频率的脉冲信号来控制电机)。
当一个CCR2匹配的中断到来时,进入该中断后,TIM1_CC的中断悬停位自动被硬件清零;(注意CCR1和CCR2共用一个TIM1_CC中断)
★此时又来了CCR1匹配中断,此时按照Cortex-M3技术规范,硬件应该再次置一TIM1_CC的中断悬停位;★
然而在实际使用中(使用Keil MDK, JLink连接芯片进行调试,且工程使用了DBGMCU_Config(DBGMCU_TIM1_STOP, ENABLE);来保证Core进入断点后Timer1停止运行),发现此种情况下,(称之为情况①,即——由CCR2触发了中断,在中断处理程序TIM1_CC_ISR中又发生了CCR1匹配中断),硬件有时可以自动置一TIM1_CC的中断悬停位,有时却不可以,从而导致了程序将错过一次CCR1匹配中断,在实际使用中是一个严重的问题。
在此请教的问题是:如何设置,才能在情况①下,能够让硬件一定置一TIM1_CC的中断悬停位,从而保证CCR1引起的中断能够使得本次中断结束后立即被执行?或者说,这是STM32硬件本身的问题?
这里附上我特意编写的测试工程、测试截图、和详细说明。
工程环境:Keil MDK 4.73,下载器:J-Link 4.76d
main.c 中的TIM1_CC_ISR(void)函数是故障所在的文件。
System_Init.c 是系统初始化文件。
需要说明一点:采用 CCR_Acc_x 等于 562,CCR_Acc_y 等于 18000。
如果使用相同的562或者18000,则不会出现该现象。
实际运行情况:
模拟运行Simulation亦如此:
期待各路高手能给出解答!
谢谢大家!
RE:【STM32F103疑问】定时器1比较输出产生2路脉冲
TIM1_CC1F是一个自己定义的标志位吗?这段代码是在中断中跑的,还是在其他函数中跑的。回复:【STM32F103疑问】定时器1比较输出产生2路脉冲
回复第 2 楼 于2014-04-11 14:08:23发表:TIM1_CC1F是一个自己定义的标志位吗?这段代码是在中断中跑的,还是在其他函数中跑的。
对,TIM1_CC1F是一个位带定义,指向TIM1->SR的CC1F。这段代码是在中断里的。我那个工程是特意写出来可以直接测试用的。。要是方便的话可以帮忙看一下吗。。程序很短。
RE:【STM32F103疑问】定时器1比较输出产生2路脉冲
TIM1-SR只能由硬件产生,软件不能设置的。回复:【STM32F103疑问】定时器1比较输出产生2路脉冲
回复第 4 楼 于2014-04-12 11:38:37发表:TIM1-SR只能由硬件产生,软件不能设置的。
一语道破梦中人啊~ 多谢。
那有什么办法完成对TIM1_SR同时的读和写吗。
因为我需要在将SR读取到内存变量TIM1_SR_mask中,然后再清零SR,然而在这两个操作之间,硬件仍然会改变SR的值,则TIM1_SR_mask不能如实的反应SR的正真状态。且第二句话又清零了SR,这样SR将无法被还原。
页:
[1]