Operácie

Sériové komunikačné rozhranie: Rozdiel medzi revíziami

Zo stránky SensorWiki

Balogh (diskusia | príspevky)
Bez shrnutí editace
Balogh (diskusia | príspevky)
Riadok 31: Riadok 31:
=== 1. Základný princíp prenosu cez USART ===
=== 1. Základný princíp prenosu cez USART ===


Ukážkový program v ktorom je všetko pohromade: inicializácia, príjem aj vysielanie.
Ukážkový program v ktorom je všetko pohromade: inicializácia, príjem aj vysielanie. Program čaká na prijatý znak a vráti znak s ASCII kódom o jedna väčším. Mohol by vrátiť aj rovnaký, ale to by sme nevedeli rozlíšiť od funkcie "local echo" v niektorých termináloch.


<source lang="c">
<source lang="c">
Riadok 37: Riadok 37:


#define BAUDRATE      9600
#define BAUDRATE      9600
#define BAUD_PRESCALE  (((F_CPU / (BAUDRATE * 16UL))) - 1)
#define BAUD_PRESCALE  (((F_CPU / (BAUDRATE * 16UL))) - 1) // vzorček z datasheetu





Verzia z 13:04, 3. apríl 2021


Sériové komunikačné rozhranie (UART)

Úlohy

  1. Nakonfigurujte USART na asynchrónnu prevádzku s parametrami N,9600,8,1
  2. Vyskúšajte demonštračný program, na strane PC použite terminál
  3. Vytvorte si knižnice pre prácu so sériovou linkou, preštudujte využitie knižnice <stdio.h> a demonštrujte.
  4. Oboznámte sa s programom StampPlot a zobrazte časový priebeh.


Literatúra:

2021



1. Základný princíp prenosu cez USART

Ukážkový program v ktorom je všetko pohromade: inicializácia, príjem aj vysielanie. Program čaká na prijatý znak a vráti znak s ASCII kódom o jedna väčším. Mohol by vrátiť aj rovnaký, ale to by sme nevedeli rozlíšiť od funkcie "local echo" v niektorých termináloch.

#include <avr/io.h>

#define BAUDRATE       9600
#define BAUD_PRESCALE  (((F_CPU / (BAUDRATE * 16UL))) - 1)  // vzorček z datasheetu


int main (void)
{
   char ReceivedChar;

   /* Initialize UART */
                                                         
   UBRR0 = (unsigned char)BAUD_PRESCALE;                 // Set baud rate: Load the UBRR register

   UCSR0B = (1 << RXEN0) | (1 << TXEN0);                 // Enable receiver and transmitter

   UCSR0C = (1<<USBS0)|(3<<UCSZ00);                      // Set format: 8data, 2stop bit 

   for (;;)                                              // Loop forever
   {
      while ((UCSR0A & (1 << RXC0)) == 0)                // Wait for data to be received 
	  {
	    // Do nothing until data have been recieved and is ready to be read from UDR
	  }; 
      ReceivedChar = UDR0;                               // Fetch the recieved byte 

   
      while ( !( UCSR0A & (1<<UDRE0)) )                  // Wait for empty transmit buffer 
   	  {
	   // Do nothing until UDR is ready for more data to be written to it
	  };
      UDR0 = ReceivedChar+1;                             // Echo back the modified received byte 
   }


}


Ak vám program fungoval, nahrajte ho do procesora a otestujte komunikáciu s terminálom. Na prácu so sériovou linkou na vašom PC odporúčame program Terminal by Bray, ale môžete to skúsiť aj s Hyperterminálom.

2. Jednoduchá knižnica

Nebudeme sa zaoberať detailmi implementácie sériového komunikačného rozhrania procesorov AVR, pre naše účely postačí jednoduchá knižnica, ktorá obsahuje základné funkcie na prenos jedného znaku. Parametre prenosu pre túto knižnicu sú 9600,n,8,1.

serial.h

/* ************************************************************************* */
/* FileName          : serial.h                                              */
/* ************************************************************************* */
         void inituart( void );
         void sendchar( unsigned char );
unsigned char recchar( void );

serial.c

/* ************************************************************************* */
/*                                                                           */
/* Description       : UART communication routines                           */
/*                     Based on AppNote AVR109 - Self-programming            */
/*                                                                           */
/* FileName          : serial.c                                              */
/*                                                                           */
/* ************************************************************************* */

#include <avr\io.h>

