Automatické nastavenie prenosovej rýchlosti: Rozdiel medzi revíziami
Zo stránky SensorWiki
(20 medziľahlých úprav od rovnakého používateľa nie je zobrazených.) | |||
Riadok 21: | Riadok 21: | ||
<strong>Link pre Datasheet ATmega328P:</strong> [https://www.mouser.sk/datasheet/2/268/Atmel_7810_Automotive_Microcontrollers_ATmega328P_-3499768.pdf Datasheet ATmega328P] | <strong>Link pre Datasheet ATmega328P:</strong> [https://www.mouser.sk/datasheet/2/268/Atmel_7810_Automotive_Microcontrollers_ATmega328P_-3499768.pdf Datasheet ATmega328P] | ||
<strong>Zapojenie:</strong> | |||
* UART prevodník bude zapojený do Arduina UNO a pomocou zapojeného prevodníka budeme môcť komunikovať s Arduinom. | |||
Riadok 28: | Riadok 31: | ||
=== Algoritmus a program === | === Algoritmus a program === | ||
<strong>Popis funkčnosti programu:</strong> | |||
<strong>1.</strong> Program inicializuje premennú "velkost" a do nej následne zapíše počet prvkov v poli "baud_rychlost". | |||
<strong>2.</strong> inicializuje premenné "baud_index", "najdeny", "znak". | |||
<strong>3.</strong> Následne program vojde do slučky a v slučke "for" bude robiť toľko cyklov, koľko je prvkov v poli "baud_rychlost". V našom prípade bude robiť 12 cyklov. | |||
<strong>4.</strong> V slučke vyberie Baud rýchlosť podľa premennej "i" a inicializuje UART, a potom počká 200ms na ustálenie komunikácie. | |||
<strong>5.</strong> Vypíše jeho očakávaný znak a následne čaka 2 sekundy na vstup znaku. | |||
<strong>6.</strong> Keď príjme znak, tak potom overí, že či znak sa rovná 'a'. Ak do 2 sekúnd nedostane očakávaný znak, tak potom ide naspäť na začiatok slučky a nastaví novú Baud rýchlosť. | |||
<strong>7.</strong> Ak príjme očakávaný znak, tak potom vypíše nájdenú Baud rýchlosť komunikácie, a následne program bude vypisovať prijímané znaky. | |||
<tabs> | <tabs> | ||
<tab name="AVR C-code"><syntaxhighlight lang="c++" style="background: LightYellow;"> | <tab name="AVR C-code"><syntaxhighlight lang="c++" style="background: LightYellow;"> | ||
#define F_CPU 16000000UL | |||
#include <stdio.h> | |||
#include <avr/io.h> | #include <avr/io.h> | ||
#include <util/delay.h> | |||
#include "uart.h" | |||
FILE uart_output = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE); | |||
FILE uart_input = FDEV_SETUP_STREAM(NULL, uart_getc, _FDEV_SETUP_READ); | |||
const unsigned long baud_rychlost[] = { | |||
600, | |||
1200, | |||
2400, | |||
4800, | |||
9600, | |||
14400, | |||
19200, | |||
28800, | |||
38400, | |||
56000, | |||
57600, | |||
115200 | |||
}; | |||
int main(void) | int main(void) | ||
{ | { | ||
int velkost = sizeof(baud_rychlost)/sizeof(baud_rychlost[0]); | |||
int baud_index = 0; | |||
int najdeny = 0; | |||
char znak; | |||
while (1) | |||
{ | |||
if(najdeny == 0){ | |||
for(int i=0; i<velkost; i++){ | |||
baud_index = i; | |||
uart_init(baud_rychlost[i]); | |||
stdout = &uart_output; | |||
stdin = &uart_input; | |||
_delay_ms(200); | |||
opakovat: | |||
znak = uart_getc_timeout(1500); // Caka na vstup znaku 1.5 sekundy | |||
if(znak=='\r'){ | |||
goto opakovat; | |||
} | |||
if(znak=='\n'){ // Ocakavany znak je "Enter" | |||
najdeny = 1; | |||
printf("Komunikacia naviazana \n"); | |||
printf("Prenosova rychlost: Baud = %lu \n",baud_rychlost[baud_index]); | |||
break; | |||
} | |||
} | |||
} | |||
else{ | |||
znak = uart_getc(); | |||
uart_putc(znak); | |||
} | |||
} | |||
} | |||
</syntaxhighlight ></tab> | |||
<tab name="uart.h"><syntaxhighlight lang="c++" style="background: LightYellow;"> | |||
void uart_init( unsigned long baudrate ); | |||
void uart_putc( char c ); | |||
void uart_puts( const char *s ); | |||
char uart_getc( void ); | |||
int uart_getc_timeout(unsigned long timeout); | |||
</syntaxhighlight ></tab> | |||
<tab name="uart.c"><syntaxhighlight lang="c++" style="background: LightYellow;"> | |||
#define F_CPU 16000000UL | |||
#include <avr/io.h> | |||
#include <util/delay.h> | |||
void uart_init(unsigned long baudrate) | |||
{ | |||
uint16_t prescaler; | |||
if (baudrate > 9600) { | |||
UCSR0A |= (1 << U2X0); | |||
_delay_ms(50); | |||
prescaler = (F_CPU / (8UL * baudrate)) - 1; | |||
} else { | |||
UCSR0A &= ~(1 << U2X0); | |||
_delay_ms(50); | |||
prescaler = (F_CPU / (16UL * baudrate)) - 1; | |||
} | |||
UBRR0H = (uint8_t)(prescaler >> 8); | |||
UBRR0L = (uint8_t)prescaler; | |||
UCSR0B = (1 << TXEN0) | (1 << RXEN0); // povoliť TX a RX | |||
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // 8 bitov, 1 stop, no parity | |||
} | |||
void uart_putc(char c) | |||
{ | |||
if (c == '\n') | |||
{ | |||
uart_putc('\r'); | |||
} | |||
loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */ | |||
UDR0 = c; | |||
} | } | ||
void | void uart_puts(const char *s) | ||
{ | |||
while(*s!='\0') | |||
{ | |||
uart_putc(*s++); | |||
} | |||
} | |||
char uart_getc(void) { | |||
loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */ | |||
return UDR0; | |||
} | |||
unsigned | int uart_getc_timeout(unsigned long timeout) { | ||
unsigned long cas = 0; | |||
while(cas < timeout){ | |||
if (UCSR0A & (1 << RXC0)) // ak prišiel znak | |||
{ | |||
return UDR0; | |||
} | |||
_delay_ms(1); | |||
cas++; | |||
} | |||
return -1; // timeout | |||
} | |||
</syntaxhighlight ></tab> | </syntaxhighlight ></tab> | ||
</tabs> | </tabs> | ||
'''Zdrojový kód:''' [[Médiá:ProjektMatusKral.zip|ProjektMatusKral.zip]] | |||
Zdrojový kód: [[Médiá: | |||
=== Overenie === | === Overenie === | ||
'''Program budeme overovať použitím Serial Terminalu:''' | |||
* Arduino pripojíme do počítača pomocou UART prevodníka. | |||
* V Serail Terminale nastavíme Data bits: 8, Parity: none, Stop bits: 1. | |||
* Nastavíme si Baud rate v rozsahu od 600 do 115200. | |||
* Serial Terminal prepojíme s Arduinom. | |||
* Cez Serial Terminal budeme opakovane posielať očakávaný znak "Enter" do Arduina. | |||
* Budeme neustále posielať znak "Enter" do momentu, keď nám Arduino neodpovie, že našiel hodnotu prenosovej rýchlosti. | |||
* Následne môžme posielať ľubovoľné znaky do Arduina a bude nám odpovedať rovnakými znakmi. | |||
[[Súbor: | [[Súbor:arduino_uno_r3.jpeg|400px|thumb|center|Arduino UNO]] | ||
'''Video:''' | '''Video:''' | ||
Riadok 75: | Riadok 214: | ||
[[Category:AVR]] [[Category:MIPS]] | [[Category:AVR]] [[Category:MIPS]] |
Aktuálna revízia z 11:10, 8. máj 2025
Záverečný projekt predmetu MIPS / LS2025 - Matúš Kráľ
Zadanie
Pri sériovej komunikácii musíme nastaviť niekoľko parametrov.: Prenosovú rýchlosť, počet dátových bitov, paritu a počet stop bitov. Vytvorte program, na automatické testovanie nastavenej prenosovej rýchlosti „druhej strany“ komunikačného kanála.

Literatúra:
Analýza a opis riešenia
Použité komponenty:
- Vývojová doska Arduino UNO (ATmega328P-PU, 16 MHz).
- UART prevodník integrovaný cez USB.
Link pre Datasheet ATmega328P: Datasheet ATmega328P
Zapojenie:
- UART prevodník bude zapojený do Arduina UNO a pomocou zapojeného prevodníka budeme môcť komunikovať s Arduinom.

Algoritmus a program
Popis funkčnosti programu:
1. Program inicializuje premennú "velkost" a do nej následne zapíše počet prvkov v poli "baud_rychlost".
2. inicializuje premenné "baud_index", "najdeny", "znak".
3. Následne program vojde do slučky a v slučke "for" bude robiť toľko cyklov, koľko je prvkov v poli "baud_rychlost". V našom prípade bude robiť 12 cyklov.
4. V slučke vyberie Baud rýchlosť podľa premennej "i" a inicializuje UART, a potom počká 200ms na ustálenie komunikácie.
5. Vypíše jeho očakávaný znak a následne čaka 2 sekundy na vstup znaku.
6. Keď príjme znak, tak potom overí, že či znak sa rovná 'a'. Ak do 2 sekúnd nedostane očakávaný znak, tak potom ide naspäť na začiatok slučky a nastaví novú Baud rýchlosť.
7. Ak príjme očakávaný znak, tak potom vypíše nájdenú Baud rýchlosť komunikácie, a následne program bude vypisovať prijímané znaky.
#define F_CPU 16000000UL
#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>
#include "uart.h"
FILE uart_output = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);
FILE uart_input = FDEV_SETUP_STREAM(NULL, uart_getc, _FDEV_SETUP_READ);
const unsigned long baud_rychlost[] = {
600,
1200,
2400,
4800,
9600,
14400,
19200,
28800,
38400,
56000,
57600,
115200
};
int main(void)
{
int velkost = sizeof(baud_rychlost)/sizeof(baud_rychlost[0]);
int baud_index = 0;
int najdeny = 0;
char znak;
while (1)
{
if(najdeny == 0){
for(int i=0; i<velkost; i++){
baud_index = i;
uart_init(baud_rychlost[i]);
stdout = &uart_output;
stdin = &uart_input;
_delay_ms(200);
opakovat:
znak = uart_getc_timeout(1500); // Caka na vstup znaku 1.5 sekundy
if(znak=='\r'){
goto opakovat;
}
if(znak=='\n'){ // Ocakavany znak je "Enter"
najdeny = 1;
printf("Komunikacia naviazana \n");
printf("Prenosova rychlost: Baud = %lu \n",baud_rychlost[baud_index]);
break;
}
}
}
else{
znak = uart_getc();
uart_putc(znak);
}
}
}
void uart_init( unsigned long baudrate );
void uart_putc( char c );
void uart_puts( const char *s );
char uart_getc( void );
int uart_getc_timeout(unsigned long timeout);
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
void uart_init(unsigned long baudrate)
{
uint16_t prescaler;
if (baudrate > 9600) {
UCSR0A |= (1 << U2X0);
_delay_ms(50);
prescaler = (F_CPU / (8UL * baudrate)) - 1;
} else {
UCSR0A &= ~(1 << U2X0);
_delay_ms(50);
prescaler = (F_CPU / (16UL * baudrate)) - 1;
}
UBRR0H = (uint8_t)(prescaler >> 8);
UBRR0L = (uint8_t)prescaler;
UCSR0B = (1 << TXEN0) | (1 << RXEN0); // povoliť TX a RX
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // 8 bitov, 1 stop, no parity
}
void uart_putc(char c)
{
if (c == '\n')
{
uart_putc('\r');
}
loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */
UDR0 = c;
}
void uart_puts(const char *s)
{
while(*s!='\0')
{
uart_putc(*s++);
}
}
char uart_getc(void) {
loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
return UDR0;
}
int uart_getc_timeout(unsigned long timeout) {
unsigned long cas = 0;
while(cas < timeout){
if (UCSR0A & (1 << RXC0)) // ak prišiel znak
{
return UDR0;
}
_delay_ms(1);
cas++;
}
return -1; // timeout
}
Zdrojový kód: ProjektMatusKral.zip
Overenie
Program budeme overovať použitím Serial Terminalu:
- Arduino pripojíme do počítača pomocou UART prevodníka.
- V Serail Terminale nastavíme Data bits: 8, Parity: none, Stop bits: 1.
- Nastavíme si Baud rate v rozsahu od 600 do 115200.
- Serial Terminal prepojíme s Arduinom.
- Cez Serial Terminal budeme opakovane posielať očakávaný znak "Enter" do Arduina.
- Budeme neustále posielať znak "Enter" do momentu, keď nám Arduino neodpovie, že našiel hodnotu prenosovej rýchlosti.
- Následne môžme posielať ľubovoľné znaky do Arduina a bude nám odpovedať rovnakými znakmi.

Video: