Arduino - softvérová sériová komunikácia (piny 2, 4)

From DT^2
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 // /...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

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 }