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

ATMega162 2UART

Доброго времени суток!

 

Стоит задача реализовать 2 uarta в меге162, uart0 на 9600 , uart1 на 56700, оба на приём/передачу. С тем, что генерит codevision не получается разобраться. то байты теряет, то вовсе зависает. к UART0 подключен девайс, к UART1 - терминалка. надо управлять девайсом и с меги и с терминалки, то есть уарт0 должен летать без тормозов. может кто-нибудь поделиться рабочим примерчиком на Си как всё это реализовать или хотя бы пинок в нужном направлении. с двумя уартами по прерыванию ни разу не работал. Спасибо!

 

#include <mega162.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)

// USART0 Receiver buffer
#define RX_BUFFER_SIZE0 8
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 USART0 Receiver buffer overflow
bit rx_buffer_overflow0;

// USART0 Receiver interrupt service routine
interrupt [uSART0_RXC] void usart0_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 USART0 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

// USART0 Transmitter buffer
#define TX_BUFFER_SIZE0 8
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

// USART0 Transmitter interrupt service routine
interrupt [uSART0_TXC] void usart0_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 USART0 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

// USART1 Receiver buffer
#define RX_BUFFER_SIZE1 8
char rx_buffer1[RX_BUFFER_SIZE1];

#if RX_BUFFER_SIZE1 <= 256
unsigned char rx_wr_index1,rx_rd_index1,rx_counter1;
#else
unsigned int rx_wr_index1,rx_rd_index1,rx_counter1;
#endif

// This flag is set on USART1 Receiver buffer overflow
bit rx_buffer_overflow1;

// USART1 Receiver interrupt service routine
interrupt [uSART1_RXC] void usart1_rx_isr(void)
{
char status,data;
status=UCSR1A;
data=UDR1;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
  {
  rx_buffer1[rx_wr_index1++]=data;
#if RX_BUFFER_SIZE1 == 256
  // special case for receiver buffer size=256
  if (++rx_counter1 == 0)
     {
#else
  if (rx_wr_index1 == RX_BUFFER_SIZE1) rx_wr_index1=0;
  if (++rx_counter1 == RX_BUFFER_SIZE1)
     {
     rx_counter1=0;
#endif
     rx_buffer_overflow1=1;
     }
  }
}

// Get a character from the USART1 Receiver buffer
#pragma used+
char getchar1(void)
{
char data;
while (rx_counter1==0);
data=rx_buffer1[rx_rd_index1++];
#if RX_BUFFER_SIZE1 != 256
if (rx_rd_index1 == RX_BUFFER_SIZE1) rx_rd_index1=0;
#endif
#asm("cli")
--rx_counter1;
#asm("sei")
return data;
}
#pragma used-
// USART1 Transmitter buffer
#define TX_BUFFER_SIZE1 8
char tx_buffer1[TX_BUFFER_SIZE1];

#if TX_BUFFER_SIZE1 <= 256
unsigned char tx_wr_index1,tx_rd_index1,tx_counter1;
#else
unsigned int tx_wr_index1,tx_rd_index1,tx_counter1;
#endif

// USART1 Transmitter interrupt service routine
interrupt [uSART1_TXC] void usart1_tx_isr(void)
{
if (tx_counter1)
  {
  --tx_counter1;
  UDR1=tx_buffer1[tx_rd_index1++];
#if TX_BUFFER_SIZE1 != 256
  if (tx_rd_index1 == TX_BUFFER_SIZE1) tx_rd_index1=0;
#endif
  }
}

// Write a character to the USART1 Transmitter buffer
#pragma used+
void putchar1(char c)
{
while (tx_counter1 == TX_BUFFER_SIZE1);
#asm("cli")
if (tx_counter1 || ((UCSR1A & DATA_REGISTER_EMPTY)==0))
  {
  tx_buffer1[tx_wr_index1++]=c;
#if TX_BUFFER_SIZE1 != 256
  if (tx_wr_index1 == TX_BUFFER_SIZE1) tx_wr_index1=0;
#endif
  ++tx_counter1;
  }
else
  UDR1=c;
#asm("sei")
}
#pragma used-

// Standard Input/Output functions
#include <stdio.h>

// 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


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

// USART1 initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART1 Receiver: On
// USART1 Transmitter: On
// USART1 Mode: Asynchronous
// USART1 Baud Rate: 57600
UCSR1A=0x00;
UCSR1B=0xD8;
UCSR1C=0x86;
UBRR1H=0x00;
UBRR1L=0x0B;


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

while (1)
     {
     // Place your code here

     }
}

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


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

Стоит задача реализовать 2 uarta в меге162, uart0 на 9600 , uart1 на 56700, оба на приём/передачу.

Тут дело может быть вот в чем. Допустим, пришел символ со скоростью 9600 и управление получил соотв. обработчик. Если этот обработчик построен не совсем правильно, то МК может выполнять его довольно долго. А за это время в адрес МК могут прийти еще и байты со скоростью 57600. Если эти байты следуют достаточно интенсивно, то МК может их терять, т.к. аппаратного FIFO у него нет.

Варианты решения:

 

- Построить обработчики прерываний так, чтобы МК выполнял их максимально быстро. Посмотрите, как это делает CodeVision. При этом обработку принимаемых символов обычно лучше всего возложить на фоновый процесс.

- Еще вариант, который, впрочем, не отменяет данную только что рекомендацию: затактировать МК как можно более высокой частотой, чтобы он работал максимально быстро.

- В обработчике от UART0 проверять состояние UART1 (и наоборот), и корректно это состояние обрабатывать.

- Использовать аппаратное управление потоком (RTS/CTS) на обоих портах. При входе в любой из обработчиков тут же выставлять соотв. линию RS232 в состояние неготовности к дальнейшему приему.

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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