Перейти к содержанию
    

atmega168 uart и прерывания

День добрый!

 

Делаю преобразователь/переходник с сигналов RC-аппаратуры (7-ми канальный HiTec) в цифру, с выходом на UART.

МК - atmega168, тактирую от встроенных 8мГц.

RC-приемник формирует на выходе стандартные серво-PWM сигналы, последовательно по каналам.

Первый канал повесил на INT0, остальные на порт С. Данные собираю по таймеру0.

Эта часть проги работает.

 

Проблема возникла, когда данные решил отправить в UART.

Передаются первые 2-3 байта и все. передача вырубается.

Код писал в CVAVR 2.05, пользовался его же визардом.

думал, что как-то все не успевает и подвисает, в итоге сократил прогу до обычного присваивания в массив чисел.

результат не изменился, выводятся в порт только 3 байта и все.

убирая буферы в UART выводится вообще полная ахинея, но передача не прерывается.

С последовательным портом в таком виде работаю впервые, поэтому прошу помощи. Гугл должных результатов не подсказал.

 

код:

/*****************************************************
This program was produced by the
CodeWizardAVR V2.05.0 Professional
Automatic Program Generator
© Copyright 1998-2010 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project : 
Version : 
Date	: 16.07.2013
Author  : NeVaDa
Company : 
Comments: 


Chip type			   : ATmega168V
Program type			: Application
AVR Core Clock frequency: 8,000000 MHz
Memory model			: Small
External RAM size	   : 0
Data Stack size		 : 256
*****************************************************/

#include <mega168.h>
#include <stdio.h>
#include <delay.h>



#ifndef RXB8
#define RXB8 1
#endif

#ifndef TXB8
#define TXB8 0
#endif

#ifndef UPE
#define UPE 2
#endif

#ifndef DOR
#define DOR 3
#endif

#ifndef FE
#define FE 4
#endif

#ifndef UDRE
#define UDRE 5
#endif

#ifndef RXC
#define RXC 7
#endif

#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<DOR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)


#define MAX_PPM_CHANNELS 7
#define CH1 PIND.2
#define CH2 PINC.5
#define CH3 PINC.4
#define CH4 PINC.3
#define CH5 PINC.2
#define CH6 PINC.1
#define CH7 PINC.0

unsigned int counter;
unsigned int Channel[MAX_PPM_CHANNELS],ChannelTX[MAX_PPM_CHANNELS];
unsigned char uart_r,flag,start_ppm,end_ppm,n_chan,lo_b,hi_b,tmp;




// USART Receiver buffer
#define RX_BUFFER_SIZE0 50
char rx_buffer0[RX_BUFFER_SIZE0];

#if RX_BUFFER_SIZE0 <= 256
unsigned char rx_wr_index0,rx_rd_index0,rx_counter0;
#else
unsigned int rx_wr_index0,rx_rd_index0,rx_counter0;
#endif

// This flag is set on USART Receiver buffer overflow
bit rx_buffer_overflow0;

