Таймер AVR с ошибкой внешнего прерывания

Я наткнулся на проект, в котором я хочу напечатать расстояние, измеренное от ультразвукового датчика до ЖК-дисплея. Схема конструкции следующая:

Схема

Соответствующий код:

    /*
C Program for Distance Measurement using Ultrasonic Sensor and AVR Microocntroller
 */ 

#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 1000000
#include <util/delay.h>
#include <stdlib.h>

#define enable            5
#define registerselection 6

void send_a_command(unsigned char command);
void send_a_character(unsigned char character);
void send_a_string(char *string_of_characters);

static volatile int pulse = 0;
static volatile int i = 0;

int main(void)
{
    DDRA = 0xFF;
    DDRB = 0xFF;
    DDRD = 0b11111011;
    _delay_ms(50);

    GICR|=(1<<INT0);
    MCUCR|=(1<<ISC00);

    TCCR1A = 0;

    int16_t COUNTA = 0;
    char SHOWA [16];


    send_a_command(0x01); //Clear Screen 0x01 = 00000001
    _delay_ms(50);
    send_a_command(0x38);
    _delay_ms(50);
    send_a_command(0b00001111);
    _delay_ms(50);

    sei();

    while(1)
    {
        PORTD|=(1<<PIND0);
        _delay_us(15);
        PORTD &=~(1<<PIND0);

        COUNTA = pulse/58;
        send_a_string ("CIRCUIT DIGEST");
        send_a_command(0x80 + 0x40 + 0);
        send_a_string ("DISTANCE=");
        itoa(COUNTA,SHOWA,10);
        send_a_string(SHOWA);
        send_a_string ("cm    ");
        send_a_command(0x80 + 0);

    }
}

ISR(INT0_vect)
{
    if (i==1)
    {
        TCCR1B=0;
        pulse=TCNT1;
        TCNT1=0;
        i=0;
    }
    if (i==0)
    {
        TCCR1B|=(1<<CS10);
        i=1;
    }
}

void send_a_command(unsigned char command)
{
    PORTB = command;
    PORTD &= ~ (1<<registerselection);
    PORTD |= 1<<enable;
    _delay_ms(8);
    PORTD &= ~1<<enable;
    PORTB = 0;
}

void send_a_character(unsigned char character)
{
    PORTB = character;
    PORTD |= 1<<registerselection;
    PORTD |= 1<<enable;
    _delay_ms(8);
    PORTD &= ~1<<enable;
    PORTB = 0;
}
void send_a_string(char *string_of_characters)
{
    while(*string_of_characters > 0)
    {
        send_a_character(*string_of_characters++);
    }
}

Технические характеристики и код были взяты отсюда: https://circuitdigest.com/microcontroller-projects/distance-measurement-using-hc-sr04-avr

Меня смущает часть ISR этого кода. Как он здесь закодирован, когда эхо от сонара переходит с ВЫСОКОГО на НИЗКИЙ, таймер запускается снова, так как он также переходит ко второму блоку if, который, как я думал, был ненужным . Но симуляция ведет себя странно и дает неверные и изменяющиеся выходные данные, если я просто помещаю второй блок if как else if, что должно было быть хорошо.

ISR(INT0_vect)
{
    if (i==1)
    {
        TCCR1B=0;
        pulse=TCNT1;
        TCNT1=0;
        i=0;
    }
    else if (i==0)
    {
        TCCR1B|=(1<<CS10);
        i=1;
    }
}

Это изменение приводит к неустойчивому и изменяющемуся результату, например:

Неверный вывод

Кажется, здесь он работает правильно, когда i = 1 код тоже должен перейти ко второму блоку. Почему использование else if дает неверные результаты? Любая помощь приветствуется.


person Abhik Bhattacharjee    schedule 06.06.2018    source источник


Ответы (1)


Несколько моментов:

  • Для меня ISR из исходного кода не имеет смысла. Ваши изменения должны привести к желаемому поведению.

  • i может быть uint8_t вместо int

  • pulse должен быть uint16_t вместо (signed) int

  • Поскольку pulse является многобайтовой переменной и доступ к ней осуществляется из ISR и из main (), прерывания должны (должны) быть отключены при доступе к ней из «основного потока».

Нравится:

cli();
COUNTA = pulse/58;
sei();

или даже лучше использовать макросы из "util / atomic.h"

ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
     COUNTA = pulse/58;
}

В противном случае вы можете получить неверные результаты при доступе.

person Rev    schedule 06.06.2018
comment
применил все упомянутые изменения, но он не работает с блоком else if. Расстояние увеличивается на каждой итерации. - person Abhik Bhattacharjee; 06.06.2018
comment
Вырос? Даже если вы не измените реальное расстояние? Исходный код без else работает без проблем? Что-то кажется странным. - person Rev; 06.06.2018
comment
да. Увеличивается без изменения фактического расстояния. Исходный код с двумя блоками if работает безупречно. - person Abhik Bhattacharjee; 06.06.2018