Ta strona używa ciasteczek (plików cookies), dzięki którym może działać lepiej. Dowiedz się więcejRozumiem i akceptuję

ATMega 8 USART Prędkość wysyłania, czemu tak wolno?

Autor Wiadomość
davidpi 



Posty: 233
Pomógł: 11 razy
Otrzymał 17 piw(a)
Skąd: Kielce
Programuję w:
C
Wysłany: 28-01-2012, 22:47   ATMega 8 USART Prędkość wysyłania, czemu tak wolno?

Witam.
Próbuję opanować USART w ATMega 8. Wewnętrzny oscylator 1MHz. Z komunikacją nie mam większych problemów. Jednak zastanawia mnie ustawianie prędkości transmisji. W moim programie ustawiłem prędkość transmisji na 9600bps. Rozumiem że 9600 bps oznacza wysłanie 9600 bitów w ciągu sekundy (jeżeli źle rozumuję to proszę o poprawienie mnie), a więc niespełna 1000 liczb 8 bitowych.
Jednak z obserwacji w urządzeniu wynika, że pracuje ono dużo wolniej.Dlatego mam kilka pytań do bardziej doświadczonych kolegów.

Oto kod programu:
Kod programu: Zaznacz cały
#include<avr\io.h>
#include<UART.c>
#include<HD44780.c>
#include<stdlib.h>

int dana=0;
char dana1=120;

void LCD()
{
    char buf[5];
    LCD_Clear();
    itoa(dana,buf,10);
    LCD_WriteText(buf);
}

int main()
{
    LCD_Initalize();
    UART_NadajnikInit();
    while(1)
    {
        UART_Wyslij(dana1);
        dana++;
        LCD();
    }
    return 0;
}


oraz kod obsługi USART

Kod programu: Zaznacz cały
#include "UART.h"

void UART_NadajnikInit()
{
    UBRRL = 6;
    UBRRH = 0;
    UCSRC |= (1<<UCSZ1) | (1<<UCSZ0);
    UCSRB |= (1<<TXEN);
    _delay_ms(100);
}

void UART_OdbiornikInit()
{
    UBRRL = 6;
    UBRRH = 0;
    UCSRC |= (1<<UCSZ1) | (1<<UCSZ0);
    UCSRB |= (1<<RXEN) | (1<<RXCIE);
}

void UART_Wyslij(char znak)
{
    while(bit_is_clear(UCSRA,UDRE)) {}
    UDR=znak;
}

void UART_WyslijTablice(char Tablica[], int Rozmiar)
{
    for(int i=0;i<Rozmiar;i++)
    {
        UART_Wyslij(Tablica[i]);
    }
}

char UART_Odbierz()
{
    return UDR;
}

Ogólnie zasada jest taka: wysyłam liczbę i po wysłaniu zwiększam licznik i wyświetlam.
Obserwując zmiany na wyświetlaczu zauważyłem, że jest wysyłanych ok 7 liczb na sekundę.
Więc najważniejsze pytanie.
Z jaką ja prędkością to w końcu wysyłam?? Czy na pewno 9600bps czy może coś pokręciłęm.
Proszę o pomoc i pozdrawiam

[ Dodano: 29-01-2012, 10:27 ]
Wyeliminowałem z programu niepotrzebne funkcje obsługo LCD. Do PC5 podpiąłem diodę led, która zmienia stan na przeciwny po każdym wysłaniu jednej liczby. Częstotliwość taktowania zmieniłem na 8MHz.
Program wygląda następująco:
Kod programu: Zaznacz cały

#include<avr\io.h>

char dana1=120;

void UART_NadajnikInit()
{
    UBRRH = 0;
    UBRRL = 51;
    UCSRC |= (1<<UCSZ1) | (1<<UCSZ0);
    UCSRB |= (1<<TXEN);
}

void UART_Wyslij(char znak)
{
    while(bit_is_clear(UCSRA,UDRE)) {}
    UDR=znak;
}

