• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Komunikacja między mikrokontrolerami.

VPS Starter Arubacloud
0 głosów
567 wizyt
pytanie zadane 23 marca 2016 w C i C++ przez Mavimix Dyskutant (8,390 p.)
edycja 23 marca 2016 przez Mavimix

Mam dwa mikrokontrolery Atmega8 i podłączony wyświetlacz LCD do jednego z nich. Chciałbym wysłać zdanie "Hello World!" z jednego i wyświetlić na drugim. To są moje kody, które niestety nie działają - na lcd'ku wyświetlają się "krzaki".

Transmiter:

#include <avr/io.h>
//header to enable data flow control over pins
#define F_CPU 8000000UL
//telling controller crystal frequency attached
#include <util/delay.h>
//header to enable delay function in program

int main(void)
{
                DDRD |= 1 << PIND1;//pin1 of portD as OUTPUT
                DDRD &= ~(1 << PIND0);//pin0 of portD as INPUT
                PORTD |= 1 << PIND0;

                int UBBRValue = 51;//AS described before setting baud rate

                //Put the upper part of the baud number here (bits 8 to 11)
                UBRRH = (unsigned char) (UBBRValue >> 8);

                //Put the remaining part of the baud number here
                UBRRL = (unsigned char) UBBRValue;

                //Enable the receiver and transmitter
                UCSRB = (1 << RXEN) | (1 << TXEN);

                //Set 2 stop bits and data bit length is 8-bit
                UCSRC = (1 << USBS) | (3 << UCSZ0);

                while (1)
                {

					   while (! (UCSRA & (1 << UDRE)) );
					   {
						   UDR = "Hello World!";
						}
                }
}

Receiver:

#include <avr/io.h>
#define F_CPU 8000000UL
#include <util/delay.h>

int main(void)
{
	LCD_Inicjuj();

                DDRD |= (1 << PIND0);//PORTD pin0 as INPUT
                DDRC=0xFF;//PORTC as OUTPUT

                int UBRR_Value = 51; // 2400 baud rate
                UBRRH = (unsigned char) (UBRR_Value >> 8);
                UBRRL = (unsigned char) UBRR_Value;
                UCSRB = (1 << RXEN) | (1 << TXEN);
                UCSRC = (1 << USBS) | (3 << UCSZ0);

                unsigned char receiveData;

                while (1)
                {
                                while (! (UCSRA & (1 << RXC)) );

                                receiveData = UDR;


                                LCD_Wyswietl(receiveData);
                                _delay_ms(100);

                                LCD_Czysc();
                }
}

 

2 odpowiedzi

+2 głosów
odpowiedź 23 marca 2016 przez Krawiec91 Pasjonat (19,600 p.)
wybrane 24 marca 2016 przez Mavimix
 
Najlepsza

Rejestr UDR jest rejestrem 8 - bitowym, więc możesz do niego przypisać zmienną o rozmiarze 8 bitów, np. typ char.  String "Hello World" musisz rozbić na pojedyńcze znaki i je kolejno wysyłać. Tak samo przy odbiorze, odbierasz kolejne znaki 'H' 'e' 'l' .....

komentarz 23 marca 2016 przez Mavimix Dyskutant (8,390 p.)

Niestety, przy próbie wysłania jednego znaku na wyświetlaczu znowu pojawiają się krzaki.

Poprawiony kod transmiter'a:

#include <avr/io.h>
//header to enable data flow control over pins
#define F_CPU 8000000UL
//telling controller crystal frequency attached
#include <util/delay.h>
//header to enable delay function in program

