Setting up my MCU.

Thread Starter

FroceMaster

Joined Jan 28, 2012
699
Hi,
Know we have been here before, and i have figured it out somehow, but now it's struggeling to much,

Have this small setup.
Controll.png
The name on each port is not correct, but portnumber is, Due to missing footprint.

I am working on to let i run precise 1 sec on each roolover, by using the 32.768 x-tal.
Did have a logicanalyser from PICKIT2 to see that signal is comming from x-tal.
But i know it's some setup that is killing me,
Have tried for days, a studing datasheet many times,
Here is my code.
Code:
/*
* File:   newmain1.c
* Author: Me self
* Created on 17. maj 2020, 13:26
*/
//#include <stdlib.h>
#include <xc.h>
#include <stdbool.h>
#include <stdint.h>



// CONFIG1
#pragma config FEXTOSC = OFF   // External Oscillator mode selection bits (Oscillator not enabled)
#pragma config RSTOSC = HFINT32 // Power-up default value for COSC bits (HFINTOSC with OSCFRQ= 32 MHz and CDIV = 1:1)
#pragma config CLKOUTEN = OFF   // Clock Out Enable bit (CLKOUT function is disabled; i/o or oscillator function on OSC2)
#pragma config CSWEN = ON       // Clock Switch Enable bit (Writing to NOSC and NDIV is allowed)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable bit (FSCM timer enabled)

// CONFIG2
#pragma config MCLRE = ON    // Master Clear Enable bit->MCLR pin is Master Clear function
#pragma config PWRTE = OFF    // Power-up Timer Enable bit->PWRT disabled
#pragma config LPBOREN = OFF    // Low-Power BOR enable bit->ULPBOR disabled
#pragma config BOREN = ON    // Brown-out reset enable bits->Brown-out Reset Enabled, SBOREN bit is ignored
#pragma config BORV = LO    // Brown-out Reset Voltage Selection->Brown-out Reset Voltage (VBOR) set to 1.9V on LF, and 2.45V on F Devices
#pragma config ZCD = OFF    // Zero-cross detect disable->Zero-cross detect circuit is disabled at POR.
#pragma config PPS1WAY = ON    // Peripheral Pin Select one-way control->The PPSLOCK bit can be cleared and set only once in software
#pragma config STVREN = ON    // Stack Overflow/Underflow Reset Enable bit->Stack Overflow or Underflow will cause a reset


// CONFIG3
#pragma config WDTCPS = WDTCPS_31    // WDT Period Select bits->Divider ratio 1:65536; software control of WDTPS
#pragma config WDTE = OFF    // WDT operating mode->WDT Disabled, SWDTEN is ignored
#pragma config WDTCWS = WDTCWS_7    // WDT Window Select bits->window always open (100%); software control; keyed access not required
#pragma config WDTCCS = SC    // WDT input clock selector->Software Control

// CONFIG4
#pragma config BBSIZE = BB512    // ->512 words boot block size
#pragma config BBEN = OFF    // ->Boot Block disabled
#pragma config SAFEN = OFF    // ->SAF disabled
#pragma config WRTAPP = OFF    // ->Application Block not write protected
#pragma config WRTB = OFF    // ->Boot Block not write protected
#pragma config WRTC = OFF    // ->Configuration Register not write protected
#pragma config WRTSAF = OFF    // ->SAF not write protected
#pragma config LVP = ON    // Low Voltage Programming Enable bit->Low Voltage programming enabled. MCLR/Vpp pin function is MCLR.

// CONFIG5
#pragma config CP = OFF    // UserNVM Program memory code protection bit->UserNVM code protection disabled
#define _XTAL_FREQ 32000000

volatile uint16_t timer1ReloadVal;
unsigned int sekund,minut,time,Hour;
char BT_Modtag,Newsecond;
uint8_t nytsekund,no70_opens,no80_opens,runs_code70,ReadyToCode70,runs_code80,ReadyToCode80,no90_opens,runs_code90,ReadyToCode90;
uint8_t ContrastValue,trash,NightContrastTime,DayContrastTime;
uint8_t BT_Data = 0;

