Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] soft serial communication c code with explanation

Status
Not open for further replies.

manu8193

Newbie level 5
Joined
Jul 22, 2019
Messages
9
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Location
hyderabad
Activity points
78
any one help to me


explan soft serial communication with c code?
 

This is highly device dependent so there is no generic 'C' code that will work in all situations.

The principle is -
Transmitting:
1. provide a timing source one bit long (the Baud rate clock).
2. drive the output low for one bit period, this is called the 'start bit'.
3. create a loop counter for each bit, usually there are 8 bits.
4. if the LSB of the data is low, drive the output low, if it is high, drive it high.
5. shift the data one bit to the right so that data bit 1 becomes the LSB.
6. subtract 1 from the loop counter.
7. wait one bit period.
8. keep going back to step 4 until the loop counter reaches zero.
9. drive the output high for one bit period, this is called the 'stop bit'

Repeat all the above for each byte of data you want to send.

Receiving:
1. provide a timing source of half of one bit (twice the Baud clock rate)
2. wait for the input to go low (detecting either a start bit of a low data bit)
3. wait one half bit length
4. create a loop counter for each bit, usually there are 8 bits.
5. read the input and save it in the LSB of your data storage variable.
6. shift the variable one bit to the left.
7. wait TWO half bit lengths.
8. subtract 1 from the loop counter
9. keep going back to step 5 until the loop counter has reached zero.
10. wait TWO half bit lengths.
11. if the input is high, the received data byte is in your variable, if the input is low you have a framing error and need to try again.
12. Wait for the input to go high so it is ready for the next byte to arrive.

Note that other than detecting a framing error, there is no fault detection. You should check the received data is as expected and have it resent if necessary. The reason for the half-bit delay after detecting the beginning of the start bit is so the next time you sample the input is is in the middle of the data bits.

Brian.
 
This is highly device dependent so there is no generic 'C' code that will work in all situations.

The principle is -
Transmitting:
1. provide a timing source one bit long (the Baud rate clock).
2. drive the output low for one bit period, this is called the 'start bit'.
3. create a loop counter for each bit, usually there are 8 bits.
4. if the LSB of the data is low, drive the output low, if it is high, drive it high.
5. shift the data one bit to the right so that data bit 1 becomes the LSB.
6. subtract 1 from the loop counter.
7. wait one bit period.
8. keep going back to step 4 until the loop counter reaches zero.
9. drive the output high for one bit period, this is called the 'stop bit'

Repeat all the above for each byte of data you want to send.

Receiving:
1. provide a timing source of half of one bit (twice the Baud clock rate)
2. wait for the input to go low (detecting either a start bit of a low data bit)
3. wait one half bit length
4. create a loop counter for each bit, usually there are 8 bits.
5. read the input and save it in the LSB of your data storage variable.
6. shift the variable one bit to the left.
7. wait TWO half bit lengths.
8. subtract 1 from the loop counter
9. keep going back to step 5 until the loop counter has reached zero.
10. wait TWO half bit lengths.
11. if the input is high, the received data byte is in your variable, if the input is low you have a framing error and need to try again.
12. Wait for the input to go high so it is ready for the next byte to arrive.

Note that other than detecting a framing error, there is no fault detection. You should check the received data is as expected and have it resent if necessary. The reason for the half-bit delay after detecting the beginning of the start bit is so the next time you sample the input is is in the middle of the data bits.

Brian.

sir could you please send me a 'c' code of AT89C51 soft serial communication
 

Ii have never coded for the AT89C51 so I can't help but if you follow the process I described it should be easy to write. You could show what you have tried yourself so we can look for problems in your own code.

Brian.
 

hello,

you can have a look on MikroC for 8051 and UART library ..
if code size < 2Ko you can use MikroC freee of charge (without licence)
pay attention tho the Quartz value !


Code:
#define Version "180702"
#define Directory  " "
#define Project   " "
#define Source     " "
#define MCU  "AT89C2051"
#define FOSC  "18.432MHz"
#define POWER_Supply "5V"
#define XTAL 18432000
#define BAUDRATE
#define BitTimer (((XTAL/BAUDRATE)/12) - 5) / 2

#define Byte unsigned char
#define Word unsigned int

#define TRUE 1
#define FALSE 0
#define CR 13
#define LF 10

