Friday, September 14, 2012

The Joy of Bit-Banging, part 2: RX

I previously discussed how to implement the Tx side of a bit-bang serial port, in The Joy of Bit-Banging, part 1: TX. This time I'll describe how to implement the receive side. This implementation uses blocking waits, as a result it should not be used unless you can tolerate delays.

In this implementation the receive pin is P2.5

Required definitions, etc:
#include "msp430x24x.h"
#define BIT_BANG_RX_PORT P2IN
#define BIT_BANG_RX_BIT BIT5
#define DISABLE_BIT_BANG_RX_INTERRUPT() (P2IE &= ~BIT5)
#define ENABLE_BIT_BANG_RX_INTERRUPT() (P2IE |= BIT5)
//Timings calculated using DCO_8_MHZ - modify if different oscillator speed or different hardware
#define BIT_LENGTH_9600 160
#define HALF_BIT_LENGTH_9600 76
#define BIT_LENGTH_19200 75
#define HALF_BIT_LENGTH_19200 27

/** Simple delay for bit width. Used in transmit and receive. */
void delayFullBit() {for (unsigned int i = 0; i < BIT_LENGTH_19200; i++) ; } //104uSec delay

/** Simple delay for 1/2 of bit width. Used in receive. */
void delayHalfBit() {for (unsigned int i = 0; i < HALF_BIT_LENGTH_19200; i++) ; } //104uSec delay

#define NUMBER_OF_DATA_BITS 8 
#define TOGGLE_DEBUG_PIN() (P4OUT ^= BIT5)  //debugging only

Output function:
/**
* Blocking UART receiver. Called by BIT_BANG_RX_PORT Interrupt Service Routine upon detection of start bit (high to low transition).
* BIT_BANG_RX_BIT should be configured as high-low edge triggered interrupt.
* Receives a byte and then processes it.
* @note BIT_BANG_RX_PORT, BIT_BANG_RX_BIT, DISABLE_BIT_BANG_RX_INTERRUPT(), and ENABLE_BIT_BANG_RX_INTERRUPT() must be #defined. Modify accordingly for other hardware.
* @pre Oscillator configured for 8MHz
* @pre A high-to-low transition has occurred on BIT_BANG_RX_BIT
* @return the byte received
*/
char bitBangInput()
{
    unsigned char receivedBitIndex = 0;
    unsigned char receivedByte = 0;
   
    DISABLE_BIT_BANG_RX_INTERRUPT();
    delayHalfBit();     //Since this method was called on detection of an edge, need to wait until we're in the middle of the bit width.
   
    TOGGLE_DEBUG_PIN();
    //Read this start bit - should be zero
    if (BIT_BANG_RX_PORT & BIT_BANG_RX_BIT)
    {
        //error - re-enable interrupt and return  
    }

    for (int i =0; i    {
        delayFullBit();
        TOGGLE_DEBUG_PIN();
        receivedByte |= (BIT_BANG_RX_PORT & BIT_BANG_RX_BIT) ? (1 << receivedBitIndex) : 0;     //Sample the bit, and if '1' then increase receivedByte accordingly
        receivedBitIndex++;
    }
        delayFullBit();   
        TOGGLE_DEBUG_PIN();
    //THIS IS STOP BIT (line should be back high)
    if (!(BIT_BANG_RX_PORT & BIT_BANG_RX_BIT))
    {
     //error - line is low; should be high because this is stop bit  
    }
    //all bits have been received!
    ENABLE_BIT_BANG_RX_INTERRUPT();
    return receivedByte;
}



No comments:

Post a Comment