void setup_system (void)
{
   
    PMD0 = 0x45;
    PMD1 = 0x05;
    PMD2 = 0x67;
    PMD3 = 0x3F;
    PMD4 = 0x00;
    PMD5 = 0x1E;
   
    LATA = 0x00;
    LATB = 0x00;
    LATC = 0x00;

   
    TRISA = 0xFF; // all input
    TRISB = 0xFB; // RB2=out to BT all other IN
    TRISC = 0xAE;//10101110

 
    ANSELC = 0x03;
    ANSELB = 0x00;
    ANSELA = 0x00;

    WPUB = 0x00;
    WPUA = 0x00;
    WPUC = 0x00;

    ODCONA = 0x00;
    ODCONB = 0x00;
    ODCONC = 0x00;

    SLRCONA = 0xFF;
    SLRCONB = 0xFF;
    SLRCONC = 0xFF;

    INLVLA = 0xFF;
    INLVLB = 0xFF;
    INLVLC = 0xFF;
         
    RB2PPS = 0x11;   //RB2->EUSART2:TX2;  
    RC6PPS = 0x0F;   //RC6->EUSART1:TX1;  
    RX2DTPPS = 0x09;   //RB1->EUSART2:RX2;  
    RX1DTPPS = 0x17;   //RC7->EUSART1:RX1;  
   
   
   
    OSCCON1 = 0x60;// NOSC HFINTOSC; NDIV 4;
    OSCCON3 = 0x00; // CSWHOLD may proceed; SOSCPWR Low power;
    OSCEN = 0x08; // MFOEN disabled; LFOEN disabled; ADOEN disabled; SOSCEN disabled; EXTOEN disabled; HFOEN disabled;
    OSCFRQ = 0x06;  // HFFRQ 32_MHz;
    OSCSTAT = 0x00;// MFOR not ready;
    OSCTUNE = 0x00; // HFTUN 0;
    SOSCEN=1; // set secondary osc allways enable
 
    T1GCON = 0x00; //T1GE disabled; T1GTM disabled; T1GPOL low; T1GGO done; T1GSPM disabled;
    T1GATE = 0x00;//GSS T1G_pin;
    T1CLK = 0x07;  //CS SOSC;
    TMR1H = 0x80;  //TMR1H 128;
    TMR1L = 0x00;  //TMR1L 0;

    // Clearing IF flag before enabling the interrupt.
    TMR1IF = 0;

    // Load the TMR value to reload variable
    timer1ReloadVal=(uint16_t)((TMR1H << 8) | TMR1L);

    // Enabling TMR1 interrupt.
    TMR1IE = 1;
   
    T1CON = 0x05;// CKPS 1:1; nT1SYNC synchronize; TMR1ON enabled; T1RD16 disabled;
   
    //SETUP EUSART1
    PIE3bits.TX1IE = 0;
     // Set the EUSART1 module to the options selected in the user interface.

    BAUD1CON = 0x00; // ABDOVF no_overflow; SCKP Non-Inverted; BRG16 8bit_generator; WUE disabled; ABDEN disabled;
    RC1STA = 0x90;// SPEN enabled; RX9 8-bit; CREN enabled; ADDEN disabled; SREN disabled;
    TX1STA = 0x24;    // TX9 8-bit; TX9D 0; SENDB sync_break_complete; TXEN enabled; SYNC asynchronous; BRGH hi_speed; CSRC slave;
    SP1BRGL = 0xBF;    // SP1BRGL 191; BAUD 10417
    SP1BRGH = 0x00;// SP1BRGH 0;
   
    // SETUP EUSART2  BT
    RC2IE = 0;
    TX2IE = 0;
 
   
    BAUD2CON = 0x00;// ABDOVF no_overflow; SCKP Non-Inverted; BRG16 8bit_generator; WUE disabled; ABDEN disabled;
    RC2STA = 0x90;// SPEN enabled; RX9 8-bit; CREN enabled; ADDEN disabled; SREN disabled;
    TX2STA = 0x24;    // TX9 8-bit; TX9D 0; SENDB sync_break_complete; TXEN enabled; SYNC asynchronous; BRGH hi_speed; CSRC slave;
    SP2BRGL = 0xCF;    // SP2BRGL 207; // BAUD 9600 standard
    SP2BRGH = 0x00;    // SP2BRGH 0;
   
    GIE=1; // global interrupt
    PEIE=1;
    TMR1IE=1;
   
}