// USART Receiver interrupt service routine
interrupt [uSART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSR0A;
data=UDR0;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
  {
  rx_buffer0[rx_wr_index0++]=data;
#if RX_BUFFER_SIZE0 == 256
  // special case for receiver buffer size=256
  if (++rx_counter0 == 0)
  {
#else
  if (rx_wr_index0 == RX_BUFFER_SIZE0) rx_wr_index0=0;
  if (++rx_counter0 == RX_BUFFER_SIZE0)
  {
  rx_counter0=0;
#endif
  rx_buffer_overflow0=1;
  }
  }
}

#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART Receiver buffer
#define _ALTERNATE_GETCHAR_
#pragma used+
char getchar(void)
{
char data;
while (rx_counter0==0);
data=rx_buffer0[rx_rd_index0++];
#if RX_BUFFER_SIZE0 != 256
if (rx_rd_index0 == RX_BUFFER_SIZE0) rx_rd_index0=0;
#endif
#asm("cli")
--rx_counter0;
#asm("sei")
return data;
}
#pragma used-
#endif

// USART Transmitter buffer
#define TX_BUFFER_SIZE0 50
char tx_buffer0[TX_BUFFER_SIZE0];

#if TX_BUFFER_SIZE0 <= 256
unsigned char tx_wr_index0,tx_rd_index0,tx_counter0;
#else
unsigned int tx_wr_index0,tx_rd_index0,tx_counter0;
#endif

// USART Transmitter interrupt service routine
interrupt [uSART_TXC] void usart_tx_isr(void)
{
if (tx_counter0)
  {
  --tx_counter0;
  UDR0=tx_buffer0[tx_rd_index0++];
#if TX_BUFFER_SIZE0 != 256
  if (tx_rd_index0 == TX_BUFFER_SIZE0) tx_rd_index0=0;
#endif
  }
}

#ifndef _DEBUG_TERMINAL_IO_
// Write a character to the USART Transmitter buffer
#define _ALTERNATE_PUTCHAR_
#pragma used+
void putchar(char c)
{
while (tx_counter0 == TX_BUFFER_SIZE0);
#asm("cli")
if (tx_counter0 || ((UCSR0A & DATA_REGISTER_EMPTY)==0))
  {
  tx_buffer0[tx_wr_index0++]=c;
#if TX_BUFFER_SIZE0 != 256
  if (tx_wr_index0 == TX_BUFFER_SIZE0) tx_wr_index0=0;
#endif
  ++tx_counter0;
  }
else
  UDR0=c;
#asm("sei")
}
#pragma used-
#endif



// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
start_ppm=1;counter=0;n_chan=0;
PORTB.0=!PORTB.0;
}


// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0=0xFE;

ChannelTX[0]=0x3031;
ChannelTX[1]=0x3233;
ChannelTX[2]=0x3435;
ChannelTX[3]=0x3637;
ChannelTX[4]=0x3839;
ChannelTX[5]=0x3A3B;
ChannelTX[6]=0x3C3D;
PORTB.1=!PORTB.1;

}

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out 
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 
PORTB=0x00;
DDRB=0xFF;

// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State6=P State5=P State4=P State3=P State2=P State1=P State0=P 
PORTC=0x7F;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=P State6=P State5=P State4=P State3=P State2=P State1=P State0=P 
PORTD=0xFF;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 1000,000 kHz
// Mode: Normal top=0xFF
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x02;
TCNT0=0xFE;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=0xFFFF
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=0xFF
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Rising Edge
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-14: Off
// Interrupt on any change on pins PCINT16-23: Off
EICRA=0x03;
EIMSK=0x01;
EIFR=0x01;
PCICR=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x01;

// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x00;

// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x00;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART0 Mode: Asynchronous
// USART Baud Rate: 19200
UCSR0A=0x00;
UCSR0B=0xD8;
UCSR0C=0x06;
UBRR0H=0x00;
UBRR0L=0x19;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
ADCSRB=0x00;
DIDR1=0x00;

// ADC initialization
// ADC disabled
ADCSRA=0x00;

// SPI initialization
// SPI disabled
SPCR=0x00;

// TWI initialization
// TWI disabled
TWCR=0x00;

// Global enable interrupts
#asm("sei")

while (1)
  {
for (tmp=0;tmp<=6;tmp++) 
{
lo_b=(unsigned char) ChannelTX[tmp];
hi_b=(unsigned char) (ChannelTX[tmp]>>8);
putchar(hi_b);
putchar(lo_b);
putchar('!');
  }
  }
}

 

Если в основном цикле запрещать таймер0, то все выводится правильно.