#define LED_Error P1.B4


#define ON 0
#define OFF 1

const char TH1_INIT = 0xB1; // Initial 20mS   at 12MHZ
const char TL1_INIT = 0xE0;

sbit Soft_Uart_RX at P3_0_bit;
sbit Soft_Uart_TX at P3_1_bit;

char TEXTE[64];
Word i,j,k;
volatile unsigned char Count1;
Byte char c1;
Byte Erreur=0;
Byte Dummy;

 /*
   //-------------- Interrupt handler routine
void Timer1InterruptHandler() org IVT_ADDR_ET1
{

  EA_bit  = 0;          // Clear global interrupt enable flag
  TR1_bit = 0;          // Stop Timer1
  TH1 = TH1_INIT;       // Reset Timer1 high byte
  TL1 = TL1_INIT;       // Reset Timer1 low byte
  Count1++;
  if (Count1 >= 20) {
    Soft_UART_Break();
    Count1 = 0;
  }
  TH0 = 0x1c;        // Set Timer1 high byte
  TL0 = 0x23;        // Set Timer1 low byte
  EA_bit = 1;        // reSet global interrupt enable flag
  TR1_bit = 1;       // stop Timer1
}



void Init_Timer1()    //
{
  ET1_bit = 0;       // disable Timer1 interrupt
  GATE1_bit = 0;     // Clear this flag to enable Timer1 whenever TR1 bit is set.
  C_T1_bit  = 0;     // Set Timer operation: Timer1 counts the divided-down systam clock.
  M11_bit   = 0;     // M11_M01 = 01    =>  TMOD=1   (16-bit Timer/Counter)
  M01_bit   = 1;
  TF1_bit = 0;       // Ensure that Timer1 interrupt flag is cleared
  TR1_bit = 0;       // Turn off Timer1
  TH1 =TH1_INIT;       // Set Timer1 high byte
  TL1 =TL1_INIT;        // Set Timer1 low byte
  PT1_bit=1;         // priorité
    // to active Here
  TR1_bit = 0;       // Stop timer1    (1=Run Timer1
  EA_bit  = 0;       // Disable global interrupt enable
  ET1_bit = 0;       // Disable Timer1 interrupt

 }
*/

void main( void)
{
  j=0;
  P3=0xFF;
  P1=0xFF;
  Delay_ms(2000);

  Erreur= Soft_UART_Init(2400,1);
  while (Erreur>0)
  {
   LED_Error=!LED_Error;
   Delay_ms(1000);
  }

   Soft_UART_Write('A');
   Soft_UART_Write('B');
   Soft_UART_Write('C');
   Soft_UART_Write('D');
   Soft_UART_Write(CR);
   Soft_UART_Write(LF);
  
  Delay_ms(1000);
  
  while(1) 
  {
    c1 = Soft_UART_Read(&Erreur);
    if (Erreur)
      LED_Error=1;
    else
      Soft_UART_Write(c1);
    }
  }
 

I think "Soft_UART_Write()" is a library function in MicroC. What Paulfjujo is saying is if you download the MicroC compiler you can look inside its library to see how it works.
The example in post #6 demonstrates how to use the library function but not what is inside it.

Brian.
 

Unfortunately, MikroC libraries don't come with source code. You can at best look at assembly listings.

Simple soft UART codes for other processors are exclusively using delay loops to generate the bit timing. Respectively they can't simultaneously perform other real time operations.
 

manu8193, I have deleted your duplicate thread asking for this software. Please keep all your posts on this topic in this thread instead of starting new ones.

We try to help people here by assisting them and instructing them with projects, whether hardware or software but we are not a free design service. If you show us what you have done so far we will try to guide you. So far all you have told us is you want someone to write code for you, we don't even know which compiler you are using. Make an effort yourself, we have already told you exactly what to do.

Brian.
 

ok sir

idont know how to write so iam asking while iam using turbo c complier
 

Agreed - my copy of Turbo C 2.00 dates back to about 1989/1990 and it only compiles code for 80x86 processors. It can not be used to write code for AT89C51 MCUs and it relies on the DOS operating system to provide hardware UART interfacing.