int main()
{
    DDRC=0xFF;
    PORTC=0xFF;
    UART_NadajnikInit();
    while(1)
    {
        UART_Wyslij(dana1);
        PORTC=0x00;
        UART_Wyslij(dana1);
        PORTC=0xFF;
    }
    return 0;
}

Prędkość ustawiona na 9600bps, a mimo to dioda miga z częstotliwością ok 15 razy na sekundę.
A więc układ wysyła 15 liczb w ciągu sekundy. To chyba trochę za mało na prędkość 9600bps??
Gdzie więc tkwi błąd??
A może tak ma być przy tej prędkości??
Proszę o pomoc bo sam już nie wiem co z tym zrobić.
Pozdrawiam

Popularny artykuł » DJI Phantom 2 + gimbal + GoPro + FPV - Pierwsze wrażenia


Ostatnio zmieniony przez davidpi 28-01-2012, 23:05, w całości zmieniany 1 raz  
Postaw piwo autorowi tego posta
 
 
KD93 




Posty: 2169
Pomógł: 66 razy
Otrzymał 298 piw(a)
Skąd: Siemianowice Śląskie
Programuję w:
C/Bascom
Moje roboty:
Wasp, Skarabeusz, Bajtel(2), Urwis, Prototyp nr.1

Wysłany: 29-01-2012, 10:40   

Próbowałeś ustawić bit UX2?


Postaw piwo autorowi tego posta
 
 
 
davidpi 



Posty: 233
Pomógł: 11 razy
Otrzymał 17 piw(a)
Skąd: Kielce
Programuję w:
C
Wysłany: 29-01-2012, 10:44   

KD93 napisał/a:

Wysłany: 1 minutę temu     
Próbowałeś ustawić bit UX2?

Ustawiłem ten bit i prędkość się zwiększyła (zapewne dwukrotnie), jednak nadal zmiany diody są zauważalne gołym okiem.
Rozumiem, że przy prędkości 9600bps układ powinien wysyłać blisko 1000 liczb na sekundę? Czy dobrze rozumuję??


Pracuję nad: Platforma Stewart'a
Postaw piwo autorowi tego posta
 
 
KD93 




Posty: 2169
Pomógł: 66 razy
Otrzymał 298 piw(a)
Skąd: Siemianowice Śląskie
Programuję w:
C/Bascom
Moje roboty:
Wasp, Skarabeusz, Bajtel(2), Urwis, Prototyp nr.1

Wysłany: 29-01-2012, 11:14   

Sam zaczynam pisać w C i mam na razie dużo problemów z UART'em, ale wydaje mi się, że nie jesteś w stanie osiągnąć takiej prędkości jaką ustawiasz, ponieważ pomiędzy kolejnymi wysyłkami mija pewna ilość cykli procesora. Ta prędkość jest już raczej zadeklarowana dla przesyłu, czyli tą twoją zmienną wysyła w tempie 9600bps, więc skoro to char i ma 8 bitów, to zajmie ci to 0,0008s, a nie wiadomo ile czasu minie do następnego przesyłu.

[ Dodano: 29-01-2012, 11:18 ]
Poza tym, robisz chyba tak:

-wysyłasz
-włączasz diodę
-wysyłasz
-wyłączasz diodę

więc na jedno mignięcie diody wysyłasz dwie zmienne.

davidpi napisał/a:
dioda miga z częstotliwością ok 15 razy na sekundę.
A więc układ wysyła 15 zmiennych w ciągu sekundy.


Skoro miga 15 razy, to wysyłasz 30 zmiennych.

Do tego napisałeś, że po ustawieniu UX2 zwiększyła się dwukrotnie, więc jest to 60 zmiennych.

60*9 = 540 (9, bo 8 bitów ma zmienna, ale masz stop bita jeszcze).

To wg mnie tak źle nie jest.

Popularny artykuł » ILIFE V7S - autonomiczny odkurzacz z Gearbest



Ostatnio zmieniony przez KD93 29-01-2012, 11:20, w całości zmieniany 1 raz  
Postaw piwo autorowi tego posta
 
 
 
davidpi 



