This is an old revision of the document!


Table of Contents

RS-232

Vajalikud teadmised: [HW] Kontroller, [AVR] USART, [LIB] USART teek, [LIB] Alfabeetilise LCD teek

Teooria

RS-232 kaabel. Vasakpoolne pistik on “isane”, parempoolne “emane”

RS-232 on füüsilise andmesideliidese standard mida kasutatakse binaarandmete edastamiseks. Standard on kasutusel peamiselt arvutite jadaportides, mida kutsutakse kõnekeeles ka “COM” portideks. Tänapäeval on RS-232 suures osas asendunud USB liidesega, kuid oma lihtsuse tõttu kasutatakse hobirakendustes RS-232 edukalt edasi, eriti veel siis kui on olemas USB - RS-232 muundurid. RS-232 standard määrab ära pistikud, elektrilised parameetrid ja signaalide tähenduse, kuid mitte protokolli.

RS-232 liidest kasutatakse peamiselt koos UART nimelise riistvaralise andmesidemooduliga millel on protokoll standardiseeritud kuid mis jällegi ei määra ära pistikuid jms. Seega RS-232 ja UART täiendavad teineteist. Kuna UART on enamasti üks moodul mikrokontrolleris millel on digitaalsed sisendid väljundid mis ei vasta RS-232 elektrilistele parameetritele, siis omavahel viiakse need kokku spetsiaalsete nivoomuunduritega. Üks tuntumaid RS-232 TTL/CMOS nivoomuundureid on näiteks MAX232.

UART on lahtitõlgituna “universaalne asünkroonne vastuvõtja/saatja” (inglise keeles universal asynchronous receiver/transmitter). USART on peaaegu sama asi kui UART, kuid selle erinevusega, et andmeid edastakse koos taktsignaaliga. UART-i võib nimetada ka jadaliideseks. Jadaliides on andmete ülekandmise mehhanism kus iga bitt edastakse ükshaaval. Näiteks selleks, et edastada 1 bait, edastakse kindla ajaintervalliga 8 bitti. Ehk siis füüsiliselt toimub jadaliidese liinil, mis on 1 mikrokontrolleri viik, kindla ajavahemiku järel selle viigu pingeväärtuse muutus kõrgeks või madalaks. Jadaliidesega on üldjuhul ühendatud 2 seadet, millest üks edastab infot (viigu väärtust muutes) ja teine võtab seda vastu (viigu väärtust registreerides). Edastava viigu lühend on TX, vastuvõtval RX. Info liigub ühel liinil alati ühes suunas. Andmete teistpidi saatmiseks kasutatakse teist liini. Andmed võivad kahel liinil sama-aegselt liikuda, ehk tegu on täisdupleks siiniga.

UART kaader, kus S on start-bitt, 0-7 andmebitid, P paarsuse bitt (olemasolul) ja T stopp-bitt (või 2)

Andmete edastamine toimub UART liideses kaadri (inglise keeles frame) kaupa, milles andmebitte on olenevalt seadistusest 5 kuni 9. Enamlevinud andmehulk on siiski 8 bitti, ehk 1 bait. Peale andmebittide edastakse kaadriga ka lisabitte mille abil toimub andmete saabumise ja lõppemise hetke äratundmine vastuvõtja poolel. Esimest neist nimetatakse start-bitiks mis on alati 0, teist aga stopp-bitiks (või bittideks) mis on alati 1. Enne stopp-bitti võib tulla ka paarsuse bitt mida kasutakse andmete korrektsuse kontrolliks. Paarsuse bitt näitab kas andmebittide hulgas on paaris või paaritu arv ühtesid. See kumba näitu see omab sõltub UART liidese häälestusest. Paaruse bitti tänapäeval enam üldjuhul ei kasutata ja selle saab häälestuses ka ära keelata. Nii nagu saab paarsuse bitti seadistada, saab ka andmebittide ja stopp-bittide arvu.

Peale kaadri struktuuri on veel üks tähtis parameeter - see on boodikiirus (baud rate) millega määratakse edastavate sümbolite arv ühes sekundis. Bood näitab nimelt sümbolite arvu. UART puhul on 1 bood aga 1 bitt ja seepärast kaadri juures bittidest saigi räägitud. Põhimõtteliselt võib andmete edastamiseks kasutada ükskõik millist boodikiirust, kuid on olemas hulk üldkasutavaid boodikiirusi mida tasub kasutada. Näiteks: 9600 bps, 19200 bps, 38400 bps, 57600 bps, 115200 bps.

