Sida 1 av 1

Problem med interrupt ccp

Postat: 23 september 2009, 20:57:22
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;
}


Re: Problem med interrupt ccp

Postat: 23 september 2009, 21:18:52
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.

Re: Problem med interrupt ccp

Postat: 23 september 2009, 21:30:56
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!

Re: Problem med interrupt ccp

Postat: 23 september 2009, 21:37:30
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);

Re: Problem med interrupt ccp

Postat: 24 september 2009, 18:49:58
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;
}


Re: Problem med interrupt ccp

Postat: 24 september 2009, 22:07:59
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;

Re: Problem med interrupt ccp

Postat: 25 september 2009, 10:30:27
av Icecap
Den kan fint vara global om man vill det!

Re: Problem med interrupt ccp

Postat: 25 september 2009, 10:52:56
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.

Re: Problem med interrupt ccp

Postat: 25 september 2009, 11:20:15
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.