Sonsivri
 
*
Welcome, Guest. Please login or register.
Did you miss your activation email?
November 01, 2024, 01:08:32 01:08


Login with username, password and session length


Pages: [1]
Print
Author Topic: rs232 software usart?  (Read 6029 times)
0 Members and 1 Guest are viewing this topic.
kang2008
Guest
« on: April 08, 2008, 08:32:12 08:32 »

//Initialize software USART by configuring the PORT
void initUART()
{
   PORT  |=0b001000;         //Set PB3 (Transmitter Pin)
   DDRB  |=0b001000;         //Configure PB3 as output pin
   DDRB  &=0b101111;         //Configure PB4(Reciever Pin) as input pin
}

//Function to transmit a character through software USART
/*
   Baud Rate    : 9600 bps
   Data Bits    : 8
   Stop Bits    : 1
   Parity       : None
   Flow Cotrol   : None   
*/

void send_char(unsigned char c)
{
unsigned char i;

   initUART();                 //Initialize the software USART
   
   //Transmit a start Bit
   PORTB &= 0b110111;
   bit_delay();

   //Transmit the remaining 8 bits
   for(i=0;i<8;++i)   
   {
      if((c & 0x01) == 0x01)          //Check if LSB is 1
         PORTB|=0b001000;         //Send a One
      else                     //Otherwise
         PORTB&=0b110111;         //Send a 0

      bit_delay();               //Wait for one bit length
      c = c >> 1;                  //Right Shift the bits so that the
                              //next bit to be transmitted becomes LSB
   }

   //IDLE High (Including a Stopbit)
   PORTB|=0b001000;
   
   //Byte Delay
   for(i=0;i<25;i++)
      bit_delay();
}

int get_char(void)
{
unsigned char i;
unsigned char data;

   initUART();                 //Initialize the software USART
   
   //Transmit a start Bit
             
   PINB &= 0b101111;
   bit_delay();

   //Transmit the remaining 8 bits
   for(i=0;i<8;++i)   
   {
       if((c & 0x01)==0x01)         //Check if LSB is 1
         PINB |= 0b010000;         //Send a One
      else                     //Otherwise
         PINB &= 0b101111;         //Send a 0

      bit_delay();               //Wait for one bit length
      c = c >> 1;                  //Right Shift the bits so that the
                              //next bit to be transmitted becomes LSB
   }

   //IDLE High (Including a Stopbit)
   PINB |= 0b010000;
   
   //Byte Delay
   for(i=0;i<25;i++)
      bit_delay();
   
   return c;    
}

i do not know get_char() function?

thank you.

Posted on: April 08, 2008, 08:17:01 08:17 - Automerged

other:

int get_char(void)
{
unsigned char i;
unsigned char data;

   initUART();                 //Initialize the software USART
   
   //Transmit a start Bit
             
   //PINB &= 0b101111;
   //bit_delay();

    data = 0;
   
   //Transmit the remaining 8 bits
   for(i=0;i<8;++i)   
   {
       data <<= 1;
      bit_delay();   

      if(data == 1)                          //Check if LSB is 1
         PINB |= 0b010000;                 //Send a One
      else                              //Otherwise
         PINB &= 0b101111;                  //Send a 0
   }

   //Byte Delay
   for(i=0;i<25;i++)
      bit_delay();
   
   return data;    
}
Logged
zuisti
Senior Member
****
Offline Offline

Posts: 409

Thank You
-Given: 242
-Receive: 780


« Reply #1 on: April 08, 2008, 11:55:43 11:55 »

Hi 'kang2008'

Your first function (send_char) may work yet even, if you are using the proper bit-time delay and this doesn't disturb with any IT routines. Maybe it's needed the disabling of all interrupts along it sends a char.
However, the long delaying at the end is unnecessary, the overall speed (chars/sec) will too slow so.

But ... the get_char will NOT work without any start bit falling edge detection. Now it get ever garbage only.

This detection is possible via polling or also via IT. And it's better using first a half bit-time delay after the detected start edge (and exit if the RX pin doesn't zero yet), and from here examine and get 9 times (after full bit-time delays) the pin value. The 9th bit is the stop bit ( do not store), but it must exist as a high level.

I'm attached here a zip with old but useful PDFs about this thing.

