Multiple Interrupts

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 
1,775件の閲覧回数
MO_84
Contributor III

Hello,

 

I have enabled the input capture interrupts on rising edge and its working fine.

I now want to add a second interrupt (Timer Overflow Interrupt). The initialization below works fine.

I'm having problems when I enable the timer over flow interrupt on the TSCR2 register by changing its value to TSCR2 = 0x82. I've tried stepping through the code and after a few steps, True time simulator looses connection with board and my PORTB LED's stop working.

If I change TSCR2 back to TSCR2 = 0x02; everything works fine again.

 

 

void input_capture_initialize(void)
{
  TSCR1=0x90; /* enable timer and fast clear, rather than writing to bit0 of TFLG1 */
  TSCR2=0x02; /* prescale to 4  6000000 pps, longest pulse width measured using*/               
  TIOS|=0xFE;  /* select input capture (all channels) */
  TCTL3=0x00; /* capture disabled on channels 4 to 7 */
  TCTL4=0x01; /*PORTT0 capture on rising edge, channels 1 to 3 disabled */
  TIE=0x01;   /* enable timer interrupt on C0 */
  TFLG2=0x80;
}

 I think i'm not initializing something properly and the problem is somewhere in the initialization of the above registers.

 

However, here is the complete code (I don't expect anyone to go through it)

 

#include <hidef.h>      /* common defines and macros */
#include "derivative.h"      /* derivative-specific definitions */

volatile unsigned int rising, frequency_int, set_point;
volatile unsigned int flag;
float actual_period, frequency, period, average, Speed_RPM=0, frequency_actual;
unsigned int old_TC0, x, count, Speed_RPM2=0, i=0;
volatile int error;

void Set_Clock(void);
void PWM0_ini(unsigned char prescale_factor, unsigned char period, unsigned char init_duty);

#pragma CODE_SEG __NEAR_SEG NON_BANKED /* Interrupt section for this module.
Placement will be in NON_BANKED area. */

/* Interrupt on a rising edge of waveform connected to PT0 */
interrupt void toc0_isr(void)
{  
    if (flag ==0)
    {
        old_TC0 = TC0;
        flag = 1;
    }
    else
    {
        x = TC0;
        period = x - old_TC0;
        old_TC0 = TC0;
        average += period;
        count ++;
        if (count == 20)
        {
            count = 0;
            period = (average/20);
            average = 0;
            actual_period = period/6000000;
            frequency = 1/actual_period;
            frequency_int = (unsigned int)frequency/100;
            frequency_actual = (unsigned int)frequency;
            //PORTB = Speed_RPM2;
            error = set_point - frequency_int;
       }
    }
   
}
#pragma CODE_SEG DEFAULT

void input_capture_initialize(void); /* prototype to initialize input capture */

void main(void)
{                        
    DDRB = 0xFF;    //PORTB as output since LEDs are connected to it
    DDRJ = 0xFF;    //PTJ as output to control Dragon12+ LEDs
    DDRT = 0xFE;    /* PT0 is input, all the rest are unchanged */
    DDRH = 0x00;    //PORTH as input
    flag = 0;
    Set_Clock();
    PWM0_ini(0x03,255,0);
    flag = 0;
    input_capture_initialize();
    EnableInterrupts; /* clear I bit of CCR */
    while(1)
    {
        set_point = PTH;
        if (error > 8) error = 8;
        if (error < -8) error = -8;
        PWMDTY0 = 15*(error+8);
        Speed_RPM = frequency_actual*0.6666666;
        if (Speed_RPM < 300) Speed_RPM = 0;
        Speed_RPM2 = (unsigned int)Speed_RPM/10;
        //PORTB = Speed_RPM2;     
     
    }
     

}
     
     
void input_capture_initialize(void)
{
  TSCR1=0x90; /* enable timer and fast clear, rather than writing to bit0 of TFLG1 */
  TSCR2=0x82; /* prescale to 4  6000000 pps, longest pulse width measured using*/               
  TIOS|=0xFE;  /* select input capture (all channels) */
  TCTL3=0x00; /* capture disabled on channels 4 to 7 */
  TCTL4=0x01; /*PORTT0 capture on rising edge, channels 1 to 3 disabled */
  TIE=0x01;   /* enable timer interrupt on C0 */
  TFLG2=0x80;
}


void Set_Clock(void)
{
    CLKSEL &= 0x7F;
    PLLCTL |= 0x40;
    SYNR  = 0x05;
    REFDV = 0x01;
    while(!(0x08 & CRGFLG));
    CLKSEL |= 0x80;
}

void PWM0_ini(unsigned char prescale_factor, unsigned char period, unsigned char init_duty)
{
    PWMPRCLK = prescale_factor; /* choose 8-bit PWM, set clock A prescaler to prescale_factor */
                                /* choose clock A as clock source, PWM channel 0 output high
                                    at the beginning of the period */
    PWMPOL = 0x01;
    PWMCAE = 0x00; /* The next statements selects left-aligned */
    PWMCTL = 0x80; /* halt PWM clock in wait mode */
    PWMPER0 = period; /* set period of PWM0 to 0.1 ms */
                      /* period in sec = 1/(bus clock / prescale_factor) * PWMPER0 */
                      /* (PWMPER0-PWMDTY0)/PWMPER0*100% */
    PWMDTY0 = init_duty; /* set duty cycle to (period-init_duty) /period *100% */
    PWME |= 0x01; /* enable PWM0 channel */
}

#pragma CODE_SEG __NEAR_SEG NON_BANKED /* Interrupt section for this module.
Placement will be in NON_BANKED area. */
interrupt void TimerOverflow_ISR(void)
{
    TFLG2=0x80; /* clear Timer Interrupt Flag bit by a write*/
    i++;
    if (i<500)
    PORTB = 0xFF;
    if(i>500)
    PORTB = 0x00;
    if (i == 1000)
    i=0;
   
   
   
}
#pragma CODE_SEG DEFAULT

 

 

Thanks

ラベル(1)
0 件の賞賛
返信
1 解決策
1,073件の閲覧回数
kef
Specialist I

/* enable timer and fast clear

 

interrupt void TimerOverflow_ISR(void)
{
    TFLG2=0x80; /* clear Timer Interrupt Flag bit by a write*/

 

^^ this won't clear overflow flag when TFFCA is set. You need to read or write TCNT to clear overflow flag.

 

元の投稿で解決策を見る

0 件の賞賛
返信
2 返答(返信)
1,074件の閲覧回数
kef
Specialist I

/* enable timer and fast clear

 

interrupt void TimerOverflow_ISR(void)
{
    TFLG2=0x80; /* clear Timer Interrupt Flag bit by a write*/

 

^^ this won't clear overflow flag when TFFCA is set. You need to read or write TCNT to clear overflow flag.

 

0 件の賞賛
返信
1,073件の閲覧回数
MO_84
Contributor III

That was it.

Thank you Kef.

 

0 件の賞賛
返信