Hallo,
Ich hab ein Problem mit dem USART an einem ATMEGA 88A.
Wenn Ich mit dem PC Daten mit 115200/8/N/1 mittels 5V USB Serial Adapter an die Schaltung sende werden die Bytes einwandfrei erkannt und an den PC per Softwareloop zurück gesendet.
Hänge Ich an den selben Port des ATMEGA 88 die eigentliche Zielschaltung mit einem ATXMEGA32U4 empfängt der USART nur "Mist" und gibt diesen dann auch so an den PC weiter.
ATXMEGA out -> in ATMEGA88 out -> in PC.
Verbinde Ich nun die Verbindungsstelle des ATXMEGA zum ATMEGA88 den 5V USB Adapter kommen die Daten aus dem XMEGA32 einwandfrei im Terminalprogramm an.
Es sieht also so aus, als ob der USART Empfänger im ATMEGA 88A das serielle Signal vom ATXMEGA nicht richtig erkennt.
Hatte schon mal einer von Euch ein ähnliches Problem?
Ich hab es auch schon mit Pullup und Pulldown Widerständen an der Verbindungsstelle versucht - Ohne Erfolg.
Die Schnittstellengeschwindigkeit sollte bei beiden Controllern stimmen.
Dazu hab ich den USART des ATMEGA 88 fortlaufend den Buchstaben "U" senden lassen.
Die Periodendauer mit 17,35µS ( + Messtoleranz ) mit dem Oszilloskop kommt hin und mit dem PC funktionierts ja auch.
Code:
/*
* OLED_SH1106.c
* Version 1.0
* Created: 05.03.2019 19:15:47
* Author : ############
*/
#define F_CPU 7372800
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <string.h>
//#include <stdlib.h>
#include "ssd1306xled.c"
//USART Section
#define FRAMING_ERROR (1<<FE0)
#define PARITY_ERROR (1<<UPE0)
#define DATA_OVERRUN (1<<DOR0)
#define DATA_REGISTER_EMPTY (1<<UDRE0)
#define RX_COMPLETE (1<<RXC0)
// USART Receiver buffer
#define RX_BUFFER_SIZE 250
volatile uint8_t rx_buffer[RX_BUFFER_SIZE];
#if RX_BUFFER_SIZE<256
volatile uint8_t rx_wr_index = 0,rx_rd_index = 0;
#else
volatile uint16_t rx_wr_index = 0,rx_rd_index = 0;
#endif
volatile uint8_t message_buffer[30];
volatile uint8_t message_pointer = 0;
volatile uint8_t readout_pointer = 0;
ISR (USART_RX_vect)
{
uint8_t status,data;
status=UCSR0A;
data=UDR0;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
{
rx_buffer[rx_wr_index++] = data; //Daten Puffern
if(rx_wr_index >= RX_BUFFER_SIZE){rx_wr_index = 0;} //
if((UCSR0A & (1<<UDRE0)) > 0) //Lokales echo
{
UDR0 = data;
}
}
}
/*
Die Idee ist nur Strings über die serielle Schnittstelle an diesen Display Controller zu senden.
Das kann der AVR Quasi nebenbei erledigen.
Hier wird dann der ankommende String in Daten für das Display umgewandelt.
Datenformat
Byte 1 = X - Position
Byte 2 = Y - Position
Byte 3 = Datenart 0x00 = Bildschirm leeren; 0x01 = kleiner Font; 0x02 = großer Font
0x10 Bild 1; 0x11 Bild 2 usw.
Byte 4....Ende ASCII Daten oder leer
Byte X länge - 1 = CR \r
letztes Byte = LF \n
Somit ist auch Kompatibilität zur PC Schnittstelle gegeben
*/
void show_display (void)
{
uint8_t i = 0, ASCII_count = 0, x_pos = 0, y_pos = 0, type = 0;
char zeile [27];
x_pos = message_buffer[0];
y_pos = message_buffer[1];
type = message_buffer[2];
switch (type)
{
case 0:
ssd1306_clear();
break;
case 1:
i = 3;
ASCII_count = 0;
while(message_buffer[i] != '\r')
{
zeile[ASCII_count++] = message_buffer[i++]; //Nachricht auslesen und in Zeilenpuffer einlesen
}
zeile[ASCII_count]=0; //Stringende setzen
ssd1306_setpos(x_pos,y_pos);
ssd1306_string_font6x8(zeile);
break;
case 2:
i = 3;
ASCII_count = 0;
while (message_buffer[i] != '\r')
{
zeile[ASCII_count++] = message_buffer[i++]; //Nachricht auslesen und in Zeilenpuffer einlesen
}
zeile[ASCII_count]=0; //Stringende setzen
ssd1306_setpos(x_pos,y_pos);
ssd1306_string_font8x16xy(x_pos , y_pos , zeile);
break;
case 0x10:
ssd1306_draw_bmp(x_pos , y_pos , 127 , y_pos + 4 , 0);
break;
case 0x11:
ssd1306_draw_bmp(x_pos , y_pos , 127 , y_pos + 4 , 1);
break;
case 0x12:
ssd1306_draw_bmp(x_pos , y_pos , 127 , y_pos + 4 , 2);
break;
case 0x13:
ssd1306_draw_bmp(x_pos , y_pos , 127 , y_pos + 4 , 3);
break;
}
}
//Copy Data from serial Buffer to command buffer
void serial_parser(void)
{
while(rx_wr_index != rx_rd_index)
{
message_buffer[message_pointer]=rx_buffer[rx_rd_index++];
if(rx_rd_index >= RX_BUFFER_SIZE){rx_rd_index = 0;}
if((message_buffer[message_pointer] == '\n') && (message_buffer[message_pointer-1] == '\r'))
{
show_display();
message_pointer = 0;
}
else
{
message_pointer++;
if(message_pointer > 29){message_pointer = 0;} //Überlauf vermeiden!
}
}
}
//Startup Display
void startup (void)
{
ssd1306_clear();
message_buffer[0] = 0;
message_buffer[1] = 2;
message_buffer[2] = 2;
message_buffer[3]= ' ';
message_buffer[4]= ' ';
message_buffer[5]= ' ';
message_buffer[6]= ' ';
message_buffer[7]= '*';
message_buffer[8]= 'M';
message_buffer[9]= 'i';
message_buffer[10]= 'D';
message_buffer[11]= 'i';
message_buffer[12]= '*';
message_buffer[13]= ' ';
message_buffer[14]= ' ';
message_buffer[15]= ' ';
message_buffer[16]= ' ';
message_buffer[17]= '\r';
message_buffer[18]= '\n';
show_display();
message_buffer[0] = 0;
message_buffer[1] = 5;
message_buffer[2] = 2;
message_buffer[3]= ' ';
message_buffer[4]= ' ';
message_buffer[5]= ' ';
message_buffer[6]= '*';
message_buffer[7]= 'M';
message_buffer[8]= 'a';
message_buffer[9]= 's';
message_buffer[10]= 't';
message_buffer[11]= 'e';
message_buffer[12]= 'r';
message_buffer[13]= '*';
message_buffer[14]= ' ';
message_buffer[15]= '\r';
message_buffer[16]= '\n';
show_display();
_delay_ms(1000);
ssd1306_clear();
}
int main(void)
{
// Crystal Oscillator division factor: 1
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);
// Input/Output Ports initialization
// Port B initialization
// Function: Bit7=In Bit6=In Bit5=Out Bit4=In Bit3=Out Bit2=Out Bit1=Out Bit0=Out
DDRB=(0<<DDB7) | (0<<DDB6) | (1<<DDB5) | (0<<DDB4) | (1<<DDB3) | (1<<DDB2) | (1<<DDB1) | (1<<DDB0);
// State: Bit7=T Bit6=T Bit5=0 Bit4=T Bit3=0 Bit2=1 Bit1=0 Bit0=1
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (1<<PORTB2) | (0<<PORTB1) | (1<<PORTB0);
// Port C initialization
// Function: Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRC=(0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (0<<DDC0);
// State: Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTC=(0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);
// Port D initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=0xFF
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (0<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (0<<CS01) | (0<<CS00);
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=0xFFFF
// OC1A output: Disconnected
// OC1B output: Disconnected
// 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=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (0<<CS10);
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=(0<<EXCLK) | (0<<AS2);
TCCR2A=(0<<COM2A1) | (0<<COM2A0) | (0<<COM2B1) | (0<<COM2B0) | (0<<WGM21) | (0<<WGM20);
TCCR2B=(0<<WGM22) | (0<<CS22) | (0<<CS21) | (0<<CS20);
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=(0<<OCIE0B) | (0<<OCIE0A) | (0<<TOIE0);
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=(0<<ICIE1) | (0<<OCIE1B) | (0<<OCIE1A) | (0<<TOIE1);
// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=(0<<OCIE2B) | (0<<OCIE2A) | (0<<TOIE2);
// External Interrupt(s) initialization
// INT0: Off
// 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=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
EIMSK=(0<<INT1) | (0<<INT0);
PCICR=(0<<PCIE2) | (0<<PCIE1) | (0<<PCIE0);
/*
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: Off
// USART0 Mode: Asynchronous
// USART Baud Rate: 38400
UCSR0A=(0<<RXC0) | (0<<TXC0) | (0<<UDRE0) | (0<<FE0) | (0<<DOR0) | (0<<UPE0) | (0<<U2X0) | (0<<MPCM0);
UCSR0B=(1<<RXCIE0) | (0<<TXCIE0) | (0<<UDRIE0) | (1<<RXEN0) | (0<<TXEN0) | (0<<UCSZ02) | (0<<RXB80) | (0<<TXB80);
UCSR0C=(0<<UMSEL01) | (0<<UMSEL00) | (0<<UPM01) | (0<<UPM00) | (0<<USBS0) | (1<<UCSZ01) | (1<<UCSZ00) | (0<<UCPOL0);
UBRR0H=0x00;
UBRR0L=0x0C;
*/
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART0 Mode: Asynchronous
// USART Baud Rate: 115200 (Double Speed Mode)
UCSR0A=(0<<RXC0) | (0<<TXC0) | (0<<UDRE0) | (0<<FE0) | (0<<DOR0) | (0<<UPE0) | (1<<U2X0) | (0<<MPCM0);
UCSR0B=(1<<RXCIE0) | (0<<TXCIE0) | (0<<UDRIE0) | (1<<RXEN0) | (1<<TXEN0) | (0<<UCSZ02) | (0<<RXB80) | (0<<TXB80);
UCSR0C=(0<<UMSEL01) | (0<<UMSEL00) | (0<<UPM01) | (0<<UPM00) | (0<<USBS0) | (1<<UCSZ01) | (1<<UCSZ00) | (0<<UCPOL0);
UBRR0H=0x00;
UBRR0L=0x07;
// Analog Comparator initialization
// Analog Comparator: Off
// The Analog Comparator's positive input is
// connected to the AIN0 pin
// The Analog Comparator's negative input is
// connected to the AIN1 pin
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0);
ADCSRB=(0<<ACME);
// Digital input buffer on AIN0: On
// Digital input buffer on AIN1: On
DIDR1=(0<<AIN0D) | (0<<AIN1D);
// ADC initialization
// ADC disabled
ADCSRA=(0<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (0<<ADPS1) | (0<<ADPS0);
/* SPI disabled here, Included in Display Routine
// SPI initialization
// SPI Type: Master
// SPI Clock Rate: 1843,200 kHz
// SPI Clock Phase: Cycle Start
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
SPCR=(0<<SPIE) | (1<<SPE) | (0<<DORD) | (1<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);
SPSR=(0<<SPI2X);
*/
// TWI initialization
// TWI disabled
TWCR=(0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWEN) | (0<<TWIE);
sei();
ssd1306_init();
ssd1306_clear();
startup();
message_pointer=0;
while (1)
{
if(rx_wr_index != rx_rd_index)
{
serial_parser();
}
}
}
Ich hab mal den kompletten Code ( ohne include Dateien ) gepostet.
Die serielle Schnittstellenbearbeitung findet im Prinzip der USART_RX_vect Routine statt.
Dort ist auch der Softwareloop integriert.
Ich bin im Augenblick ziemlich ratlos und weiss nicht, was Ich noch versuchen soll.
Übrigens beide Controller hängen an der selben 3,3V Stromversorgung ( Labornetzteil ).
Lesezeichen