// Following calculation assumes that F_CPU is assigned in 'Project/Options'
#define BAUDRATE       9600      
#define BAUD_PRESCALE  (((F_CPU / (BAUDRATE * 16UL))) - 1)


/* definitions for UART control */      
                                        // Valid for ATmega328
#define	BAUD_RATE_REG	        UBRR0   // 
#define	UART_STATUS_REG		UCSR0A  // OK, checked (but also control reg.)
#define	UART_CONTROL_REG_B	UCSR0B  // OK, checked
#define UART_CONTROL_REG_C      UCSR0C  // Added for mode setting
#define	ENABLE_TRANSMITTER_BIT	TXEN0   // OK, checked
#define	ENABLE_RECEIVER_BIT	RXEN0   // OK, checked
#define DATA_REGISTER_EMPTY_BIT UDRE0   // Added, for possible speed-up
#define	TRANSMIT_COMPLETE_BIT	TXC0    // OK, checked
#define	RECEIVE_COMPLETE_BIT	RXC0    // OK, checked
#define	UART_DATA_REG		UDR0    // OK, checked


void inituart(void)
{
 BAUD_RATE_REG = (unsigned char)BAUD_PRESCALE;    // Set baud rate: Load the UBRR register

 UART_CONTROL_REG_B = (1 << ENABLE_RECEIVER_BIT)|
                    (1 << ENABLE_TRANSMITTER_BIT); // Enable receive + transmit 

 UART_CONTROL_REG_C = (3<<UCSZ00);                 // Added: Async. UART, None 
                                                   // Parity, 8-data, 1 stopbit
                                                   
}


void sendchar(unsigned char c)
{
  UART_DATA_REG = c;                                   // prepare transmission
  while (!(UART_STATUS_REG & (1 << TRANSMIT_COMPLETE_BIT)));// wait until byte sendt
  UART_STATUS_REG |= (1 << TRANSMIT_COMPLETE_BIT);          // delete TXCflag
}


unsigned char recchar(void)
{
  while( !(UART_STATUS_REG & (1 << RECEIVE_COMPLETE_BIT)) );  // wait for data
  return UART_DATA_REG;
}

Testovací program:

main.c

#include <avr\io.h>
#include "serial.h"              // Nasa kniznica... 

int main(void) 
{
 char c;

  DDRD = 0b00000010;
 PORTD = 0b00000011;    // Set TxD pin as an output, RxD input
 
 inituart();

 sendchar('O');
 sendchar('K');
 sendchar('\n');

 for (c=32;c<=127;c++) 
   sendchar(c);

 for (;;) {
     /* Do nothing */
          }
}

printf() na jednočipe?

Ak si napíšete vlastnú funkciu na zobrazenie jedného znaku na displej, alebo pre vyslanie jedného znaku po sériovej linke, potom môžete používať naozaj aj funkciu printf so všetkými jej vymoženosťami. Využívame pre tom knižnicu stdio.h, ktorá sa používa takto:

...
#include <stdio.h>

FILE mystdout = FDEV_SETUP_STREAM(sendchar, NULL, _FDEV_SETUP_WRITE);
                              // 'sendchar' je nova funkcia pre jeden znak

int main(void)
{ 
 inituart();	               // Inicializacia seriovej linky
 stdout = &mystdout;           // Odteraz funguje printf();

 printf("Hello, world!");
 return 0;
}

Takto potom môžete používať naozaj aj funkciu printf() so všetkými jej vymoženosťami... Úplne rovnako sa dá implementovať printf() aj na LCD displej, len ho treba na začiatku zinicializovať a namiesto funkcie sendchar napísať niečo ako LCDsendchar().

Kompletný vstup/výstup potom vyzerá takto:

FILE uart_output = FDEV_SETUP_STREAM(sendchar, NULL, _FDEV_SETUP_WRITE);
FILE uart_input = FDEV_SETUP_STREAM(NULL, recchar, _FDEV_SETUP_READ);

int main(void) {

    inituart();
    stdout = &uart_output;
    stdin = &uart_input;
                
    char input;

    while(1) {
        puts("Hello world!");
        input = getchar();
        printf("You wrote %c\n", input);
    }
        
    return 0;
}

Pozn.: pre MiniMEXLE - Prevod TTL úrovní na RS-232 je realizovaný takto - schéma zapojenia, ktorá vychádza z tohoto návodu.


Terminál

