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

Configuring Timer1 Gate on PIC12F1840

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



Joined: 09 Dec 2006
Posts: 5
Location: Ontario, Canada

View user's profile Send private message Visit poster's website MSN Messenger

Configuring Timer1 Gate on PIC12F1840
PostPosted: Tue Mar 17, 2015 7:48 pm     Reply with quote

I have spent quite some time with the datasheet and experimenting but I cannot seem to get the Timer1 Gate feature working as expected. I am using a PIC12F1840 and compiler 4.129.

My end goal is to measure a short pulse width by using the Timer1 Gate on pin RA4 to control Timer1 like a stopwatch, and fetch the sampled time in an ISR or by polling between pulses.

I have tried to scale back on any complexity and just enable the T1G at all (without single pulse mode for nw).

Code:

#include <debug_serial.h>
#use rs232(uart1, baud=19200,parity=N,stop=1,bits=8)

void main() {
   printf("Hello\r\n");

   // Set to use internal oscillator at 16MHz with no PLL
   setup_oscillator(OSC_16MHZ|OSC_INTRC);

   // Disable ADC
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);   

   // Disable ECCP
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);

   // Pin       543210
   set_tris_a(0b011010);


   setup_timer_1(T1_INTERNAL|T1_DIV_BY_4|T1_GATE_INVERTED);

   // Main loop
   while (true) {
      delay_ms(1000);
      printf("val: %Lu\r\n", get_timer1());
   }
}


My expectation would be that this would keep printing "val: ####" over and over where the number #### is unchanged so long as T1G is held low. As soon as T1G is pulled high I would expect Timer1 to start counting (and rolling over) giving some other value.

However, it seems to be continuously running regardless of the state of T1G as my "val" never freezes.

Until I can understand this, it seems pointless to go off writing interrupt handlers and trying to enable the single-pulse mode.

Thanks!
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Tue Mar 17, 2015 9:57 pm     Reply with quote

how short is "short"?

and what is the interval between pulses ??

that gate could open and close many times in 1000msec ,
and the value you get from timer 1 could be many pulses or just one ,
but since you never CLEAR timer1
all you will get is random accumulating garbage anyway.

you need to very fundamentally rethink what the procedure
should be to use the gate to do what you want.

hint: you need to monitor gate state and clear the counter after a read

. it could be tricky.....
in reality this might be better handled with the capture module
instead.

post a complete program that will actually compile please..
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 18, 2015 1:00 am     Reply with quote

I made it work. The program below displays the following output on
the terminal window (TeraTerm) when I quickly press a push-button switch
on pin A4 once every 3 to 4 seconds.

If I don't press the switch, the timer value holds the same value and
continuously displays it, once per second. If I press the switch and then
release it, the timer counts up to a new value during the time that I held
the switch down. When I release the switch, it then displays the new
value once per second. You can see that below:
Code:

val: 0
val: 0
val: 0
val: 0
val: 18708
val: 18708
val: 18708
val: 31844
val: 31844
val: 41731
val: 41731
val: 58043
val: 7849
val: 7849
val: 7849
val: 7849
val: 7849
val: 7849


This is a schematic of the push-button switch circuit on Pin A4:
Code:

           +5v
            |
            <
            > 4.7K       
            <         ___  Switch 
To          |        _|_|_
PIC -----------------o   o------
pin                            |             
A4                            --- GND
                               -   
 

I tested this on a Microchip Low Pin Count board. I added the extra
switch to the board. It doesn't come with it. For serial output, I have
a small Sparkfun RS232 Shifter board. https://www.sparkfun.com/products/449
I have jumpers between the Low Pin Count board and the Shifter board
for Vcc, Gnd, and from Pin A0 on the PIC to the Rx-In pin on the Shifter
board. This was tested with CCS vs. 5.042.

Test program:
Code:

#include <12F1840.h>
#fuses INTRC_IO, NOWDT, BROWNOUT
#use delay(clock=4M)
#use rs232(baud=9600, UART1)

//======================================
void main()
{
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8 | T1_GATE |  T1_GATE_A4);
set_timer1(0);

while(TRUE)
  {
   delay_ms(1000);
   printf("val: %Lu\r\n", get_timer1());
  }

}
Marcoose



Joined: 09 Dec 2006
Posts: 5
Location: Ontario, Canada

View user's profile Send private message Visit poster's website MSN Messenger

PostPosted: Wed Mar 18, 2015 3:39 pm     Reply with quote

Thanks both asmboy and PCM programmer for your feedback!

Apologies for not providing a more clear explanation.

My test setup is eerily similar to what PCM programmer did, and I should have said so. I am using a breadboard with SMD adapter and have the serial connected to PC via a USB-TTL dongle and TeraTerm. Am using a switch exactly as in PCM programmer's example except the logic level inverted (A4 pulled low with 10k resistor, switch pulls it high) -- hence my T1_GATE_INVERTED.

I was trying to produce the exact same result (i.e. unchanging serial output until I tap the switch, not caring what the actual timer count is).

I just flashed PCM programmer's code and reversed my breadboard switch polarity to match. Strangely I am seeing the same behaviour I had before: an output where "val: ###" is constantly changing regardless of the switch state.

At least given that I now have a known-working piece of code and hardware setup from PCM programmer I will have to see if there is something wrong with my incredibly simple circuit (I made sure A4 wasn't floating with a logic probe, but will keep digging). If the hardware checks out, perhaps there is a glitch in my version of the compiler. I'm not sure I understand the assembly listing enough to figure out if a register isn't being set correctly per the data sheet but I'll try.

Apologies for not supplying a full program. I didn't expect anyone to go so far as compiling and testing for me!

Many many thanks!

P.S. the eventual goal is to capture a signal from a hobby RC receiver (1 - 2ms pulse, about 20ms apart). I know this has been done countless times, but I have always seen an interrupt-on-change used and wanted to try my hand at the timer1 gate since it seems perfectly suited.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 18, 2015 4:38 pm     Reply with quote

Quote:
I am using a PIC12F1840 and compiler 4.129.
perhaps there is a glitch in my version of the compiler

Try adding the lines shown in bold below:
Quote:

#include <12F1840.h>
#fuses INTRC_IO, NOWDT, BROWNOUT
#use delay(clock=4M)
#use rs232(baud=9600, UART1)

#byte APFCON = getenv("SFR:APFCON")
#bit T1GSEL = APFCON.3


//======================================
void main()
{
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8 | T1_GATE | T1_GATE_A4);
set_timer1(0);

T1GSEL = 0;

while(TRUE)
{
delay_ms(1000);
printf("val: %Lu\r\n", get_timer1());
}

}
Marcoose



Joined: 09 Dec 2006
Posts: 5
Location: Ontario, Canada

View user's profile Send private message Visit poster's website MSN Messenger

PostPosted: Wed Mar 18, 2015 7:00 pm     Reply with quote

And like magic it works! A great many thanks!

In trying to understand better what is going on I had already started digging through the .lst file and "learning" assembly. Very Happy

Or rather using the datasheet and opcode cheat sheet a line at a time to try and understand what was being put where. I hadn't spotted a problem (was looking for T1GCON) but looking at the diff now it is obvious.

Code:
.................... setup_timer_1(T1_INTERNAL | T1_DIV_BY_8 | T1_GATE | T1_GATE_A4); 
00E2:  BSF    1D.3
00E3:  MOVLW  35
00E4:  MOVLB  00
00E5:  MOVWF  18
00E6:  MOVLW  80
00E7:  MOVWF  19
.................... set_timer1(0); 
00E8:  CLRF   17
00E9:  CLRF   16

With added code
Code:

.................... T1GSEL = 0; 
00EA:  MOVLB  02
00EB:  BCF    1D.3


The randomly-activated timer gate makes a lot more sense when T1G was assigned to A3/MCLR.

I think this detour into the .lst file has been very helpful to my future troubleshooting! I'm always incredibly hesitant to doubt my tools (I tend to be the one wrong 99% of the time), but it's nice to know I wasn't completely crazy this time.

Thanks again so much for sharing your time and knowledge!
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Thu Mar 19, 2015 8:22 am     Reply with quote

if you wanted to measure individual pulses - with a value for each one-
you could link pin RA4 to an edge interrupt pin on portB
and use it to detect the falling edge of each pulse -

Then within the interrupt handler for the edge signal -
put the captured timer1 value into a circular buffer - and lastly
reset timer 1 to zero before leaving the int handler.

This would eliminate the malarky with using a delay_ms and
idle time in main AND
you would have a safe record of a number of sequential pulse timings - limited only by capture buffer size and how often you read/ clear buffer entries from main();

a personal note: in my own work, i deprecate using delay calls ( other than delay_cycles) except for barest initial hardware setup.
For "in program" delays - loops using an uncommitted timer - on a polled basis allows other critical activities to go on unimpeded.

delay_ms is great for proof of concept and fundamental screwing around, but IMHO not the way to create reliable complex programs in the time domain. With up to 7 system timers -the 18F46/26K family has a generous number of surplus counters that make this approach so easy to follow.
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