Hallo zusammen,
ich benutze einen ATMega644 und will daten vom ADC über den UART Senden.
Leider kommt da nichts an. Mit einem ATMega32 funktioniert es ohne
Probleme d.h. dass mein Terminal Programm richtig geschrieben ist und
der Fehler am uC liegt. Die Register hab ich auch angepasst, sodass es
eigentlich auf dem AtMega644 funktionieren sollte.
Hier der Code:
#ifdef F_CPU
#undef F_CPU
#define F_CPU 16000000UL
#endif
#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
// Diese Beispiel zeigt die Anwendung des ADC eines ATmega169
// unter Verwendung der internen Referenzspannung von nominell 1,1V.
// Zur Anpassung an andere AVR und/oder andere Referenzspannungen
// siehe Erläuterungen in diesem Tutorial und im Datenblatt
/* ADC initialisieren */
void ADC_Init(void)
{
// die Versorgungsspannung AVcc als Referenz wählen:
//ADMUX = (1<<REFS0);
// oder interne Referenzspannung als Referenz für den ADC wählen:
ADMUX = (1<<REFS1) | (1<<REFS0);
// Bit ADFR ("free running") in ADCSRA steht beim Einschalten
// schon auf 0, also single conversion
ADCSRA = (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler
ADCSRA |= (1<<ADEN); // ADC aktivieren
/* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man
liest
also einen Wert und verwirft diesen, um den ADC "warmlaufen zu
lassen" */
ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
while (ADCSRA & (1<<ADSC) ) { // auf Abschluss der
Konvertierung warten
}
/* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
Wandlung nicht übernommen. */
(void) ADCW;
}
/* ADC Einzelmessung */
uint16_t ADC_Read( uint8_t channel )
{
// Kanal waehlen, ohne andere Bits zu beeinflußen
ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while (ADCSRA & (1<<ADSC) ) { // auf Abschluss der Konvertierung
warten
}
return ADCW; // ADC auslesen und zurückgeben
}
void USART_Init( unsigned int baud )
{
/*Set baud rate*/
UBRR0H = (unsigned char)(baud>>8);
UBRR0L = (unsigned char)baud;
/* Enable receiver and transmitter*/
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
/* Set frame format: 8data, 2stop bit*/
UCSR0C = (1<<USBS0)|(3<<UCSZ00);
}
void USART_Transmit( unsigned char data )
{
/* Wait for empty transmit buffer*/
while
( !( UCSR0A & (1<<UDRE0)) );
/* Put data into buffer, sends the data*/
UDR0 = data;
}
void uart_puts( char *s )
{
/* while *s != '\0' so unequally "string-end characters (terminator)
*/
while (*s)
{
USART_Transmit(*s);
s++;
}
}
void main(void)
{
USART_Init(0x67);
char String[16] = {"Test "};
short ADCWert;
ADC_Init();
while(1)
{
ADCWert = ADC_Read(4);
sprintf(String,"Test: %i\n", ADCWert);
uart_puts(String);
//USART_Transmit(S);
_delay_ms(1000);
}
}
muss ich die Baudrate neu berechnen?
am Quarz hab ich aber nichts geändert.
der ATMega32 läuft bis zu 16Mhz
der AtMega644 läuft bis zu 20 Mhz
Ich betreibe den Controller mit 16Mhz
S. Landolt schrieb:> Also ich verstehe weder vorbild noch prx.
Ich auch nicht. ;-)
Tippfehler im Taschenrechner.
Allerdings war ein Hex-Angabe an dieser Stelle arg verdächtig.
Wer macht denn sowas?
Muss ich nur diese Einstellungen ändern?
UCSR0A = (1<<RXEN0)|(1<<TXEN0);
hat leider auch nichts gebracht
#ifdef F_CPU
#undef F_CPU
#define F_CPU 16000000UL
#endif
#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
// Diese Beispiel zeigt die Anwendung des ADC eines ATmega169
// unter Verwendung der internen Referenzspannung von nominell 1,1V.
// Zur Anpassung an andere AVR und/oder andere Referenzspannungen
// siehe Erläuterungen in diesem Tutorial und im Datenblatt
/* ADC initialisieren */
void ADC_Init(void)
{
// die Versorgungsspannung AVcc als Referenz wählen:
//ADMUX = (1<<REFS0);
// oder interne Referenzspannung als Referenz für den ADC wählen:
ADMUX = (1<<REFS1) | (1<<REFS0);
// Bit ADFR ("free running") in ADCSRA steht beim Einschalten
// schon auf 0, also single conversion
ADCSRA = (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler
ADCSRA |= (1<<ADEN); // ADC aktivieren
/* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man
liest
also einen Wert und verwirft diesen, um den ADC "warmlaufen zu
lassen" */
ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
while (ADCSRA & (1<<ADSC) ) { // auf Abschluss der
Konvertierung warten
}
/* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
Wandlung nicht übernommen. */
(void) ADCW;
}
/* ADC Einzelmessung */
uint16_t ADC_Read( uint8_t channel )
{
// Kanal waehlen, ohne andere Bits zu beeinflußen
ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while (ADCSRA & (1<<ADSC) ) { // auf Abschluss der Konvertierung
warten
}
return ADCW; // ADC auslesen und zurückgeben
}
void USART_Init( unsigned int baud )
{
/*Set baud rate*/
UBRR0H = (unsigned char)(baud>>8);
UBRR0L = (unsigned char)baud;
/* Enable receiver and transmitter*/
UCSR0A = (1<<RXEN0)|(1<<TXEN0);
/* Set frame format: 8data, 2stop bit*/
UCSR0C = (1<<USBS0)|(3<<UCSZ00);
}
void USART_Transmit( unsigned char data )
{
/* Wait for empty transmit buffer*/
while
( !( UCSR0A & (1<<UDRE0)) );
/* Put data into buffer, sends the data*/
UDR0 = data;
}
void uart_puts( char *s )
{
/* while *s != '\0' so unequally "string-end characters (terminator)
*/
while (*s)
{
USART_Transmit(*s);
s++;
}
}
void main(void)
{
USART_Init(0x67);
char String[16] = {"Test "};
short ADCWert;
ADC_Init();
while(1)
{
ADCWert = ADC_Read(4);
sprintf(String,"Test: %i\n", ADCWert);
uart_puts(String);
//USART_Transmit(S);
_delay_ms(1000);
}
}
S. Landolt schrieb:> Also ich verstehe weder vorbild noch prx.
Ja, ich verstehe mich selbst auch nicht.
Hans-Peter schrieb:> Muss ich nur diese Einstellungen ändern?> UCSR0A = (1<<RXEN0)|(1<<TXEN0);
Bloß nicht. Mach das wieder rückgängig. Das war ein Fall von geistiger
Umnachtung.
Hallo zusammen,
nun kommen Daten an der Seriellen Schnittstelle an.
Allerdings werden mir diese als nichtlesbare Zeichen dargestellt.
Ich habe die Taktrate wie beschrieben auf 2 MHz gesetzt.
den UART habe ich wie folgt initilaisiert:
USART_Init(0xc);
das bedeutet dass er nun mit 2 Mhz läuft.
weiter komme ich allerdings nicht.
Kann mir sonst noch jemand sagen was ich beachten sollte?
vielen Dank im voraus.
hier mein code:
#ifdef F_CPU
#undef F_CPU
#define F_CPU 2000000UL
#endif
#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
// Diese Beispiel zeigt die Anwendung des ADC eines ATmega169
// unter Verwendung der internen Referenzspannung von nominell 1,1V.
// Zur Anpassung an andere AVR und/oder andere Referenzspannungen
// siehe Erläuterungen in diesem Tutorial und im Datenblatt
/* ADC initialisieren */
void ADC_Init(void)
{
// die Versorgungsspannung AVcc als Referenz wählen:
//ADMUX = (1<<REFS0);
// oder interne Referenzspannung als Referenz für den ADC wählen:
ADMUX = (1<<REFS1) | (1<<REFS0);
// Bit ADFR ("free running") in ADCSRA steht beim Einschalten
// schon auf 0, also single conversion
ADCSRA = (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler
ADCSRA |= (1<<ADEN); // ADC aktivieren
/* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man
liest
also einen Wert und verwirft diesen, um den ADC "warmlaufen zu
lassen" */
ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
while (ADCSRA & (1<<ADSC) ) { // auf Abschluss der
Konvertierung warten
}
/* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
Wandlung nicht übernommen. */
(void) ADCW;
}
/* ADC Einzelmessung */
uint16_t ADC_Read( uint8_t channel )
{
// Kanal waehlen, ohne andere Bits zu beeinflußen
ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while (ADCSRA & (1<<ADSC) ) { // auf Abschluss der Konvertierung
warten
}
return ADCW; // ADC auslesen und zurückgeben
}
void USART_Init( unsigned int baud )
{
/*Set baud rate*/
UBRR0H = (unsigned char)(baud>>8);
UBRR0L = (unsigned char)baud;
/* Enable receiver and transmitter*/
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
/* Set frame format: 8data, 2stop bit*/
UCSR0C = (1<<USBS0)|(3<<UCSZ00);
}
void USART_Transmit( unsigned char data )
{
/* Wait for empty transmit buffer*/
while
( !( UCSR0A & (1<<UDRE0)) );
/* Put data into buffer, sends the data*/
UDR0 = data;
}
void uart_puts( char *s )
{
/* while *s != '\0' so unequally "string-end characters (terminator)
*/
while (*s)
{
USART_Transmit(*s);
s++;
}
}
void main(void)
{
USART_Init(0xc);
char String[16] = {"Test "};
short ADCWert;
// ADC_Init();
ADCWert = 123;
while(1)
{
//ADCWert = ADC_Read(4);
sprintf(String,"Test: %i\n", ADCWert);
uart_puts(String);
//USART_Transmit(S);
_delay_ms(1000);
}
}
Die Fuses vom Controller, wo du die Taktquelle, Brownout usw einstellst.
https://www.mikrocontroller.net/articles/AVR_Fuses
Hast du an den was geändert ? Mit was programmierst du ? Was für einen
ISP Programmer hast du ?
Gruß JackFrost
Nach dem http://www.engbedded.com/fusecalc/ läuft der Atmega644 mit dem
internen RC Oszillator und ohne die CKDIV8 Fuse. Damit solltest du den
Wert für die Baudrate mit 8 MHz berechnen.
Gruß JackFrost
Hallo,
von C Programmierung der ATMEGA - Controller habe ich mich schon vor ein
paar Jahren verabschiedet.
Somit nur ein Hinweis: Unterschied der 32 hat nur einen Hardware Uart
der 644 zwei. Somit ist es zwingend nötig den Controller zu sagen
welcher frei gegeben wird.
Mit Bascom sehr einfach im Header einzustellen.
Beispiel:
$baud = 19200 ‚ ist 1
$baud1 = 19200 ‚ ist 2
Was auch immer wieder missachtet wird der 644 kann mit 20 M getaktet
werden aber nur stabil mit Betriebsspannung 3,3 Volt.
Kommen „wüste“ Zeichen zum Terminal an,ist es erst mal ein Zeichen, UART
hat Verbindung aufgebaut nur die Baudrate ist nicht synchron
eingestellt.
Mit freundlichen Grüßen
Fred R. schrieb:> Was auch immer wieder missachtet wird der 644 kann mit 20 M getaktet> werden aber nur stabil mit Betriebsspannung 3,3 Volt.
Datenblatt sagt was anderes.
– ATmega644: 0 - 10MHz @ 2.7V - 5.5V, 0 - 20MHz @ 4.5V - 5.5V
Wolfsente schrieb:> Fred R. schrieb:>> Was auch immer wieder missachtet wird der 644 kann mit 20 M getaktet>> werden aber nur stabil mit Betriebsspannung 3,3 Volt.>> Datenblatt sagt was anderes.>> – ATmega644: 0 - 10MHz @ 2.7V - 5.5V, 0 - 20MHz @ 4.5V - 5.5V
Hallo,
ja die Wortwahl „missachtet“ ist wohl falsch gewählt.
Kenne Datenblatt und diese Info hat mich auch viele Nerven und Zeit
geraubt. Im Nachhinein sieht man den Widerspruch. Schon die Bezeichnung
von 0 bis xx ist doch schon sehr missverständlich. Mit 0 Takt wird wohl
nichts mehr funktionieren.
Hatte das gleiche Problem mit Uart Controller und Terminal. Haben
einfach keine synchrone Baudrate bekommen. Obwohl das Programm „sauber“
abgearbeitet wurde. Nur durch Zufall den Controller mit 3,3 Volt
betrieben und siehe da alles bestens. Als nächsten Versuch den Takt auf
8 M eingestellt. Nun ist es Wurst ob 3,3 Volt oder 5,0 Volt, es
funktionier halt. Ich nenne es mal in meiner Rhetorik “ Der Controller
war übertaktet“
Zu meiner Entschuldigung für Antwort(ist ja sehr wichtig für einige in
diesem Forum) bin nur ein Amateur und sehr ausdauernd bei Fehlersuche.
Also „basteln“ und probieren hat mehr Erfolg, als nur die Antwort zu
bekommen „siehe Datenblatt“. Die meiste machen es wie auch ich.
Somit wollte ich nur meine praktischen Erfahrungen vermitteln.
MfG