Creation date 21.07.2001
Chapter of:
Author(s): hpbaby
Navigator: previous main
Version:     EN

Best in:1024*768

THE HIGH REALIZATIONS

The RS232 protocol


Used every time on serial wires for short distances, this protocol (well known in the industrial field) allows to backup,configure,command many tiny systems AGENDAS,PSION,HP..


I - THEORIC SIDE

1) The complete frame

It is the result of 10 patterns spread into 3 blocks like this:

with ?=0 or 1 for the pattern value (depends on the block to transmit).

 

2) Meaning of the blocks


START:Indicates the end of transmission and allows receiver synchronization
DATA:Contains the value of the char sent: DATA=D7*128+D6*64+D5*32+D4*16+D3*8+D2*4+D1*2+D0*1
STOP:Indicates the end of transmission for this frame

3) Basic patterns

Here are the elementary and repetitive pieces of the electric signal :

  • representing either 0 or 1 , the value of the pattern.
  • forming the whole frame.


Pattern START
D0 à D7
STOP
Possible values 1 0 1 0
Representation

Warning, the glue between each pattern is not shown here.

4) The dynamic model

Difficulties to understand? then look at this. The datas (or several control fields, ie not constant) of the frame are located in the patterns of the frame that can be changed. These are represented for you by buttons you can manipulate. The value on the buton is either the value of a block (see the meaning in paragraph 2 ) or the value of the pattern. Click on the buttons , observe , et analyze what happens on the electric signal..
  • if the frame is

  • then electricaly , the signal will be:

 

Try now do do the inverse : take one electric signal , deduce the value transmitted for each pattern you see, calculate each bloc value and guess what action is triggered. Click on one or more pattern on the signal and you will get the answer! If you let your mouse cursor on one pattern, you will even get its name.


RS232 PRATIQUE

II - PRATICAL SIDE

Just have a look on the basis patterns..you will notice that the value of the pattern is the inverse read on the signal. Hereby , you need to invert the signal before reading .As the max232 chip our friend, it does this for in the two ways of the exchanges. All you need to do is to read at the half duration of each pattern.

 

1) Decoding a RS232 frame

I have generated a low pulse on yellow signal to indicate the instants you should extract the 8 data patttern values that represents the char sent.

The START pattern has been ignored, I start to read the first DATA pattern in its half.


Then, I go to the next pattern by jumping a pattern duration. The value is read in the half of the pattern too to be sure not to read a transient level (edge). In this sample, the read char (8 paterns) value is 72 or H (72 CHR ENTER) in ASCII.

Binary digit read 1 1 1 0 1 1 0 1
Total
Binary digit true value or value of the pattern 0 0 0 1 0 0 1 0
Multiplicator factor (binary weight) 1 2 4 8 16 32 64 128
Multiplicator Result 0 0 0 8 0 0 64 0
72

 

The following tables give two interessant values: 85 et 170.

Phenomenon not insignifiant, the microcontroler take the signa linto account only after a latteny time (TirqLatency) of 60 microsecondes.


That means that if the signal last less than TirqLatency, the microrontroler didn't even notice the signal change and did not trigger the program associeted with the pin.

Binary digit read 1 0 1 0 1 0 1 0
Total
Binary digit true value or value of the pattern 0 1 0 1 0 1 0 1
Multiplicator factor (binary weight) 1 2 4 8 16 32 64 128
Multiplicator Result 0 2 0 8 0 32 0 128
170


Here I show with vertical markers , the jump over the start pattern to select the half first data pattern for reading.

 

Be very precise for the jump durations or you will overflow on either the next or previous pattern..The worse thing It can happen to you in to read on a edge (random value).

Binary digit read 0 1 0 1 0 1 0 1 Total
Binary digit true value or value of the pattern 1 0 1 0 1 0 1 0
facteur multiplicatif (poids binaire) 1 2 4 8 16 32 64 128
Résultat multiplication 1 0 4 0 16 0 64 0
85


2) Encoding a RS232 frame

I generate the electrical signal by software using delay routines.

On the left, during the copy (in yellow) of the char received (in white), I have revealed a parasite(glitch) .