Lisainformatsioonina võiks teada, et RS-232 standard sisaldab peale andmesignaalide (RX, TX) veel voo-kontrolli viike DTR, DCD, DSR, RI, RTS ja CTS mida kasutatakse seadmete vahelise suhtluse juhtimiseks. Näiteks võib seade nende kaudu teada anda kas ta on valmis andmeid vastu võtma või mitte. Kuna RS-232 liidese originaalne eesmärk oli ühendada arvuteid modemiga, siis mõned signaalid on (pigem olid) kasutusel telefoniliini seisundi näitamiseks.

Praktika

Kodulabori kontrollerimoodulil on RS-232 isa-tüüpi pesa. Selle kaudu saab kontrolleri arvutiga või teise kontrolleriga ühendada. Arvutiga ühendamiseks tuleb kasutada tavalist pööramata kaablid mille üks pistik on ema-tüüpi, teine isa-tüüpi. Teise kontrolleriga ühendamiseks tuleb kasutada kaablit kus RX ja TX ning voo-kontrolli signaalid on risti keeratud ja mõlemad pistikud on ema-tüüpi. Pööratud kaablit nimetatakse ka null-modemi kaabliks. Järgnevalt on toodud UART jadaliidese kasutamise näiteprogramm. Programm saadab käivitades RS-232 liidese kaudu tervituse ja kuvab sõnumeid mis saabuvad. Kasutatud on LCD ja USART teeke.

//
// Kodulabori kontrollerimooduli arvutiga RS-232 kaudu liidestamine.
// Näide kasutab digitaalset sisend-väljund moodulit koos LCD ekraaniga.
// Arvuti terminalis sisestatud tekst kuvatakse LCD-l.
//
#include <homelab/usart.h>
#include <homelab/module/lcd_alpha.h>
 
//
// USART liidese määramine
//
usart port = USART(0);
 
//
// Põhiprogramm
//
int main(void)
{
	char c;
	unsigned char row = 1;
 
	// USART liidese seadistamine
	usart_init_async(port,
		USART_DATABITS_8,
		USART_STOPBITS_ONE,
		USART_PARITY_NONE,
		USART_BAUDRATE_ASYNC(9600));
 
	// LCD ekraani seadistamine
	lcd_alpha_init(LCD_ALPHA_DISP_ON_BLINK);
 
	// Ekraanil tervituse ütlemine
	lcd_alpha_puts("Ootan teadet");
 
	// Kursori teise rea algusesse viimine
	lcd_alpha_gotoxy(0, row);
 
	// Arvutile tere ütlemine
	usart_send_text(port, "Tere, kirjuta midagi!\r\n");
 
	// Lõputu tsükkel
	while (true)
	{
		// Jadaliidesest märgi lugemine
		if (usart_try_read_char(port, &c))
		{		
			// Kas tegu on reavahetuse märgiga?
			if (c == '\r')
			{
				// Rea vahetamine
				row = 1 - row;
 
				// Rea tühjendamine eelmisest teatest
				lcd_alpha_clr_line(row);
			}
			else
			{
				// Märgi otse ekraanile väljastamine
				lcd_alpha_putc(c);
			}
		}
	}
}

Järgnevalt on toodud UART jadaliidese kasutamise näide. Programm võimaldab edastada tekstisõnumeid AVR ja teise AVR-i või arvuti vahel. Kasutatud on viikude, LCD ja USART teeke.

FIXME (pilt kahest ühendatud kontrollerist)

#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>
#include "pin.h"
#include "lcd.h"
#include "usart.h"
 
// Pin configuration
#define BUTTON_CHAR     PORTPIN(C, 0)
#define BUTTON_NEXT     PORTPIN(C, 1)
#define BUTTON_ENTER    PORTPIN(C, 2)
 
// Characters list
#define NUM_CHARS 26
const char chars[NUM_CHARS] = " ABCDEFGHIJKLMOPQRSTUVWXYZ";
 
// General configuration
#define MAX_MESSAGE     16
 
//
// My message variables
//
char my_message[MAX_MESSAGE + 3];	
unsigned char my_char_index = 0;
unsigned char my_char_position = 0;
 
//
// Incoming message variables
char rx_message[MAX_MESSAGE + 3];
unsigned char rx_char_position = 0;
 
