Wednesday, January 11, 2017

SOFTWARE BASED UART ON ANY CONTROLLER

UART are very easy way for communication in electronics, it is used mostly in any where. UART are available in any micro controllers and very easy to use and understand. 
Sometimes in some controllers we may required some extra UART than available in hardware, in such case we can use software based UART. The details of USART communication is out of scope of this post. 

The code is running on MSP430FR5969, the device is running on 4 MHz DCO. The following code do not utilized any kind of interrupt and strictly depended on polling. While receiving the data, it uses while statement for the start bit. But this code be easily be made efficient using techniques like interrupts and also using PT thread technique. This just gives a basic implementation for the newbies.

The setup is as


Here macros are used for making the code simpler, following are the snippets of the functions.

#define settxoutput P1DIR |= BIT4  //SET AS TX OUTPUT PORT 1 BIT 4
#define highontx P1OUT |= BIT4 //SET OUTPUT HIGH ON TX
#define setlowontx P1OUT &= ~BIT4 //SET OUTPUT LOW ON TX

#define setrxinput P1DIR &= ~BIT3 //SET AS RX INPUT PORT 1 BIT 3
#define isrxhigh P1IN&BIT3

#define baudrate 9600
#define Bittime 4000000/baudrate // one bit time in uS
#define bittime Bittime - 40
#define rbittime Bittime - 40

void tx8_uart(unsigned char data8){
unsigned char i;
setlowontx;
__delay_cycles(bittime); //since frequency of operation is 1mhz its 1us
for( i = 0;i < 8 ; i++){
if( ( (data8>>i) & 0x01) == 0x01 )
highontx;
else
setlowontx;
__delay_cycles(bittime);
}
highontx;
__delay_cycles(bittime);
}


unsigned char  rx8_uart(){
unsigned char data8=0;
int i;

while(isrxhigh); //start bit is 0

__delay_cycles(rbittime);
__delay_cycles(rbittime/2);//taking sample at mid time

for( i = 0;i<8;i++){
if( /*i%2 == 0*/ isrxhigh ){
data8 += (1<<i);
//P1OUT |= BIT7;
}
else{
data8 = data8;
// P1OUT &= ~BIT7;
}
__delay_cycles(rbittime);
}

if( isrxhigh ){
__delay_cycles(rbittime/2);
return data8;
}else{
__delay_cycles(rbittime/2);
return 0x00;
}
}