carmaster 0 27 октября, 2013 Опубликовано 27 октября, 2013 · Жалоба Доброго времени суток! Стоит задача реализовать 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 } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kovigor 5 27 октября, 2013 Опубликовано 27 октября, 2013 · Жалоба Стоит задача реализовать 2 uarta в меге162, uart0 на 9600 , uart1 на 56700, оба на приём/передачу. Тут дело может быть вот в чем. Допустим, пришел символ со скоростью 9600 и управление получил соотв. обработчик. Если этот обработчик построен не совсем правильно, то МК может выполнять его довольно долго. А за это время в адрес МК могут прийти еще и байты со скоростью 57600. Если эти байты следуют достаточно интенсивно, то МК может их терять, т.к. аппаратного FIFO у него нет. Варианты решения: - Построить обработчики прерываний так, чтобы МК выполнял их максимально быстро. Посмотрите, как это делает CodeVision. При этом обработку принимаемых символов обычно лучше всего возложить на фоновый процесс. - Еще вариант, который, впрочем, не отменяет данную только что рекомендацию: затактировать МК как можно более высокой частотой, чтобы он работал максимально быстро. - В обработчике от UART0 проверять состояние UART1 (и наоборот), и корректно это состояние обрабатывать. - Использовать аппаратное управление потоком (RTS/CTS) на обоих портах. При входе в любой из обработчиков тут же выставлять соотв. линию RS232 в состояние неготовности к дальнейшему приему. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
carmaster 0 27 октября, 2013 Опубликовано 27 октября, 2013 · Жалоба спасибо, буду пробовать Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться