打印
[STM8]

中断里面读定时器异常

[复制链接]
1138|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
roalychen|  楼主 | 2016-4-26 10:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM8S903K的片子做红外遥控接收,用I/O口的中断加定时器测低电平脉冲宽度(项目限制,不能用捕捉),I/O口设定是上升和下降沿中断,下降沿清零并启动定时器,上升沿读取
发现测量的脉宽都一样,并且不准确。
代码如下:
void IRInit(void) // 初始化
{
        TIM2->PSCR = 2;  // 4MHz
        TIM2->CR1 = 0x03;   /*!< control register 1 */

        EXTI->CR1 = 0x30; /*!< External Interrupt Control Register for PORTA to PORTD */
        GPIO_Init(GPIOC,  0x10  , GPIO_MODE_IN_PU_IT);
}


@interrupt void INT1_Exception (void)  //ISR
{
    static INT16U   tcnt1bk, tcnt2pre,tcnt2,tcnt2bk;
    static INT16U   count   = 0;
    INT8U   i;
        static INT16U bk[32];

       
       
        {
                ucCnt++;  // 这个变量的计数来看,中断次数是正确的
                #if 1
               
                if(IRPort)  // PC_IDR4
                {
                        tcnt2bk = TIM2->CNTRH;
                        tcnt2bk <<= 8;
                        tcnt2bk |= TIM2->CNTRL;
                        if(count<32)
                        {
                             bk[count] = tcnt2bk ;  // 这里除了记录的头码是正确的之外,其他都基本差不多,且不准确
                             count++;
                          }
                }
                else
                {
                        TIM2->CR1 = 0;
                        TIM2->CNTRH = 0;
                          TIM2->CNTRL = 0;
                        TIM2->CR1 = 0x03;  // 这里改为TIM2->EGR |= 0X01;也是一样结果
                }
               
                #endif
        }
}


我看ST的触摸库也是用TIM2来测量时间,只是读取是用ASM读取,并且不是在中断读取,这个会有影响吗?
以前也用过ST的片子的IO口来模拟SPI总线,也出现诸多问题
沙发
quray1985| | 2016-4-26 10:40 | 只看该作者
我用IO口模拟过I2C,没有出现过类似的问题

使用特权

评论回复
板凳
江枫渔火| | 2016-4-26 12:33 | 只看该作者
中断中使用变量,尽量都加那个volitxxxxx声明!

使用特权

评论回复
地板
shauew| | 2016-4-26 13:45 | 只看该作者
被优化了

使用特权

评论回复
5
roalychen|  楼主 | 2016-4-28 09:46 | 只看该作者
江枫渔火 发表于 2016-4-26 12:33
中断中使用变量,尽量都加那个volitxxxxx声明!

哦,我试试看。谢谢!

使用特权

评论回复
6
roalychen|  楼主 | 2016-4-28 09:57 | 只看该作者

??求指点。谢谢!

使用特权

评论回复
7
Soraka| | 2016-4-28 21:10 | 只看该作者
中断中使用变量,尽量都加那个volitxxxxx声明!

volitxxxxx声明是什么,为什么要加这个

使用特权

评论回复
8
bayuan0414| | 2016-4-29 01:21 | 只看该作者
Soraka 发表于 2016-4-28 21:10
volitxxxxx声明是什么,为什么要加这个

volatile,表示被修饰的变量是易变的。这样对这个变量的访问,每次都会从内存拷贝到寄存器,改变了值之后也会立即从寄存器更新到变量所在内存。

使用特权

评论回复
9
wsnsyy| | 2016-4-29 08:48 | 只看该作者
volatile防止被优化了

使用特权

评论回复
10
江枫渔火| | 2016-4-29 13:11 | 只看该作者
我英文不好,不知道全拼怎么写,所以就胡乱写了下。应该就是volatile。
我跟你说,这个声明的作用是什么,它就是告诉编译器,这个变量虽然没有在代码的流程中进行过赋值操作,但是,你每次取这个变量的值时,都要实实在在的去读一下这个内存,而不要以为它没有赋值过所以值还是原来定义的那个值。没有这个声明,代码经过优化后,可能在所有这个用到这个变量的地方,直接用初始值替代了,也就是这个值不会变化了。
那么,问题来了,这到底他么的怎么回事?我想用最简单的话解析一下:
如果你按图索骥,从main函数开始,顺序执行的每个角落,编译系统都是知道的,但是中断函数和硬件改变的值,编译系统是不知道的,因为这是外部插入的执行过程。如果你在顺序执行的过程里,从来没有对一个声明的变量进行过再次赋值,那编译系统以为这个变量是不会更改值的,它一直就是初始化值,或者就算在顺序执行的过程中,有对这个变量再次赋值,但你每次取这个变量时,都是取得这个变量最后被在顺序执行过程中赋值后的值。但实际呢?中断可能改变这个变量,或者端口上的电平变化改变这个变量,对不对?
就是这样了,所有CPU的寄存器引用定义,绝对都是声明为volatile的。

使用特权

评论回复
11
cnb12345| | 2016-4-29 15:26 | 只看该作者

使用特权

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

本版积分规则

102

主题

227

帖子

0

粉丝