[SOLVED] 16F877A : TMR1L/H, can not load values inside with sprintl

Status
Not open for further replies.

Eric_O

Advanced Member level 4
Joined
May 31, 2020
Messages
104
Helped
0
Reputation
0
Reaction score
0
Trophy points
16
Activity points
996
Has somebody an idea, a suggestion in order to help me ?
PIC 16F877A > Hereunder the code consisting of driving two servomotors separately for a 2 axes pan tilt.
TMR2 : for 20 mS period
TMR1 : for Ton UPPER servomotor
TMR0 : for Ton LOWER servomotor
I deleted the code consisting of driving LOWER servomotor because it’s works properly.
For UPPER servomotor, the 16 bits data in consigne_1 never loads in both 8 bits registers TMR1L and TMR1H when troobleshooting with Debugger of MIkroC For PIC.
Both registers are empty. In that case servo never turns.

Code :
Code:
unsigned int consigne_1;
unsigned char *p1;
volatile unsigned char flag_TMR1;

// Timer2 (8 bits) : 20 mS period
// Prescaler 1:16
// Postscaler 1:5
// PR2 preload = 250
// TMR2 preload = 0
// Interrupt time : 20,005 mS

void Init_Timer2()
{
 // Timer 2 in timer mode :
 T2CON = 0x26;
 PR2 = 250;
 TMR2IE_bit = 1;
 INTCON = 0xC0;
}

// Timer1 (16 bits) : Ton servomotor UPPER
// Prescaler 1:1
// TMR1 preload = 64536
// Interrupt time : 1 mS

void Init_Timer1()
{
 // Timer 1 in timer mode :
 T1CON = 0x01;
 TMR1IF_bit = 0;       
 TMR1H = 0xFC;
 TMR1L = 0x18;
 TMR1IE_bit = 1;
 INTCON = 0xC0;
 flag_TMR1 = 1;
}

// Timer0 (8 bits) : Ton servomotor LOWER
// Prescaler 1:1
// TMR0 Preload = 156
// Interrupt Time : 0,1 mS (100 uS)

void Init_Timer0()
{
 // Timer 0 in timer mode :
 OPTION_REG = 0x88;
 TMR0 = 156;
 INTCON = 0xA0; 
 cnt0 = 0;
}

/* ----------------------------------------------------------------------------*/

void Interrupt()
{
 if (TMR2IF_bit && TMR2IE_bit)  // After 20 mS elapsed with Timer2 ...
 //if (TMR2IF_bit == 1)
    {
     // Timer 0 :               // Servomotor LOWER.
     TMR0IE_bit = 0;            // Disenables Timer0 interrupt bit (stops Timer0).
     TMR0 = 156;
     TMR0IF_bit = 0;
     portd.b0 = 1;              // Servomotor LOWER ON.
     portc.b2 = 1;              // LED ON.
     TMR0IE_bit = 1;            // Enables Timer0 interrupt bit (starts Timer0).

     // Timer 1 :               // Servomotor UPPER.
     flag_TMR1 = 1;             // Timer1 is counting.
     //TMR1ON_bit = 0;    
     p1 = &consigne_1; 
     TMR1L = *(p1);
     TMR1H = *(p1 + 1); 
     TMR1IE_bit = 1;            // Enables Interrupt.
     TMR1IF_bit = 0;            // Resets Interrupt Flag.
     portd.b1 = 1;              // Servomotor UPPER ON.
     portc.b2 = 1;              // LED ON.
     //TMR1ON_bit = 1;          // Enables (start) Timer1.

     // Restarts Timer 2 :
     TMR2IE_bit = 1;            // XXX optionnel XXX
     TMR2IF_bit = 0;
     PR2 = 250; 
    }

 if (TMR0IF_bit && TMR0IE_bit)  // After 100 uS elapsed with TMR0 ...
 //if (TMR0IF_bit == 1)
    {
     cnt0++;                    // Increments "100 uS" counter.
     //TMR0IE_bit = 0;
     TMR0IE_bit = 1;
     TMR0IF_bit = 0;
     TMR0 = 156;
    }

 if (TMR1IF_bit && TMR1IE_bit)  // After n x 100 uS elapsed with TMR1 ...
 //if (TMR1IF_bit == 1)
    {
     flag_TMR1 = 0;             // Timer1 stops counting.
     portd.b1 = 0;              // Servomotor UPPER OFF.
     portc.b2 = 0;              // LED OFF.
     flag_TMR1 = 0;
     TMR1ON_bit = 0;            // Stops (disenables) Timer
     TMR1IF_bit = 0;
     TMR1IE_bit = 1;            // XXX optionnel XXX
     TMR1L = *(p1);
     TMR1H = *(p1 + 1);
    }
}

