Rev 305 | Blame | Last modification | View Log | Download
//----------------------------------------------------------------------------------// Prevodnik RS232 <--> RS485// pri startbitu na RS232 zapne okamzite vysilac pokud nejsou detekovana data z RS485.//----------------------------------------------------------------------------------////Algoritmus:// Princip je zalozen na mereni nejkratsiho casoveho useku v osmi vzorcich, delka vzorku// se odviji od velikosti prave nejmensiho zmereneho vzorku.// delka vzorku 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.)//// 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./////////////////////////////////////////////////////////////////////////////////////////TODO:// Optimalizovat kod, (hlavne najit casove vyhodnejsi umisteni pro nastavovani defaultnich hodnot promennych)// Bylo bydobre zavest uspavani pred prijetim bajtu.// Vykouset program na ATtiny13// Program neni vyzkousen pri extremne nizkych rychlostech, kdy by teoreticky// mohlo dochazet k preteceni promenne cas.// Neni vyzkousen break, byly testovany pouze ASCII znaky vysilane pres terminal z klavesnice.////////////////////////////////////////////////////////////////////////////////////////#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 int bitdelay; // obsahuje aktualni zmereny cas delky bituvolatile unsigned 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;// DDRD |= (1<<DDD5); // povoleni vystupu pro blikani ledkou (mozno odebrat)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 vysilanibit=0; // vynuluj vsechny promenne pro mereni casu a pocitani bituTCNT0=0;preteceni=0;cas = 0xFFFF; // nastav cas delky bitu na nejvetsi moznywhile (bit <= 8) // odpocitej dobu 8mi bitu{if ((100+TCNT0+preteceni*0x0100) >= cas) // zkontroluj jestli necekame na dalsi bit dele nez je nekratsi znema delka bitu{TCNT0 = 0; // zacni znova merit cas do dalsiho mozneho bitupreteceni=0;bit++; // pokud jsme cekali dele, tak bit uz ubehl, to znamena, ze muzeme pocitadlo bitu posunout o jednicku}}/* 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);}