int main(void)
{
                DDRD |= 1 << PIND1;//pin1 of portD as OUTPUT
                DDRD &= ~(1 << PIND0);//pin0 of portD as INPUT
                PORTD |= 1 << PIND0;

                int UBBRValue = 51;//AS described before setting baud rate

                //Put the upper part of the baud number here (bits 8 to 11)
                UBRRH = (unsigned char) (UBBRValue >> 8);

                //Put the remaining part of the baud number here
                UBRRL = (unsigned char) UBBRValue;

                //Enable the receiver and transmitter
                UCSRB = (1 << RXEN) | (1 << TXEN);

                //Set 2 stop bits and data bit length is 8-bit
                UCSRC = (1 << USBS) | (3 << UCSZ0);

                while (1)
                {

                	char znak = 'H';

					   while (! (UCSRA & (1 << UDRE)) );
					   {
						   UDR = znak;
						}
                }
}
komentarz 23 marca 2016 przez Krawiec91 Pasjonat (19,600 p.)
Od strony sprzętowej nadajnik i odbiornik są zgodne (częstotliwość taktowania procesora)?  Żeby 8 - bitową ramkę danych skonfigurować, zerujesz bit UCSZ2 i ustawiasz bity UCSZ1 i UCSZ0.  A tak poza tym, nie widzę ustawionego bitu URSEL, żeby wpisywać dane do UCSRC.
http://mikrokontrolery.blogspot.com/2011/04/Pulapki-AVR-Rejestry-pod-tym-samym-adresem.html
komentarz 23 marca 2016 przez Mavimix Dyskutant (8,390 p.)

Oba uC pracują na 8MHz. Poprawiłem kod na taki:

/////----------TRANSMITER----------/////

#include <avr/io.h>
//header to enable data flow control over pins
#define F_CPU 8000000UL
//telling controller crystal frequency attached
#include <util/delay.h>
//header to enable delay function in program

int main(void)
{
                DDRD |= 1 << PIND1;//pin1 of portD as OUTPUT
                DDRD &= ~(1 << PIND0);//pin0 of portD as INPUT
                PORTD |= 1 << PIND0;

                int UBBRValue = 2400;//AS described before setting baud rate

                //Put the upper part of the baud number here (bits 8 to 11)
                UBRRH = (unsigned char) (UBBRValue >> 8);

                //Put the remaining part of the baud number here
                UBRRL = (unsigned char) UBBRValue;

                //Enable the receiver and transmitter
                UCSRB = (1 << RXEN) | (1 << TXEN);

                //Set 2 stop bits and data bit length is 8-bit
                UCSRC = (1<<URSEL) | (1 << USBS) | (3 << UCSZ0);

                while (1)
                {

					   while (! (UCSRA & (1 << UDRE)) );
					   {
						   UDR = 'H';
						}
                }
}


/////----------RECEIVER----------/////

int main(void)
{
	LCD_Inicjuj();

                DDRD |= (1 << PIND0);//PORTD pin0 as INPUT
                DDRC=0xFF;//PORTC as OUTPUT

                int UBRR_Value = 2400;// 2400 baud rate
                UBRRH = (unsigned char) (UBRR_Value >> 8);
                UBRRL = (unsigned char) UBRR_Value;
                UCSRB = (1 << RXEN) | (1 << TXEN);
                UCSRC = (1<<URSEL) | (1 << USBS) | (3 << UCSZ0);

                unsigned char receiveData;

                while (1)
                {
                                while (! (UCSRA & (1 << RXC)) );

                                receiveData = UDR;


                                LCD_Wyswietl(receiveData);
                                _delay_ms(100);

                                LCD_Czysc();
                }
}

Niestety, cały czas nie działa

 

komentarz 23 marca 2016 przez Krawiec91 Pasjonat (19,600 p.)

Spróbuj z tym:
 

UCSRC=(1<<URSEL) | (1<<USBS) | (1<UCSZ1)  | (1<<UCSZ0);

@edit
UCSRC=(1<<URSEL) | (1<<USBS) | (1<<UCSZ1)  | (1<<UCSZ0);

 

komentarz 23 marca 2016 przez Mavimix Dyskutant (8,390 p.)

Zamiast UCSRC = (1<<URSEL) | (1 << USBS) | (3 << UCSZ0); dałem to co Napisałeś, w obydwu uC. Teraz na lcd się nic nie wyświetla, jak by nadajnik był martwy.

