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

Timer1 in RC0 and RC1
Goto page Previous  1, 2, 3, 4, 5, 6  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
picman62



Joined: 12 Dec 2014
Posts: 77

View user's profile Send private message

PostPosted: Tue Jan 20, 2015 10:51 am     Reply with quote

Add this to the puzzle:

When I set TMR1 to INternal, it works. LCD displays the value and bargraph.

So my question now resumes to this:

Why when TMR1 is set to EXternal and I inject a 5kHz square wave in RC0 input, it works in Proteus but not in the hardware?

I would appreciate if anyone who has a protoboard and this PIC could replicate this and help me find out what is going on.
Thanks.

Code:

#include <16F877A.h>
#device adc=10
#fuses HS,NOWDT,NOPROTECT,NOLVP, BROWNOUT
#use delay(clock=20000000)
#include <LCD.c>
#include <LCD_bargraph.c>
#byte portc=0x07
#bit led=portc.1

long value;
int A;

#define PORTC<0>



void main() {
 
    delay_ms(100);
    lcd_init();
    init_user_chars();    // loads special characters into LCD CGRAM for bargraph
 
   while(TRUE)
   {
             
      set_timer1(0);
      setup_timer_1(t1_external | T1_DIV_BY_1);
      delay_ms(50);
      setup_timer_1(T1_DISABLED);
 
      value=get_timer1();
   
     delay_ms(20);     //pause so we don't blur the LCD display     
      A=value/6;
             //calculate the full scale for our bar
   
      output_c (get_timer1()); // read ADC and copy result to LEDs
      lcd_putc('\f');   //clear the LCD
      printf(lcd_putc, "%lu \n",value); //Print top line with ADC value
      bargraph(A);      //print line 2 with the bargraph output.         
   }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Jan 20, 2015 12:09 pm     Reply with quote

What are the voltage levels for your 5 KHz square wave ? They must
be 0v for the low level and at least 4.0v for the high level, and preferably
greater than 4.0v.

Also, what is this line that you keep putting in your code ?
Code:
#define PORTC<0>

It's not useful. It doesn't follow CCS syntax for any CCS function or
feature. What does it do ?
Ttelmah



Joined: 11 Mar 2010
Posts: 20063

View user's profile Send private message

PostPosted: Tue Jan 20, 2015 2:44 pm     Reply with quote

Also as a general comment, always set things up before you use them.
You zero the time, then set it up. Sometimes changing things like prescaler values, will cause timers to count. So setup, zero, wait, read.
picman62



Joined: 12 Dec 2014
Posts: 77

View user's profile Send private message

PostPosted: Tue Jan 20, 2015 4:43 pm     Reply with quote

PCM programmer wrote:
What are the voltage levels for your 5 KHz square wave ? They must
be 0v for the low level and at least 4.0v for the high level, and preferably
greater than 4.0v.

Also, what is this line that you keep putting in your code ?
Code:
#define PORTC<0>

It's not useful. It doesn't follow CCS syntax for any CCS function or
feature. What does it do ?


I have tried with 2.5v, 3, 3.5, 4, 4.5 and even 5v. No go.

The line above was taken from a code I saw here in this forum somewhere to turn RC0 an input.

What line do you suggest for this?
picman62



Joined: 12 Dec 2014
Posts: 77

View user's profile Send private message

PostPosted: Tue Jan 20, 2015 4:50 pm     Reply with quote

Ttelmah wrote:
Also as a general comment, always set things up before you use them.
You zero the time, then set it up. Sometimes changing things like prescaler values, will cause timers to count. So setup, zero, wait, read.


I have already tried different prescalers. They only help to reduce the number of bars across the display or increase them.

There is something that is avoiding the code to run in timer1 which I still did not identify. Maybe it's software related, but could be hardware. This last possibility is almost null in my opinion. If the bargraph works in ADC mode, why then not working in TMR1 mode?

Code:

value=get_timer1();


I think this is where the problem is. It reads 'get timer2' fine. Why not TMR1? I mean it reads TMR1 if I set it to internal, but not as 'external'. What could be blocking the incoming generator signal, software wise?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Jan 20, 2015 5:14 pm     Reply with quote

This line below sets all PortC pins to be outputs. They stay that way.
Code:
 output_c (get_timer1());

You cannot clock the timer with its input (pin C0) set to be an output.
picman62



Joined: 12 Dec 2014
Posts: 77

View user's profile Send private message

PostPosted: Tue Jan 20, 2015 6:45 pm     Reply with quote

PCM programmer wrote:
This line below sets all PortC pins to be outputs. They stay that way.
Code:
 output_c (get_timer1());

You cannot clock the timer with its input (pin C0) set to be an output.


Thanks for the information.

So what would be the correct statement for that?

I need pin RC0 to be an input for the incoming external signal and RC1 to be the output for the LED to 'get timer1'.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Jan 20, 2015 7:05 pm     Reply with quote

Quote:
RC1 to be the output for the LED to 'get timer1'.

I don't get what you're doing. You read Timer1, which is a 16-bit number.
Then you want to somehow output it to one LED pin ? What does this
LED signify ?

Your comment below implies there are multiple LEDs.
Quote:
output_c (get_timer1()); // read ADC and copy result to LEDs
picman62



Joined: 12 Dec 2014
Posts: 77

View user's profile Send private message

PostPosted: Wed Jan 21, 2015 12:52 pm     Reply with quote

PCM programmer wrote:
Quote:
RC1 to be the output for the LED to 'get timer1'.

I don't get what you're doing. You read Timer1, which is a 16-bit number.
Then you want to somehow output it to one LED pin ? What does this
LED signify ?

Your comment below implies there are multiple LEDs.
Quote:
output_c (get_timer1()); // read ADC and copy result to LEDs


Actually I am using a LED in proteus simulator, but it will not necessarily be the case for the hardware. It will be a buzzer or speaker. The plan is, the closer the received frequency is from the intended frequency the more frequent the speaker or buzzer will sound and more bars will show up in the display. So I am using the LED because it is much more reliable then using a virtual buzzer.

Please correct me if I am wrong. I am using timer1 in external mode to serve as a reference for the incoming frequency pulse. Pin RC0 is acting or should act as a frequency counter. Hence the reference to TIMER1. Once a particular frequency is received, I will program the speaker or buzzer in RC1 to sound based on a specific value reading of TMR1.
Code:
read ADC and copy result to LEDs

This was taken from some code and copied to my own one. But it will not 'read ADC', but actually 'get value from TMR1' and it is only one LED.

I would appreciate if in case the lines of the code are not working for my requirements above, regarding pins RC0, RC1 and TMR1, if you could correct them.
Thanks.
picman62



Joined: 12 Dec 2014
Posts: 77

View user's profile Send private message

PostPosted: Wed Jan 21, 2015 3:47 pm     Reply with quote

I am on a trip right now and unfortunately for this reason I do not have access to the protoboard and hardware which is in my lab.
However I got my notebook and this afternoon I put together with some changes, a frequency counter code I found for CCS and I expect to test it in a few days upon my return.

This code looks more elaborate and precise than the previous one. Specially because now the display shows the correct value for frequencies other than just values based on variables like the other one.

I have one problem tough that I hope someone can help me.

This code uses TIMR1, so pins RC0 and RC1 are set to inputs and both are 'reading' the signal generator output.
Considering also that I will have RC2 as an output for PWM,
I would like to set PIN C1 also as an output due to the fact already explained in my previous post that this pin will 'read' TIMR1 and light the led or sound the buzzer with blinks or beeps when the chosen frequency is 'received'.

What lines and instructions should I add?
Thanks in advance.
Code:

#include <16f877a.h>             
                               
#FUSES NOWDT                     //No watchdog timer
#FUSES HS                       
#FUSES NOPROTECT                 
#FUSES NOLVP                     //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD    //No EE protection
#FUSES NOBROWNOUT 
//#FUSES NOMCLR
#use delay(clock=20000000)       
#byte portc=0x07

#include <LCD.C>               
#include <LCD_bargraph.c>

#bit t1_overflow=0x0C.0

// #bit t1_overflow=0xF9E.0  (PIC18, Reminder)

void main() {
   delay_ms(100);
   lcd_init();
   init_user_chars();
   int cycles8, cycles;
   int32 freq;
   long freqc_high;
   long freqc_low;
   int A;   
   int B;
   int C;
 
   while (TRUE) {
      cycles8=0;
      cycles=0;
      freqc_high=0;
      t1_overflow=0;
      set_timer1(0);
      setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);
/* ___ wait one second ___  */
      while (cycles!=0xFF) { //true=3, false=4
       cycles8=0; //1 cycle
       //start inner loop
       while (cycles8!=0xFF) { //true=3, false=4
         if (t1_overflow)//true=2,false=3             //----|
            {t1_overflow=0;freqc_high++;}//6 cycles   //    |
         else                                         //    |-- 8 cycles
            {delay_cycles(5);}                        //----|
         delay_cycles(62); //x
         cycles8++; //1
 ///2 cycles to jump to top
 //math: end inner loop
 //math: total inner loop=((3+8+x+1+2)*255 + 4)*255
 //math: if x=62.87781 then inner loops takes 5mil instructions
 //math: if x=62 then inner loop takes 4942920, have to fill 57080 cycles
  }
 delay_cycles(216);      //y
 cycles++;          ///1 cycle
 ///2 cylces to jump to top
 //math: outer=(3+1+y+1+2)*255+4=57080
 //math: y=(57080-4)/255)-(3+1+0+0+1+2)
 //math: if y=216.827450980392156862745098039216 then outer loop cylces is 57080
 //math: if y=216 then outer loop cycles is off by 211 cycles.  z=211
}
      delay_cycles(211);   //z
/* ___ end waiting 1 second ___ */
      setup_timer_1(T1_DISABLED);   //turn of counter to prevent corruption while grabbing value
      if (t1_overflow)            //check one last time for overflow
          freqc_high++;
     
      freq=make32(freqc_high,freqc_low); //use new make32 function to join lsb and msb
      freqc_low=get_timer1();      //get timer1 value as the least sign. 16bits of freq counter
     
     
      A=freqc_low/200; //gives about 9 bars in bargraph
      B=freqc_low/400; //gives about 4 bars
      C=freqc_low/800; //gives 2 bars
     
      printf (lcd_putc,"\f%LU Hz\n",freqc_low);      //and print frequency
     
      if(freqc_low>=4998 && freqc_low<=5000)
      bargraph(A);      //print line 2 with the bargraph output.
     
      if((freqc_low>=4994 && freqc_low<4998) || (freqc_low>=5005 && freqc_low<5020))
      bargraph(B);// simulates offset of exact frequency
     
      if((freqc_low>=4985 && freqc_low<4994) || (freqc_low>=5020 && freqc_low<5035))
      bargraph(C); // further out from exact frequency
     
     
 
   }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jan 21, 2015 6:05 pm     Reply with quote

If you want to turn on an LED, assuming it's connected like this,
Code:

PIC      470 ohms      LED       
pin -----/\/\/\/------->|----
C2                          |
                            |
                          -----  Ground 
                           ---
                            -

Then use this code:
Code:
output_high(PIN_C2);
picman62



Joined: 12 Dec 2014
Posts: 77

View user's profile Send private message

PostPosted: Wed Jan 21, 2015 6:37 pm     Reply with quote

PCM programmer wrote:
If you want to turn on an LED, assuming it's connected like this,
Code:

PIC      470 ohms      LED       
pin -----/\/\/\/------->|----
C2                          |
                            |
                          -----  Ground 
                           ---
                            -

Then use this code:
Code:
output_high(PIN_C2);


Yes, thanks. Actually it's pin C1. C2 is the PWM.
But suppose I wish that PIN_C1 'reads' from timer1.

You see, there is a difference in just making the LED light up when a certain programmed parameter is achieved and when it actually 'blinks' reading from an ADC input or from timers.

In the previous code, I included 'output_c(get_timer1());'
But as you told, this was setting all C pins as outputs. This is not what I want, since I need pinC0 to be an input for the signal generator.
So as you correctly pointed out, the 'output_c' statement, included all C pins as outputs, creating a big mistake when feeding C0 with a frequency pulse to a pin that was set as an 'output'. Probably this was the one mistake that caused the hardware error yesterday.

Regarding the code to make pin C1 an output to 'read' TIMR1, I tried 'output_c1(get_timer1());' but CCS gives me an error message about 'output_c1'.

So, to summarize all this: When setting TMR1, I see that both C0 and C1 become inputs for the signal generator since they both have TMR1s in their addresses. I then need to set RC1 as output for the LED, able to 'read from TMR1.
'output_high(pin_c1)(get_timer1());' does not work.

1 - How would you write this line then?
2 - Do you think writing
Code:
set_tris_c(0b00000001);
would suffice for setting only C0 as input?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jan 21, 2015 8:08 pm     Reply with quote

Quote:

When setting TMR1, I see that both C0 and C1 become inputs for the
signal generator since they both have TMR1s in their addresses.

I assume you mean the pin descriptions (not addresses):
RC0/T1OSO/T1CKI
RC1/T1OSI/CCP2
The fact that both descriptions have "T1" in them does not mean
they are both required for Timer1 in External input mode. It also does
not mean that both pins must be inputs.

You want to use Timer1 with an external clock. This comes in on Pin C0.
Pin C0 will be an input pin.
Pin C1 is available for PWM (as CCP2), or it could be an ordinary I/O pin.
It could be an output pin.

The only configuration in which both pins (C0 and C1) would be required
for Timer1, is if you were using an external watch crystal on those pins,
for use with the Timer1 oscillator. You are not doing this, and therefore,
pin C1 is completely free for use as an I/O pin.
picman62



Joined: 12 Dec 2014
Posts: 77

View user's profile Send private message

PostPosted: Wed Jan 21, 2015 8:43 pm     Reply with quote

PCM programmer wrote:

The fact that both descriptions have "T1" in them does not mean
they are both required for Timer1 in External input mode. It also does
not mean that both pins must be inputs.

You want to use Timer1 with an external clock. This comes in on Pin C0.
Pin C0 will be an input pin.
Pin C1 is available for PWM (as CCP2), or it could be an ordinary I/O pin.
It could be an output pin.

The only configuration in which both pins (C0 and C1) would be required
for Timer1, is if you were using an external watch crystal on those pins,
for use with the Timer1 oscillator. You are not doing this, and therefore,
pin C1 is completely free for use as an I/O pin.



Yes, this is what I had in mind when I wrote this:
Code:

Void main()
set_tris_c(0b00000001);

Which hopefully would set C0 as an input and all other pins in portC as outputs.

Then I wrote:

Code:
output_high(pin_c1)==get_timer1();


This line was compiled with no errors by CCS.
Then I included it in the following instruction:
Code:

if(freqc_low>=4998 && freqc_low<=5000)
       output_high(pin_c1)==get_timer1();
       else
       output_low(pin_c1);


Which makes the LED light up only in this interval of values.
It worked fine in Proteus.

When I disconnected the signal generator from pin C0 and set it on pin C1, which by the TRIS statement above, should display a blank LCD since it was set as an output, to my surprise it displayed the same as pin C0 with bargraph and frequency counter values.

So, why the TRIS line setting RC0 as input and RC1 as output did not work and RC1 keeps acting as an input? Am I missing something obvious here?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jan 21, 2015 8:52 pm     Reply with quote

Quote:
output_high(pin_c1)==get_timer1();

This statement is wrong, doesn't work as you intend, and should not
be written.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2, 3, 4, 5, 6  Next
Page 4 of 6

 
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