void main()
{
 TRISC = 0; 
 PORTC = 0; 
 TRISD = 0;
 PORTD = 0;

 while(1)
 {
   p1 = & TMR1L
  consigne_1 = 65535 - 1000;              // consigne_1 = 65535 - 1000 => 64535 à 65535 = 1000 x uS = 1 mS = Ton.
  sprintl(*p1, "%5u", consigne_1);
  Delay_ms(1000);
  consigne_1 = 65535 - 1500;              // consigne_1 = 65535 - 1500 => 64035 à 65535 = 1500 x uS = 1,5 mS = Ton.
  sprintl(*p1, "%5u", consigne_1);
  Delay_ms(1000);
  consigne_1 = 65535 - 2000;              // consigne_1 = 65535 - 2000 => 63535 à 65535 = 2000 x uS = 2,0 mS = Ton.
  sprintl(*p1, "%5u", consigne_1);
  Delay_ms(1000);
 }
}
 
Last edited by a moderator:

I don't use MicroC but I suspect your problem is to do with the way you load 'p1' with values in the while() loop but in the ISR you use 'p1' and 'p1+1' with no assurance that p1+1 holds the other half of the value.

You may be overwriting the value in *(p1+1) with another variable. If you want to do it that way I suggest you use a different stage for the high bits, maybe use 'p1' and 'p2' for the two halves.

Brian.
 

hello Eric,

Be carrefull

sprinti and sprintl confusion !

sprintl is for long (32 bits)
*(p1) point on a byte ...

Code:
  // autre façon avec  16 bits
   // ici pInt est un pointeur sur entier non signé
unsigned int *pInt;


    TEXTE[0]=0;
    pInt=&TMR1L;
    // ATTENTION sprinti buggé: n'accepte pas un byte (8bits)  comme argument,il faut un int (16bits)
 
    sprinti(TEXTE,"%5u",*(pInt));  // pInt pointe sur le couple TMR1L;TMR1H
    UART1_Write_Text(TEXTE);
    UART1_Write(13); // CR
    UART1_Write(10); // LF
    // resultat sur terminal
   //  64035

remark:
with mikroC editor it is very difficult to distingusih i and l (I and L)
i changed the font and size of editor , to see the difference
after loosing many hours about this problem ( and maybe also obliged to weare glasses !)
 

I don't recognize that interrupts are ever started in the post #1 code.

Shouldn't main() call the init functions?
 
Reactions: Eric_O

    Eric_O

    Points: 2
    Helpful Answer Positive Rating
Dear FvM,
Thank you so much for your remark. I was so focused of my initial problem consisting of how to write in both 8 bits registers of TMR1 starting of a 16 bits variable (a great MERCI to Paullfjugo, that shows and explains me how to do with pointers, &, and * �� ... not easy when starting, thru it’s website), that I missed to call Init_Timer2() and Init_Timer1() in main(). Now good values are loaded in both registers when monitoring with Debbuger. This is a very convenient tool, I did use it so much before, but it’s saves time.
Thanks Betwixt for your suggestion too. I was hesitating to use two pointers, but in case I would not received the advise of FvM, I would have plan to try your idea that probably works too after inserting Init_Timer routines.
Merci Beaucoup !
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…