Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: mega644P-прерывание по совпадению таймер2
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
ILNUR
mega644P
Происходит бесконечно долгий опрос вывода PD6, если 1 то инкрементируетя counter1, иначе counter0. Подтяжка на PD6 есть. Каждые 2 сек значение выводится через usart.
Даже если все время на PD6 стоит 1 значение counter1 периодически меняется сильно (в старших разрядах), в чем может быть проблема?

Код
#include <avr/io.h>
#include <avr/interrupt.h>

#define check_num_pin (1<<PIND6)
#define check_pin PIND

unsigned long counter1;
unsigned long counter0;

void USART_Init()   // Initializing USART
{
    UBRR0 = 0x33;
    /* Enable receiver and transmitter */
    UCSR0B = (1<<RXEN0)|(1<<TXEN0);
    /* Set frame format: 8data, 1stop bit */
    UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
}
void USART_Transmit( char data )
{
    /* Wait for empty transmit buffer */
    while ( !(UCSR0A & (1<<UDRE0)) );
    /* Put data into buffer, sends the data */
    UDR0 = data;
}
void TIMER2_Init()  // Initializing TIMER1
{
    ASSR=(1<<AS2);
    TCCR2A=(1<<WGM21);
    TCCR2B=(1<<CS22)|(1<<CS21)|(1<<CS20);
    OCR2A=0x40;
    TIMSK2=(1<<OCIE2A);  
}

int main()
{  
    counter1=0;
    counter0=0;
    TIMER2_Init();
    USART_Init();
    PORTD=(1<<PORTD6);
    sei();
    while(1)
    {
      if (check_num_pin & check_pin)
      {
        counter1++;
        
      }
      else
      {
        counter0++;
        
      }
   }
}
ISR(TIMER2_COMPA_vect)
{  
    TCCR2B=0;
    USART_Transmit(counter1);
    USART_Transmit(counter1>>8);
    USART_Transmit(counter1>>16);
    USART_Transmit(counter1>>24);
    counter1=0;
    counter0=0;
    TCCR2B=(1<<CS22)|(1<<CS21)|(1<<CS20);
}
AHTOXA
Цитата(ILNUR @ May 21 2010, 11:59) *
Даже если все время на PD6 стоит 1 значение counter1 периодически меняется сильно (в старших разрядах), в чем может быть проблема?


Проблем две.
Первая - опрос происходит не по таймеру, поэтому за две секунды может произойти разное количество опросов (из-за прерываний).
Вторая - counter1++; и counter1--; надо выполнять при запрещённых прерываниях. Иначе прерывание может произойти посередине изменения переменной, и значение будет неверным.
ILNUR
Переписал код на ассемблере работает корректно. Что неправильно написал на С?
sigmaN
а ещё volatile на каунтеры.
Ну и всё остальное уже сказал АНТОХА.
dimka76
Цитата(ILNUR @ May 21 2010, 09:59) *
Каждые 2 сек значение выводится через usart.
Даже если все время на PD6 стоит 1 значение counter1 периодически меняется сильно (в старших разрядах), в чем может быть проблема?

Если PD6 постоянно в единице, то сколько вышеприведенный фрагмент кода можно на следующий
Код
while(1) counter1++;


Сколько за две секунды насчитает counter1 ?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.