что может таймер делать с буфером, если даже когда обработчик пустой, то буфер виснет.

 

    TIMSK0=0x00;
    for (tmp=0;tmp<=6;tmp++) 
        {
        lo_b=(unsigned char) ChannelTX[tmp];
        hi_b=(unsigned char) (ChannelTX[tmp]>>8);
        putchar(hi_b);
        putchar(lo_b);
        putchar('!');
        };
    putchar(0x0A);
    putchar(0x0D);
    TIMSK0=0x01;

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я правильно понимаю, по задумке Timer0 у Вас с частотой 100кГц переполняется?????

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Совершенно верно, с этой частотой я измеряю ШИМ из приемника.

 

Такой точности мне вполне хватит.

Подумываю уже о том, чтобы сделать последовательно и без таймера замерять шим на выходах, а потом отправлять данные, и затем ждать начала новой посылки сигналов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да уж, с таким обработчиком частота вызова перываний таймера 500 кГц? За один период - 16 тактов для процессора, даже Ваш обработчик выполниться поди не успеет :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, именно в этом и была проблема. На пустом обработчике прерываний только и успевал МК не накосячить с uart'ом. Я решил проблему тем, что, сначала замеряю ШИМ по каналам, и в перерыве между сериями отправляю данные.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А хорошо ли это - пользоваться встроенным RC-генератором для тактирования UART-а?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А хорошо ли это - пользоваться встроенным RC-генератором для тактирования UART-а?
А это, по-моему, каждый решает в соответствиями с требованиями по точности скорости того самого UART'а :)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Чтобы не плодить темы, задам вопрос здесь.

 

Есть мега644. Нужно организовать два UART'а.

Все было бы нормально, но второй uart не заводится вообще.

 

// USART0 initialization
// USART0 Baud Rate: 115200
UCSR0A=0x00;
UCSR0B=0xD8;
UCSR0C=0x06;
UBRR0H=0x00;
UBRR0L=0x0A;

// USART1 initialization
// USART1 Baud Rate: 115200
UCSR1A=0x00;
UCSR1B=0xD8;
UCSR1C=0x06;
UBRR1H=0x00;
UBRR1L=0x0A;


while (1)
      {
    while(!(UCSR0A & (1<<UDRE0))); UDR0 = 0b10100011;
    while(!(UCSR1A & (1<<UDRE1))); UDR1 = 0b10100101;    
      }

 

из UART0 все отсылается как часы, а UART1 молчит вообще (мониторю осциллографом).

бьюсь над этим уже пару дней, и с портами шаманствовал на вход/выход/подтяжки, и контроллер менял,

результата нет.

 

Уважаемые Гуру, посоветуйте пожалуйста, в какую сторону копать-то.

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

The ATmega644 has one USART, USART0.

 

Выдрано слово в слово из даташита... Предлагаю копать в сторону другого контроллера ))

Изменено пользователем artkam

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как так, вот из моего даташита

19.2 USART1 and USART0

The ATmega164A/164PA/324A/324PA/644A/644PA/1284/1284P has two USART’s, USART0

and USART1.

 

Хм, понял, не уточнил. у меня atmega644P

 

 

И, благодаря Вашему замечанию, есть мысли что попались в партии либо брак, либо ошибка маркировки. Хотя на атмел такое не мог подумать.

Изменено пользователем Vooze

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

UCSR0B=0xD8

У Вас работают сразу 2 прерывания , причем одно из них похоже Вам совсем не нужно т.к. приемник даже не включён

Отключите 0-ой скорее всего будет работать и 1-ый

И научитесь писать без всяких HEX и BIN

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

проблема решилась заменой контроллера. походу брак.

И научитесь писать без всяких HEX и BIN

мне так, как-то удобнее. Это еще со времен z80. BIN в HEX "в уме" раскладывается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я имел ввиду вот так, как пример

 

DDRB = (1<<PB7)|(1<<PB6)|(0<<PB5)|(1<<PB4)|(0<<PB3)|(1<<PB2)|(1<<PB1)|(1<<PB0)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...