Rev 409 | Blame | Compare with Previous | Last modification | View Log | Download
// 1.6.2007//----------------------------------------------------------------------------------// Prevodnik RS232 <--> RS485// pri startbitu na RS232 zapne okamzite vysilac pokud nejsou detekovana data z RS485.//----------------------------------------------------------------------------------//Program je urcen k rizeni toku dat v prevodniku RS232 na RS485. S cilem eliminovat jakekoliv prvky nastavovene uzivatelem//bez nutnosti pouziti hardwaroveho rizeni toku. Program tedy dokaze detekovat prenosovou rychlost, paritni bit a stopbit.//////Algoritmus:// Princip je zalozen na mereni nejkratsiho casoveho useku v osmi vzorcich, delka vzorku// se odviji od velikosti prave nejmensiho zmereneho vzorku.// Vzorek se meri pomoci 8mi bitoveho casovace a interruptu od zmeny vstupu. casovac je osetren// proti pretekani (pocet preteceni se uklada, do promenne s ktere se zpetne vypocita 16bitove cislo,// casovac se tedy virtualne chova jako 16ti bitovy.)// Mereni delky bitu//// Aktualni implementace teto metody se chova tak, ze pokud je vyslan bajt ktery po startbitu obsahuje N// stejnych bitu, tak je tato sekvence detekovana jako jeden bit to zpusobi ze detekovana rychlost je N krat// mensi, nez skutecna. Dusledkem je, ze pokud se jeste pred stopbitem neobjevi samostatny bit s jinou hodnotou,// nez predchozi sekvence. Tak bude vysílání povoleno po dubu osminásobku zmìøené délky "bitu" plus dalí dva bity jako stopbity.//////Vlastnosti:// Tento program je shopen detekovat pararitní bit, ale neni shopen detekovat poèet stopbitù.// To znamená e kdy bude parita logická jedna, tak bude rozpoznána jako stop bit.// Tato vlastnost ale pøíli nevadí, protoe chování algoritmu lze upravit tak, e bude predpokládat dva nebo tøi stopbity.// V takovém pøípadì se packet pøenese korektnì i kdy parita bude jedna, i nula.//// Tento zpusob detekce neni imuni proti nahodnym chybovim spickam vzniklych v dusledku ruseni.// Proto je nutene napajeni kvalitne stbilizovat, pouzivat blokovaci kondenzatory a// zabezpecit, aby nedochazelo ke zvedani zeme.////////////////////////////////////////////////////////////////////////////////////////////Autor: Jakub Kakona (kaklik@mlab.cz)////////////////////////////////////////////////////////////////////////////////////////////TODO:// Optimalizovat kod, (hlavne najit casove vyhodnejsi umisteni pro nastavovani defaultnich hodnot promennych)// Bylo bydobre zavest uspavani pred prijetim bajtu.// Vykouset program na ATtiny13// Pri rychlostech mensich nez 9600kbps dochazi k pretekani promennych a algoritmus se nechova korektne.// Neni vyzkousen break, byly testovany pouze ASCII znaky vysilane pres terminal z klavesnice.// Aktivovat WatchDog timer.// Neni vyzkouseno na vyssím taktu CPU jak 3,7MHz////////////////////////////////////////////////////////////////////////////////////////#include <avr/io.h>#include <avr/interrupt.h>#include <stdlib.h>#include <ctype.h>#include <avr/eeprom.h>#include <avr/pgmspace.h>#define POVOLOVAK_LOW PORTB &= ~(1<<PB3) // nastaveni nuly na vystup, krery zapina povoleni vysilani RS485#define POVOLOVAK_HIGH PORTB |= (1<<PB3) // nastaveni jednicky na tentyz vystup#define DATA (PIND & (1<<PD3)) // nastaveni vstupu, na kterem se budou detekovat data, musi byt stejny jako vstup pouziteho interruptuvolatile unsigned int preteceni; // promenna na ukladani poctu preteceni casovacevolatile unsigned int bit; // promena pro pocitani bitu v bajtuvolatile unsigned long int bitdelay; // obsahuje aktualni zmereny cas delky bituvolatile unsigned long int cas; // urcuje nejkratsi nalezeny cas delky bituISR(TIMER0_OVF_vect) // interrupt od preteceni casovace{preteceni++; // kdyz pretece, poznamenej to.}ISR(INT1_vect) // interrupt od zmeny vstupu na datech{if ((bitdelay=(TCNT0+preteceni*0x0100)) < cas) cas = bitdelay; // provnani jestli zrovna zmereny cas je kratsi nez nejmensi znamy casTCNT0 = 0; // zacni znova merit cas zacatku stopbitupreteceni=0; // vynuluj vsechny casove promennebit++; // posun pocitadlo bitu o jednicku}// ------------------------------------------------------------------// Main// ------------------------------------------------------------------int main(void){int stopbit;int ctvrtbit;/*typedef struct { // struktura pro celoèíselné dìleníint quot;int rem;} div_t;*/DDRB |= (1<<DDB3); // povoleni vystupu na povolovakTIMSK |= (1 << TOIE0); // Enable timer overflow interruptMCUCR |= (1 << ISC10); // nastaveni preruseni od zmeny vstupu pro interrupt INT0GIMSK |= (1 << INT1); // povoleni interruptu INT0TCCR0B |= (1 << CS00); // Set up timersei(); // enable interruptswhile(1){if(!DATA) // kdyz je 0 na datech{POVOLOVAK_HIGH; // zapni vysilaniTCNT0=0;preteceni=0;bit=0; // vynuluj vsechny promenne pro mereni casu a pocitani bitucas = 0xFFFF; // nastav cas delky bitu na nejvetsi moznywhile (bit <= 8) // odpocitej dobu 8mi bitu{if ((TCNT0+preteceni*0x0100) >= (cas + (ctvrtbit = cas >> 2))) // zkontroluj jestli necekame na dalsi bit dele nez je nekratsi znema delka bitu// v kontrole je rezerva delky ctvrt bitu{bit++; // pokud jsme cekali dele, tak bit uz ubehl, to znamena, ze muzeme pocitadlo bitu posunout o jednicku// div(ctvrtbit,0x0100); // funkce pro implementaci celociselneho deleni zustava ale nepouzita kvuli nutnosti zavest datove struktury, bude ji nutno pouzit pro vetsi rychlostiTCNT0 = ctvrtbit % 0x0100; //reminder; // zacni znova merit cas do dalsiho mozneho bitupreteceni = ctvrtbit/0x0100; //quota;}}while (!DATA); // cekani na stop bit (detekce pripadneho paritniho bitu)for (stopbit=2;stopbit >= 0;stopbit--) // odpocitej dva stopbity{while ((TCNT0+preteceni*0x0100) <= cas){if(!DATA) break;}}}else POVOLOVAK_LOW; // kdyz je 1 prepni na prijem}return(0);}