Hope this helps
zuisti
Logged
kang2008
Guest
« Reply #2 on: April 08, 2008, 02:05:47 14:05 »

hi. zuisti  thank you.

;***************************************************************************
;*
;* "getchar"
;*
;* This subroutine receives one byte and returns it in the "Rxbyte" register
;*
;* Number of words   :14 including return
;* Number of cycles   :Depens on when data arrives
;* Low registers used   :None
;* High registers used   :2 (bitcnt,Rxbyte)
;* Pointers used   :None
;*
;***************************************************************************

getchar:   ldi    bitcnt,9   ;8 data bit + 1 stop bit

getchar1:   sbic    PIND,RxD   ;Wait for start bit
      rjmp    getchar1

      rcall UART_delay   ;0.5 bit delay

getchar2:   rcall UART_delay   ;1 bit delay
      rcall UART_delay      

      clc         ;clear carry
      sbic    PIND,RxD   ;if RX pin high
      sec         ;

      dec    bitcnt      ;If bit is stop bit
      breq    getchar3   ;   return
               ;else
      ror    Rxbyte      ;   shift bit into Rxbyte
      rjmp    getchar2   ;   go get next

getchar3:   ret

possiable asm to c source?
Logged
zuisti
Senior Member
****
Offline Offline

Posts: 409

Thank You
-Given: 242
-Receive: 780


« Reply #3 on: April 08, 2008, 03:03:07 15:03 »

Hi Kang2008,

It's easy but depends from your C dialect (red is error handling only):
(PORTB.4 = RX pin)

int Get_Char(void) {
 char n, int ch;
 do while (PORTB.4); // a loop for waiting the start bit falling edge (until pin goes low)
 delay_05bit();
 if (PORTB.4) // if high, it's not a real start bit !!
   return (-1); // or other value, error

 for ( n = 8, ch = 0 ; n ; --n ) {
   delay_05bit();
   delay_05bit(); //1 bit delay
   ch >>= 1;   
   if (PORTB.4)
     ch += 0x80;
 }
 delay_05bit();
 delay_05bit(); //1 bit delay
  if (!PORTB.4)   //stop bit (1) exists? if not, error
   return (-1);     // or other value, error
 
 delay_05bit();  // wait for end of stop bit
 return ((int) ch); //received char
}

Not tried !!
zuisti
Logged
kang2008
Guest
« Reply #4 on: April 08, 2008, 03:39:35 15:39 »

other do not test in the get_char() function?

// 4.6mhz attiny13 (DO NOT USED 8CKDIV) 
// Include Directives
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/SIGNAL.h>
#include <avr/sleep.h>


#define sbi(PORT,BIT) PORT|= _BV(BIT)   
#define cbi(PORT,BIT) PORT&=~_BV(BIT)   

void bit_delay();                  //A duration of time equal to one bit length
void initUART();                  //Initialize software USART
void send_char(unsigned char c);      //Transmit a character through software USART


//Bit Delay: A length of time equal to one bit duration at 9600 bps
//No timers used, using hardware registers
void bit_delay()
{
   //register declaration to maximize and caliberate speed of operation
   register unsigned char i;
   
   for(i=0;i<36;++i)
   {      
      //Inline assembly code statements occupy precise amount of time
      asm("NOP");
      asm("NOP");
      asm("NOP");
      asm("NOP");
      asm("NOP");
      asm("NOP");
      asm("NOP");
      asm("NOP");
      asm("NOP");
      asm("NOP");
   }
   //Additional inline assembly code statements to caliberate the exact
   //amount of time
   asm("NOP");
   asm("NOP");
}

/**********************************************************************************/

//Initialize software USART by configuring the PORT
void PORT_init()
{
    PORTB    =0b000000;
    DDRB     =0b001000;   // PORTB3 TXD  OR PORTB4  RXD
}

//Function to transmit a character through software USART
/*
   Baud Rate    : 9600 bps
   Data Bits    : 8
   Stop Bits    : 1
   Parity       : None
   Flow Cotrol   : None   
*/