In fact , this can't be considered as as parasite but
a well know problem with pic micocontrolers: if you attempt to write the same value twice (one after the other) on the same pin (like here with 0), the mircocontroler redo a not necessary write .

 

Unfortunately , like all operation, it lasts and let the pin level to undefined level (to tristrate) for a short time. Although this is not blocking for the receiver, I have corrected my program to avoid such things.

 

Here I sent the char U twice (bottom signal)

If you compare the two signals, you will notice that the second char is ignored.

That is due to my program who wait the end of a frame before procesing an other one .This can be fixed by sending during the receiving phase.

III - MY PROGRAM

Use this to establish a link at 9600 bauds between a PIC16F84 (PICSYS) and any other RS232 system .

rs232.c

#include <pic.h> //obligatory

//Quartz 4Mhz
#define PIC_CLK 4000000

//The delay routines
#include "delay.h"

//I use a chrystal and my code is not protected
__CONFIG(FOSC0|PWRTE |CP);

/**
* RS232 link management at 9600 bauds
*
*/

//This replaces bitfields implementation

#define PORTBIT(adr, bit) ((unsigned)(&adr)*8+(bit))
#define getbit(data,bitno) ((data>>bitno)&0x01)
#define setnbit(data,bitno) (data<<bitno)
#define setbit(data,bitno,value) (data&(~setnbit(1,bitno))|setnbit(value,bitno))
#define togglebit(data) (data^0x01)

//Duration in microsecond (the microcontroler is blind during this duration if the signal change on its 'IT interruption pin)
#define TirqLatency 60

/************Serial link*******************************/

//Receiver parameters
//-----------------------------

#define Tbit_rx_RS232 104 //Reception T=1/9600=104us à 9600 bauds
#define Jump_over_RS232_rx_startbit (Tbit_rx_RS232-TirqLatency+(Tbit_rx_RS232/2))
#define Nb_RS232_rx_databits 8 // 8 bits de données
#define Jump_over_RS232_rx_databits (Tbit_rx_RS232-15) //the loop takes 12us
#define Nb_RS232_rx_stopBits 1 //1 bit stop
#define Jump_over_RS232_rx_stopbits (Nb_RS232_rx_stopBits*Tbit_rx_RS232)

//Emitter parameters
//--------------------------

#define Tbit_tx_RS232 104
#define Duration_RS232_tx_startbit (Tbit_tx_RS232-30)
#define Nb_RS232_tx_databits 8
#define Duration_RS232_tx_databits (Tbit_tx_RS232-30)
#define Nb_RS232_tx_stopBits 1
#define Duration_RS232_tx_stopbits (Nb_RS232_tx_stopBits*Tbit_tx_RS232)


#define ITMask 0B10110000

//---- Pin attributions -------------

static bit RS_OUT @ PORTBIT(PORTA, 4); //Send pin
static bit RS_IN @ PORTBIT(PORTB, 7); //Get pin

//To display voir the char on a 8 leds panel
volatile bit D1 @ PORTBIT(PORTB, 3);
volatile bit D2 @ PORTBIT(PORTB, 2);
volatile bit D3 @ PORTBIT(PORTB, 1);
volatile bit D4 @ PORTBIT(PORTB, 0);
volatile bit D5 @ PORTBIT(PORTA, 3);
volatile bit D6 @ PORTBIT(PORTA, 2);
volatile bit D7 @ PORTBIT(PORTA, 1);
volatile bit D8 @ PORTBIT(PORTA, 0);

//---- Working variables ---------------------------
//used by the delay routines
volatile unsigned int timeout;

//buffer variable
unsigned char Buff;

unsigned char TxBuff; // char to send
unsigned char RxBuff;// char received

//------ Declaration of the RS232 routines -------------------------------

void RSsend(void); /* Send the char Buff on the serial port */
void RSget(void); /* Read the serial port and save it into Buff*/

//-------Panel Leds routines -------------

void WriteParport(void);
void ReadParport(void);

//------ Main program to init ports and allow interrupts---------
main()
{

//Indicate pin direction (INPUT /OUTPUTS)
TRISB = ITMask;
TRISA = 0;

//Set the default pin levels
PORTA = 0;
PORTB = 0b10000000;
RS_OUT=1;

//grant the interrupts on the port B
RBIE=1;
GIE=1;

//infinite loop to disturb
for(;;) {

}

}

