Problem med interrupt ccp

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Stene
Inlägg: 276
Blev medlem: 13 maj 2008, 19:21:52
Ort: Uppsala

Problem med interrupt ccp

Inlägg av Stene »

Hej!
Jag har nu suttit ett tag o försökt få igång en interrupt funktion på ccp. Jag använder mig av en 16f628 som går på 4 Mhz. Jag har Prescalen står på 1:8 på timer 1 som ccp:n använder. Jag får värdet "t1" överfört till pc men problemet är att den överför värdet konstant. Jag vill bara ha en överföring av "t1" och sen vill jag att den ska vänta tills flaggan är satt och då skicka över det nya värdet. Den ändrar värdet om man pulsar den på ccp ingången men den stannar aldrig upp och väntar på flaggan. Är det någon som ser vad jag gjort för fel? Programmet är skrivet i en compilator från B Knudsen Data

Kod: Markera allt

#include "16F628.h" 
#include "int16Cxx.h"
#pragma config |= 0x3f81             

unsigned long  t1 ;  

            
#pragma origin 4
interrupt int_server( void )
{
  int_save_registers 
  if( CCP1IF == 1)                             /* test if it is the INT-interrupt?         */   
   {     
    t1  = CCPR1H*256;
    t1 += CCPR1L;
    CCP1IF = 0;   
    }
  int_restore_registers  
}


#include "math16.h"
void initserial( void );
bit putchar( char );
void string_out1( void );
void unslongtoa( unsigned long );

void main( void)
{
   char i;
    
    TRISB.3 = 1;                            /* CCP1-pin is input            */
    initserial();  
    T1CON = 0b00.11.0.0.0.1 ;         /* 0b00.11.0.0.0.1  prescal 1:8  */
    CCP1CON = 0b00.00.0101;  
    OPTION .7 =0;                          /*  .7 =0;                     */  
    GIE     = 1 ;
    PEIE    = 1 ;
    CCP1IE  = 1 ;                    
                         
                
while(1)
  {
    
  

    unslongtoa(t1);                      
    string_out1();
    putchar('\n');
    
  }
}

void initserial( void )            /* initialise serialcom port */
{
   SPEN = 1;
   BRGH = 1;                        /* Async high speed   */
   TXEN = 1;                        /* transmit enable    */
   SPBRG = 26 -1;                 /* 9600 Baud @ 20 MHz-clockfrequency */
   CREN = 1;                        /* Continuous receive */
   RX9  = 0;                         /* 8 bit reception    */
   TRISB.2 = 0;                     /* serial_out is output */  
   TRISB.1 = 1;                     /* serial_in is input   */  
  

}


bit putchar( char d_out )           /* sends one char */
{

   if(d_out == '\0') return 0;     /* refuse to send 0 "end of string" */
   while (!TXIF) ;                 /* wait until previus character transmitted   */
   TXREG = d_out;
   return 1;                       /* done */

}


void OverrunRecover(void)
{  
   char trash;
   trash = RCREG;                 /* the two char's that locked the reciever  */
   trash = RCREG;                 /* are read and ignored                     */
   CREN = 0;                      /* the unlock procedure ...                 */
   CREN = 1;
}

Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Problem med interrupt ccp

Inlägg av Icecap »

if( CCP1IF == 1) kan ge mycket fel värde!
Använd if(CCP1IF) istället. Orsaken är att vissa kompilatorer kollar CCP1IF som en ren maskning och den kan enbart bli ==1 om det är bit 0 i en byte.

Sedan är det sannolikt snabbare att överföra på detta vis:
*(unsigned char*)(&t1 + 1) = CCPR1H;
*(unsigned char*)(&t1) = CCPR1L;

Men jag tror att felet kommer av det första.
Niklas-k
Inlägg: 354
Blev medlem: 10 mars 2004, 15:59:21
Ort: Katrineholm

Re: Problem med interrupt ccp

Inlägg av Niklas-k »

Kod: Markera allt

while(1)
  {
   
 

    unslongtoa(t1);                     
    string_out1();
    putchar('\n');
   
  }
Du loopar här i evighet oberoende om det blir interrupt och skickar hela tiden t1.
Behöver ett villkor till tror jag!
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Problem med interrupt ccp

Inlägg av bearing »

Interruptet ser helt korrekt ut. if( CCP1IF == 1) eller if( CCP1IF ) spelar ingen roll i CC5X.

Använd en flagga i interruptet som berättar för huvudprogrammet när en ny period sparats. T.ex. såhär:

Kod: Markera allt

unsigned long  t1 ; 
bit captureFlag; //Flagga som berättar för huvudprogrammet att t1 har uppdaterats
           
#pragma origin 4
interrupt int_server( void )
{
  int_save_registers
  if( CCP1IF == 1)                             /* test if it is the INT-interrupt?         */   
   {     
    t1  = CCPR1H*256; //Går att göra fortare: t1.high8=CCPR1H;
    t1 += CCPR1L;  //t1.low8=CCPR1L;
    CCP1IF = 0;
    captureFlag=1; //
    }
  int_restore_registers 
}

Kod: Markera allt

