View previous topic :: View next topic |
Author |
Message |
agreement
Joined: 08 Oct 2010 Posts: 10
|
USART multiprocessors |
Posted: Sat Mar 12, 2011 1:43 am |
|
|
Hi! I'm going to setup a small network with 1 master and 2 slave .
I use 9th bit mode with address detect.
In slave chip, data will be received when interrupt be called by 9th bit =1 , RCIF bit=1 and interrupt be enabled.
Here is my code for master and slave:
Master
Code: |
#include <16F877A.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=20000000)
#byte SPBRG =0x99 // baudrate reg
#byte TXREG =0x19 // trans data reg
#byte RCSTA =0x18 // recieve data reg
#define SPEN 7
#define RX9 6
#define SREN 5
#define CREN 4
#define ADDEN 3
#define FERR 2
#define OERR 1
#define RX9D 0
#byte TXSTA =0x98 // trans data control reg
#define CSRC 7
#define TX9 6
#define TXEN 5
#define SYNC 4
#define BRGH 2
#define TRMT 1
#define TX9D 0
int i;
void Init_UART(void)
{
TXSTA|=(1<<TX9); //select 9-bit transmissio
SPBRG= 31; // set baudrate 9600
SET_TRIS_B( 0xFF); // set TX, RX
TXSTA&=~(1<< BRGH ); //Low speed
TXSTA&=~(1<<SYNC); //Asynchronous mode
TXSTA|=(1<<TXEN); //Transmit enable
RCSTA|=(1<<SPEN); //Serial port enable
RCSTA|=(1<<CREN ); // eneble reception.
}
// trans address
void tx_add(unsigned int chr)
{
while(!(TXSTA&(1<<TRMT)));
for( i=0; i<30;i++);
TXSTA|= (1<<TX9D); // set bit 9th
TXREG= chr;
}
// trans data
void tx_data(unsigned int chr)
{
while(!(TXSTA&(1<<TRMT)));
for( i=0; i<30;i++);
TXSTA&= ~(1<<TX9D); // clear bit 9th
TXREG= chr;
}
void main()
{
Init_UART();
while(1){
tx_add(1);
tx_data(66);
}
}
|
Code for slave:
Code: |
#include <16F877A.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=20000000)
#byte SPBRG =0x99 // baudrate reg
#byte TXREG =0x19 // trans data reg
#byte RCSTA =0x18 // rev data reg
#define SPEN 7
#define RX9 6
#define SREN 5
#define CREN 4
#define ADDEN 3
#define FERR 2
#define OERR 1
#define RX9D 0
#byte TXSTA =0x98 // trans data control reg
#define CSRC 7
#define TX9 6
#define TXEN 5
#define SYNC 4
#define BRGH 2
#define TRMT 1
#define TX9D 0
#byte PIE1 =0x8C //
#define PSPIE 7
#define ADIE 6
#define RCIE 5
#define TXIE 4
#define SSPIE 3
#define CCP1IE 2
#define TMR2IE 1
#define TMR1IE 0
#byte RCREG = 0x1A
// ngat
//#byte INTCON = 0x0b
#define GIE 7
#define PEIE 6
#byte PIR1 = 0x0C
#define PSPIF 7
#define ADIF 6
#define RCIF 5
#define TXIF 4
#define SSPIF 3
#define CCP1IF 2
#define TMR2IF 1
#define TMR1IF 0
unsigned char ind;
unsigned char data;
unsigned char all_data[2];
unsigned char addr= 1;
#INT_RDA
RDA_ISR(unsigned char data, unsigned char all_data[2] )
{
while (!(PIR1&(1<<RCIF)));
data= RCREG;
if ( ind == 0)
{
if ( addr == data)
{
RCSTA&= ~(1<<ADDEN); // clear bit 9th
ind ++;
}
}
else{
all_data[ind]= data;
ind ++;
// TXREG= all_data[ind];
while(!(TXSTA&(1<<TRMT)));
TXREG= all_data[ind];
if( ind ==2)
{
RCSTA|= (1<<ADDEN); // set bit 9th
ind =0;
}
}
}
void Init_UART(void)
{
TXSTA|=(1<<TX9); //select 9-bit transmission.
TXSTA&=~(1<<SYNC);
RCSTA|=(ADDEN<<1); //enable address detection.
PIE1|=(RCIE << 1); //enable interrupt.
RCSTA|=(RX9 << 1); //select 9-bit reception.
INTCON|=(GIE << 1); // for interrupt
INTCON|=(PEIE << 1);
SPBRG= 31; // set baudrate
SET_TRIS_B( 0xFF); // set TX, RX
TXSTA&=~(1<< BRGH ); //Low speed
TXSTA&=~(1<<SYNC); //Asynchronous mode
TXSTA|=(1<<TXEN); //Transmit enable
RCSTA|=(1<<SPEN); //Serial port enable
RCSTA|=(1<<CREN ); // eneble reception.
}
void tx_data(unsigned char chr)
{
while(!(TXSTA&(1<<TRMT)));
TXREG= chr;
}
char temp;
void main()
{
// long int i,j;
// TODO: USER CODE!!
Init_UART();
set_tris_a(0xFF);
enable_interrupts(GLOBAL);
while(1)
{
}
}
|
I use Proteus to debug it and see RCIF doesn't change its value although RCREG have received data. So it can't go to the interupt service. Can you help me plzzz? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Mar 12, 2011 4:16 pm |
|
|
I strongly suggest that you use CCS functions. Example of why:
Here, you have defined GIE and PEIE as their bit numbers instead of
their bitmasks.
Code: |
#define GIE 7
#define PEIE 6
INTCON|=(GIE << 1); // for interrupt
INTCON|=(PEIE << 1);
|
So then you shift the bit numbers left by 1. So you are shifting 0x07
and 0x06 left by 1 bit position. Considering that the true bitmask for
GIE is 0x80 and PEIE is 0x40, your code will not work. Here is the .LST
file for your code. Notice that it's putting 0x0E and 0x0C into INTCON.
This is incorrect.
Code: |
....... INTCON|=(GIE << 1); // for interrupt
000F: MOVLW 0E
0010: BCF STATUS.RP0
0011: IORWF INTCON,F
.................... INTCON|=(PEIE << 1);
0012: MOVLW 0C
0013: IORWF INTCON,F
|
Now let's look at the CCS function, which you did not want to use.
It does it correctly. It turns on GIE and PEIE correctly in INTCON:
Code: |
.................... enable_interrupts(GLOBAL);
0014: MOVLW C0
0015: IORWF INTCON,F
|
Use the CCS functions. They will prevent errors like this. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9244 Location: Greensville,Ontario
|
|
Posted: Sat Mar 12, 2011 4:34 pm |
|
|
Also put a delay in your xmt forever loop to give your rcv units time to process what's being sent. |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Sat Mar 12, 2011 4:35 pm |
|
|
Hi,
I agree with PCM, there is no need to "roll your own" serial functions, just use the built-in functions provided by the compiler. I also don't know why you want to mess around with the '9th bit' for addressing? Just define a simple protocol that includes a slave address. Each slave will receive all broadcast messages, but only the 'addressed' slave will respond. I just finished a multi-node sensor network using the canned CCS serial routines, and my own data protocol, and it works like a charm!
John |
|
|
agreement
Joined: 08 Oct 2010 Posts: 10
|
|
Posted: Sat Mar 12, 2011 7:03 pm |
|
|
Quote: | I strongly suggest that you use CCS functions. Example of why:
Here, you have defined GIE and PEIE as their bit numbers instead of
their bitmasks.
Code: |
#define GIE 7
#define PEIE 6
INTCON|=(GIE << 1); // for interrupt
INTCON|=(PEIE << 1);
|
|
that's a fool mistake. It must be:
INTCON|=( 1<<GIE); // for interrupt
INTCON|=( 1<<PEIE);
Anyway, use the built in func will be better.
I have corrected that mistake but the program still not work properly, bit RCIF not be set although RCREG have receive data.
Last edited by agreement on Sat Mar 12, 2011 7:06 pm; edited 2 times in total |
|
|
agreement
Joined: 08 Oct 2010 Posts: 10
|
|
Posted: Sat Mar 12, 2011 7:05 pm |
|
|
temtronic wrote: | Also put a delay in your xmt forever loop to give your rcv units time to process what's being sent. |
Thanks! That's good idea! but slave still not go to interrupt service to receive data. :( |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9244 Location: Greensville,Ontario
|
|
Posted: Sat Mar 12, 2011 7:44 pm |
|
|
It'd be a whole lot easier to figure out if you'ld used the built in functions that CCS supplies !
However you seem to be missing the following line from the rcv main ..
enable_interrupts(int_rda);
This line should be before
enable_interrupts(GLOBAL);
Look at the CCS supplied ex_sisr.c example program as well as the help files( F11) in PCM. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Mar 12, 2011 8:45 pm |
|
|
Quote: |
void Init_UART(void)
{
TXSTA|=(1<<TX9); //select 9-bit transmission.
TXSTA&=~(1<<SYNC);
RCSTA|=(ADDEN<<1); //enable address detection.
PIE1|=(RCIE << 1); //enable interrupt.
RCSTA|=(RX9 << 1); //select 9-bit reception.
INTCON|=(GIE << 1); // for interrupt
INTCON|=(PEIE << 1);
SPBRG= 31; // set baudrate
SET_TRIS_B( 0xFF); // set TX, RX
TXSTA&=~(1<< BRGH ); //Low speed
TXSTA&=~(1<<SYNC); //Asynchronous mode
TXSTA|=(1<<TXEN); //Transmit enable
RCSTA|=(1<<SPEN); //Serial port enable
RCSTA|=(1<<CREN ); // eneble reception.
} |
The hardware UART is on pins C6 and C7. It's on Port C, not Port B.
Use 100% CCS library code and functions. Then this won't happen. |
|
|
agreement
Joined: 08 Oct 2010 Posts: 10
|
|
Posted: Sun Mar 13, 2011 12:31 pm |
|
|
PCM programmer wrote: | Quote: |
void Init_UART(void)
{
TXSTA|=(1<<TX9); //select 9-bit transmission.
TXSTA&=~(1<<SYNC);
RCSTA|=(ADDEN<<1); //enable address detection.
PIE1|=(RCIE << 1); //enable interrupt.
RCSTA|=(RX9 << 1); //select 9-bit reception.
INTCON|=(GIE << 1); // for interrupt
INTCON|=(PEIE << 1);
SPBRG= 31; // set baudrate
SET_TRIS_B( 0xFF); // set TX, RX
TXSTA&=~(1<< BRGH ); //Low speed
TXSTA&=~(1<<SYNC); //Asynchronous mode
TXSTA|=(1<<TXEN); //Transmit enable
RCSTA|=(1<<SPEN); //Serial port enable
RCSTA|=(1<<CREN ); // eneble reception.
} |
The hardware UART is on pins C6 and C7. It's on Port C, not Port B.
Use 100% CCS library code and functions. Then this won't happen. |
It's realy a fool mistake. Im sorry about that.
But after I changed it to TRISC or use:
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9)
there is no change in RCIF bit . |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9244 Location: Greensville,Ontario
|
|
Posted: Sun Mar 13, 2011 2:12 pm |
|
|
Since you've made a few changes, repost the program, it'll be easier to follow.... |
|
|
agreement
Joined: 08 Oct 2010 Posts: 10
|
|
Posted: Mon Mar 14, 2011 1:16 am |
|
|
temtronic wrote: | Since you've made a few changes, repost the program, it'll be easier to follow.... |
Yes, this is my code:
For master:
Code: |
#include <16F877A.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9)
#byte TXREG =0x19 // trans data reg
#byte RCSTA =0x18 // recieve data control reg
#define SPEN 7
#define RX9 6
#define SREN 5
#define CREN 4
#define ADDEN 3
#define FERR 2
#define OERR 1
#define RX9D 0
#byte TXSTA =0x98 // trans data control reg
#define CSRC 7
#define TX9 6
#define TXEN 5
#define SYNC 4
#define BRGH 2
#define TRMT 1
#define TX9D 0
int i;
// trans address
void tx_add(unsigned int chr)
{
while(!(TXSTA&(1<<TRMT)));
TXSTA|= (1<<TX9D); // set bit 9th
TXREG= chr;
}
// trans data
void tx_data(unsigned int chr)
{
while(!(TXSTA&(1<<TRMT)));
TXSTA&= ~(1<<TX9D); // clear bit 9th
TXREG= chr;
}
void main()
{
while(1){
delay_ms(500); // wait for slave setup
tx_add(1);
delay_ms(500); // wait for slave go to ISR to receive data
tx_data(66);
}
}
|
For slave
Code: |
#include <16F877A.h>
#device adc=8
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9)
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#byte TXREG =0x19 // trans data reg
#byte RCSTA =0x18 // receive data reg
#define SPEN 7
#define RX9 6
#define SREN 5
#define CREN 4
#define ADDEN 3
#define FERR 2
#define OERR 1
#define RX9D 0
#byte TXSTA =0x98 // trans data control reg
#define CSRC 7
#define TX9 6
#define TXEN 5
#define SYNC 4
#define BRGH 2
#define TRMT 1
#define TX9D 0
#byte RCREG = 0x1A
#byte PIR1 = 0x0C
#define PSPIF 7
#define ADIF 6
#define RCIF 5
#define TXIF 4
#define SSPIF 3
#define CCP1IF 2
#define TMR2IF 1
#define TMR1IF 0
unsigned char ind;
unsigned char data;
unsigned char all_data[2];
unsigned char addr= 1;
#INT_RDA
RDA_ISR(unsigned char data, unsigned char all_data[2] )
{
data= RCREG;
if ( ind == 0)
{
if ( addr == data)
{
RCSTA&= ~(1<<ADDEN); // clear bit 9th
ind ++;
}
}
else{
all_data[ind]= data;
ind ++;
TXREG= all_data[ind];
if( ind ==2)
{
RCSTA|= (1<<ADDEN); // set bit 9th
ind =0;
}
}
}
void main()
{
RCSTA|= (1<<ADDEN); // set bit 9th for slave
enable_interrupts(int_rda);
enable_interrupts(GLOBAL);
while(1)
{
while(!(TXSTA&(1<<TRMT))); // Transmit data which have just reveived
TXREG= all_data[1];
}
}
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9244 Location: Greensville,Ontario
|
|
Posted: Mon Mar 14, 2011 6:41 am |
|
|
one item...
You need to add 'errors' to the RS232(....) function.
If you receive more than 2 characters and haven't cleared the buffer , it overruns and stops ! |
|
|
|