void send_char(unsigned char c)   // TEST OK
{
unsigned char i;

   //Transmit a start Bit
   cbi(PORTB,3);
   bit_delay();

   //Transmit the remaining 8 bits
   for(i=0;i<8;++i)   
   {
      if((c & 0x01) == 0x01)          //Check if LSB is 1
         sbi(PORTB,3);               //Send a One
      else                     //Otherwise
         cbi(PORTB,3);               //Send a 0
      bit_delay();               //Wait for one bit length
      c = c >> 1;                  //Right Shift the bits so that the
                              //next bit to be transmitted becomes LSB
   }

   sbi(PORTB,3);
   
   //Byte Delay
   for(i=0;i<25;i++)
      bit_delay();
}

/***************************************/

int get_char(void)    // DO NOT TEST
{
unsigned char n;
unsigned int ch;

    //while(!PINB4) break;
    bit_delay();
 
    if (PINB4)  return (-1);   // or other value, error
 
    for ( n = 8, ch = 0 ; n ; --n )
   {
        bit_delay();
      bit_delay();
        ch >>= 1;   
       
      if (PINB4)  ch += 0x80;
    }
    bit_delay();
    bit_delay();
    if (!PINB4)  return (-1);   // or other value, error   
    bit_delay();                // wait for end of stop bit
   
   send_char(ch);
   
    return((unsigned int) ch);  //received char
}

   
/***************************************/
      
void send_string(char *p)
{
  char rd;
 
  while(rd = *p++) send_char(rd);
}



/**********************************************************************************/

//The main function
int main(void)
{
unsigned char i,key;

    PORT_init();              
   
   for(i=0;i<100;i++);
   send_string("Welcome to Sonsivri!!!\r\n");
    for(i=0;i<100;i++);
   
   while(1) {
   
      key = get_char();
      
      switch(key) {
          case 0x0d: send_string("\r\n");
                      send_string("\r\n>");
                      break;
         
            case '?':  send_string("\r\n");
                      break;
           
           case '1':  send_string("test1\r\n>");
                      break;
           
           case '2':  send_string("test2\r\n>");
                      break;
          default :  break;   
       } 
    }
   return 0;      //Never executed
}
Logged
sabyes
Inactive

Offline Offline

Posts: 4

Thank You
-Given: 0
-Receive: 0


« Reply #5 on: April 30, 2008, 04:57:56 04:57 »

Cool, I will test it.
I try to do this long time ago and I don't know how to start with.
Logged
pickit2
Moderator
Hero Member
*****
Offline Offline

Posts: 4658

Thank You
-Given: 832
-Receive: 4301


There is no evidence that I muted SoNsIvRi


« Reply #6 on: September 21, 2014, 05:42:11 17:42 »

Cool, I will test it.
I try to do this long time ago and I don't know how to start with.
I see this was your Last Post in Forum.
Today I see you log-in, so now its truly your last post here, until system clock resets to 1905 Tongue  

http://www.sonsivri.to/forum/index.php?action=profile;u=14236;sa=summary
Logged

Note: I stoped Muteing bad members OK I now put thier account in sleep mode
gan_canny
Junior Member
**
Offline Offline

Posts: 89

Thank You
-Given: 101
-Receive: 26


« Reply #7 on: September 21, 2014, 06:52:21 18:52 »

RS232 is asynchronous and this feature is very important with a software UART. Asynchronous means a character can and will arrive at anytime. Any bit in the character must be caught before the next bit arrives. The time available to catch a bit is determined by the baud rate. So the software loop must complete within approx one half the bit time. Depending on the speed of the processor either very little or just a little amount of processing can be done within the loop. This means since chars arrive asynchronously many CPU cycles are wasted preparing for bits that could have arrived but didn't. Only in specific situations is a software UART a reasonable solution. Most chips will have a hardware UART and interrupt logic. Not using the interrupt with a hardware UART can be wasteful since the loop timing is still heavily restricted.
Logged
Pages: [1]
Print
Jump to:  


DISCLAIMER
WE DONT HOST ANY ILLEGAL FILES ON THE SERVER
USE CONTACT US TO REPORT ILLEGAL FILES
ADMINISTRATORS CANNOT BE HELD RESPONSIBLE FOR USERS POSTS AND LINKS

... Copyright © 2003-2999 Sonsivri.to ...
Powered by SMF 1.1.18 | SMF © 2006-2009, Simple Machines LLC | HarzeM Dilber MC