你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【STM32F103疑问】定时器1比较输出产生2路脉冲

[复制链接]
helixwmonkey 提问时间:2014-4-10 18:40 /
找到原因了。但是没有全部解决。
对于我之前提出的问题,原因是:当产生了CC2中断,且正要进入程序段2时,此时发生了CC1中断。由于CC2IF是1,则TIM1_CC的中断悬停位不会被置一,此情况如下图所示:

5.png
然而当程序段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,即:
6.png
于是我采用了流水线指令隔离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硬件本身的问题?
这里附上我特意编写的测试工程、测试截图、和详细说明。
 
TestPrj.rar (276.92 KB, 下载次数: 27)
收藏 评论4 发布时间:2014-4-10 18:40

举报

4个回答
废鱼 回答时间:2014-4-11 14:08:23

RE:【STM32F103疑问】定时器1比较输出产生2路脉冲

TIM1_CC1F是一个自己定义的标志位吗?这段代码是在中断中跑的,还是在其他函数中跑的。
helixwmonkey 回答时间:2014-4-11 15:42:29

回复:【STM32F103疑问】定时器1比较输出产生2路脉冲

回复第 2 楼 于2014-04-11 14:08:23发表:
TIM1_CC1F是一个自己定义的标志位吗?这段代码是在中断中跑的,还是在其他函数中跑的。
对,TIM1_CC1F是一个位带定义,指向TIM1->SR的CC1F。这段代码是在中断里的。我那个工程是特意写出来可以直接测试用的。。要是方便的话可以帮忙看一下吗。。程序很短。
 
废鱼 回答时间:2014-4-12 11:38:37

RE:【STM32F103疑问】定时器1比较输出产生2路脉冲

TIM1-SR只能由硬件产生,软件不能设置的。
helixwmonkey 回答时间:2014-4-12 16:00:30

回复:【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将无法被还原。
 

 
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版