【问题标题】:Interupt - microcontroller, Atmega 328p - Capturing time中断 - 微控制器,Atmega328p - 捕获时间
【发布时间】:2019-12-17 10:51:01
【问题描述】:

免责声明 - 在中断方面,我是个大菜鸟,所以如果您有一些错误要指出,我很高兴听到。 我正在编程一个数字霍尔传感器,只要有磁铁,它就像一个开关,我想为它使用一个计时器。 d10 引脚,PB2,由 5V 供电。 [Atmega328p]
我想使用oneround 作为稍后计算风速的单轮时间,无限循环。
磁铁以小半径旋转,因此 PIN [默认开启] 将在 0.1s-1.0s 之间的任何速度关闭,然后再打开。

当我尝试打印值 TCNT1 时出现问题,如果我使用 256 的预分频器,它会给出一个数字 - 仍然是随机的,但是数字。现在,如果我使用 1024 预分频器,每次出现磁铁时,它都会不断加 1。
你能告诉我我做错了什么吗?
我可以打印TCNT1 作为 PIN 转回 On 点(即 360 度)的时间差吗?

我需要以毫秒为单位的时间来计算风速。


//include user/defined libraries
#include "i2cmaster.h"
#include "lcd.h"
#include "ds1621.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <unistd.h>
#include <util/delay.h>

//void init_timer1();

volatile unsigned char run = 0;
volatile unsigned int oneround;


void init_timer1() {
    //______________________________// Set the Timer Mode to CTC and start timer
    TCCR1B |= (1 << WGM12);
    OCR1A = 0x3D; // Set the value that you want to count to OCR1A = 0x3D;          
    PCICR |= (1 << PCIE0);
    PCIFR |= (1 << PCIF0);
    PCMSK0 |= (1 << PCINT2);
    //________________________________________________________________________________________pray  this 1010011 1001000 1001001  1010100 works
    sei();

}
int main(void) {
    // WINDSPEED"
    DDRB &= ~(1 << DDB2); //     DIRECTION REGISTER  INOUT              D10  PCINT2 OC1B     PB2     SS   PWM  CTC
    PORTB |= (1 << PORTB2); //  OUTPUT REGISTER  hIGH
    //DDRB  = 0b11111011;         //   DIRECTION REGISTER  IN OUT
    //PORTB = 0b00000100;           //   OUTPUT REGISTER

    i2c_init(); //initialization of communication
    LCD_init(); //initialization of the LCD
    init_timer1(); // Lets count those laps baby

    while (1) {                          /*  O_O KAPUT!  */

    LCD_set_cursor(1, 1);
    printf("%u            ", oneround);
        // rest of the sensors

    }


return 0;
}                                           // Main close 

ISR(PCINT0_vect) {
    if (run == 0) {
TCCR1B &= ~(1 << CS12); // clear timer and stop

        oneround = TCNT1; 
    TIFR1 |= (1 << OCF1A) | (1 << OCF1B) | (1 << TOV1);
    TCCR1B |= (1 << CS22) | (1 << CS21) | (1 << CS20); // set prescaler to  1024   and start timer    1sec 
    run = 1;
}

else {
    run = 0;
}
}




【问题讨论】:

    标签: c timer embedded interrupt


    【解决方案1】:

    首先。

    TCCR1B |= (1 << CS22) | (1 << CS21) | (1 << CS20); // set prescaler to  1024   and start timer    1sec 
    

    您正在使用 Timer2 (CS2x) 的位名称并将它们分配给计时器 1 (TCCR1x) 的寄存器。 CS2x == CS1x,但在语义上这是一个错误。

    请参考datasheet,章节15.11.2 TCCR1B – 定时器/计数器1 控制寄存器B,页面110

    当所有三个位 CS12CS11CS10 被设置时,定时器在 T1 引脚上的外部时钟源上工作。如果你想要 1:1024 的预分频器,那么 CS11 位应该是 0。

    下一步。

    当逻辑电平向任一方向变化时,可以触发引脚变化中断。偶尔会有小尖峰,水平可以改变两次,但中断只会触发一次。所以,不要忘记检查输入引脚上的电平。

    当你写作时

    TCCR1B &= ~(1 << CS12);
    

    它不会停止定时器,因为它只清除 CS12 位但 CS10 和 CS11 位保留(导致定时器继续使用另一个预分频器计数)。

    此外,停止计时器不会重置其值。你需要写TCNT1 = 0;来重置它。

    您也不需要停止计数器。只需使用完整的循环来计算差异。

    volatile uint16_t prev_timer_value = 0;
    volatile uint16_t oneround = 0;
    
    
    
    ISR(PCINT0_vect) {
        if ((PINB & (1 << PINB2)) == 0) { // Low level on the pin
            uint16_t tval = TCNT1; // latch the current timer value;
            oneround = tval - prev_timer_value; // calc the difference;
            prev_timer_value = tval; // remember a new val
        }
    }
    
    // To start the timer just start it in the Normal mode 
    TCCR1A = 0;
    TCCR1B = (1 << CS12) | (1 << CS10); // 1:1024
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-20
      • 2020-12-30
      • 1970-01-01
      • 1970-01-01
      • 2010-10-27
      • 2018-12-31
      相关资源
      最近更新 更多