Serial on 16f1509

Thread Starter

FroceMaster

Joined Jan 28, 2012
702
Hi Again
Have been testing a lot , but it will not Work the right way.
From master inside, it sends the right commands out, and if i send data return( PK2), the PIC use them correct.
From slave chip outside, i also get the correct data, when asking for it with PK2
BUT when i connect the 2 PICs nothing happens, the inside chip sends out the commands, but the outside PIC not responding on them.Checked with PK2.
can i just not connect 2 PICs that way,
Could Draw a schematik later, but basicaly RX is connected to TX and TX is connected to RX. on the 2 PICs.
 

Thread Starter

FroceMaster

Joined Jan 28, 2012
702
Finaly i think its working, but it has run "Cold" once, can anyone see anything i the code, somehow why it run Cold.

First the Code for inside chip.
Follow in text file.... to big to post here.
config part is here
Rich (BB code):
#include <htc.h>
#include <stdio.h>
#include <stdlib.h>
#include "lcd.h"
#include <string.h>
__CONFIG (CLKOUTEN_OFF & FCMEN_ON & IESO_OFF & BOREN_OFF & CP_OFF & MCLRE_OFF & PWRTE_ON & WDTE_OFF & 
FOSC_INTOSC);//XT
__CONFIG (LVP_ON & LPBOR_OFF & BOREN_ON & STVREN_ON & WRT_OFF);
//#define LED RC0
#define set_hour RC2 //knapper
#define set_minut RB4
#define set_week RC1
#define set_time RC3
#define _XTAL_FREQ 4000000
//global defs
volatile unsigned char week_day;
volatile unsigned char hour, minut, sec;
volatile bit timer_tick, minut_tick,regn_tick,vis,data_tick;
volatile int mm,i, x,xx,skift,g,today_rain,r_regn,data_inde,rainTMR0;
volatile signed int samletgrader,grader,offsetgrad,ude_temp;
volatile signed int max,min,sendt;
char minold[6],maxold[6];
char minx[6],offgrad[6];
unsigned char rain_data[30];
unsigned char raindays[31];
unsigned char mintime[3];
unsigned char maxtime[3];
//const char rain_mem[]@0x1f80=
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31};
const char * const day_of_week_names[] = {"Mandag ",
                                          "Tirsdag",
                                          "Onsdag ",
                                          "Torsdag",
                                          "Fredag ",
                                          "Lordag ",
                                          "Sondag " 
                                         };
  union 
{ 
unsigned int res;
char bytes[2];
}
ADC;
char ADC_num[6],xxx[6];
float temprature;

And here for outside chip.


Rich (BB code):
#include <htc.h>
#include <stdio.h>
#include <stdlib.h>
#include "lcd.h"
#include <string.h>
__CONFIG (CLKOUTEN_OFF & FCMEN_ON & IESO_OFF & BOREN_OFF & CP_OFF & MCLRE_OFF & PWRTE_ON & WDTE_OFF & FOSC_INTOSC);//XT
__CONFIG (LVP_ON & LPBOR_OFF & BOREN_ON & STVREN_ON & WRT_OFF);
#define _XTAL_FREQ 4000000
volatile int g,data_inde;
volatile signed int samletgrader;
volatile bit data_tick,led;
volatile int send_grader;
  union 
{ 
unsigned int res;
char bytes[2];
}
ADC;
char ADC_num[6],xxx[6];
static void interrupt isr(void)   // Here is interrupt function - the name is unimportant.
{
    if(RCIF) // data in uart.
    {
 
   data_inde=RCREG;
  data_tick=1;
  RC4=!RC4;
   // CREN=0;
    }
}// end interrupt
 
