PIC12F1571 timer issues. - Page 1
Forum section: electronics / general

author: step_s
author_rank: Regular Contributor
timestamp: December 11, 2016, 05:45:28 pm
content: Hi EEV'ers.Wanted to set up a simple project, but I can't get the timer1 function to work. . .So I made the code to be sure to get a response, make RA5 go high no matter if the timer1 gate value is high or low, but nothing seems to happen.RA4 is standard timer1 gate input, and is set as input, connected to a button that pulls it up when pressed, and down when not pressed.It's most likely some small stupid error, but would be nice if anyone could point it outCode:void main(void) {TRISA = 0b00010000; //RA4 inputANSELA = 0b00000000; //All digitalLATA = 0b00000000; //Sets all lowODCONA = 0b00000000; //No open-drainOSCCON = 0b11110000; //32MHz internal//comparator settingsCM1CON0 = 0b11110000; //on, CP>CN, output on pin, non-inverted, low-power, no hysteresis, not synchronous.CM1CON1 = 0b00000000; //No interrupt, C1IN+ and C1IN- pins.//timer settingsT1CON = 0b11000100; //LFINTOSC, 1:1 prescaler, no-sync, disabled.T1GCON = 0b11011000; //Gate on, active-high, no toggle, single pulse, T1G pinwhile (1) {TMR1ON = 1; //Timer1 onif (T1GCONbits.T1GGO_nDONE = 0) { //Resets bit, if doneT1GCONbits.T1GGO_nDONE = 1;}if (T1GVAL = 1) { //Timer gate value highRA5 = 1;}if (T1GVAL = 0) { //Timer gate value lowRA5 = 1;}}return;}

author: Buriedcode
author_rank: Super Contributor
timestamp: December 11, 2016, 06:55:03 pm
content: I'm not sure what you're trying to achieve here, but you have two 'if' statements, where both make RA5 = 1. Actually, I'll just list the issues.problems:1) In C a single '=' is an assignment operator. Equality.. as in to compare values, it should be double. '==' eg:Code:if (T1GCONbits.T1GGO_nDONE == 0) { //Resets bit, if done2) RA5, I presume is a digital pin. You should use the output latch register. LATAbits.LATA5. That is the port output register LATx, which for PORTA is LATA. To set individual bits within that register you use 'LATAbits', and the individual pin... LATA5. eg:Code:LATAbits.LATA5 = 1; // set output pin, to 1LATAbits.LATA5 = 0; //clear output pin, to 0.2) you check if (T1GVAL = 1) - > should be == 1, see above, and then set RA5. But you also set RA5 if the result is 0, so whats the point in checking T1GVAL if you always set RA5?Code:if (T1GVAL == 1) { //Timer gate value highRA5 = 1;}if (T1GVAL == 0) { //Timer gate value lowRA5 = 1;} // RA5 will be set to '1' regardless of the state of T1GVALare you trying to simply use a pin to indicate the state of T1GVAL? in which case:Code:if (T1GVAL == 1) { //Timer gate value highRA5 = 1;}else {RA5 = 0;}But if you're trying to actually write to the output port.. putting it together:Code:if (T1GVAL == 1) { //Timer gate value highLATAbits.LATA5 = 1;}else {LATAbits.LATA5 = 0;}3) Why are you using the timer gate pin to read an input button? You can use any IO on the device, set it as an input (by setting its appropriate TRIS bit) and just read it using its PORT register (read its state using the PORTx register, set its state using the LATx register). I guess if you were testing the timer gates input pin then it can serve a purpose.There could well be more problems but the above will certainly help - right now your code isn't actually doing anything apart from setting up the port, configuring the oscillator, and turning on the comparator. Might be helpful for others if you included the device you were using - the part number, as well as the compiler. I'm assuming MPLABX with XC8.

author: step_s
author_rank: Regular Contributor
timestamp: December 11, 2016, 07:09:47 pm
content: Thanks for the answer Buried.The code here is simply to get a response from the timer gate, since I can't seem to make it work. This code was just to see if the gate value ever went high. The == part is right, thank you, forgot that. Also RA5 is enough to set output pinsThe code works now, but I'm afraid that even if i can get the response that the gate value of timer1 is 0, the button press should put it at 1, which it doesn't. This is where I'm stranded right now.The device was in the thread title PIC12F1571Yes, MPLABX XC8.

author: Buriedcode
author_rank: Super Contributor
timestamp: December 12, 2016, 01:20:42 am
content: Ok, sorry I missed the title!So just to be clear, you have a button on RA4, which is the default location of T1G. This button is active high, so you have a pull-down on this to make it 0 when no button is pressed. You set RA5 as an output, and this should indicate the state of T1G, but reading the T1GCON register and looking at its state.When you say the code 'is working', that implies it is doing what you want it to do. I'll admit the timer-gate module of timer1 looks very confusing, but you only enter your toggling routine if T1GCONbits.T1GGO_nDONE is 0 here:Code:if (T1GCONbits.T1GGO_nDONE = 0) { //Resets bit, if doneT1GCONbits.T1GGO_nDONE = 1;This bit is cleared by hardware, and must be set in software - as you are doing. However, the hardware only clears this bit on thefallingof the timer gate pin (datasheet, page 149). Therefore your will only change the state of the output pin when the timer gate is 0. And because it reads the state of the gate, and sets the output pin to the same state, that will also always be 0.It does this for 'single pulse mode' so the T1GGO_nDONE bit can indicate when an input pulse has ended - so you can check the contents of TMR1 to measure the pulse width.In order to do what you wish to do, you would either have to fiddle about switching the polarity of T1G (so it inverts the input and see's a rising edge from your button, as a falling edge) OR... more simply:In your loop, just constantly read the state of T1G. You could disable 'single pulse mode' as you're not actually measuring the input pulse width. But if you wish to keep it, you would have to set it to one, only when you read T1GVAL as 0 (falling edge on the gate, causes it to be cleared in hardware, and when its 0, T1GVAL will not change, even if the input does).Code:TMR1ON = 1; //Timer1 on - only need to do this once, outside of the main loopwhile (1) {if (T1GVAL == 1) { //Timer gate value highLATAbits.LATA5 = 1;}else { //Timer gate value lowLATAbits.LATA5 = 0;// if you've got single pulse mode enabled, set the T1GGO bit here, or it will ignore subsequent input changes.T1GCONbits.T1GGO_nDONE = 1;}}return;long story short, its a complicated bit of hardware, but makes sense when you realize what it is designed for - to capture input pulses and measure their width, without subsequent pulses causing timer1 to increment before you have had time to read the TMR1 value. You can set the 'polarity' of the pulse (measuring rising to falling, or falling to rising), and 'arm' it by setting the T1GGO_nDONE bit, and once it has the pulse, it fires an interrupt, so you can read the contents of timer1, and 're-arm' it.