void __interrupt()ISR (void)
{
    if ((TMR1IE == 1) && (TMR1IF == 1))
    {
    TMR1IF = 0;
   
     TMR1H = (timer1ReloadVal >> 8);
        TMR1L = timer1ReloadVal;
        nytsekund=1;  // tell main loop that new second is gone.
}
   
   
   
}


void EUSART1_Write(uint8_t txData)
{  
        TX1REG = txData;
   
}

uint8_t EUSART2_Read(void)
{
    //uint8_t readValue  = 0;
   
    return RC2REG;
   
}



void SendTimeToSlave (void)
{ // do something later.
}


void main(void)
{
    setup_system();
    time=0;
    sekund=0;
    minut=0;
    RC4=!RC4; // test only....
    while(1)
    {
   
        // if new second
        if (nytsekund==1)
         
        {
             RC4=!RC4; // test only
            sekund++; // add one
        nytsekund=0;  // clears the bit
        if (sekund==60) { // if one minut gone
            sekund=0; // sets second to zero
            minut++; // add 1 minute
            if (minut==60) // if minut is 60,
            {
                minut=0; // minut is zero
                time++; // add to hour
                if(time==24)time=0; // if midnight hours is zero
               
            }//end minut
           
           
        } //end sekund
        //send to all other.
        SendTimeToSlave(); // empty yet
       
       
       
        }//end nyt sekund
       
    }// end while
   
   
}
it's killing me....
 

AlbertHall

Joined Jun 4, 2014
12,345
As the 32kHz oscillator is 1000 times slower than the internal 32MHz oscillator that is to be expected. You will need to change other things to match - XTAL_FREQ declaration, timer settings, baud rate generator and so on. Then everything will run as you expect.
 

MaxHeadRoom

Joined Jul 18, 2013
28,619
The way I use the 32.khz Xtal, the internal oscillator has no bearing, I use the xtal to clock the T1osc input.
Set the MSB to one, result 1 sec time out.
Max.
 

Thread Starter

FroceMaster

Joined Jan 28, 2012
699
I want a 1 sec tick on SOSC, where timer1 is connected,.
But i do not get an interrupt, ergo the timer1 is not counting,
Have set timer1 input to "T1CLK = 0x07; //CS SOSC; " meaning it should count on SOSC, Have testing on OSC input pin, that i get a high low signal, looks ok, but "PICKIT2" logic analyser can only do up to 2400 Hz,.

The internal freq are set to 32 mhz i think.
 

trebla

Joined Jun 29, 2019
542
As i had only PIC16F15376 Curiosity Nano board here, i modified your code settings to work without secondary oscillator. I set OSCFRQ to 2MHz clock , TMR1 to maximum delay from FOSC/4 and OSCEN to only HFINTOSC to be able see LED flashing at reasonable speed. Interrupt routine was working well at the first time, but if you want watch LED flashing, you need to change RC4 to LATC4 in your code. For toggle routines is better write to output latch register instead of port register.
 

Thread Starter

FroceMaster

Joined Jan 28, 2012
699
Have been playing with NCO and that creates interrupts and the led flashing pretty well. Only problem with NCO is not precise, according to data and info online, the 1 hz is not precise 1 hz, in 1 minute it goes 3 sec to slow.
Back to timer again.
 

Thread Starter

FroceMaster

Joined Jan 28, 2012
699
Have changed to this.
Use timer0 and maked input from FOSC/4 = 8.000.000 hz.
Prescale 32 = 8.000.000 / 32 = 250.000 hz
Set compare part of timer to 250.
Set Postscale to 10.
Gives me an interrupt every 1/100 sec.
In my ISR i count to 100 to give a second.

But it runs a little bit to fast.
a couple of second pr half hour.