void setup(void)
{  
IRCF3=1;//4MHz clock speed
IRCF2=1;
IRCF1=0;
IRCF0=1;
//REGISTER 5-1: OSCCON: OSCILLATOR CONTROL REGISTER
// bit 6-3 IRCF<3:0>: Internal Oscillator Frequency Select bits
//1111 = 16MHz
//1110 = 8MHz
//1101 = 4MHz
//1100 = 2MHz
//1011 = 1MHz
//1010 = 500 kHz(1)
//1001 = 250 kHz(1)
//1000 = 125 kHz(1)
//0111 = 500 kHz (default upon Reset)
//0110 = 250 kHz
//0101 = 125 kHz
//0100 = 62.5 kHz
//001x = 31.25 kHz
//000x = 31kHz LF 
//Port analog / digital
 TRISA=1; //set all port in
 TRISB5=1; // ind
 TRISB7=0; // ud
 TRISA2=1;
 TRISC=0; //port 0 ud.
 GIE = 0;  // Global interrupt disable just in case
 ANSELA = 0b00000001;  // Set PORT AN0 to analog input AN1 to AN7 digital I/O
 ANSELB=0;
 ANSELC=0;//turn off all analog functions
 
 ///ADCON0=0b00000000;   // select right justify result. ADC port channel 0
//adcon1
ADFM=1; //right justified
//ADCS=100; // fosc/4
ADPREF0=1;
ADPREF1=0;
//ADPREF=00; //vref+ = vdd
TRIGSEL0=0;
TRIGSEL1=0;
TRIGSEL2=0;
TRIGSEL3=0;
CHS0=0;
CHS1=0;
CHS2=0;
CHS3=0;
CHS4=0; // AN0  analog kanal  intern kanal
/*//timer1 settings
TMR1CS1=1; //CLOCK SOURCE S-ELECTIONS
TMR1CS0=1;
//11 =Timer1 clock source is Capacitive Sensing Oscillator (CAPOSC)
//10 =Timer1 clock source is pin or oscillator:
//If T1OSCEN = 0:
//External clock from T1CKI pin (on the rising edge)
//If T1OSCEN = 1:
//Crystal oscillator on SOSCI/SOSCO pins
//01 =Timer1 clock source is system clock (FOSC)
//00 =Timer1 clock source is instruction clock (FOSC/4)
T1CKPS1=0; // <1:0>: Timer1 Input Clock Prescale Select bits
T1CKPS0=0;
//11 = 1:8 Prescale value
//10 = 1:4 Prescale value
//01 = 1:2 Prescale value
//00 = 1:1 Prescale value
T1OSCEN=1;//LP Oscillator Enable Control bit
//1 = Dedicated Timer1 oscillator circuit enabled
//0 = Dedicated Timer1 oscillator circuit disabled
//Timer1 Interrupt prepare*/
   TMR1IE=1;// PIE1 register
   PEIE=1; //INTCON register
   PIR1=0; // Clear all bits PERIPHERAL INTERRUPT REQUEST REGISTER 1
 
   //todo now in order to generate interrupt GEI=1 and TMR1ON=1
//timer0 settings.
// TMR0IE=1; //use timer0 interrupt register.
 TMR0CS=1; // bruger tæller,
 TMR0SE=0; // lav til høj tælning.
 IOCIE=1; // enable interrupt on change
 PSA=1; //not assign prescaler.  
//setup serial
CSRC=0; //Clock Source Select bit not used in async.
    TX9=0; // 9-bit Transmit Enable bit
    TXEN=1; // Transmit Enable bit(1)
    SYNC=0; //1 = Synchronous mode 0 = Asynchronous mode
    SENDB=0; //Send Break Character bit 1 = Send Sync Break on next transmission (cleared by hardware upon completion)
    //0 = Sync Break transmission completed
    BRGH=0; //High Baud Rate Select bit 0= low
    TRMT=1; //Transmit Shift Register Status bit 1 = TSR empty 0 = TSR full
    TX9D=0; //Ninth bit of Transmit Data
    RCIE=1;
 
    //RCSTA    //SEE THE DATA SHEET FOR RCSTA 
    SPEN=1; //Serial Port Enable bit
    RX9=0;  // 8bit
    SREN=0; // Single Receive Enable bit
 
    ADDEN=0; //Not Used.
    FERR=0; //Framing Error bit
    OERR=0; // Overrun Error bit
    RX9D=0; // Ninth bit of Received Data
BRGH=0;            //  low baud rate  
    SPBRGL=0b00011001;//0b11001111;      //baud rate 300 
    SPBRGH=0b00000000;
 } //end setup
 
 void beregn_temp (void) // beregner temp.
{
 
  GO_nDONE=1;             // initiate conversion on the channel 0   
       while(GO_nDONE) continue;
     ADC.bytes[0]=ADRESL;
                 ADC.bytes[1]=ADRESH;
 
      samletgrader=samletgrader+ADC.res;  // samler op i ca 3 sec.
      g++;        // antal målinger.
 
 }
 
 
void send_regn (void)
{  
 TXREG = TMR0;
// CREN=1;
}
void send_temp (void)
{
 if (g==0) g=1;
 send_grader=samletgrader/g;
 
 TXREG=send_grader;
 
 samletgrader=0;
 g=0;
// CREN=1;
}
 
void main (void) 
 {
 setup();   //kører setup
 
   TMR0=0;  // timer 0 til 0
   samletgrader=0;
   g=0;
 
    ADON=1;    // Turn on A/D Reading    
     CREN=1; //1 = Enables receiver
     GIE=1;  //interrupt klar
        while (1)// kører loop
       {  // STORE LOOP STARTER
       beregn_temp();
       __delay_ms(100);
 
       RC0=!RC0;
       __delay_ms(100);
       if (data_tick)
       { 
        RC1=!RC1;
 
        data_tick=0;
        if (data_inde==0x01)
        {
          RC1=!RC1;
          TMR0=0;
      //    CREN=1;
        }  
        if (data_inde==0x02)
        {
          RC2=!RC2;
     //     CREN=0;
          send_regn();
        }  
        if (data_inde==0x03)
        { RC3=!RC3;
      //   CREN=0;
         send_temp();
        }
        __delay_ms(100);
 
       } 
       }//end while endless loop 
 }//End main
And 2 scematics.
 

Attachments

Thread Starter

FroceMaster