captureFlag=0;
while(1)
  {
 if (captureFlag) //Om t1 uppdaterats - skicka till datorn
{
   captureFlag=0;
    unslongtoa(t1);                     
    string_out1();
    putchar('\n');
  } 
  }
Det vore även bra att spara en kopia av t1 innan den görs om till sträng, ifall ett interrupt skulle ske just då. T.ex. såhär:

Kod: Markera allt

GIE=0;  //Stäng kort av intterupt
period=t1; //Medans t1 sparas
GIE=1;
unslongtoa(period);
Stene
Inlägg: 276
Blev medlem: 13 maj 2008, 19:21:52
Ort: Uppsala

Re: Problem med interrupt ccp

Inlägg av Stene »

Hej!
Nu fungerar det som jag skrev att jag ville att det skulle göra. Gjorde som bearing skrev. Hade stirrat mig blind på interrupten. Har stöt på ett nytt problem. Nu när jag la "t1 koden" i unterruptet så blev värdet konstigt. vid en simulering med en roterande axel med en induktiv givare på som drivs av en borrmaskin så är värdet stort mellan att ha den i interrupt eller inte. Utan interrupt logade jag värde 26400, 26373, 26353, 26343, 26353 och att ha den i interrupt 222,75,171,85,66.
Jag har också ändrat hastigheten för att se någon skillnad med det vills sig ändå inte . 4 Mhz 1:1 till 1:8. 10 Mhz 1:1 till 1:8. 20 Mhz 1:1 till 1:8. Ska det bli så eller har jag gjort något mera fel som jag inte ser?

Kod: Markera allt

#include "16F628.h" 
#include "int16Cxx.h"
#pragma config |= 0x3f81             

unsigned long  t1 ;  
bit captureFlag; 
char period;           
#pragma origin 4
interrupt int_server( void )
{
  int_save_registers 
  if( CCP1IF == 1)                             /* test if it is the INT-interrupt?         */   
   {     
 
    t1.high8=CCPR1H;
    t1.low8=CCPR1L;

    CCP1IF = 0; 
    captureFlag=1;
    

    }
  int_restore_registers  
}
#include "math16.h"
void initserial( void );
bit putchar( char );
void string_out1( void );
void unslongtoa( unsigned long );
char RPM[6];                        /* 11 Global char array for digits */

void main( void)
{
   char i;
    
    TRISB.3 = 1;                      /* CCP1-pin is input            */
    initserial();  
    T1CON = 0b00.11.0.0.0.1 ;         /* 0b00.11.0.0.0.1  prescal 1:8  */
    CCP1CON = 0b00.00.0111;  
    OPTION .7 =0;                     /*  .7 =0;                     */  
    GIE     = 1 ;
    PEIE    = 1 ;
    CCP1IE  = 1 ;                    
                         
                
while(1)
  {
    
  if (captureFlag == 1) 
 {
      captureFlag=0;
      GIE=0;  
      period=t1;
      GIE=1;  
      unslongtoa(period);
      string_out1();
      putchar('\n');
  } 

  
    
  }
}

void initserial( void )            /* initialise serialcom port */
{
   SPEN = 1;
   BRGH = 1;                        /* Async high speed   */
   TXEN = 1;                        /* transmit enable    */
   SPBRG = 26 -1;                   /* 9600 Baud @ 20 MHz-clockfrequency   26 = 4 khz 65 = khz*/
   CREN = 1;                        /* Continuous receive */
   RX9  = 0;                        /* 8 bit reception    */
   TRISB.2 = 0;                     /* serial_out is output */  
   TRISB.1 = 1;                     /* serial_in is input   */  
  

}


bit putchar( char d_out )           /* sends one char */
{

   if(d_out == '\0') return 0;     /* refuse to send 0 "end of string" */
   while (!TXIF) ;                 /* wait until previus character transmitted   */
   TXREG = d_out;
   return 1;                       /* done */

}


void OverrunRecover(void)
{  
   char trash;
   trash = RCREG;                 /* the two char's that locked the reciever  */
   trash = RCREG;                 /* are read and ignored                     */
   CREN = 0;                      /* the unlock procedure ...                 */
   CREN = 1;
}

bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Problem med interrupt ccp

Inlägg av bearing »

variabeln "period" måste vara en unsigned long, eftersom att "t1" har den typen. variabeln ska heller inte vara global, eftersom att den bara används i main().

Kod: Markera allt

void main( void)
{
   char i;
   unsigned long period;
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Problem med interrupt ccp

Inlägg av Icecap »

Den kan fint vara global om man vill det!
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Problem med interrupt ccp

Inlägg av bearing »

Klart den kan. Jag övervägde en stund att skriva "bör" istället för "ska". Men varför? det är väl bättre att ha som vana att börja med lokala variabler, och ändra dem till globala först när behovet kommer.
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Problem med interrupt ccp

Inlägg av Icecap »

Jo, ganska sant. Tyvärr kan detta med lokala variabler ställa till det lite, i ett projekt fick jag en del konstiga fel under kompileringen och det var just för att jag hade lokala variabler, deras minne kom ifrån heap'en som helt enkelt i ett fall (stor debugbuffer) inte var stor nog.

Men jag gillar också att hålla variabler där de används, nice and tight.
Skriv svar