Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // LPC1114FN28+MBED software UART test
- //
- // This is a pure-mbed software UART implementation.
- // I tested this with 9600-8n1 configuration on LPC1114FN28/102.
- //
- #include "mbed.h"
- //
- // Timing control parameters
- //
- // As it is hard to be clock-precise on mbed, timing control parameter
- // for bit sampling (for RX) and bit toggling (for TX) is obtained
- // experimentally. So it probably needs tweaking with other CPU.
- //
- // With 9600baud, bitclock is ~104[us/bit].
- // However, due to mbed API overhead (overhead by attach_us and interrupt
- // routing), I ended up attaching RX/TX function with ~85us delay.
- //
- // Here, TX bitspace != RX bitspace just to make my logic analyzer happy.
- // It samples bits with different timing, and this change was needed to make
- // every device (RX/TX on both sides + LA) recognize data as same value. YMMV.
- //
- #define TX_BITSPACE 86 /* make this + overhead == ~104us */
- #define TX_BITSPACE_ONSTART 10 /* big enough to finish attach_us */
- #define RX_BITSPACE 82 /* make this + overhead == ~104us */
- #define RX_BITSPACE_ONRESET 1000 /* big enough to skip whole transfer */
- #define RX_BITSPACE_ONSTART 110 /* big enough to skip START bit */
- enum { LED_ON = 0, LED_OFF };
- enum { IDLE = 1, STOP = 1, START = 0 };
- DigitalOut led(P1_5);
- // TX/RX bitclock must be separate as call to attach_us may compete.
- Timeout rxclock, txclock;
- InterruptIn rxint(P1_6);
- DigitalOut tx(P1_7);
- DigitalIn rx(P1_6);
- static struct uart_buffer {
- uint8_t buffer[16];
- uint8_t ri, wi;
- uint8_t cc;
- struct {
- bool in_process:1;
- unsigned int data_len:4;
- unsigned int stop_len:2;
- unsigned int parity_len:1;
- bool parity_even:1;
- unsigned int parity:1;
- bool frame_error:1;
- bool parity_error:1;
- bool overflow_error:1;
- } state;
- } rb, sb;
- void send_bit() {
- int bit;
- if (sb.state.data_len) {
- sb.state.data_len--;
- bit = sb.cc & 0x01;
- sb.cc >>= 1;
- if (sb.state.parity_len) {
- sb.state.parity ^= bit;
- }
- }
- else if (sb.state.parity_len) {
- sb.state.parity_len--;
- bit = sb.state.parity ^ sb.state.parity_even;
- }
- else if (sb.state.stop_len) {
- sb.state.stop_len--;
- bit = STOP;
- }
- else {
- if (sb.ri == sb.wi) {
- sb.state.in_process = 0;
- return;
- }
- sb.cc = sb.buffer[sb.ri++];
- sb.ri = sb.ri < sizeof(sb.buffer) ? sb.ri : 0;
- sb.state.data_len = 8;
- sb.state.parity_len = 0;
- sb.state.stop_len = 1;
- bit = START;
- }
- tx = bit;
- txclock.attach_us(&send_bit, TX_BITSPACE);
- }
- int uart_putc(uint8_t c) {
- uint8_t wi = sb.wi++;
- sb.wi = sb.wi < sizeof(sb.buffer) ? sb.wi : 0;
- if (sb.wi == sb.ri) {
- sb.wi = wi;
- goto buffer_overflow;
- }
- sb.buffer[wi] = c;
- if (sb.state.in_process == 0) {
- sb.state.in_process = 1;
- txclock.attach_us(&send_bit, TX_BITSPACE_ONSTART);
- }
- return 0;
- buffer_overflow:
- return -1;
- }
- int uart_getc() {
- if (rb.ri == rb.wi) {
- return -1;
- }
- int c = rb.buffer[rb.ri++];
- rb.ri = rb.ri < sizeof(rb.buffer) ? rb.ri : 0;
- return c;
- }
- void recv_reset() {
- rb.state.in_process = 0;
- //rxint.enable_irq();
- }
- void recv_bit() {
- led = LED_ON;
- int bit = rx;
- led = LED_OFF;
- if (rb.state.data_len) {
- rb.state.data_len--;
- rb.cc >>= 1;
- rb.cc |= bit ? 0x80 : 0x00;
- if (rb.state.parity_len) {
- rb.state.parity ^= bit;
- }
- }
- else if (rb.state.parity_len) {
- rb.state.parity_len--;
- if (bit != (rb.state.parity ^ rb.state.parity_even)) {
- goto parity_error;
- }
- }
- else if (rb.state.stop_len) {
- rb.state.stop_len--;
- if (bit != STOP) {
- goto frame_error;
- }
- // receive completed
- if (rb.state.stop_len == 0) {
- uint8_t wi = rb.wi++;
- // save to buffer
- rb.wi = rb.wi < sizeof(rb.buffer) ? rb.wi : 0;
- if (rb.wi == rb.ri) {
- rb.wi = wi;
- goto buffer_overflow;
- }
- rb.buffer[wi] = rb.cc;
- // prepare for next event
- recv_reset();
- return;
- }
- }
- rxclock.attach_us(&recv_bit, RX_BITSPACE);
- return;
- buffer_overflow:
- rb.state.overflow_error = 1;
- rxclock.attach_us(&recv_reset, RX_BITSPACE_ONRESET);
- return;
- parity_error:
- rb.state.parity_error = 1;
- frame_error:
- rb.state.frame_error = 1;
- rxclock.attach_us(&recv_reset, RX_BITSPACE_ONRESET);
- }
- void recv_start() {
- //rxint.disable_irq();
- if (rb.state.in_process == 0) {
- rb.state.in_process = 1;
- rb.state.data_len = 8;
- rb.state.parity_len = 0;
- rb.state.stop_len = 1;
- rxclock.attach_us(&recv_bit, RX_BITSPACE_ONSTART);
- }
- }
- void uart_init() {
- led = LED_OFF;
- tx = IDLE;
- rxint.fall(&recv_start);
- }
- int main(void) {
- uart_init();
- for (;;) {
- int c = uart_getc();
- if (c > 0) {
- while (uart_putc(c) < 0);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement