I was recently asked for a project which I had worked on during my undergraduate studies. The Project involved writing a firmware through which two Microchip family based 16f877A Micro-controllers could communicate with each other using a single bidirectional port the input they received was from a serial RS-232 port (I know they are obsolete now .. however porting this project to a PIC 18F4550 for a USB interface is definitely on my to do list since i no longer work with firmware that would definitely be a welcoming change) .
The .hex file got generated using the following code
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, float_high, bits=9, xmit=PIN_B0, rcv=PIN_B0)
#define OUR_ID 1
#define MAX_MESSAGES 4
#define MAX_LENGTH 7
byte pbus_buffer[MAX_MESSAGES][MAX_LENGTH+1];
byte next_in=0;
byte next_out=0;
enum pbus_states {PBUS_IDLE=0x80,PBUS_NEED_LEN=0x81,PBUS_NEED_TO=0x82,
PBUS_NEED_FROM=0x83,PBUS_NEED_CS=0x84};
byte pbus_state=PBUS_IDLE;
byte checksum;
byte last_byte;
#bit ninth_bit = RS232_ERRORS.7
#bit collision = RS232_ERRORS.6
#bit intf = 11.1
#int_ext
void pbus_isr() {
byte data;
if(kbhit()) {
data=getc();
if(ninth_bit) {
switch(pbus_state) {
case PBUS_IDLE : if(data==0xf1)
pbus_state=PBUS_NEED_TO;
break;
case PBUS_NEED_TO :
if(data==OUR_ID)
pbus_state=PBUS_NEED_FROM;
else
pbus_state=PBUS_IDLE;
checksum=data;
break;
case PBUS_NEED_FROM :
pbus_buffer[next_in][0] = data;
pbus_state=PBUS_NEED_LEN;
checksum^=data;
break;
case PBUS_NEED_LEN :
last_byte = data+1;
pbus_buffer[next_in][1] = data;
pbus_state=2;
checksum^=data;
break;
}
} else
if(pbus_state==PBUS_NEED_CS) {
if(checksum==data)
next_in = (next_in+1) % MAX_MESSAGES;
pbus_state=PBUS_IDLE;
} else if(pbus_state<0x80) {
pbus_buffer[next_in][pbus_state] = data;
checksum^=data;
if(++pbus_state>last_byte)
pbus_state=PBUS_NEED_CS;
}
}
}
void pbus_send( byte * message, byte to, byte len) {
byte checksum,i;
retry:
checksum=len^OUR_ID^to;
disable_interrupts(GLOBAL);
collision=false;
ninth_bit=1;
putc(0xf1); if(collision) goto error;
putc(to); if(collision) goto error;
putc(OUR_ID); if(collision) goto error;
putc(len); if(collision) goto error;
ninth_bit=0;
for(i=1;i<=len;++i) {
checksum^=*message;
putc(*(message++)); if(collision) goto error;
}
putc(checksum); if(collision) goto error;
intf=false;
enable_interrupts(GLOBAL);
return;
error:
delay_ms(16);
enable_interrupts(GLOBAL);
goto retry;
}
#if defined( __PCB__)
#use rs232(baud=9600, xmit=PIN_A3, rcv=PIN_A2)
#elif defined(__PCM__)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#elif defined(__PCH__)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#endif
#include <input.c>
void main() {
byte to,len,i,msg[MAX_LENGTH];
printf("\r\nOur unit ID is %d\r\nPress S to send.\r\n",OUR_ID);
ext_int_edge( h_to_l );
enable_interrupts(global);
enable_interrupts(int_ext);
do {
if(next_in!=next_out) {
printf("\r\nMessage from #%d: ",pbus_buffer[next_out][0]);
for(i=2;i<=pbus_buffer[next_out][1]+1;++i)
printf(" %2X",pbus_buffer[next_out][i]);
next_out=(next_out+1) % MAX_MESSAGES;
}
if(kbhit())
if(toupper(getc())=='S') {
printf("\r\nSend to: ");
to=gethex();
printf("\r\nLength: ");
len=gethex();
for(i=0;i<len;++i) {
printf("\r\nByte %d: ",i+1);
msg[i]=gethex();
}
pbus_send(msg,to,len);
printf("\r\nSent.");
}
} while (TRUE);
}
and offcourse the schematic diagram is :
The .hex file got generated using the following code
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, float_high, bits=9, xmit=PIN_B0, rcv=PIN_B0)
#define OUR_ID 1
#define MAX_MESSAGES 4
#define MAX_LENGTH 7
byte pbus_buffer[MAX_MESSAGES][MAX_LENGTH+1];
byte next_in=0;
byte next_out=0;
enum pbus_states {PBUS_IDLE=0x80,PBUS_NEED_LEN=0x81,PBUS_NEED_TO=0x82,
PBUS_NEED_FROM=0x83,PBUS_NEED_CS=0x84};
byte pbus_state=PBUS_IDLE;
byte checksum;
byte last_byte;
#bit ninth_bit = RS232_ERRORS.7
#bit collision = RS232_ERRORS.6
#bit intf = 11.1
#int_ext
void pbus_isr() {
byte data;
if(kbhit()) {
data=getc();
if(ninth_bit) {
switch(pbus_state) {
case PBUS_IDLE : if(data==0xf1)
pbus_state=PBUS_NEED_TO;
break;
case PBUS_NEED_TO :
if(data==OUR_ID)
pbus_state=PBUS_NEED_FROM;
else
pbus_state=PBUS_IDLE;
checksum=data;
break;
case PBUS_NEED_FROM :
pbus_buffer[next_in][0] = data;
pbus_state=PBUS_NEED_LEN;
checksum^=data;
break;
case PBUS_NEED_LEN :
last_byte = data+1;
pbus_buffer[next_in][1] = data;
pbus_state=2;
checksum^=data;
break;
}
} else
if(pbus_state==PBUS_NEED_CS) {
if(checksum==data)
next_in = (next_in+1) % MAX_MESSAGES;
pbus_state=PBUS_IDLE;
} else if(pbus_state<0x80) {
pbus_buffer[next_in][pbus_state] = data;
checksum^=data;
if(++pbus_state>last_byte)
pbus_state=PBUS_NEED_CS;
}
}
}
void pbus_send( byte * message, byte to, byte len) {
byte checksum,i;
retry:
checksum=len^OUR_ID^to;
disable_interrupts(GLOBAL);
collision=false;
ninth_bit=1;
putc(0xf1); if(collision) goto error;
putc(to); if(collision) goto error;
putc(OUR_ID); if(collision) goto error;
putc(len); if(collision) goto error;
ninth_bit=0;
for(i=1;i<=len;++i) {
checksum^=*message;
putc(*(message++)); if(collision) goto error;
}
putc(checksum); if(collision) goto error;
intf=false;
enable_interrupts(GLOBAL);
return;
error:
delay_ms(16);
enable_interrupts(GLOBAL);
goto retry;
}
#if defined( __PCB__)
#use rs232(baud=9600, xmit=PIN_A3, rcv=PIN_A2)
#elif defined(__PCM__)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#elif defined(__PCH__)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#endif
#include <input.c>
void main() {
byte to,len,i,msg[MAX_LENGTH];
printf("\r\nOur unit ID is %d\r\nPress S to send.\r\n",OUR_ID);
ext_int_edge( h_to_l );
enable_interrupts(global);
enable_interrupts(int_ext);
do {
if(next_in!=next_out) {
printf("\r\nMessage from #%d: ",pbus_buffer[next_out][0]);
for(i=2;i<=pbus_buffer[next_out][1]+1;++i)
printf(" %2X",pbus_buffer[next_out][i]);
next_out=(next_out+1) % MAX_MESSAGES;
}
if(kbhit())
if(toupper(getc())=='S') {
printf("\r\nSend to: ");
to=gethex();
printf("\r\nLength: ");
len=gethex();
for(i=0;i<len;++i) {
printf("\r\nByte %d: ",i+1);
msg[i]=gethex();
}
pbus_send(msg,to,len);
printf("\r\nSent.");
}
} while (TRUE);
}
and offcourse the schematic diagram is :
No comments:
Post a Comment