author: step_s
author_rank: Regular Contributor
timestamp: December 13, 2016, 05:14:59 pm
content: What I need from the timer is to measure the frequency of a touch switch, so I need to make it work in single pulse mode. I just need to get the timer to work before making any more complicated code.What you said in the beginning is right. RA4 is pulled low, and is active high when button is pressed. TG1 is set to "trigger high" so when the button is pressed and then released again, this should count as a single pulse, right?I've simplified the code to just look for the T1GGO_nDONE bit.Code://timer settingsT1CON = 0b11000101; //FOSC, 1:1 prescaler, no-sync, enabled.T1GCON = 0b11011000; //Gate on, active-high, no toggle, single pulse, T1G pinwhile (1) {if (T1GGO_nDONE = 0) {RA5 = 0;}if (T1GGO_nDONE = 1) {RA5 = 1;}}return;If the bit is armed, the LED turns on, if the single pulse mode has been triggered, the T1GGO_nDONE bit should be cleared, and the LED should turn off. The button press should trigger the single pulse mode, and make the bit clear, but this doesn't happen. . .(Forgot the double = doh)

author: Buriedcode
author_rank: Super Contributor
timestamp: December 13, 2016, 07:56:32 pm
content: I'm still unsure what you are doing. I understand you want to get the timer working, but... you aren't really using the timer, you're just testing the single pulse mode.I believe I have that device in 'stock', so later I'll knock up a test circuit and check. In your latest code snippet, its behaving as a 'one-shot' because you aren't 're-arming' it, but if your output pin never goes low, then yes, something isn't working right. I assume you've still got 'ANSELA = 0' in your code? as PORTA defaults to analogue inputs.Did you try my code?