打印
[STM32F1]

冒昧再次出现请教WHILE语句的问题

[复制链接]
4245|57
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gdszzyq|  楼主 | 2015-5-11 23:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 gdszzyq 于 2015-5-11 23:24 编辑

怎么想用STM32就那么难啊,以下这些语句在51哪里绝对没问题的,但始终不明白在这里就是不行,始终卡在这句while(test<2000);不退出。真不好意思再问了,实在找不出原因。
u16 test;
int main(void)
{
   SystemInit ();
  LED_Init();
  TIM6_Int_Init(10,7200);//10Khz的计数频率,定时1毫秒
  uart_init(9600);
  while (1)
  {
      test=0;     // 一直没执行    ....
     LED1=!LED1;      // 只执行一次就再没执行
     while(test<2000);    为什么test>=2000还没跳出来?
  }
}

void TIM6_IRQHandler(void)   //TIM6中断
{
        if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
        {
            TIM_ClearITPendingBit(TIM6, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源                 
            test++;
            if(test>8000)LED0=0;      //居然能点亮,说明卡在 while(test<2000);这里
        }
}


沙发
Xflyan| | 2015-5-11 23:18 | 只看该作者
void TIM6_IRQHandler(void)   //TIM3中断
确定软件里是这么写的?TIM3?TIM6?

使用特权

评论回复
评论
gdszzyq 2015-5-11 23:23 回复TA
函数名也忘记改了,里面的定义都改成TIM6了 
gdszzyq 2015-5-11 23:21 回复TA
原来是TIM3的,后来改成TIM6了忘记改批注了 
板凳
gdszzyq|  楼主 | 2015-5-11 23:20 | 只看该作者
TIM6,定时没问题的,都测试过的,我改成IF语句都可以正常运行,我只不过是想让程序按一定周期运行一次以方便定时,以前在51一直都是这么做的

使用特权

评论回复
地板
wind~风| | 2015-5-11 23:22 | 只看该作者
中断函数名写错了,还有检查中断有没有正确配置

使用特权

评论回复
评论
gdszzyq 2015-5-11 23:26 回复TA
函数名是忘记改了,不过里面的定义是TIM6的,初始化函数名错了不影响程序运行的,中断函数没错就行 
5
Lyc1992| | 2015-5-11 23:24 | 只看该作者
用无符号数,加个test清零看下

使用特权

评论回复
6
Xflyan| | 2015-5-11 23:26 | 只看该作者
gdszzyq 发表于 2015-5-11 23:20
TIM6,定时没问题的,都测试过的,我改成IF语句都可以正常运行,我只不过是想让程序按一定周期运行一次以方 ...

那你初始化又写着TIM3!!!   if 语句当然可以过,如果你的test++根本没有执行的话,if (test < 2000)始终成立

使用特权

评论回复
7
gdszzyq|  楼主 | 2015-5-11 23:28 | 只看该作者
Xflyan 发表于 2015-5-11 23:26
那你初始化又写着TIM3!!!   if 语句当然可以过,如果你的test++根本没有执行的话,if (test < 2000)始终 ...

test如果没加这句就不可能通过if(test>8000)LED0=0;,但这句却执行了,我加这一句就是检验你说的这个问题

使用特权

评论回复
8
Xflyan| | 2015-5-11 23:28 | 只看该作者
在中断里修改的变量最好是加上 volatile u16 test; 估计是给优化了,while 判断里的值没有变化

使用特权

评论回复
9
Xflyan| | 2015-5-11 23:31 | 只看该作者
gdszzyq 发表于 2015-5-11 23:28
test如果没加这句就不可能通过if(test>8000)LED0=0;,但这句却执行了,我加这一句就是检验你说的这个问题 ...

因为优化的关系,while 里判断的 test 跟中断里判断的 test 不是同一个东西

使用特权

评论回复
10
gdszzyq|  楼主 | 2015-5-11 23:34 | 只看该作者
这样又可以,说明test正常加1.
int main(void)
{
   SystemInit ();
  LED_Init();
  TIM6_Int_Init(10,7200);//10Khz的计数频率,计数到5000为500ms
  uart_init(9600);
   LED1=1;
  while (1)
  {
     if(test>2000)
     {
          ...
          test=0;
          LED1=!LED1;
     }
  }
}

使用特权

评论回复
11
Xflyan| | 2015-5-11 23:38 | 只看该作者
gdszzyq 发表于 2015-5-11 23:34
这样又可以,说明test正常加1.
int main(void)
{

变量加个 volatile 试试就知道有没有被优化了
while判断里面如果不执行动作的话,那个变量会被寄存器替代的

使用特权

评论回复
12
gdszzyq|  楼主 | 2015-5-11 23:43 | 只看该作者
Xflyan 发表于 2015-5-11 23:38
变量加个 volatile 试试就知道有没有被优化了
while判断里面如果不执行动作的话,那个变量会被寄存器替代 ...

可能真的是这种情况,但我设的是全局变量呀,明天再验证吧,谢谢各位指点

使用特权

评论回复
13
Xflyan| | 2015-5-11 23:46 | 只看该作者
gdszzyq 发表于 2015-5-11 23:43
可能真的是这种情况,但我设的是全局变量呀,明天再验证吧,谢谢各位指点 ...

while 判断的内容如果有可能在中断里改变的变量必须加 volatile ,否则不知道什么情况会被优化
这也是寄存器为什么必须定义成 volatile 类型的

使用特权

评论回复
14
whtwhtw| | 2015-5-12 08:54 | 只看该作者
本帖最后由 whtwhtw 于 2015-5-12 09:21 编辑

额,只能看看汇编代码查找问题了






使用特权

评论回复
15
ETjason| | 2015-5-12 09:11 | 只看该作者
test不大于2000执行空语句,但如果test大于2000主程序不是一直在循环,是不能退出啊。

使用特权

评论回复
16
aozima| | 2015-5-12 09:12 | 只看该作者
回炉重炼,既然 test = 0,那么 0永远小于2000,编译器 直接优化成 while(1); 了

使用特权

评论回复
评论
myxiaonia 2015-5-12 12:33 回复TA
没看清楚问题,评论失误。。。 
myxiaonia 2015-5-12 12:29 回复TA
为何编译器会优化这种情况,编译器不知道变量可能会在其他c文件更改,还是会强行优化掉呢。。。 如果要避免这种情况 
gdszzyq 2015-5-12 09:56 回复TA
请看清楚了,中断函数定时加1的,等到等于2000时退出WHILE。 
17
gdszzyq|  楼主 | 2015-5-12 09:22 | 只看该作者
Xflyan 发表于 2015-5-11 23:46
while 判断的内容如果有可能在中断里改变的变量必须加 volatile ,否则不知道什么情况会被优化
这也是寄 ...

真是这个原因造成的,改成volatile 类型就好了,我真是不明白了,为什么我用IF语句时就可以正常运行呢,难道我要将所有变量都定义成volatile 类型?对STM32我真是越来越糊涂了,到底哪些变量要定义成volatile 类型,哪些又不用呢,库函数里也有很多普通变量啊

使用特权

评论回复
18
mark0668| | 2015-5-12 09:48 | 只看该作者
调试能进中断吗?

使用特权

评论回复
19
gdszzyq|  楼主 | 2015-5-12 09:58 | 只看该作者
当然能进,这句就是在中断里的也执行了把灯点亮 if(test>8000)LED0=0;      //居然能点亮,说明卡在 while(test<2000);这里

使用特权

评论回复
20
Xflyan| | 2015-5-12 10:24 | 只看该作者
gdszzyq 发表于 2015-5-12 09:22
真是这个原因造成的,改成volatile 类型就好了,我真是不明白了,为什么我用IF语句时就可以正常运行呢, ...

可能在中断里被改变的全局变量,循环判断操作里没有动作的变量,建议都是 volatile 的
你的应用里 if 是每次重新读取了内存里的值,而 while 没有,被编译器优化了

使用特权

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

本版积分规则

46

主题

322

帖子

3

粉丝