2,7 → 2,27 |
// 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. |
// |
// |
// Tento zpusob detekce neni imuni proti nahodnym chybovim sickam 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. |
////////////////////////////////////////////////////////////////////////////////////// |
// |
|
|
#include <avr/io.h> |
#include <avr/interrupt.h> |
#include <stdlib.h> |
12,13 → 32,12 |
|
#define POVOLOVAK_LOW PORTB &= ~(1<<PB3) |
#define POVOLOVAK_HIGH PORTB |= (1<<PB3) |
#define DATA (PIND & (1<<PD1)) |
#define DATA (PIND & (1<<PD3)) |
|
volatile unsigned int preteceni; |
unsigned int bit; |
unsigned int bitdelay; |
unsigned int last; |
unsigned int cas; |
volatile unsigned int bit; |
volatile unsigned int bitdelay; |
volatile unsigned int cas; |
|
ISR(TIMER0_OVF_vect) // interrupt od preteceni casovace |
{ |
25,6 → 44,13 |
preteceni++; // kdyz pretece, poznamenej to. |
} |
|
ISR(INT1_vect) |
{ |
if ((bitdelay=TCNT0+preteceni*0x0100) < cas) cas = bitdelay; // |
TCNT0 = 0; // zacni znova merit cas zacatku stopbitu |
preteceni=0; |
bit++; |
} |
|
// ------------------------------------------------------------------ |
// Main |
32,11 → 58,17 |
int main(void) |
{ |
|
DDRD |= (1<<DDD5); |
DDRB |= (1<<DDB3); |
DDRD |= (1<<DDD5); // povoleni vystupu pro blikani ledkou (mozno odebrat) |
|
TIMSK |= (1 << TOIE0); // Enable timer overflow interrupt |
TCCR0B |= (1 << CS10); // Set up timer |
DDRB |= (1<<DDB3); // povoleni vystupu na povolovak |
|
TIMSK |= (1 << TOIE0); // Enable timer overflow interrupt |
|
MCUCR |= (1 << ISC10); // nastaveni preruseni od zmeny vstupu pro interrupt INT0 |
GIMSK |= (1 << INT1); // povoleni interruptu INT0 |
|
TCCR0B |= (1 << CS00); // Set up timer |
|
sei(); // enable interrupts |
|
while(1) |
45,32 → 77,25 |
{ |
POVOLOVAK_HIGH; // zapni vysilani |
|
bitdelay = 0; |
bit=0; |
TCNT0=0; |
preteceni=0; |
cas = 0xFFFF; |
bitdelay = 0; |
|
for (bit=0;bit<=7;bit++) // odpocitej dobu 8mi bitu |
|
while (bit <= 10) // odpocitej dobu 8mi bitu |
{ |
last = DATA; |
TCNT0 = 0; // vynuluj citac pred tim, ne smazes preteceni, protoze jinak by se mohlo stat, ze se nastavi preteceni driv, nez ma |
preteceni = 0; |
|
while ((TCNT0+preteceni*0x0100) <= cas) // bit poznas tak, ze je to nejmensi nalezena delka trvaleho stavu |
if ((TCNT0+preteceni*0x0100) > cas) |
{ |
bitdelay=TCNT0+preteceni*0x0100; |
if(DATA != last) // zkontroluj, jestli se nezmenil stav dat. |
{ |
if (bitdelay < cas) cas = bitdelay; //kdyz se zmenil a trvalo to kratsi dobu nez pred tim poznemenej, jak dlouho to trvalo |
break; |
} |
} |
TCNT0 = 0; // zacni znova merit cas zacatku stopbitu |
preteceni=0; |
bit++; |
} |
} |
while (!DATA); // cekani na stop bit |
while (!DATA); // cekani na stop bit (detekce pripadneho paritniho bitu) |
|
/* for (bit=2;bit >= 0;bit--) // odpocitej dva stopbity |
{ |
TCNT0 = 0; // zacni znova merit cas zacatku stopbitu |
preteceni=0; |
|
while ((TCNT0+preteceni*0x0100) <= cas) |
{ |
if(!DATA) break; |