komentarz 23 marca 2016 przez Krawiec91 Pasjonat (19,600 p.)
Robiłeś coś na mikrokontrolerze, co wiązałoby się z zależnością od częstotliwości taktowania procesora (odmierzanie czasu za pomocą timerów czy transmisja szeregowa)? Dokładniej chodzi mi odpowiednie ustawienie fusebitów, czy są ustawione na zewnętrzny kwarc, bo domyślnie atmegi ustawione są na wewnętrzny oscylator RC 1 MHz.
komentarz 23 marca 2016 przez Mavimix Dyskutant (8,390 p.)
W mkAVRCalc. ustawiłem wewnętrzny oscylator 8 MHz. Zewnętrznego kwarcu nie mam.
komentarz 23 marca 2016 przez Krawiec91 Pasjonat (19,600 p.)

Zobacz, czy to pójdzie.
Transmitt:
 

#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 8000000UL

void usart_init(void)
{
  UCSRB=(1<<TXEN);
  UCSRC=(1<<UCSZ1) | (1<<UCSZ0) | (1<<URSEL);
  UBRRL=207;      //2400 bits/s
}

void usart_send(unsigned char ch)
{
   while (! (UCSRA & (1<<UDRE)));
   UDR=ch;
}

int main(void)
{
    usart_init();
    while(1)
       usart_send('A');
    return 0;
}

Receiver:
 

#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 8000000UL

void usart_init(void)
{
   UCSRB=(1<<RXEN);
   UCSRC=(1<<UCSZ1)|(1<<UCSZ0)|(1<<URSEL);
   UBRRL=207;   // 2400 bits/s
}

int main(void)
{
   LCD_Inicjuj();
   unsigned char znak; 
   while(1)
   {
      while (! (UCSRA & (1<<RXC)));
         znak=UDR;
      LCD_Wyswietl(znak);
      _delay_ms(100);

       LCD_Czysc();
  }
  return 0;
}
       

Inne ustawienia ramki, ale jak pójdzie, to ramkę danych sobie odpowiednio skonfigurujesz. Funkcje z LCD sprawdzone w jakiś sposób, że są w porządku?

komentarz 23 marca 2016 przez Mavimix Dyskutant (8,390 p.)

W funkcji main receiver'a dodałem usart_init(); Jeśli chodzi o LCD, wszystkie funkcje są poprawne. Program niestety nie działa. Co ciekawe działa program z tej strony. Problem pojawia się przy próbie wysłania znaku.

komentarz 23 marca 2016 przez Krawiec91 Pasjonat (19,600 p.)
Jaki problem?
komentarz 23 marca 2016 przez Mavimix Dyskutant (8,390 p.)
Gdy zrobię UDR='A', a przy odbiorze LCD_Wyswietl(UDR), to na LCD wyświetlają się "krzaki" (regularnie te same), albo nic.
komentarz 23 marca 2016 przez Krawiec91 Pasjonat (19,600 p.)
O kurde, o tej porze to głupi jestem. Wrócę z roboty jutro, to sobie przeanalizuje na spokojnie kody z całego posta. Spróbuj może zrobić, ten układ z linka, który podesłałeś (ten z diodą, już nawet bez przycisku), czy to zatrybi.
komentarz 24 marca 2016 przez Mavimix Dyskutant (8,390 p.)
Tak robiłem - wysyłałem jeden bajt i funkcją if sprawdzałem czy ten bajt przyszedł czy nie - jak tak to wyświetlało "Tak", jak nie to "Nie". To działało. Jak bajt zamieniłem np. na "A" to całość przestawała działać.
komentarz 24 marca 2016 przez Nondzu Obywatel (1,910 p.)
odpiszę na powyższe

Znak "A" to nie to samo co 'A'

znak "A" składa się z dwóch bajtów

spróbuj wpisać 'A' i napisz co się dzieje ;)

Pozdrawiam
komentarz 24 marca 2016 przez Mavimix Dyskutant (8,390 p.)

