1 | #include <avr/io.h>
|
2 | #include <avr/interrupt.h>
|
3 | #include "soft_uart.h"
|
4 | #include "ports.h"
|
5 |
|
6 | #define RX_PIN ( PINB & (1<<PINB6) )
|
7 |
|
8 | #define BAUDRATE_0 4800
|
9 | #define TIMER_PRESC 256
|
10 | #define CPU_CLOCK 10000000
|
11 | #define TIMER_VALUE (((CPU_CLOCK/TIMER_PRESC)/BAUDRATE_0)-1)
|
12 |
|
13 | volatile unsigned char ucBitCount = 0;
|
14 | volatile unsigned char ucStatus = 0;
|
15 | volatile unsigned char ucBuffer [8];
|
16 | volatile unsigned char ucNewChar;
|
17 | volatile unsigned char ucTempByte = 0;
|
18 | volatile unsigned char ucBufferCounter = 0;
|
19 | volatile unsigned char ucSynchroCount = 0;
|
20 | volatile unsigned char ucSynchro = 0;
|
21 |
|
22 | ISR(PCINT1_vect)
|
23 | {
|
24 | if(RX_PIN == 0) //Negative Flanke
|
25 | {
|
26 | if((ucStatus & 0x01)) //0x01 ist gesetzt, dies bedeutet wir haben vorhin eine längere high-phase erkannt.
|
27 | {
|
28 | PCICR &= ~(1<<PCIE1); //Interrupt deaktivieren für den PinChange
|
29 |
|
30 | TIMSK0 |= (1<<OCIE0A); //Timer Interrupt aktivieren
|
31 | TCNT0 = 0; //Timer Counter auf 0
|
32 | OCR0A = (TIMER_VALUE / 2) ; //Timing auf ein Halbes bit setzen
|
33 |
|
34 | ucStatus &= ~(1<<0x01); //Startbit erkennung deaktivieren, bzw. wurde erkannt
|
35 | }
|
36 | }
|
37 | }
|
38 |
|
39 |
|
40 | ISR(TIMER0_COMPA_vect)
|
41 | {
|
42 | //LED_1;
|
43 |
|
44 | if(ucSynchro == 0) //Kein Synchronisationsmodus
|
45 | {
|
46 | if((ucStatus & 0x02) == 0) //0x02 ist nicht gesetzt, wir sind das erstemal nach der Startbiterkennung hier
|
47 | {
|
48 | TCNT0 = 0; //Timerzähler auf 0 setzen
|
49 | OCR0A = TIMER_VALUE; //Timing auf ein ganzes bit setzen
|
50 | ucStatus |= 0x02;
|
51 | }
|
52 | else //wir sind nicht das erste mal hier, somit befinden wir uns im Datenbyte oder den Steuerbits (parity oder stopbit)
|
53 | {
|
54 | //if(ucBitCount == 0)
|
55 | //{
|
56 | // OCR0A = TIMER_VALUE; //Timing auf ein ganzes bit setzen
|
57 | //}
|
58 | if(ucBitCount < 8) //Wir lesen nun die Bits ein
|
59 | {
|
60 | if(RX_PIN)
|
61 | {
|
62 | ucTempByte |= 0x80;
|
63 | }
|
64 |
|
65 | if(ucBitCount != 7)
|
66 | {
|
67 | ucTempByte = ucTempByte >> 1;
|
68 | }
|
69 |
|
70 | }
|
71 | ucBitCount++;
|
72 |
|
73 | if(ucBitCount == 9) //Hier befindet sich das Stoppbit
|
74 | {
|
75 | LED_1;
|
76 | if(RX_PIN) //Stoppbit erkannt
|
77 | {
|
78 | ucBuffer[ucBufferCounter] = ucTempByte;
|
79 | ucBufferCounter++;
|
80 | if(ucBufferCounter == 8) ucBufferCounter = 0;
|
81 | ucNewChar = 1;
|
82 |
|
83 | ucStatus = 0x01; //Bereit für nächstes Startbit
|
84 | PCICR |= (1<<PCIE1); //Interrupt aktivieren für den PinChange
|
85 | TIMSK0 &= ~(1<<OCIE0A); //Interrupt deaktivieren
|
86 | LED_0;
|
87 | }
|
88 | else //kein Stoppbit erkannt
|
89 | {
|
90 | ucSynchro = 1; //Synchronisieren
|
91 | //Interrupt für den Timer nicht deaktivieren.
|
92 | }
|
93 |
|
94 | ucBitCount = 0;
|
95 | }
|
96 |
|
97 | }
|
98 |
|
99 |
|
100 |
|
101 |
|
102 | }
|
103 | else // Synchronisationsmodus
|
104 | {
|
105 | //LED_1
|
106 | if(RX_PIN) //Prüfen ob RX high ist
|
107 | {
|
108 | ucSynchroCount++;
|
109 | }
|
110 | else
|
111 | {
|
112 | ucSynchroCount = 0; //Sobald RX einmal low war, wieder auf 0 setzen
|
113 | }
|
114 |
|
115 | if(ucSynchroCount == 40) //Es wurde 20bitzeiten lang high erkannt, somit muss nun das startbit folgen
|
116 | { //auflösung ist ein halsbes bit
|
117 | ucSynchroCount = 0;
|
118 | TIMSK0 &= ~(1<<OCIE0A); //TIMER Interrupt deaktivieren und somit auf startbit warten
|
119 | ucSynchro = 0; //Synchrobit löschen
|
120 | PCICR |= (1<<PCIE1); //PinChange Interrupt aktivieren
|
121 | ucStatus = 0x01; //Startbit aktivieren
|
122 | }
|
123 |
|
124 | }
|
125 | //LED_0;
|
126 | }
|
127 |
|
128 |
|
129 | void init_soft_uart(void)
|
130 | {
|
131 |
|
132 | //PCINT14 ist der Interrupt des RX-Pins
|
133 | PCMSK1 |= (1<<PCINT14); //Interruptgruppe 1
|
134 |
|
135 | ucSynchro = 1; //Synchronisation aktiveren
|
136 |
|
137 | OCR0A = TIMER_VALUE; //Timer auf eine ganze bitlänge setzen
|
138 | TCCR0A |= (1<<WGM01); //CTC MODE
|
139 | TCCR0B |= (1<<CS02); //256 Prescaler
|
140 | TIMSK0 |= (1<<OCIE0A); //Interrupt aktivieren
|
141 |
|
142 | }
|