Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[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?
 
  • Like
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 F76D455E-DAC9-4CA3-A387-7872C0150584.jpg 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 !F76D455E-DAC9-4CA3-A387-7872C0150584.jpg
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top