Poprawiłem kod i napisałem dodatkową funkcję sprawdzającą czy odebrano znak. Na potrzeby util/delay zmieniłem też taktowanie uC na 1MHz:

/////----------Transmiter----------/////

#include <avr/io.h>
//header to enable data flow control over pins
#define F_CPU 1000000UL
//telling controller crystal frequency attached
#include <util/delay.h>
//header to enable delay function in program

int main(void)
{
                DDRD |= 1 << PIND1;//pin1 of portD as OUTPUT
                DDRD &= ~(1 << PIND0);//pin0 of portD as INPUT
                PORTD |= 1 << PIND0;

                int UBBRValue = 12;//AS described before setting baud rate

                //Put the upper part of the baud number here (bits 8 to 11)
                UBRRH = (unsigned char) (UBBRValue >> 8);

                //Put the remaining part of the baud number here
                UBRRL = (unsigned char) UBBRValue;

                //Enable the receiver and transmitter
                UCSRB = (1 << RXEN) | (1 << TXEN);

                //Set 2 stop bits and data bit length is 8-bit
                UCSRC=(1<<UCSZ1) | (1<<UCSZ0) | (1<<URSEL);

                while (1)
                {

                   while (! (UCSRA & (1 << UDRE)) );
                   {
                	   UDR = 'A';//once transmitter is ready sent eight bit data
                   }

                }
}

/////----------Receiver----------/////

#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>
int main(void)
{
	LCD_Inicjuj();

                DDRD |= (1 << PIND0);//PORTD pin0 as INPUT
                DDRB |= (1<<PB1);

                int UBRR_Value = 12; // 2400 baud rate
                UBRRH = (unsigned char) (UBRR_Value >> 8);
                UBRRL = (unsigned char) UBRR_Value;
                UCSRB = (1 << RXEN) | (1 << TXEN);

                UCSRC=(1<<UCSZ1) | (1<<UCSZ0) | (1<<URSEL);

                unsigned char receiveData;
                while (1)
                {
                                while (! (UCSRA & (1 << RXC)) );

                                receiveData = UDR;

                                if(receiveData == 'A')
                                {
                                	PORTB ^= (1<<PB1);
                                }

                                LCD_Wyswietl(receiveData);

                                _delay_ms(500);

                                LCD_Czysc();
                }
}

Co ciekawe dioda świeci (miga). Zauważyłem, że jak w funkcji LCD_Wyswietl string dam w 'A' to nic nie wyświetla, a jak w "A" to wyświetla. Da się to jakoś przekonwertować?

komentarz 24 marca 2016 przez Mavimix Dyskutant (8,390 p.)

Pomógłbyś mi jeszcze z tym?

0 głosów
odpowiedź 24 marca 2016 przez Nondzu Obywatel (1,910 p.)
Witam

A jak taktujesz te atmegi ? W kodzie masz F_CPU 8MHz, a czy zmieniłeś fuse bity w nich na 8 MHz ? Do wyliczania wartości do UBRR_Value  służy odpowiednie makro. Puki co nie mam czasu aby sprawdzić czy zapisana wartość jest poprawna dla prędkości 2400, ale jeśli nie zmieniłeś taktowania Atmeg na 8 MHz to będą krzaki.

 

Pozdrawiam
komentarz 24 marca 2016 przez Mavimix Dyskutant (8,390 p.)

Oba procesory chodzą na 8 MHz - wartość UBBR mam z tej strony

Podobne pytania

0 głosów
1 odpowiedź 221 wizyt
pytanie zadane 24 marca 2016 w C i C++ przez Mavimix Dyskutant (8,390 p.)
+1 głos
1 odpowiedź 428 wizyt
pytanie zadane 13 marca 2016 w C i C++ przez Mavimix Dyskutant (8,390 p.)
0 głosów
1 odpowiedź 489 wizyt
pytanie zadane 18 stycznia 2016 w C i C++ przez qwertz Użytkownik (850 p.)

92,453 zapytań

141,262 odpowiedzi

319,088 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...