Why ?

C:
/*
 * File:   newmain1.c
 * Author: Me self
 * Created on 17. maj 2020, 13:26
 */
//#include <stdlib.h>
#include <xc.h>
#include <stdbool.h>
#include <stdint.h>



// CONFIG1
#pragma config FEXTOSC = LP   // External Oscillator mode selection bits (Oscillator not enabled)
#pragma config RSTOSC = HFINT32 // Power-up default value for COSC bits (HFINTOSC with OSCFRQ= 32 MHz and CDIV = 1:1)
#pragma config CLKOUTEN = OFF   // Clock Out Enable bit (CLKOUT function is disabled; i/o or oscillator function on OSC2)
#pragma config CSWEN = ON       // Clock Switch Enable bit (Writing to NOSC and NDIV is allowed)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable bit (FSCM timer enabled)

// CONFIG2
#pragma config MCLRE = ON    // Master Clear Enable bit->MCLR pin is Master Clear function
#pragma config PWRTE = OFF    // Power-up Timer Enable bit->PWRT disabled
#pragma config LPBOREN = OFF    // Low-Power BOR enable bit->ULPBOR disabled
#pragma config BOREN = ON    // Brown-out reset enable bits->Brown-out Reset Enabled, SBOREN bit is ignored
#pragma config BORV = LO    // Brown-out Reset Voltage Selection->Brown-out Reset Voltage (VBOR) set to 1.9V on LF, and 2.45V on F Devices
#pragma config ZCD = OFF    // Zero-cross detect disable->Zero-cross detect circuit is disabled at POR.
#pragma config PPS1WAY = ON    // Peripheral Pin Select one-way control->The PPSLOCK bit can be cleared and set only once in software
#pragma config STVREN = ON    // Stack Overflow/Underflow Reset Enable bit->Stack Overflow or Underflow will cause a reset


// CONFIG3
#pragma config WDTCPS = WDTCPS_31    // WDT Period Select bits->Divider ratio 1:65536; software control of WDTPS
#pragma config WDTE = OFF    // WDT operating mode->WDT Disabled, SWDTEN is ignored
#pragma config WDTCWS = WDTCWS_7    // WDT Window Select bits->window always open (100%); software control; keyed access not required
#pragma config WDTCCS = SC    // WDT input clock selector->Software Control

// CONFIG4
#pragma config BBSIZE = BB512    // ->512 words boot block size
#pragma config BBEN = OFF    // ->Boot Block disabled
#pragma config SAFEN = OFF    // ->SAF disabled
#pragma config WRTAPP = OFF    // ->Application Block not write protected
#pragma config WRTB = OFF    // ->Boot Block not write protected
#pragma config WRTC = OFF    // ->Configuration Register not write protected
#pragma config WRTSAF = OFF    // ->SAF not write protected
#pragma config LVP = ON    // Low Voltage Programming Enable bit->Low Voltage programming enabled. MCLR/Vpp pin function is MCLR.

// CONFIG5
#pragma config CP = OFF    // UserNVM Program memory code protection bit->UserNVM code protection disabled
#define _XTAL_FREQ 32000000

volatile uint16_t timer1ReloadVal,timer0ReloadVal;
uint8_t sekund,minut,time,Hour,xx;
char BT_Modtag,Newsecond;
char nytsekund;
uint8_t no70_opens,no80_opens,runs_code70,ReadyToCode70,runs_code80,ReadyToCode80,no90_opens,runs_code90,ReadyToCode90;
uint8_t ContrastValue,trash,NightContrastTime,DayContrastTime,countForSecond;
uint8_t BT_Data = 0;