Terminál je jednoduché elektronické zariadenie, ktoré slúži na komunikáciu s počítačom. Vytvára tak vzdialené užívateľské rozhranie (angl. Human-Machine Interface, HMI), cez ktoré je možné počítač ovládať, spúšťať programy, zadávať vstupné dáta (klávesnicou) a zobrazovať výstupy (na monitore). Zjednodušene si ho môžeme predstaviť, ako klávesnicu a monitor osobného počítača, pričom samotný počítač na ktorom pracujeme sa nachádza niekde inde - napr. aj v inej budove. Ku jednému takémuto počítaču je obvykle pripojených viacero terminálov (aj niekoľko desiatok). Pôvodné terminály boli znakové a pripájali sa k počítaču pomocou sériovej linky, telefónneho modemu, neskôr aj počítačovej siete. Neskôr vznikli aj grafické terminály, označované aj ako tenký klient (thin client).

Jedným z prvých (1978) sériovo vyrábaných terminálov bol typ VT100 (Video Terminal) spoločnosti Digital Equipment Corporation (DEC). Ako jeden z prvých podporoval tzv. ANSI sekvencie pre riadenie pohybu kurzora na obrazovke. V súčasnosti sa hardvérové terminály už prakticky nepoužívajú, jednoduchšie je využívať softvérové emulátory, ktorých je k dispozícíí niekoľko desiatok (napr. PuTTY, xterm, konsole, Br@y Terminal a mnoho ďalších).

Na príjem a vysielanie znakov na strane PC máme k dispozícii niekoľko takýchto emulátorov (pozn. pre školské počítače: len niektoré z nich umožňujú spustenie pod Windows bez administrátorského oprávnenia - napr. Br@y Terminal). Jedným z najdôležitejších rozlišovacích znakov pre terminálové programy je možnosť rozdeliť okno na vysielacie a prijímacie alebo spoločné okno pre oba kanály.


Serial Terminal by Bray

Na testovanie a prvé pokusy so sériovým rozhraním sa vám určite zíde aj nejaký terminálový program, masochisti môžu použiť aj Hyperterminál z Windows. Terminál je jednoduchý program, v ktorom sa zobrazujú všetky prijaté znaky a naopak, je možné nejaké iné znaky odvysielať. Dajú sa samozrejme aj nastaviť základné komunikačné parametre.


Ukážka práce s Terminalom vrátane správneho nastavenia parametrov


Núdzové riešenie: cmd.exe

V núdzi vám možno pomôže aj obyčajný príkazový riadok. Takto ho prepneme do režimu, v ktorom bude prijímať znaky zo sériovej linky:

mode com5: baud=9600 parity=None data=8 stop=1

copy com5 con:

Režim sa ukončí Ctrl+Z alebo Ctrl+C.

Poslať pár znakov z príkazového riadku sa dá takto:

echo X > com5

Pre čísla portov nad 9 treba použiť \\.\COM22

Žiaľ, nepoznám spôsob, ako uskutočniť prenos oboma smermi.


3. Vizualizácia

Vizualizáciu dát môžeme robiť rozlične. Jeden z možných spôsobov je vypisovať po sériovej linke v pravidelných intervaloch holé data a tie potom uložiť ako maticu do Matlabu a tam nakresliť graf, priebeh, čo treba...

Iná možnosť je použiť napr. program StampPlot, ktorý kreslí prichádzajúce data priamo ako graf, s výnimkou reťazcov, ktoré začínajú znakom '!', tie považuje za konfiguračné príkazy.


Serial Plotter

Serial Plotter je trocha sofistikovanejší program ako Terminal, jeho úlohou je zakresliť graficky všetky prijaté informácie. Najjednoduchšie je posielať mu čísla, pričom ich môže byť aj viac, oddelených čiarkami. Každá jedna n-tica hodnôt musí končíť znakom pre nový riadok. V knižnici Serial použite bloky Serial Write Number pre čísla, Serial Write String pre čiarky a Serial Write Line pre ukončenie riadka. Neposielajte hodnoty príliš často, aby sa nepreplnil vstupný buffer.




Serial Studio

Serial Console je ešte sofistikovanejší program ako Serial Plotter, dokážeme s ním vytvárať rozličné panely s údajmi zoskupenými do rozličných skupín a s možnosťou grafického záznamu, použitia rozličných virtuálnych prístrojov a jednoduchou konfiguráciou.



Download

Terminal 1.9b

StampPlot Lite 1.7

Serial Plot 0.1.11

Serial Studio 1.0.12