Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronic 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.

Register Log in

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

Eric_O

Newbie level 5
Joined
May 31, 2020
Messages
10
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
106
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:

betwixt

Super Moderator
Staff member
Joined
Jul 4, 2009
Messages
14,128
Helped
4,678
Reputation
9,371
Reaction score
4,415
Trophy points
1,393
Location
Aberdyfi, West Wales, UK
Activity points
120,720
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.
 

paulfjujo

Advanced Member level 4
Joined
Jun 9, 2008
Messages
1,343
Helped
273
Reputation
546
Reaction score
265
Trophy points
1,363
Location
France 01800
Activity points
9,394
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 !)
 

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
46,806
Helped
13,894
Reputation
28,036
Reaction score
12,530
Trophy points
1,393
Location
Bochum, Germany
Activity points
273,114
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

Eric_O

Newbie level 5
Joined
May 31, 2020
Messages
10
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
106
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 registersF76D455E-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
 

Toggle Sidebar

Part and Inventory Search


Welcome to EDABoard.com

Sponsor

Sponsor

Design Fast


×
Top