Manu8193, as I stated in post #3, a 'soft' UART is one where your code drives the pins under software control, you have to tell the pins when to go high or low and when to do it, the code for each MCU is different so the code has to be specific to the MCU you are using and which pins on it you are using to transmit and receive. The principle is the same for all MCUs though, that's why I explained how to do it but couldn't give you working code.

Brian.
 

hello,


You want to use a AT89C51 ?
You want use C langage ?
so load MikroC for 8051 , you will have all to do it

IDE & Compiler

MikroC_for_8051.jpg


but you will have to do some work and efforts to understand how softuart works
keyword are "Full_bit" and "half_bit"
learn theory before to pratice..



extract of *.LSt file resulting of compilation C program

Code:
;__Lib_SoftUART.c,152 :: 		
0x024D	0x851C0E  	MOV __Lib_SoftUART_FullBit, Soft_UART_Init_temp_word_L0+0
;__Lib_SoftUART.c,153 :: 		
0x0250	0xAC18    	MOV R4, Soft_UART_Init_q2_L0
0x0252	0xAD19    	MOV R5, Soft_UART_Init_q2_L0+1
0x0254	0xAE1A    	MOV R6, Soft_UART_Init_q2_L0+2
0x0256	0xAF1B    	MOV R7, Soft_UART_Init_q2_L0+3
0x0258	0xA814    	MOV R0, Soft_UART_Init_q1_L0
0x025A	0xA915    	MOV R1, Soft_UART_Init_q1_L0+1
0x025C	0xAA16    	MOV R2, Soft_UART_Init_q1_L0+2
0x025E	0xAB17    	MOV R3, Soft_UART_Init_q1_L0+3
0x0260	0x3153    	ACALL _Div_32x32_S
0x0262	0xA804    	MOV R0, R4
0x0264	0xA905    	MOV R1, R5
0x0266	0xAA06    	MOV R2, R6
0x0268	0xAB07    	MOV R3, R7
0x026A	0x850014  	MOV Soft_UART_Init_q1_L0, 0
0x026D	0x850115  	MOV Soft_UART_Init_q1_L0+1, 1
0x0270	0x850216  	MOV Soft_UART_Init_q1_L0+2, 2
0x0273	0x850317  	MOV Soft_UART_Init_q1_L0+3, 3
;__Lib_SoftUART.c,155 :: 		
0x0276	0x7C01    	MOV R4, #1
0x0278	0xA818    	MOV R0, Soft_UART_Init_q2_L0
0x027A	0xA919    	MOV R1, Soft_UART_Init_q2_L0+1
0x027C	0xAA1A    	MOV R2, Soft_UART_Init_q2_L0+2
0x027E	0xAB1B    	MOV R3, Soft_UART_Init_q2_L0+3
0x0280	0x31B1    	ACALL __shr_longint
0x0282	0xD3      	SETB C
0x0283	0xE514    	MOV A, Soft_UART_Init_q1_L0
0x0285	0x98      	SUBB A, R0
0x0286	0xE515    	MOV A, Soft_UART_Init_q1_L0+1
0x0288	0x99      	SUBB A, R1
0x0289	0xE516    	MOV A, Soft_UART_Init_q1_L0+2
0x028B	0x9A      	SUBB A, R2
0x028C	0xEB      	MOV A, R3
0x028D	0x6480    	XRL A, #128
0x028F	0xFC      	MOV R4, A
0x0290	0xE517    	MOV A, Soft_UART_Init_q1_L0+3
0x0292	0x6480    	XRL A, #128
0x0294	0x9C      	SUBB A, R4
0x0295	0x4002    	JC L_Soft_UART_Init23
;__Lib_SoftUART.c,156 :: 		
0x0297	0x050E    	INC __Lib_SoftUART_FullBit
L_Soft_UART_Init23:
;__Lib_SoftUART.c,158 :: 		
0x0299	0x7801    	MOV R0, #1
0x029B	0xE50E    	MOV A, __Lib_SoftUART_FullBit
0x029D	0x08      	INC R0
0x029E	0x8002    	SJMP L__Soft_UART_Init32
L__Soft_UART_Init33:
0x02A0	0xC3      	CLR C
0x02A1	0x13      	RRC A
L__Soft_UART_Init32:
0x02A2	0xD8FC    	DJNZ R0, L__Soft_UART_Init33
0x02A4	0xF9      	MOV R1, A
0x02A5	0x85010D  	MOV __Lib_SoftUART_HalfBit, 1
;__Lib_SoftUART.c,160 :: 		
0x02A8	0xC3      	CLR C
0x02A9	0xE9      	MOV A, R1
0x02AA	0x9407    	SUBB A, #7
0x02AC	0x5005    	JNC L_Soft_UART_Init24
;__Lib_SoftUART.c,161 :: 		
0x02AE	0x7801    	MOV R0, #1
0x02B0	0x7900    	MOV R1, #0
0x02B2	0x22      	RET