//-----Show the Buff content on the 8 leds panel
void WriteParport(void) {

D1=getbit(Buff,0);
D2=getbit(Buff,1);
D3=getbit(Buff,2);
D4=getbit(Buff,3);
D5=getbit(Buff,4);
D6=getbit(Buff,5);
D7=getbit(Buff,6);
D8=getbit(Buff,7);

}

//----Retreive the value of the 8 leds (D1-D8) and store it into Buff .
void ReadParport(void) {

Buff=setbit(Buff,0,D1);
Buff=setbit(Buff,1,D2);
Buff=setbit(Buff,2,D3);
Buff=setbit(Buff,3,D4);
Buff=setbit(Buff,4,D5);
Buff=setbit(Buff,5,D6);
Buff=setbit(Buff,6,D7);
Buff=setbit(Buff,7,D8);

}

unsigned char prev_portb=0B10000000; //latch the value of B port

// Interruption routine triggered by a signal change (and lasts more thanTirqLatency!) on any pin:
// RB7, RB6,RB5,RB4 and RB0

interrupt isr()
{


//Try to know which pin change..
if (RBIF)
{
RBIF=0; //Interruption acquittment


if ((prev_portb ^ (PORTB&ITMask)) == 0B10000000)
{


//It is the RB7=RS IN which has changed, a char need to be analyzed
if ((PORTB & 0B10000000) == 0) //If it is the falling edge of the start bit then
{
//receive the char behind
RSget();
//display its value on the panel leds
Buff=RxBuff;
WriteParport();
//and send it for acknowledgment
TxBuff=RxBuff;
RSsend();
}

}

prev_portb=PORTB&ITMask; //Next char..

}


}



// RS232 routines
//------------------

/*Send a char defined in TxBuff on RA4 pin at RS232 format */

void RSsend(void) {
unsigned b;
unsigned prevbit;

// start pattern
RS_OUT=0;
DelayUs(Duration_RS232_tx_startbit); // start pattern duration

//for each data pattern
for(b=Nb_RS232_tx_databits;b--;) {

prevbit=(TxBuff&0x01);

if(prevbit^RS_OUT) //si the previous pattern value is different from the actual pattern value
RS_OUT=TxBuff&0x01; //send it else don't change anything

if(b>0) //if it is not the first pattern, go on..
TxBuff=TxBuff>>1; //I have finished the process for this patttern , newt one pleaset

DelayUs(Duration_RS232_tx_databits);//data pattern duration

}

//Bit stop
RS_OUT=1;
DelayUs(Duration_RS232_tx_stopbits);//stop pattern duration

}

/* Receives a char on RA1 and stores it into RXBuff **/

void RSget(void) {


unsigned b;
RxBuff='\0';


//Jump over the start pattern and select the half first data pattern .
//RS_OUT=0;
DelayUs(Jump_over_RS232_rx_startbit); // Delay for this
//RS_OUT=1;

//Read the 8 data patterns one after the other that is being send to me..
for(b=Nb_RS232_rx_databits;b--;) {

RxBuff=RxBuff | ((RS_IN&0x01)<<(Nb_RS232_rx_databits-1));

/* For debug */
//RS_OUT=0;

if(b>0) //Patterns remaining?
RxBuff=RxBuff >> 1; //yes, next please.

DelayUs(Jump_over_RS232_rx_databits); //we jump a pattern duration to go to the next pattern
//RS_OUT=1;

}


DelayUs(Jump_over_RS232_rx_stopbits); //optionnal as STOP pattern does not contain any data.

}

 

 



Lab48 :
Scope for HP and
signal generator +5/-5V 
with 8 logical Inputs/Outputs
Hpmodem :
To dial by an radio link between
2 HP - externals power supply are required
Hptalk :
How to spell alphabet letters with HP by the use a vocal digitalizer from ISD
HpDomotic  :
1)Build your PIC  programmer (picdev)
2)Build you domotic interface  (picsys)
3)The multiusage Infrared module
  a)IR management of the HP
  b)Serial management HP / PC
  c)Encoding/decoding  RC5 frames
  to :
   Control PC , TV, Recorder.