CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

PWM, Timer0, Timer2 in 12F615

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
jjacob



Joined: 08 Mar 2008
Posts: 54
Location: PORTUGAL (PORTO)

View user's profile Send private message

PWM, Timer0, Timer2 in 12F615
PostPosted: Sat Jul 18, 2009 9:59 am     Reply with quote

Hello.

I'm using :

Compiler Version : 4.057
PIC12F615
5V power supply
Internal Oscillator ...

I need to count the frequency of the input signal... 0 ... 50Hz ... and make it in a 0 ... 5V signal.

I've tested this software in 18F452 and it worked ... but it's a big PIC ... so I want to put this working in a 12F615...

This the code :
Code:

#include <12F615.H>

#fuses INTRC_IO,NOWDT,NOPROTECT,NOMCLR,NOBROWNOUT
#use delay(clock=4000000)

#define in PIN_A3

int sec, N1;
int16 pwm, count;

//http://www.ccsinfo.com/forum/viewtopic.php?p=118216
#int_RTCC
void RTCC_isr(void) {
   sec++;
      if(sec>=2){
// Instead of calculate pwm to 1023, i limit to 1000... for easier math...
// Max. freq. is 50Hz
// 0Hz - 0V. For 50Hz - 5V.
// pwm=(N*1000)/50, where N is the frequency value...
// As i sample every 2 seconds, freq=count/2;
         pwm=((((count)/(int16)2)*(int16)1000)/((int16)50));
         count=0;
         sec=0;
         N1=1;
   }
}


// I do software 'debouncing', because the input of the pic, comes from a
// LM311 and sometimes is has some 'garbage' ... so i complete with software...
void wait_for_low() {
   int count=0;

   while(count<100 && !N1){             /* debouncing... */
      if(!input(in)) count++;
      delay_us(100);
   }
}

void wait_for_high() {
   int count=0;

   while(count<100 && !N1){             /* debouncing... */
      if(input(in)) count++;
      delay_us(100);
   }
}

// ************************************
//   RTCC is the same as TIMER0  !!!!!
// ************************************
void main(){
   
      setup_adc_ports(ADC_OFF);
     delay_us(10);                          // A small delay is necessary

   setup_timer_2(T2_DIV_BY_4, 255, 1);

      setup_ccp1(CCP_PWM);                     // Configure CCP1 as a PWM

// I get an interrupt each 2 seconds ...

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16);
   enable_interrupts(INT_RTCC);
   enable_interrupts(GLOBAL);

   count=0;
   sec=0;
   N1=0;

   set_pwm1_duty(512);

   while(1){
      wait_for_low();
      wait_for_high();
      count++;
      if (N1){
         set_pwm1_duty(pwm);
         //printf("\n\r count = %Lu   pwm = %Lu", count, pwm);
         N1=0;
      }

   }
}

For test the 12F615, I made a simple software : ReadADC put in PWM.
It worked fine, if I varied the input voltage in the ADC the PWM changed in the same way.

With the above code, I made some debug, commenting lines and I always had the same PWM (50%) because of the line before the 'while(1)' in the end of my code.

When I uncomment the line :
Code:
enable_interrupts(GLOBAL);


The PWM goes to zero and nothing change on the PWM output, even with a 50Hz input !!!

Any idea ?? PWM works with Timer2 ... my interrupts are with Timer0 ... any problem with this ? I'm using the internal oscillator. Is this a problem ?

Thank you for your attention
Jacob
jjacob



Joined: 08 Mar 2008
Posts: 54
Location: PORTUGAL (PORTO)

View user's profile Send private message

PostPosted: Sat Jul 18, 2009 12:35 pm     Reply with quote

Hi all Very Happy

I found the problem ...
Timer0 in 18F452 is a 8/16 bit (i was using as a 16bits...).
Timer0 in 12F615 is a 8 bit !! So the migration was not direct !!!

I change the code and use timer1 to do the 2 seconds 'tick'... I think that the calculations are correct. I have an interrupt ... near every 2 seconds ...
To see that i use a 'led' Surprised

Still, i haven't understand why i have to put 'sec>=8' instead of 'sec>=4' for the 2 seconds pwm refresh value ??!!!


Here is the code :
Code:

#include <12F615.H>

#fuses INTRC_IO,NOWDT,NOPROTECT,NOMCLR,NOBROWNOUT
#use delay(clock=4000000)


#define in PIN_A3
#define led PIN_A4

int sec, N1;
int16 pwm, count;

//http://www.ccsinfo.com/forum/viewtopic.php?p=118216


// Timer1 interrupt is called every 0.524288 segundos
// 'timer1' é de 4MHz/4 = 1MHz = 1us
//  1us*2^16*8 = 0.524288 seconds  ???????? why 'sec>=8'
// With this math, it would be 'sec>=4'   ???????
#int_timer1
void timer1_isr(void) {
   sec++;
      if(sec>=8){
// Instead of calculate pwm to 1023, i limit to 1000... for easier math...
// Max. freq. is 50Hz
// 0Hz - 0V. For 50Hz - 5V.
// pwm=(N*1000)/50, where N is the frequency value...
// As i sample every 2 seconds, freq=count/2;
         pwm=((((count)/(int16)2)*(int16)1000)/((int16)50));
         output_toggle(led);
      //printf("count : %Lu  pwm = %Lu\n\r", count, pwm);
         count=0;
         sec=0;
         N1=1;
   }
}


// I do software 'debouncing', because the input of the pic, comes from a
// LM311 and sometimes is has some 'garbage' ... so i complete with software...
void wait_for_low() {
   int count=0;

   while(count<100 && !N1){             /* debouncing... */
      if(!input(in)) count++;
      delay_us(100);
   }
}


