Comunicacion serial
Dependents: comunicacion Bluetooth
Revision 0:064ba08b22ef, committed 2017-09-23
- Comitter:
- briandk
- Date:
- Sat Sep 23 21:01:23 2017 +0000
- Commit message:
- Comunicacion serial
Changed in this revision
diff -r 000000000000 -r 064ba08b22ef SoftSerial.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SoftSerial.cpp Sat Sep 23 21:01:23 2017 +0000 @@ -0,0 +1,40 @@ +#include "SoftSerial.h" + +SoftSerial::SoftSerial(PinName TX, PinName RX, const char* name) { + tx_en = rx_en = false; + if (TX != NC) { + tx = new DigitalOut(TX); + tx_en = true; + tx->write(1); + tx_bit = -1; + txticker.attach(this, &SoftSerial::tx_handler); + } + if (RX != NC) { + rx = new InterruptIn(RX); + rx_en = true; + out_valid = false; + rxticker.attach(this, &SoftSerial::rx_handler); + rx->fall(this, &SoftSerial::rx_gpio_irq_handler); + } + + baud(9600); + format(); +} + +SoftSerial::~SoftSerial() { + if (tx_en) + delete(tx); + if (rx_en) + delete(rx); +} + +void SoftSerial::baud(int baudrate) { + bit_period = 1000000 / baudrate; +} + +void SoftSerial::format(int bits, Parity parity, int stop_bits) { + _bits = bits; + _parity = parity; + _stop_bits = stop_bits; + _total_bits = 1 + _bits + _stop_bits + (bool)_parity; +}
diff -r 000000000000 -r 064ba08b22ef SoftSerial.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SoftSerial.h Sat Sep 23 21:01:23 2017 +0000 @@ -0,0 +1,124 @@ +#ifndef SOFTSERIAL_H +#define SOFTSERIAL_H + +#include "mbed.h" +#include "SoftSerial_Ticker.h" +/** A software serial implementation + * + */ +class SoftSerial: public Stream { + +public: + /** + * Constructor + * + * @param TX Name of the TX pin, NC for not connected + * @param RX Name of the RX pin, NC for not connected, must be capable of being InterruptIn + * @param name Name of the connection + */ + SoftSerial(PinName TX, PinName RX, const char* name = NULL); + virtual ~SoftSerial(); + + /** Set the baud rate of the serial port + * + * @param baudrate The baudrate of the serial port (default = 9600). + */ + void baud(int baudrate); + + enum Parity { + None = 0, + Odd, + Even, + Forced1, + Forced0 + }; + + enum IrqType { + RxIrq = 0, + TxIrq + }; + + /** Set the transmission format used by the serial port + * + * @param bits The number of bits in a word (default = 8) + * @param parity The parity used (SerialBase::None, SerialBase::Odd, SerialBase::Even, SerialBase::Forced1, SerialBase::Forced0; default = SerialBase::None) + * @param stop The number of stop bits (default = 1) + */ + void format(int bits=8, Parity parity=SoftSerial::None, int stop_bits=1); + + /** Determine if there is a character available to read + * + * @returns + * 1 if there is a character available to read, + * 0 otherwise + */ + int readable(); + + /** Determine if there is space available to write a character + * + * @returns + * 1 if there is space to write a character, + * 0 otherwise + */ + int writeable(); + + /** Attach a function to call whenever a serial interrupt is generated + * + * @param fptr A pointer to a void function, or 0 to set as none + * @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty) + */ + void attach(void (*fptr)(void), IrqType type=RxIrq) { + fpointer[type].attach(fptr); + } + + /** Attach a member function to call whenever a serial interrupt is generated + * + * @param tptr pointer to the object to call the member function on + * @param mptr pointer to the member function to be called + * @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty) + */ + template<typename T> + void attach(T* tptr, void (T::*mptr)(void), IrqType type=RxIrq) { + fpointer[type].attach(tptr, mptr); + } + + /** Generate a break condition on the serial line + */ + void send_break(); + +protected: + DigitalOut *tx; + InterruptIn *rx; + + bool tx_en, rx_en; + int bit_period; + int _bits, _stop_bits, _total_bits; + Parity _parity; + + FunctionPointer fpointer[2]; + + //rx + void rx_gpio_irq_handler(void); + void rx_handler(void); + int read_buffer, rx_bit; + volatile int out_buffer; + volatile bool out_valid; + bool rx_error; + FlexTicker rxticker; + + //tx + void tx_handler(void); + void prepare_tx(int c); + FlexTicker txticker; + int _char; + volatile int tx_bit; + + + + virtual int _getc(); + virtual int _putc(int c); +}; + + +#endif +
diff -r 000000000000 -r 064ba08b22ef SoftSerial_Ticker.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SoftSerial_Ticker.h Sat Sep 23 21:01:23 2017 +0000 @@ -0,0 +1,38 @@ +//A modified version of the regular ticker/timeout libraries to allow us to do timeout without losing accuracy + +#ifndef FLEXTICKER_H +#define FLEXTICKER_H + +#include "mbed.h" + +class FlexTicker: public TimerEvent { + public: + template<typename T> + void attach(T* tptr, void (T::*mptr)(void)) { + _function.attach(tptr, mptr); + } + + /** Detach the function + */ + void detach() { + remove(); + } + + void setNext(int delay) { + insert(event.timestamp + delay); + } + + void prime(void) { + event.timestamp = us_ticker_read(); + } + +protected: + virtual void handler() { + _function.call(); + } + + unsigned int _delay; + FunctionPointer _function; +}; + +#endif \ No newline at end of file
diff -r 000000000000 -r 064ba08b22ef SoftSerial_rx.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SoftSerial_rx.cpp Sat Sep 23 21:01:23 2017 +0000 @@ -0,0 +1,84 @@ +#include "SoftSerial.h" + +uint32_t overhead_us = 200 * 1000000 / SystemCoreClock; //Random estimation of the overhead of mbed libs, makes slow devices like LPC812 @ 12MHz perform better + +int SoftSerial::_getc( void ) { + while(!readable()); + out_valid = false; + return out_buffer; +} + +int SoftSerial::readable(void) { + return out_valid; +} + +//Start receiving byte +void SoftSerial::rx_gpio_irq_handler(void) { + rxticker.prime(); + rxticker.setNext(bit_period + (bit_period >> 1) - overhead_us); + rx->fall(NULL); + rx_bit = 0; + rx_error = false; +}; + +void SoftSerial::rx_handler(void) { + //Receive data + int val = rx->read(); + + rxticker.setNext(bit_period); + rx_bit++; + + + if (rx_bit <= _bits) { + read_buffer |= val << (rx_bit - 1); + return; + } + + //Receive parity + bool parity_count; + if (rx_bit == _bits + 1) { + switch (_parity) { + case Forced1: + if (val == 0) + rx_error = true; + return; + case Forced0: + if (val == 1) + rx_error = true; + return; + case Even: + case Odd: + parity_count = val; + for (int i = 0; i<_bits; i++) { + if (((read_buffer >> i) & 0x01) == 1) + parity_count = !parity_count; + } + if ((parity_count) && (_parity == Even)) + rx_error = true; + if ((!parity_count) && (_parity == Odd)) + rx_error = true; + return; + } + } + + //Receive stop + if (rx_bit < _bits + (bool)_parity + _stop_bits) { + if (!val) + rx_error = true; + return; + } + + //The last stop bit + if (!val) + rx_error = true; + + if (!rx_error) { + out_valid = true; + out_buffer = read_buffer; + fpointer[RxIrq].call(); + } + read_buffer = 0; + rxticker.detach(); + rx->fall(this, &SoftSerial::rx_gpio_irq_handler); +} +
diff -r 000000000000 -r 064ba08b22ef SoftSerial_tx.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SoftSerial_tx.cpp Sat Sep 23 21:01:23 2017 +0000 @@ -0,0 +1,80 @@ +#include "SoftSerial.h" + +int SoftSerial::_putc(int c) +{ + while(!writeable()); + prepare_tx(c); + tx_bit = 0; + txticker.prime(); + tx_handler(); + return 0; +} + +void SoftSerial::send_break(void) { + while(!writeable()); + tx_bit = 0; //Just to make sure it appears as non-writable to other threads/IRQs + tx->write(0); + wait_us((bit_period * _total_bits * 3) / 2); + tx->write(1); + tx_bit = -1; +} + +int SoftSerial::writeable(void) +{ + if (!tx_en) + return false; + if (tx_bit == -1) + return true; + return false; +} + +void SoftSerial::tx_handler(void) +{ + if (tx_bit == _total_bits) { + tx_bit = -1; + fpointer[TxIrq].call(); + return; + } + + //Flip output + int cur_out = tx->read(); + tx->write(!cur_out); + + //Calculate when to do it again + int count = bit_period; + tx_bit++; + while(((_char >> tx_bit) & 0x01) == !cur_out) { + count+=bit_period; + tx_bit++; + } + + txticker.setNext(count); +} + +void SoftSerial::prepare_tx(int c) +{ + _char = c << 1; + + bool parity; + switch (_parity) { + case Forced1: + _char |= 1 << (_bits + 1); + case Even: + parity = false; + for (int i = 0; i<_bits; i++) { + if (((_char >> i) & 0x01) == 1) + parity = !parity; + } + _char |= parity << (_bits + 1); + case Odd: + parity = true; + for (int i = 0; i<_bits; i++) { + if (((_char >> i) & 0x01) == 1) + parity = !parity; + } + _char |= parity << (_bits + 1); + } + + _char |= 0xFFFF << (1 + _bits + (bool)_parity); + _char &= ~(1<<_total_bits); +}