logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.
REKLAMA
  • #1 6569710
    Syntax
    Poziom 14  
    Witam,
    prosze o sprawdzenie mojego programu bo moim zdaniem jest OK a wciąż nie chce zadziałać.

    Używając hyper terminal-a wysyłam znak poprzez RS232 do układu na USART0, chcę żeby po odebraniu znaku zapaliła się dioda podłączona do portu E.

    Hyper terminal mam skonfigurowany następująco: 4800b/s, 8bitow danych, bit parzystosci, 2 bity stopu, kontrola przeplywu-brak

    Oto program:
    
    define F_CPU 16000000UL
    
    #include <avr/io.h> //dostep do rejestow
    #include <util/delay.h> //dostep do funkcji opozniajacych
    #include "lcd_dom.h" //dostep do lcd
    
    #include <string.h>
    #include <avr/signal.h> //definicje SIGNAL, INTERRUPT 
    #include <avr/interrupt.h> // funkcje sei(), cli() 
    
    
    ISR (USART0_RX_vect, ISR_NOBLOCK) //obsluga przerwania po odbiorze bajtu z USART1
    {
    //pisz_znak(UDR1);
    DDRE=255;
    PORTE=0;
    
    }
    
    int main(void)
    {
    unsigned char buffer=0;//////////
    
    _delay_ms(45);  // Czekaj 45 ms Na wykonanie się procedury zerującej sterownik LCD
    LCD_init();
    
    //inicjalizacja UART
    cli(); //wyłączenie przerwań
    UBRR0L=207; //ustalamy predkosc transmisji uart na 4800
    UBRR0H=0;
    UCSR0C=0b00101110; //tryb asynchroniczny, bit parzystosci, parzystosc, 1bit stopu, slowo 8bit 
    UCSR0B=0b10010000; //wlaczenie obslugi przerwan od RX, wlaczenie odbiornika
    UCSR0A=0b00000000; //wyzerowanie znacznikow, pojedyncza predkosc transmisji, komunikacja NIE wieloprocesorowa
    sei(); //wlaczenie przerwan
    buffer=UCSR0A; ////////////////////////////////////
    //koniec inicjalizacji UART
    
    
    LCD_command(0b00000001); //czyszczenie ekranu
    
    
    LCD_text("czekam:");
    
    while (1==1)
    {
    if (UCSR0A != buffer) /////////////////////////////////
    {
    
    DDRE=255;
    PORTE=0;
    }
    
    }
    
    return 0;
    }


    Proszę stosować znaczniki [code] - poprawiłem.
    [zumek]



    PS:

    Znalazłem pewną rzecz:
    - gdy wyzeruje bit RXCIE to komunikacja działa, gdy jest on ustawiony to nie działa ani przerwanie ani ręczne sprwadzanie znacznika zgloszenia przerwania RXC. Zależy mi żeby obslużyć to przerwanie, dlaczego więc nie działa?
  • REKLAMA
  • #2 6584062
    HIOB
    Poziom 17  
    Witam,

    Nie kompilowałem tego programu więc na 100% nie mogę obiecać, że gdzieś się nie bachnąłem...
    W HyperTerminal-u zmień na wszelki wypadek liczbę bitów stopu na 1 - choć teoretycznie z 2 też powinno działać.

    #include <avr/io.h>
    #include <util/delay.h> 
    #include "lcd_dom.h"
    
    #include <string.h> 
    #include <avr/signal.h>
    #include <avr/interrupt.h>
    
    #define		ZEGAR				16000000UL 
    #define		PREDKOSC_USART		4800								//Prędkość transmisji
    #define		W_U2X0				1									//Prędkości transmisji: normalna/podwojona
    
    #if(W_U2X)															//Jeżeli opcja podwojenia częstotkiwości załączona
    	#define		BAUD	((ZEGAR / (PREDKOSC_USART * 8UL)) - 1)		//Wzór na wyliczenie "BAUD"
    #else																//Jeżeli opcja podwojenia częstotkiwości wyłączona
    	#define		BAUD	((ZEGAR / (PREDKOSC_USART * 16UL)) - 1)		//Wzór na wyliczenie "BAUD"
    #endif																//Koniec warunku
    
    #define		W_UBRRL				(unsigned char)(BAUD)						//Wyłuskaj niższa część "BAUD"
    #define		W_UBRRH				(unsigned char)(BAUD >> 8)					//Wyłuskaj wyższa część "BAUD"
    
    volatile char bufor;												//Zakaz optymalizacji - zmienna globalna
    
    int main(void) 
    { 
    	LCD_init();														//Zakładam, że wyświetlacz jest konfigurowany prawidłowo
    	_delay_ms(45);													//Opóźnienie powinno być za wywołaniem funkcji
    
    	cli();
    	UBRR0H = W_UBRRH;												//Ustaw rejestr "UBRR0H"
    	UBRR0L = W_UBRRL;												//Ustaw rejestr "UBRR0L"
    
    	UCSR0A |= (W_U2X0 << U2X0);									//W zależności od wybranej opcji
    	UCSR0B=0b10010000;
    	UCSR0C = 0b00100110;
    	
    	sei();
    
    	LCD_command(0b00000001);										//Zakładam, że wyświetlacz jest konfigurowany prawidłowo
    	LCD_text("czekam:"); 											//Zakładam, że wyświetlacz jest konfigurowany prawidłowo
    
    	while (true) 
    	{ 
    		if(!(UCSR0A & (1 << RXC0)))								//Sprawdza czy zostało coś odebrane
    		{ 
    			DDRE=255; 
    			PORTE=0;
    			
    			pisz_znak(bufor);										//Zakładam, że wyświetlacz jest konfigurowany prawidłowo
    		} 
    	} 
    
    	return 0; 
    }
    
    ISR(USART0_RX_vect)
    {
    	bufor = UDR0;
    }


    Pozdrawiam,
    Piotr.
  • REKLAMA
  • #3 6590598
    budzik1678
    Poziom 10  
    Ja piszę tylko w asemblerze ale pamiętaj o jednym. Kwarc musi mieć odpowiednią wartość np 18.432Mhz. Nawet dobrze napisany program ze złą wartością nie będzie działał. W pdfie o atmedze jest tabelka z wyliczonymi wartościami ubrr L i H i kwarce które pasują najbardziej.
  • REKLAMA
  • #4 8936669
    rafmos
    Poziom 13  
    Mam kilka pytań odnośnie USARTA ATMEGA128.

    1. Czy błąd transmisji 0.2% dla kwarca 16MHz będzie miał duży wpływ na transmisję przy przesyłaniu ramki 19 bitowej z komputera do urządzenia.
    2. W programie mikrokontrolera AVR co 5ms wywoływane jest przerwanie od timera1 output Compare które wywołuje procedury które trwają 1.5ms. W pętli głównej wyświetlane są wyniki pomiarów. Czy jest szansa na realizacja transmisji ramki 19bitowej używając przerwania od USARTA które będzie zapełniało bufor. W jaki sposób timer 1 współpracuje z USARTEM czy można to jakoś pogodzić. Czy nie pogubię danych z ramki. Dodam że przerwania od timera 1 nie mogę zatrzymać.
  • REKLAMA
  • #5 8937612
    Fredy
    Poziom 27  
    Błąd transmisji na poziomie 0.2% to jest bardzo mały błąd. Transmisja będzie śmigać super.
    Jeśłi chodzi o przerwania od UARTA i Timera to są one zamiennie - to znaczy że jeśli procek obsługuje przerwanie od Tmiera to w tym czasie blokuje inne przerwania które czekają w kolejce. Dlatego jeśli Twoje przerwanie od Timera jest takie długie to może być problem.
    Generalnie dąży się do tego aby przerwanie było bardzo krótkie - tylko zaznaczenie jakiejś flagi i koniec.
    Jest też możliwość zrobienia przerwań w przerwaniach ale tego nie polecam.
  • #6 8938301
    rafmos
    Poziom 13  
    A jakby zrobić coś takiego. W przerwaniu timera 1 i poza nim uruchomić przerwanie od Usarta w którym znaki będą zapisywane do tablicy, a w pętli głównej programu sprawdzać tylko zapełnienie tablicy. Po jej zapełnieniu analizować dostarczone dane przy wyłączonym przerwaniu z Usarta. Pytanie czy Usart daje przerwanie przy zakończeniu odbioru znaku (wypełnieniu bufora). Master komputer wyśle ramkę raz i będzie czekał na odpowiedź z urządzenia. Będzie to działać?
REKLAMA