Posty: 233
Pomógł: 11 razy
Otrzymał 17 piw(a)
Skąd: Kielce
Programuję w:
C
Wysłany: 29-01-2012, 11:23   

Problem rozwiązałem, choć nie do końca rozumiem. Ustawiłem bit URSEL w rejestrze UCSRC. Teraz działa jak należy, tzn. przy prędkości 9600bps wysyła kilkaset liczb na sekundę. Doczytałem, że ten bit służy do wyboru rejestru UCSRA lub UBRRH. Czy ktoś mógłby mi wyjaśnić na chłopski rozum, do czego służy ten bit??
Bo w tym momencie program działa, ale sam nie rozumiem do końca swojego programu.


Pracuję nad: Platforma Stewart'a
Postaw piwo autorowi tego posta
 
 
Więcej szczegółów
Wystawiono 1 piw(a):
KD93
dondu 



Posty: 903
Pomógł: 39 razy
Otrzymał 71 piw(a)
Skąd: Gliwice
Programuję w:
C
Wysłany: 29-01-2012, 11:51   

davidpi napisał/a:
Ustawiłem bit URSEL w rejestrze UCSRC. Teraz działa jak należy, tzn. przy prędkości 9600bps wysyła kilkaset liczb na sekundę. Doczytałem, że ten bit służy do wyboru rejestru UCSRA lub UBRRH. Czy ktoś mógłby mi wyjaśnić na chłopski rozum, do czego służy ten bit??

Rejestry UCSRC i UBRRH mają ten sam adres w przestrzeni adresowej rejestrów. Dlatego w zależności na którym z nich chcesz operować musisz dodatkowo korzystać z bitu URSEL. Przeczytaj rozdział: Accessing UBRRH/UCSRC Registers
Zobacz pokazane tam przykłady kodu C zarówno dla odczytu jak i zapisu rejestrów UCSRC i UBRRH i popraw swój program.


---> Multimetr DT-830B za darmo! <---
Ostatnio zmieniony przez dondu 29-01-2012, 11:56, w całości zmieniany 2 razy  
Postaw piwo autorowi tego posta
 
 
davidpi 



Posty: 233
Pomógł: 11 razy
Otrzymał 17 piw(a)
Skąd: Kielce
Programuję w:
C
Wysłany: 29-01-2012, 12:11   

Oki. Już rozumiem o co chodzi z tym bitem URSEL. Musi być ustawiony gdy wpisujemy do UCSRC. Gdy URSEL=0, to wpisujemy do UBRRH. Dzięki za pomoc


Pracuję nad: Platforma Stewart'a
Postaw piwo autorowi tego posta
 
 
dondu 



Posty: 903
Pomógł: 39 razy
Otrzymał 71 piw(a)
Skąd: Gliwice
Programuję w:
C
Wysłany: 29-01-2012, 12:19   

davidpi napisał/a:
Oki. Już rozumiem o co chodzi z tym bitem URSEL. Musi być ustawiony gdy wpisujemy do UCSRC. Gdy URSEL=0, to wpisujemy do UBRRH. Dzięki za pomoc

czyli takim kodem:

Kod programu: Zaznacz cały
void UART_NadajnikInit()
{
    UBRRH = 0;
    UBRRL = 51;
    UCSRC |= (1<<UCSZ1) | (1<<UCSZ0);
    UCSRB |= (1<<TXEN);
}

faktycznie wpisywałeś do UBRRH =6 a nie 0, a do UBRRL = 51, czyli spowalniałeś transmisję 6x, ponieważ zamiast zapiać do UCSRC zapisywałeś do UBRRH.

Natomiast bity UCSZ1 i UCSZ0 w UCSRC miałeś ustawione poprawnie dlatego, że to domyślny stan bitów UCSZ czyli przypadek :)


---> Multimetr DT-830B za darmo! <---
Ostatnio zmieniony przez dondu 29-01-2012, 12:27, w całości zmieniany 3 razy  
Postaw piwo autorowi tego posta
 
 
marek1707 