.. bit bang software uart for a PIC ... but principle is same as for other MCU
Code:
#ifndef CR
#define CR 13
#define LF 10
#endif


// la Pin de sortie est definie dans le main program
 sbit TX3_Pin at LATA.B2;
 sbit TX3_Pin_Direction at TRISA.B2;


unsigned char c3 absolute 0x0020;
unsigned char RS_Count;
unsigned char  RS_tmp;
unsigned char RS_Delay  ;


void UART3_Write(unsigned char c1);         // ecrit 1 char
void UART3_Write_Text(unsigned char *T);    // ecrit un texte situé en RAM
void UART3_Write_CText(const char *txt3);    // ecrit un texte en dur (situé en ROM)
void CRLF3(void) ;                     // envoit saut de Ligne  13 , 10   ( CR LF)




void UART3_Write_CText(const char *txt3)
 {
   while (*txt3)
     {
     UART3_Write(*txt3++);
    // Delay_us(500);
     }
}


void UART3_Write_Text(unsigned char *T)    // at adress  0x002 taille 42 bytes
{
  while(*(T)>0)     // verif sur VBRAY en mode ASCII
   {
    UART3_Write(*(T++));   // c3 variable globale
   }
}


void CRLF3()
{
 UART3_Write(CR);
 UART3_Write(LF);
}




void UART3_Write(unsigned char cc)      // 16MHz 19200 bauds
{
    c3=~cc;    // complement du caractere !
    // avec TX3_PIN => RA2
  _asm{
    RSsend2:
        movlw   8                ; 8 bits
        movwf   _RS_Count        ; compteur de bits envoyés
        bcf     LATA,2            ; bit de start
        call    RSdelai2        ; tempo
       //   rrf        _c1,f        ; on recupere dans C le bit à envoyer
       //  syntaxe à revoir en fonction du PIC utilisé   rrcf avec 18F87J50
    L00:
        rrf    _c3,1        ; on recupere dans C le bit à envoyer
        btfsc   STATUS,C        ; bit à envoyer = 1 ?
        goto    L10                ; oui
        bsf     LATA,2          ; sinon 0
        goto    L20                ; on continue sur la tempo
    L10:
        bcf     LATA,2          ; bit à 1
    L20:
        call    RSdelai2                ; tempo
        decfsz  _RS_Count,1        ; on decremente le compteur de bits envoyés
        goto    L00                ; on continue sur les bits suivants
        bsf     LATA,2         ; bit de stop
        call    RSdelai2        ; tempo pour bit de stop
         call    RSdelai2        ; tempo pour bit de stop
        goto    LA1


    RSdelai2:                 // 52µS / bit at 19200 bauds
         MOVLW 28 ;
         MOVWF _RS_tmp ;
    RS00:
         NOP;                ; fait parti de la tempo!
         NOP;
         NOP;
         NOP;
        // NOP;
         DECFSZ _RS_tmp,F ;
         GOTO   RS00 ;
         NOP;
         NOP;
         NOP;
         RETURN ;


    LA1:    nop;
   }
 }
 
Last edited:

That narrows it down to about 100 different compilers. IDE = Integrated Development Environment but which one are you using?
It is a generic term for any development software where the component parts are combined into one program.

Brian.
 

sir could you send me a full code and theroy of this soft why because iam trying to search so many books and online websites to learn soft UART

i didn't find this soft serial UART

so please send me this topic and code with explaination
 

Hi,

First you asked for an explanation.
Now you ask for code. But this is not how a forum is meant to work.
If you want someone to write code for you, then consider to pay for this.

Klaus
 

turbo c compiler is used sir
Again, Turbo C is not compatible with AT89C51.
It is not possible to compile code that will work with that MCU.
Turbo C only compiles code for 80x86 processors.

Brian.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top