void wait_for_high() {
   int count=0;

   while(count<100 && !N1){             /* debouncing... */
      if(input(in)) count++;
      delay_us(100);
   }
}

// ************************************
//   RTCC is the same as TIMER0  !!!!!
// ************************************
void main(){
   
      setup_adc_ports(ADC_OFF);
     delay_us(10);                          // A small delay is necessary

   setup_timer_2(T2_DIV_BY_4, 255, 1);

      setup_ccp1(CCP_PWM);                     // Configure CCP1 as a PWM

   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);

   count=0;
   sec=0;
   N1=0;

   set_pwm1_duty(512);

   output_low(led);
   
   while(1){
      wait_for_low();
      wait_for_high();
      count++;
      if (N1){
         set_pwm1_duty(pwm);
         //printf("\n\r count = %Lu   pwm = %Lu", count, pwm);
         N1=0;
      }

   }
}


Now i have a PWM refresh rate of about 2 seconds ...

But i would like to do the EXACT math ... i've looked into 12F615 datasheet 'TIMER1 BLOCK DIAGRAM' but cant' figure out if the clock source is FOsc or FOsc/4. For my code i would say that is FOsc ... but i can't understand ...
Can anyone help me ??

Thank you
Jacob
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Jul 18, 2009 3:21 pm     Reply with quote

Quote:

setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);

but can't figure out if the clock source is FOsc or FOsc/4.

The PIC data sheet says this:
Quote:

REGISTER 6-1: T1CON: TIMER1 CONTROL REGISTER

bit 1 TMR1CS: Timer1 Clock Source Select bit
1 = External clock from pin RC0/T1OSO/T1CKI (on the rising edge)
0 = Internal clock (FOSC/4)

You have configured the Timer for T1_INTERNAL, therefore the clock
is Fosc/4.
jjacob



Joined: 08 Mar 2008
Posts: 54
Location: PORTUGAL (PORTO)

View user's profile Send private message

PostPosted: Sat Jul 18, 2009 4:24 pm     Reply with quote

Thank you PCM programmer for your simple explanation Smile


In the datasheet that i've download it is writen :

bit 1 TMR1CS: Timer1 Clock Source Select bit
1 = External clock from T1CKI pin (on the rising edge)
0 = Internal clock (FOSC/4) or system clock (FOSC)(3)

(3) is a note :
3: See T1ACS bit in CMCON1 register.

In CMCON1 :

bit 4 T1ACS: Timer1 Alternate Clock Select bit
1 = Timer 1 Clock Source is System Clock (FOSC)
0 = Timer 1 Clock Source is Instruction Clock (FOSC\4)


CCS is a 'high level' language, how can i know what is the state of bit 4 in T1ACS ?

Thank you for your attention
Jacob
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Jul 18, 2009 4:32 pm     Reply with quote

I'm not at my regular computer so I didn't have access to the 12F615
data sheet. I used the 16F877 data sheet.

To see what the compiler is loading into the Timer1 registers:
Go to the Project / Build Options menu in your IDE, and set the List file
format to Symbolic. Then re-compile and look at the .LST file. Find the
line for setup_timer_1(), and you'll see the register settings in ASM code.
jjacob



Joined: 08 Mar 2008
Posts: 54
Location: PORTUGAL (PORTO)

View user's profile Send private message

PostPosted: Sat Jul 18, 2009 5:10 pm     Reply with quote

No problem Smile

Here is part of my .lst :
Code:

....................       setup_ccp1(CCP_PWM);                     // Configure CCP1 as a PWM
00EA:  BCF    05.2
00EB:  BCF    03.5
00EC:  BCF    05.2
00ED:  MOVLW  0C
00EE:  MOVWF  15
00EF:  CLRF   16
....................    setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
00F0:  MOVLW  B5
00F1:  MOVWF  10
....................    enable_interrupts(INT_TIMER1);



It's been a long long time that I don't program in ASM ... and really don't understand what is what Sad

If you would be so kind and patient to explain me ... I would appreciate.
Thank you for you help
Jacob
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Jul 18, 2009 5:28 pm     Reply with quote

You didn't put it in Symbolic List file format. It's still in normal CCS format.
But, it doesn't matter. Here's the explanation:
Quote:
...... setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
00F0: MOVLW B5
00F1: MOVWF 10 // T1CON

It's moving 0xB5 into the T1CON register. Converting 0xB5 to binary
gives: 1011 0101

Look in the Timer1 section of the 12F615 data sheet. It has a section
that describes the functions controlled by each bit in the T1CON register.
Look the binary value above (Bit 7 is on the left, and bit 0 is on the right)
and see what the settings mean.

It's easier if you print that page in the data sheet, and write in the bit
values below the register diagram: 10110101
Then study the explanations below them.
jjacob



Joined: 08 Mar 2008
Posts: 54
Location: PORTUGAL (PORTO)

View user's profile Send private message

PostPosted: Sat Jul 18, 2009 5:46 pm     Reply with quote

OK ...

I have in my .lst :
Code:

00D7:  CLRF   1C


This means that register '1C' (CMCON1 register) is cleared. So :
Code:

bit 4 T1ACS: Timer1 Alternate Clock Select bit
1 = Timer 1 Clock Source is System Clock (FOSC)
0 = Timer 1 Clock Source is Instruction Clock (FOSC\4)


I have bit4 cleared, so, as you said, i have FOSC\4 for timer1 ...

UFFF ... it was 'hard' to understand ... if what i've said is write, i think that i've learned VERY MUCH with this post Very Happy

Thank you very much ... but please tell me if i'm wrong ...
Jacob
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Jul 18, 2009 6:56 pm     Reply with quote

Yes, that's correct. It uses Fosc/4.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group