Posty: 4924
Pomógł: 513 razy
Otrzymał 672 piw(a)
Skąd: WAW
Programuję w:
C, asm
Wysłany: 29-01-2012, 13:38   

Malutka poprawka: wpis wartości 6 do UBRRH dawał podzielnik (6*256)+51+1=1588 w porównaniu do 51+1 przy UBRRH=0 co zwalniało prędkość transmisji 1588/52 czyli ok 30.5 raza.
I jeszcze to, że wysyłany przez UART znak ma oprócz bitów danych (zwykle 8) dodatkowe bity STARTu i STOPu czyli typowo jest ich 10 - łatwiej liczy się w pamięci liczbę znaków na sekundę :)
No i nie ma sensu dwa razy inicjować zawartości rejestrów UBRRL/H jak to było w pierwotnej wersji programu. Podzielnik jest wspólny więc i szybkości nadawania i odbioru są zawsze takie same. Osobne funkcje inicjalizacji nadajnika i odbiornika mogą mieć sens gdy pracując w half-dupleksie chcemy mieć dwie różne prędkości lub formaty danych ale to bardzo wyuznany przypadek, np. gdy odbieramy dane z jednego urządzenia a wysyłamy coś do zupełnie innego.

Acha, i nieprawdą jest, że "pomiędzy kolejnymi wysyłkami mija pewna ilość cykli procesora". Nadajnik UARTa jest buforowany i zgłasza swoją gotowość do załadowania nowego znaku zanim do końca zostanie nadany bit stopu. Tak więc znaki są "przyklejone" do siebie bez żadnych przerw chyba, że spóźnimy się z podesłaniem następnych danych. Dlatego warto obsługiwać UARTa na przerwaniach.

Coś takiego nie działa niestety w SPI w ATmegach - tam nie ma buforowania i czas reakcji procesora wlicza się do przerw w transmisji :( co widać szczególnie przy szybszych transferach. Dla zegara SCK rzędu kilku MHZ nawet obsługa SPI w przerwaniu robi dziury pożerające np. 1/4 szybkości.

EDIT: dopisałem zdanie o dwóch szybkościach transmisji.

Ostatnio zmieniony przez marek1707 29-01-2012, 13:44, w całości zmieniany 1 raz  
Postaw piwo autorowi tego posta
 
 
dondu 



Posty: 903
Pomógł: 39 razy
Otrzymał 71 piw(a)
Skąd: Gliwice
Programuję w:
C
Wysłany: 29-01-2012, 13:44   

marek1707 napisał/a:
Malutka poprawka: wpis wartości 6 do UBRRH dawał podzielnik (6*256)+51+1=1588 w porównaniu do 51+1 przy UBRRH=0 co zwalniało prędkość transmisji 1588/52 czyli ok 30.5 raza.

Celna poprawka :)


---> Multimetr DT-830B za darmo! <---
Postaw piwo autorowi tego posta
 
 
SeerKaza 




Posty: 190
Pomógł: 5 razy
Otrzymał 15 piw(a)
Skąd: Białystok
Programuję w:
C,C++,C#
Wysłany: 29-01-2012, 14:24   

Oj mieszacie chłopaki. Przypisujac do UBRRL wartość 51 otrzymacie max 2400bps

Prawidłowy kod inicjujacy na 9600 dla atmegi pracującej przy 1 MHz wyglada tak

Cytat:
UBRRH = 0;
UBRRL = 0x33;

UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
UCSRA &= ~(1<<U2X);
UCSRB = (1<<RXEN)|(1<<TXEN);


ramka 8 bitów bez parzystosci 2 bity stopu. UBRRL przypisujesz 12 i podciagasz bit U2X

Acha i to jest max jaki możesz wyciągnąć z tego procka przy takim taktowaniu. Potem przesunięcia zegara są zbyt wielkie. Bez bitu U2X możesz max wyciągnąć 4800.
Jak chcesz więcej musisz dodać kwarc.

Ostatnio zmieniony przez SeerKaza 29-01-2012, 15:15, w całości zmieniany 4 razy  
Postaw piwo autorowi tego posta
 
 
 
