- LiTime Speicher und Akkus         
Ergebnis 1 bis 10 von 10

Thema: UART problem mega168

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    30.03.2006
    Ort
    Lübeck
    Alter
    36
    Beiträge
    60

    UART problem mega168

    Anzeige

    Powerstation Test
    moin,
    ich hab ein problem, und zwar versuche ich einen über adc eingelesenen wert über UART an den pc zu übertragen, das kabel hab ich mir gelötet und es scheint zu funzen, denn es kommt was an, aber nicht das was ich will.
    es kommen immer C mit häkchen unten an...

    ich benutze das terminal von Bascom.
    Einen mega168, programmiert in avr-studio

    hier der wichtige code (das mit dem ADC funzt, deswegen hab ichs weggelassen)
    Code:
    #include <avr/io.h>
    
    int uart_putc(unsigned char d);
    void uart_puts (char *s);
    
    void init_uart(void)
    {
    	UBRR0H = (unsigned char) (103>>8);
    	UBRR0L = (unsigned char) 103;
    	UCSR0B = (1<<RXEN0) | (1<<TXEN0);
    
    }
    
    int main(void)
    {
        	init_uart();
    
       	uint8_t d = 231;
    
    	while (1)
    	{
       		while (!(UCSR0A & (1<<UDRE0))); 		// warten bis Senden moeglich
    		UDR0 = d; 								// sende Zeichen
    	}
    
            return 0;
    }
    
    int uart_putc(unsigned char d)
    {
    	while (!(UCSR0A & (1<<UDRE0))); 		/* warten bis Senden moeglich */
    	UDR0 = d; 								/* sende Zeichen */
    	return 0;
    }
    							
    void uart_puts (char *s)
    {
    	while (*s)
    	{ 							/* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
    		uart_putc(*s);
    		s++;
    	}
    }

  2. #2
    Benutzer Stammmitglied
    Registriert seit
    07.01.2006
    Beiträge
    36
    hallo lionking - ich mal wieder

    also der code in main() und init_uart() sieht ok aus. Habe gerade gelernt, dass UCSR0C bereits vorinitialisiert ist...

    Habe das Programm auf meinen mega168 geladen und es läuft mit Hyperterminal (Windows XP). Dein mega168 ist mit 4 MHz getaktet? Dann sollten die 103 wohl stimmen - habe es mit 207 getestet, weil meiner mit 8 MHz getaktet ist (außerdem habe ich es mit d = 83) getestet - Zeichen 231 ist etwas obskur. Hast Du das Terminal richtig eingestellt (2400, 8bit, no parity, 1 Stopbit)?

    Dann könnte der Fehler ja doch am Kabel liegen?

    Gruß
    kanal28

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    30.03.2006
    Ort
    Lübeck
    Alter
    36
    Beiträge
    60
    soo ich hab mal die baudraten im terminal durchprobiert und tatsächlich funktioniert es bei 1200... wie kommt das??? ich hab doch im code 9600 eingestellt.
    oder läuft mein mega168 etwa auf einer anderen frequenz? eigentlich sollen es 16Mhz sein... wie kann ich das testen?

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    30.03.2006
    Ort
    Lübeck
    Alter
    36
    Beiträge
    60
    sowas nenn ich timing wir warn gleichzeitig...

    laut der formel F_CPU/(rate*16)-1 läuft mein AVR mit ner frequenz von 2mhz
    also liegt da der fehler.

    achja, wo gibs das hyperterminal?

    und ich hatte auch beim pwm das problem dass die frequenz nicht stimmte, jetzt weiss ich warum

    also woher kommts, dass ich nur 2mhz hab?

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    07.01.2006
    Beiträge
    36
    cool, aber eine ne Sekunde war ich vorn!

    also 2 MHz finde ich auch seltsam - original sollte es wohl 1 MHz sein. Hm, habe hier ein Tool zur Berechnung von http://www.rowalt.de/ - da gibts eine Berechnungsoption "double speed transmission" - dann wäre Deiner mit 1 MHz getaktet - aber das müsste man in UCSR0A aktivieren. Also Bascom kann ja die Fusebits auslesen - da kannst Du sehen, wie er getaktet ist.

    Hyperterminal ist im Zubehör->Komm, wird aber nicht standardmäßig installiert. http://rowalt.de/ hat auch ein nettes kleines Terminalprogramm

    kanal28

    PS: welche Funktion erkundest Du als nächstes, dann kann ich mich schon mal vorbereiten

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    30.03.2006
    Ort
    Lübeck
    Alter
    36
    Beiträge
    60
    in Bascom hab ich das entsprechende fusebit auf 1111:1111 external Xtal... und der hat 16Mhz

    hyperterminal hab ich gefunden...danke

    das nächste wird wohl die ansteuerung eines displays sein, aber da ich noch keins hab wird das wohl och nen paar tage dauern... vielleicht bis dahin schonmal interrupt und son kram

    nochwas:
    eher ein C problem, ich will ja den wert des adc per UART ausgeben...
    jetzt wollte ich das so machen:

    c = ReadChannel(1); //lese analogen wert aus channel 1 in c

    unsigned char y[] = "der Wert ist: %i \r\n", c;

    uart_puts(y); // sende Zeichen

    nur kommt beim terminal
    der Wert ist: %i
    an... wie mache ich das, dass dann da
    der Wert ist:
    und dann der wert steht?

  7. #7
    Benutzer Stammmitglied
    Registriert seit
    07.01.2006
    Beiträge
    36
    Also die Taktfrequenz verbuche ich erstmal als rätselhaft - keine Ahnung was da ist.

    Du musst den Zahlenwert in einen String umwandeln. Eine formatierte Ausgabe kriegst Du mit sprintf() hin (http://www.elook.org/programming/c/sprintf.html). Leider wird der Code dann ziemlich groß. Etwas sparsamer, aber ohne Formatierung sind itoa() und dtostrf() - sind wohl beide nicht Standard-C; google sollte weiterhelfen.

    kanal28

    PS: Wenn Du schon mal LCD üben willst - mit der großartigen Sim-Seite hier habe ich mein LCD verstanden http://www.geocities.com/dinceraydin.../djlcdsim.html

  8. #8
    Benutzer Stammmitglied
    Registriert seit
    30.03.2006
    Ort
    Lübeck
    Alter
    36
    Beiträge
    60
    hab rausgefunden woran das mit dem tackt lag... da war noch nen fusebit gesetzt, nähmlich "divide Clock by 8" daher die 2Mhz
    naja jetzt hab ich die 16Mhz, aber muss nun die teiler neu einstellen vom adc und pwm

    es funzt mit itoa()... so:

    Code:
    ...
    c = ReadChannel(1);         			//lese analogen wert aus channel 1 in c 
    
    OCR1A = c;                                          //sende wert zum PWM
    
    unsigned char y[] = "Der Wert ist: ";
    
    unsigned char z[3];
    
    itoa(c, z, 10);
    
    uart_puts(y); 								// sende Zeichen 
    uart_puts(z);
    uart_puts("\r\n");
    ...

  9. #9
    Benutzer Stammmitglied
    Registriert seit
    30.03.2006
    Ort
    Lübeck
    Alter
    36
    Beiträge
    60
    so neues problem, dismal mit der ansteuerung eines servos...
    noch ohne interrupt... sollte ich mir glaubich mal angucken...
    naja hier mal der code, er sollte denke ich genug kommtentiert sein.
    Code:
    #include <avr/io.h>
    #include <my.h>
    
    int main(void)
    {
        DDRD |= (1<<PD2);                   //PORTD2 wird als ausgang gesetzt
     
        uint16_t a   = 0;                   //wert des adc
        uint32_t a32 = 0;                   //wert des adc in 32bit, zum berechnen
    
        uint8_t ar = 0;                     //Statuswerte: ob der ADC ausgelesen wurde
        uint8_t t  = 0;                     //und in welchem Abschnitt wir sind
        
        while(1)
        {     
            if(t==0)                        //wenn wir im zweiten zyklus sind...
            {
                if(!ar)                     //wenn der ADC noch nicht ausgelesen wurde wird das getan
                {
                    a32 = ReadChannel(0)*125/8+16000;  //ADC wird ausgelesen und "normiert" auf 16000-32000 (1-2ms)
                    a  = (uint16_t) a32;
                    ar = 1;                 //ADC wurde ausgelesen
                }
    
                if(TCNT1 >= 20000)          //wenn der Timer bei 20000 ist (10ms) wird:
                {
                    t = 1;                  //sind wir als nächstes im ersten Zyklus, also wird:
                    TCCR1B |= (1<<CS10);    //PORTD2 gesetzt,
                    PORTD  |= (1<<PD2);     //der Taktteiler auf 1 gestellt
                    TCNT1 = 0;              //und der Timer zurückgesetzt
                }               
            } 
            
            if(t==1)                        //wenn wir im ersten Zyklus sind...
            {
                if(TCNT1 >= a)              //...und der Timer den ausgerechneten Wert erreicht hat
                {
                    t  = 0;                 //sind wir als nächstes im zweiten Zyklus, also:
                    ar = 0;                 //ist der ADC-Wert verbraucht
                    TCCR1B |= (2<<CS10);    //und der Taktteiler wird auf 8 gestellt,
                    PORTD  &= ~(1<<PD2);    //PORTD2 wird nicht gesetzt
                    TCNT1 = 0;              //und der Timer wird zurückgesetzt
                }
            }
        }
    
        return 0;
    }
    leider funzt es nicht, wahrscheinlich irgend ne blöde sache drin...
    naja an PD2 kommt jedenfalls nix an
    ReadChannel is von mir und funzt auf jeden Fall.

    edit, blöder fehler,, hab ich grad gemerkt, der timer sollte vielleicht gestartet werden
    naja er macht trotzdem noch nicht was er soll, es ist einfach ne rechteckspannung am ausgang

  10. #10
    Benutzer Stammmitglied
    Registriert seit
    30.03.2006
    Ort
    Lübeck
    Alter
    36
    Beiträge
    60
    so es funzt... irgendwie hat das mit der umrechnung auf 16-32k nich geklappt... jetzt gehts
    hab folgendes geändert:
    Code:
    a32 = ReadChannel(0);  //ADC wird ausgelesen und "normiert" auf 16000-32000
    a32 = a32*125/8+16000;
    a = (uint16_t) a32;

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiTime Speicher und Akkus