Arduino - softvérová sériová komunikácia (piny 2, 4)
Revision as of 05:27, 3 August 2018 by 95.105.230.221 (talk) (Created page with "Nasledujúci program implementuje komunikáciu po sériovom porte na pinoch 2,4 v softvéri pomocou prerušenia. <syntaxhighlight lang="C" line=line> // dtdt_serial.ino // /...")
Nasledujúci program implementuje komunikáciu po sériovom porte na pinoch 2,4 v softvéri pomocou prerušenia.
1 // dtdt_serial.ino
2 //
3 // implements software serial communication using pin change interrupt on RX=D2, TX=D4
4 // in a clean way (unlike SoftwareSerial library)
5 //
6 // Implemented for dtdt.ninja
7
8 #define SERIAL_STATE_IDLE 0
9 #define SERIAL_STATE_RECEIVING 1
10 #define SERIAL_BUFFER_LENGTH 20
11
12 static volatile uint8_t serial_state;
13 static uint8_t serial_buffer[SERIAL_BUFFER_LENGTH];
14 static volatile uint8_t serial_buf_wp, serial_buf_rp;
15
16 static volatile uint8_t receiving_byte;
17
18 static volatile uint32_t time_startbit_noticed;
19 static volatile uint8_t next_bit_order;
20 static volatile uint8_t waiting_stop_bit;
21 static uint16_t one_byte_duration;
22 static uint16_t one_bit_duration;
23 static uint16_t half_of_one_bit_duration;
24
25 void setup() {
26 Serial.begin(9600);
27 init_serial(9600);
28 }
29
30 void init_serial(uint32_t baud_rate)
31 {
32 pinMode(2, INPUT);
33 pinMode(4, OUTPUT);
34
35 serial_state = SERIAL_STATE_IDLE;
36
37 one_byte_duration = 9500000 / baud_rate;
38 one_bit_duration = 1000000 / baud_rate;
39 half_of_one_bit_duration = 500000 / baud_rate;
40
41 PCMSK2 |= 4; //PCINT18;
42 PCIFR &= ~4; //PCIF2;
43 PCICR |= 4; // PCIE2;
44 }
45
46
47 ISR(PCINT2_vect)
48 {
49 uint32_t tm = micros();
50 if (serial_state == SERIAL_STATE_IDLE)
51 {
52 time_startbit_noticed = tm;
53 serial_state = SERIAL_STATE_RECEIVING;
54 receiving_byte = 0xFF;
55 next_bit_order = 0;
56 }
57 else if (tm - time_startbit_noticed > one_byte_duration)
58 {
59 serial_buffer[serial_buf_wp] = receiving_byte;
60 serial_buf_wp++;
61 if (serial_buf_wp == SERIAL_BUFFER_LENGTH) serial_buf_wp = 0;
62 time_startbit_noticed = tm;
63 receiving_byte = 0xFF;
64 next_bit_order = 0;
65 }
66 else if (PIND & 4)
67 {
68 int8_t new_next_bit_order = (tm - time_startbit_noticed - half_of_one_bit_duration) / one_bit_duration;
69 while (next_bit_order < new_next_bit_order)
70 {
71 receiving_byte &= ~(1 << next_bit_order);
72 next_bit_order++;
73 }
74 if (next_bit_order == 8)
75 {
76 serial_buffer[serial_buf_wp] = receiving_byte;
77 serial_buf_wp++;
78 if (serial_buf_wp == SERIAL_BUFFER_LENGTH) serial_buf_wp = 0;
79 serial_state = SERIAL_STATE_IDLE;
80 }
81 } else
82 next_bit_order = (tm - time_startbit_noticed - half_of_one_bit_duration) / one_bit_duration;
83 }
84
85 uint8_t serial_available()
86 {
87 cli();
88 if (serial_buf_rp != serial_buf_wp)
89 {
90 sei();
91 return 1;
92 }
93 if (serial_state == SERIAL_STATE_RECEIVING)
94 {
95 uint32_t tm = micros();
96 if (tm - time_startbit_noticed > one_byte_duration)
97 {
98 serial_state = SERIAL_STATE_IDLE;
99 serial_buffer[serial_buf_wp] = receiving_byte;
100 serial_buf_wp++;
101 if (serial_buf_wp == SERIAL_BUFFER_LENGTH) serial_buf_wp = 0;
102 sei();
103 return 1;
104 }
105 }
106 sei();
107 return 0;
108 }
109
110 int16_t serial_read()
111 {
112 cli();
113 if (serial_buf_rp != serial_buf_wp)
114 {
115 uint8_t ch = serial_buffer[serial_buf_rp];
116 serial_buf_rp++;
117 if (serial_buf_rp == SERIAL_BUFFER_LENGTH) serial_buf_rp = 0;
118 sei();
119 return ch;
120 }
121
122 if (serial_state == SERIAL_STATE_RECEIVING)
123 {
124 uint32_t tm = micros();
125 if (tm - time_startbit_noticed > one_byte_duration)
126 {
127 uint8_t ch = receiving_byte;
128 serial_state = SERIAL_STATE_IDLE;
129 sei();
130 return ch;
131 }
132 }
133 sei();
134 return -1;
135 }
136
137 void serial_write(uint8_t ch)
138 {
139 PORTD &= ~16;
140 delayMicroseconds(one_bit_duration);
141 for (uint8_t i = 0; i < 8; i++)
142 {
143 if (ch & 1) PORTD |= 16;
144 else PORTD &= ~16;
145 ch >>= 1;
146 delayMicroseconds(one_bit_duration);
147 }
148 PORTD |= 16;
149 delayMicroseconds(one_bit_duration);
150 }
151
152 uint16_t serial_readln(uint8_t *ln, uint16_t max_length)
153 {
154 uint16_t len;
155 uint16_t ch;
156 do {
157 ch = serial_read();
158 if (ch == 13) continue;
159 } while (ch == -1);
160
161 do {
162 if ((ch != 13) && (ch != 10) && (ch != -1))
163 {
164 *(ln++) = ch;
165 max_length--;
166 len++;
167 }
168 ch = serial_read();
169 } while ((ch != 13) && max_length);
170 *ln = 0;
171 return len;
172 }
173
174 void serial_print(uint8_t *str)
175 {
176 while (*str) serial_write(*(str++));
177 }
178
179 void serial_println(uint8_t *str)
180 {
181 serial_print(str);
182 serial_write(13);
183 serial_write(10);
184 }
185
186 void loop()
187 {
188 if (Serial.available()) serial_write(Serial.read());
189 if (serial_available()) Serial.write(serial_read());
190 }