void setup_system (void)
{
    
    PMD0 = 0x00;
    PMD1 = 0x00;
    PMD2 = 0x00;
    PMD3 = 0x00;
    PMD4 = 0x00;
    PMD5 = 0x00;
    
    LATA = 0x00;
    LATB = 0x00;
    LATC = 0x00;

    
    TRISA = 0xFF; // all input
    TRISB = 0xFB; // RB2=out to BT all other IN
    TRISC = 0xAE;//10101110

  
    ANSELC = 0x03;
    ANSELB = 0x00;
    ANSELA = 0x00;

    WPUB = 0x00;
    WPUA = 0x00;
    WPUC = 0x00;

    ODCONA = 0x00;
    ODCONB = 0x00;
    ODCONC = 0x00;

    SLRCONA = 0xFF;
    SLRCONB = 0xFF;
    SLRCONC = 0xFF;

    INLVLA = 0xFF;
    INLVLB = 0xFF;
    INLVLC = 0xFF;
          
    RB2PPS = 0x11;   //RB2->EUSART2:TX2;   
    RC6PPS = 0x0F;   //RC6->EUSART1:TX1;   
    RX2DTPPS = 0x09;   //RB1->EUSART2:RX2;   
    RX1DTPPS = 0x17;   //RC7->EUSART1:RX1;   
    
    
    
    OSCCON1 = 0x60;// NOSC HFINTOSC; NDIV 4;
    OSCCON3 = 0x00; // CSWHOLD may proceed; SOSCPWR Low power;
    OSCEN = 0x00; // MFOEN disabled; LFOEN disabled; ADOEN disabled; SOSCEN disabled; EXTOEN disabled; HFOEN disabled;
    OSCFRQ = 0x06;  // HFFRQ 32_MHz;
    OSCSTAT = 0x00;// MFOR not ready;
    OSCTUNE = 0x00; // HFTUN 0;
    SOSCEN=1; // set secondary osc allways enable
    
    //set timer0 to run at fosc/4 and .
    //Prescale 32, POST 10. Output 125 pr sec. count to 200.
    T016BIT=0; // set 8 bit
    T0CS0=0; // set fosc/4
    T0CS1=1;
    T0CS2=0;
    T0ASYNC=0; // sync to fosc.
    
    T0CKPS0=1; // prescale 32  8.000.000 / 32 = 250.000
    T0CKPS1=0;
    T0CKPS2=1;
    T0CKPS3=0;
    
    T0OUTPS0=1;//set postscale to 10  250.000 / 10 = 25.000 to tmr0 /250 = 100 roolovers.
    T0OUTPS1=0;
    T0OUTPS2=0;
    T0OUTPS3=1;
    
    TMR0H=250; // as we need 200 counts.
    TMR0L=0; // set low part to 0.
    
    T0EN=1; // start timer 0
    
    //SETUP EUSART1
    PIE3bits.TX1IE = 0;
     // Set the EUSART1 module to the options selected in the user interface.

    BAUD1CON = 0x00; // ABDOVF no_overflow; SCKP Non-Inverted; BRG16 8bit_generator; WUE disabled; ABDEN disabled;
    RC1STA = 0x90;// SPEN enabled; RX9 8-bit; CREN enabled; ADDEN disabled; SREN disabled;
    TX1STA = 0x24;    // TX9 8-bit; TX9D 0; SENDB sync_break_complete; TXEN enabled; SYNC asynchronous; BRGH hi_speed; CSRC slave;
    SP1BRGL = 0xBF;    // SP1BRGL 191; BAUD 10417
    SP1BRGH = 0x00;// SP1BRGH 0;
    
    // SETUP EUSART2  BT
    RC2IE = 1;
    TX2IE = 0;
  
    
    BAUD2CON = 0x00;// ABDOVF no_overflow; SCKP Non-Inverted; BRG16 8bit_generator; WUE disabled; ABDEN disabled;
    RC2STA = 0x90;// SPEN enabled; RX9 8-bit; CREN enabled; ADDEN disabled; SREN disabled;
    TX2STA = 0x24;    // TX9 8-bit; TX9D 0; SENDB sync_break_complete; TXEN enabled; SYNC asynchronous; BRGH hi_speed; CSRC slave;
    SP2BRGL = 0xCF;    // SP2BRGL 207; // BAUD 9600 standard
    SP2BRGH = 0x00;    // SP2BRGH 0;
    
    GIE=1; // global interrupt
    PEIE=1;
  // TMR1IE=1;
    TMR0IE=1;
    
}

 void __interrupt()ISR (void)
{
     if (TMR0IF==1)
     {   
         TMR0IF=0;
         countForSecond++; // runs to give 1 second
         if (countForSecond==100) // if 100, then one second is gone
         {
             nytsekund=1;  // newsecond.
         countForSecond=0; // sets to 0 again
         }
     }
    
   if(PIE3bits.RC2IE == 1 && PIR3bits.RC2IF == 1)
        {
            BT_Data=RC2REG;
            BT_Modtag=1;
        }
    
}
void main(void)
{
    setup_system();
    time=0;
    sekund=0;
    minut=0;
    RC4=0; // test only....
    while(1)
    {
    
        // if new second
        
      
        if (nytsekund==1)
          
        {
             RC4=!RC4; // test only
            sekund++; // add one
        nytsekund=0;  // clears the bit
        if (sekund==60) { // if one minut gone
            sekund=0; // sets second to zero
            minut++; // add 1 minute
            if (minut==60) // if minut is 60,
            {
                minut=0; // minut is zero
                time++; // add to hour
                if(time==24)time=0; // if midnight hours is zero
                
            }//end minut
            
            
        } //end sekund
        //send to all other.
        SendTimeToSlave();
        
        
        
        }//end nyt sekund
        
        
        
            
    }// end while
 

jpanhalt

Joined Jan 18, 2008
11,087
Two seconds per hour = 0.056% (556 ppm).

Are you using the internal oscillator or crystal for 8 MHz? If internal oscillator, that is not bad.
 

Thread Starter

FroceMaster

Joined Jan 28, 2012
699
Internal, runs at 32000000 hz.
If this is not precise, then how ?
Use external at 32,768 hz,(20 ppm) would be same accuracy as internal 32mhz, +-1% ?

Cant get the external x-tal function, the signal is going to in pin, but cant get the timer to count,, that way use internal osc.
 

jpanhalt

Joined Jan 18, 2008
11,087
Sorry, I assumed you were using 4xPLL with an 8 MHz source.

If you must have more accuracy, then a crystal/ceramic resonator or a similarly controlled source* should be used. You can "tune" the internal oscillator, but temperature changes will cause it to change too.

*Edit: Such as an RTC or GPS-disciplined oscillator (GPSDO)
 
Last edited:

trebla

Joined Jun 29, 2019
542
Internal oscillator is usually not that precice compared to crystal-driven. I found in the datasheet that before man can use secondary oscillator it's nessesary make some software delay into startup routine:

Note: The oscillator requires a start-up and
stabilization time before use. Thus,
SOSCEN should be set and a suitable
delay observed prior to using Timer1 with
the SOSC source. A suitable delay similar
to the OST delay can be implemented in
software by clearing the TMR1IF bit then
presetting the TMR1H:TMR1L register
pair to FC00h. The TMR1IF flag will be set
when 1024 clock cycles have elapsed,
thereby indicating that the oscillator is
running and reasonably stable.
 

Thread Starter

FroceMaster

Joined Jan 28, 2012
699
Have still been struggeling a lot.
Testing something, with or without resistor in paralell and in serie to X-tal.
Have got a scope and got this picture from input pin on X-tal.
20200711_133726.jpg
It's now a high difference to low-high, but maybe it's ok ,?
If i let the intenal clk go to pin, i get a very fine 0-4,8v square wave signal.

Have tried to use Timer0, and set SOCS as input, but that also fails.
Look like my X-tal curcuit is non function.
Btw, have also tried another x-tal.

Edit : Any other soulutions ?. Should i use hz from mains to go into MCU ?
If yes, then how ?
 
Last edited:

jpanhalt

Joined Jan 18, 2008
11,087
When I set up oscillators, I use code to delay until the oscillator is stable. The MCU counts something on the order of 1024 cycles, then sets a flag. If you wish, you can use that flag to turn on an LED. Then you know the oscillator(s) are working.

There are some caveats:
1) It can hang. You may want to use WDT to circumvent that and reset.
2) You must review the errata. For some chips, the usual flag does not work, but there are other flags (e.g., PLL stable) that you can use.
 
Top