dondu 



Posty: 903
Pomógł: 39 razy
Otrzymał 71 piw(a)
Skąd: Gliwice
Programuję w:
C
Wysłany: 29-01-2012, 14:45   

SeerKaza napisał/a:
Oj mieszacie chłopaki. Przypisujac do UBRRL wartość 51 otrzymacie max 2400bps

Oj, zanim zarzucisz komuś "mieszanie" najpierw dokładnie przeczytaj, co napisałem: https://www.forbot.pl/for...59126.htm#59126
Autor tematu nie ustawiał URSEL, przez co zapisywał do UBRRH najpierw zero, by zaraz później wpisać tam wartość (1<<UCSZ1) | (1<<UCSZ0) czyli 6.


---> Multimetr DT-830B za darmo! <---
Ostatnio zmieniony przez dondu 29-01-2012, 14:48, w całości zmieniany 3 razy  
Postaw piwo autorowi tego posta
 
 
SeerKaza 




Posty: 190
Pomógł: 5 razy
Otrzymał 15 piw(a)
Skąd: Białystok
Programuję w:
C,C++,C#
Wysłany: 29-01-2012, 14:54   

Tak znalazłeś błąd w UBRRH ale wartość UBRRL była nieprawidłowa. Bez bitu U2X to około 1200bps.

Postaw piwo autorowi tego posta
 
 
 
dondu 



Posty: 903
Pomógł: 39 razy
Otrzymał 71 piw(a)
Skąd: Gliwice
Programuję w:
C
Wysłany: 29-01-2012, 14:58   

SeerKaza napisał/a:
Tak znalazłeś błąd w UBRRH ale wartość UBRRL była nieprawidłowa. Bez bitu U2X to około 1200bps.

O tym na samym początku napisał KD93: https://www.forbot.pl/for...59118.htm#59118
KD93 napisał/a:
Próbowałeś ustawić bit UX2?

Autor prosił o tłumaczenia, a nie gotowce, a patrząc na jego słownictwo, ładnie pisany kod i umiejętność czytania datasheetów sądzę, że sobie radzi bez nich.
Więc następnym razem zanim coś napiszesz kol. SeerKaza, czytaj proszę ze zrozumieniem całość tematu.

Bo gdybyś czytał dokładnie to byś doczytał, że:
davidpi napisał/a:
Częstotliwość taktowania zmieniłem na 8MHz.


---> Multimetr DT-830B za darmo! <---
Ostatnio zmieniony przez dondu 29-01-2012, 15:05, w całości zmieniany 1 raz  
Postaw piwo autorowi tego posta
 
 
SeerKaza 




Posty: 190
Pomógł: 5 razy
Otrzymał 15 piw(a)
Skąd: Białystok
Programuję w:
C,C++,C#
Wysłany: 29-01-2012, 15:12   

Fakt masz racje nie zauważyłem że zmienił częstotliwość taktowania. A co do czytania. Kilka osob znajduje jakiś błąd każda inny. A wartość 51 w UBRRL była także w 1MHz. Widać ktoś się lubi kłócić. I atakować za jeden żartobliwy zwrot.

Ostatnio zmieniony przez SeerKaza 29-01-2012, 15:13, w całości zmieniany 1 raz  
Postaw piwo autorowi tego posta
 
 
 
Wyświetl posty z ostatnich:   
Odpowiedz do tematu
Nie możesz pisać nowych tematów
Nie możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Nie możesz załączać plików na tym forum
Możesz ściągać załączniki na tym forum
Wersja do druku

Skocz do:  

Nie rozwiązałeś swojego problemu? Zobacz podobne tematy: Generowanie przebieg... Jaki język programow... "Mikroprocesoro... Kombinowanie z przer...
lub przeszukaj forum po wybranych tagach: atmega, czemu, predkosc, tak, usart, wolno, wysylania


Powered by phpBB modified by Przemo © 2003 phpBB Group
Popularne kursy: Arduinopodstawy elektroniki