Joined Jan 28, 2012
702
Have found that inside(master) PIC goes Cold after some minutes.
Have normal transmision like this.
Rich (BB code):
RX:  02 
TX:  00
RX:  03
TX:  8A 
RX:  02 
TX: 00
RX:  03
TX:  8A 
RX:  02 
TX:  00
RX:  03
But when the transmission hangs, this is the recieving data,
Rich (BB code):
RX:  02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03 02 03
Somehow it gets stuck in sending code, and not moving on in program code.

edit :
it hang everytime, after approx. 10 minutes. the "master" pic is just stopping.
 
Last edited:

Thread Starter

FroceMaster

Joined Jan 28, 2012
702
Could someone check why my code is stopping each time, after it has read and writet 512 times,
As can see in code, the job is to send a command to slave chip every 3 seconds, and get a respond each time, that part is correct working, and the slave chip keeps on running. it seems like some kind of buffer or... get full at 512 readings, as can see, that info is only from 00 to ff.

Rgds FroceMaster
 

Thread Starter

FroceMaster

Joined Jan 28, 2012
702
Hi,
Have now tried to reset the serial comm after 500 readings/writings, SPEN=0, Little NOP and then SPEN=1, but it keeps stopping after 512 total reads.
any hint on reason ???

as read on datasheet
22.1.2.5 Receive Overrun Error
The receive FIFO buffer can hold two characters. An
overrun error will be generated if a third character, in its
entirety, is received before the FIFO is accessed. When
this happens the OERR bit of the RCSTA register is set.
The characters already in the FIFO buffer can be read
but no additional characters will be received until the
error is cleared. The error must be cleared by either
clearing the CREN bit of the RCSTA register or by
resetting the EUSART by clearing the SPEN bit of the

RCSTA register.
 

JohnInTX

Joined Jun 26, 2012
4,787
Hi,
Have now tried to reset the serial comm after 500 readings/writings, SPEN=0, Little NOP and then SPEN=1, but it keeps stopping after 512 total reads.
any hint on reason ???

as read on datasheet
You should not have to do that. You SHOULD always inspect OERR on every char received and reset the USART if its ever set. The reason is because the USART will stop generating interrupts after that. If you don't handle it there, you won't get another chance because the USART will not interrupt again until its cleared.

Of course, OERR means that you are not keeping up with the data rate. As others have said things like writing to the LCD are usually bad form in an interrupt routine. The PIC requires that you keep all interrupt services short, posting values for later processing if necessary. The reason is that interrupts can't be nested on a PIC. You can't interrupt an interrupt writing the LCD to receive another character. OERR will be the result and (unfortunately) you won't know if you don't catch it on the first occurrence of the error.

BTW you should also inspect FERR although that is usually due to a baud rate problem. Still, it means that the data received is suspect and you should act accordingly.

EDIT: General observations of your code.
(So geeze, finally someone posts complete code and its.. a lot to go through.)

But some things jumped out and here they are. I'll go out on a limb without drilling down to your specific details but in general:

You should TX and RX out of FIFO buffers. You are getting / putting chars via interrupts and that is good but you are only copying them to one byte registers. Later in the code, you have delays, Inner curcuit code.txt page 7, that say __delay_ms(10) etc etc. Red flag. Haven't gone through it all but here is MY personal secret to ANY comms-oriented success:

Make it interrupt driven - as you have.

Detect and handle all error flags- OERR is a big deal since it crashes your comms. FERR is a problem as well since it means you didn't get the data you expected.

Construct and use interrupt-driven FIFO buffers for both RX and TX. Learn how to set them up so that you can just push chars to the TX and get chars from the RX without thinking about it. Push all of the time-critical stuff to the hardware->FIFO and as long as your buffers are long enough, you won't have to worry about it.
 
Last edited:

Thread Starter

FroceMaster

Joined Jan 28, 2012
702
I dont have a clue,
Could maybe understand, if the "hangup" was random, but it accours after excact 511 reading from RX.
Rich (BB code):
 if(RCIF) // data in uart.
    {
   
   data_inde=RCREG;
  data_tick=1;
  RA2=!RA2;
   }
Data is not corruptet or bad, have logged with pc same time.
on test it just only recieves 0 in RCREG. so i cant see how it should come with an overrun or something.
overrun should not be happening same time,. each time..
 

Thread Starter

FroceMaster

Joined Jan 28, 2012
702
You should TX and RX out of FIFO buffers. You are getting / putting chars via interrupts and that is good but you are only copying them to one byte registers.
Have tried to fix some of it.
Like this,
Rich (BB code):
 if(RCIF) // data in uart.
        {
 
 if(FERR==1 || OERR==1 )
    {
      CREN=0;    //Overrun error (can be cleared by clearing bit CREN)
      data_inde=RCREG;    //clear Framing error 
      CREN=1;
    }  
    else
{
       data_inde = RCREG; // read new data into variable
       data_tick = 1; // new data received. so enable flg
        RA2=!RA2;
    }
 
   }
It doesnt help anything, the pic stops after 511 reads.
the data that is been reading is 0. and besides, i use "data_inde" declared as "int" that should be more than one byte long ?
 
Top