здравствуйте.
столкнулся со следующим непонятным поведением timer0 на atmega16.
первоначально была программа, в которой, помимо всего прочего, таймер отсчитывал 5 мс по кругу.
однако после добавления куска инициализации uart, а точнее только разрешения работы передатчика, приводит к тому что таймер срабатывает раз в 10 мс.
все это я прекрасно вижу на осциллографе. стоит только убрать бит TXEN, как все становиться нормально.
я с МК работаю недавно, и на ум ничего не приходит самому.
в чем может быть дело???
далее предлагаю исходник. компилятор IAR 5.11 (все оптимизации выключены)
Код
#define ENABLE_BIT_DEFINITIONS
#include <stdio.h>
#include <inavr.h>
#include <iom16.h>
#define USART_PC
volatile int intFront; //содержит значения фронта сигнала по которому происходит прерывание (0 - спадающий, 1 - возрастающий)
//================================================================
//На вход подается сигнал с частотой 100 Гц, длительность импульса 160 мкс
//
//
//================================================================
#pragma vector=INT0_vect
__interrupt void int0_gen(void)
{
if (intFront==0)
{
//============================================================
//спадающий фронт сигнала
TIMSK |= (1<<OCIE0); //разрешения прерывания таймера по совпадению
TCCR0 = 0x0D; //start timer
}
else
{
//установка генерации прерывания по спадающему фронту фронту
intFront = 0;
GICR &= ~(1<<INT0); //запрещение прерывания на INT0
MCUCR |= (1<<ISC01); //генерация прерывания по спадающему фронту сигнала на ножже 11 (INT0)
MCUCR &= ~(1<<ISC00);
GICR |= (1<<INT0); //разрешение прерывания на INT0
}
}
//================================================================
//Обработка прерывания по совпадению таймера
//
//
//================================================================
#pragma vector=TIMER0_COMP_vect
__interrupt void timer0_5ms(void)
{
PORTA ^= 0x01;
TIMSK &= ~(1<<OCIE0); //запрещение прерывания таймера по совпадению
TCCR0 = 0x08; //останавливаем таймер
//============================================================
//установка генерации прерывания по возрастающему фронту
intFront = 1;
GICR &= ~(1<<INT0); //запрещение прерывания на INT0
MCUCR |= (1<<ISC01) | (1<<ISC00); //генерация прерывания по нарастающему фронту сигнала на ножке 11 (INT0)
GICR |= (1<<INT0); //разрешение прерывания на INT0
}
void timer0_init(void) //таймер на 5 мс
{
TCCR0 = 0x00; //stop
TCNT0 = 0x00; //set count
OCR0 = 0x24; //set compare
TCCR0 = 0x08; //пока остановлен
//TCCR0 = 0x0D; //start timer
}
void uart_pc_init(void)
{
UCSRB = 0x00; //disable while setting baud rate
UCSRA = 0x00;
UCSRC = (1<<URSEL) | 0x06;
UBRRL = 0x03; //set baud rate lo
UBRRH = 0x00; //set baud rate hi
UCSRB = 0x18; // !!!! после включения передатчика и начинаются все казусы
}
int main( void )
{
__disable_interrupt(); //disable all interrupts
DDRA |= (1<<PA0); //PortA0 as output
timer0_init();
void uart_pc_init(void)
intFront = 0; //сигнал того что первоначально прерывание по спадающему фронту
MCUCR |= (1<<ISC01); //генерация прерывания по спадающему фронту на ножке 11 (INT0)
GICR |= (1<<INT0); //разрешение внешнего прерывания
__enable_interrupt(); //разрешения всех прерываний
while(1)
{
}
}