//
// Resetting my message
//
void reset_my_message()
{	
	// Fill the message with nulls
	for (my_char_position = 0; my_char_position < MAX_MESSAGE + 3; my_char_position++)
	{
		my_message[my_char_position] = 0;
	}		
 
	// Reset indexes
	my_char_position = 0;
	my_char_index = 0;			
}
 
//
// Displaying my current message
//
void display_my_message()
{	
	lcd_gotoxy(0, 0);
	lcd_puts("                 ");
	lcd_gotoxy(0, 0);
	lcd_puts(my_message);
	lcd_gotoxy(my_char_position, 0);
}
 
//
// Resetting received message
//
void reset_rx_message()
{
	// Fill the message with nulls
	for (rx_char_position = 0; rx_char_position < MAX_MESSAGE + 3; rx_char_position++)
	{
		rx_message[rx_char_position] = 0;
	}
 
	// Reset position
	rx_char_position = 0;
}
 
//
// Displaying received message
//
void display_rx_message()
{	
	lcd_gotoxy(0, 1);
	lcd_puts("                 ");	
	lcd_gotoxy(0, 1);
	lcd_puts(rx_message);	
}
 
//
// Main function
//
int main(void)
{	
	// Button state variables	
	unsigned char button_char_new,  button_char_old  = 1;
	unsigned char button_next_new,  button_next_old  = 1;
	unsigned char button_enter_new, button_enter_old = 1;	
 
	// LCD configuring
	lcd_init(LCD_DISP_ON_BLINK);
	lcd_clrscr();
 
	// UART configuring
	usart0_init_async(USART_DATABITS_8, USART_STOPBITS_1, USART_PARITY_NONE, 9600);
 
	// Buttons configuring
	pin_setup_input(BUTTON_CHAR);
	pin_setup_input(BUTTON_NEXT);
	pin_setup_input(BUTTON_ENTER);
 
	// Reset
	reset_my_message();
	reset_rx_message();	
 
	// Endless cycle
	while (1)
	{
		// Get new button values
		pin_get_value(BUTTON_CHAR,  button_char_new);
		pin_get_value(BUTTON_NEXT,  button_next_new);
		pin_get_value(BUTTON_ENTER, button_enter_new);
 
		// Char selection button pressed ?
		if (!button_char_new && button_char_old)
		{
			// Change char
			my_char_index++;
 
			// Wrap
			if (my_char_index >= NUM_CHARS)
			{
				my_char_index = 0;
			}
 
			// Update message
			my_message[my_char_position] = chars[my_char_index];			
 
			// Display message text
			display_my_message();
 
			// Pause
			//_delay_ms(100);			
		}
 
		// Next char button pressed ?
		if (!button_next_new && button_next_old)
		{
			// Increase current position			
			my_char_position++;
 
			// If message is full, restart
			if (my_char_position >= MAX_MESSAGE)
			{
				reset_my_message();
			}
			else
			{
				// Fill new places with space
				my_char_index = 0;
				my_message[my_char_position] = chars[my_char_index];				
			}
 
			// Display message text
			display_my_message();
 
			// Pause
			//_delay_ms(100);
		}
 
		// Enter button pressed ?
		if (!button_enter_new && button_enter_old)
		{						
			// Send message if it's not empty
			if ((my_char_position > 0) || (my_message[0] != 0))
			{
				// Inser line feed and carriage return before terminator
				my_message[my_char_position + 1] = '\r';
				my_message[my_char_position + 2] = '\n';
				my_message[my_char_position + 3] = 0;
 
				// Send message
				usart0_send_text(my_message);
 
				// Restart
				reset_my_message();
				display_my_message();
			}
		}
 
		// Remember old button values
		button_char_old  = button_char_new;
		button_next_old  = button_next_new;
		button_enter_old = button_enter_new;
 
		// Got data ?
		if (usart0_has_data())
		{
			// Read char
			rx_message[rx_char_position++] = usart0_read_char();
 
			// Show message if it's too long or the delimiter has arrived
			if ((rx_char_position >= MAX_MESSAGE + 3) ||
				 ((rx_message[rx_char_position - 2] == '\r') && (rx_message[rx_char_position - 1] == '\n')))
			{
				// Replace line chars with null terminator
				rx_message[rx_char_position - 2] = 0;
				rx_message[rx_char_position - 1] = 0;
 
				// Display message
				display_rx_message();
				reset_rx_message();
			}
		}
	}
}
et/examples/communication/rs232.1263799469.txt.gz · Last modified: 2020/07/20 09:00 (external edit)
CC Attribution-Share Alike 4.0 International
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0