Mr RB
Well-Known Member
Hi, I've just updated my "zero error 1 second timer routines" page, there is a new section at the bottom that now supports zero-jitter period generation.
Like the other code on the page it will generate any period (or frequency) from any xtal using juts one simple constant to set theperiod. But this new system generates the period with zero jitter (which many people have requested). It is now useful for xtal-locked signal generation etc like to generate exactly 50Hz output or a 1 second clock signal etc.
The algortihm and code may not be immediately obvious so I will explain the basics;
ZEZJ algorithm;
(first, #define PERIOD in TMR0 ticks)
1. generate X interrupts of 100 ticks length
2. generate 1 interrupt of "remainder" length 100-199
3. done! make the event (toggle PIC pin etc)
It is "zero-error" as the interrupt always subtracts the 100 tick period (or remainder period) from TMR0, so that any immediate latency will be corrected on the next interrupt.
It is "zero jitter" because the remainder period syncs to the #defined PERIOD so the event (toggle PIC pin) always happens at exactly PERIOD.
The clever part is the "X*100 + remainder 100-199" because it means that the end of PERIOD can can never conflict with the TMR0 interrupt! This is because subtracting 100-199 will always result in a legal TMR0 count that will be corrected on the next int. So the result is that you can just #define PERIOD and it will automatically generate an exact jitter free period with no messy timing conflicts.
# Note! If you wanted to use the code below to generate other xtal-locked frequencies, you just need to change the PERIOD value (and maybe the xtal);
# toggle PERIOD = (xtal / 4 / freq / 2)
# 1 second; 4MHz xtal, PERIOD = 500000
# 50 Hz; 8MHz xtal; PERIOD = 20000
# 60 Hz; 6MHz xtal, PERIOD = 12500
# 60 Hz; 12MHz xtal, PERIOD = 25000
# 1 second; 8.867238MHz cheap TV xtal, PERIOD = (8867238 / 4 / 2)
Here is the code to generate 50Hz with a PIC 12F675 4MHz xtal.
This can be used on even the smallest cheapest PICs, I deliberately chose TMR0 for this reason. ROM needed is about 54, RAM needed is 2.
Code was programmed and tested out perfectly, all values of PERIOD >=100.
There is more info here;
https://www.romanblack.com/one_sec.htm
Like the other code on the page it will generate any period (or frequency) from any xtal using juts one simple constant to set theperiod. But this new system generates the period with zero jitter (which many people have requested). It is now useful for xtal-locked signal generation etc like to generate exactly 50Hz output or a 1 second clock signal etc.
The algortihm and code may not be immediately obvious so I will explain the basics;
ZEZJ algorithm;
(first, #define PERIOD in TMR0 ticks)
1. generate X interrupts of 100 ticks length
2. generate 1 interrupt of "remainder" length 100-199
3. done! make the event (toggle PIC pin etc)
It is "zero-error" as the interrupt always subtracts the 100 tick period (or remainder period) from TMR0, so that any immediate latency will be corrected on the next interrupt.
It is "zero jitter" because the remainder period syncs to the #defined PERIOD so the event (toggle PIC pin) always happens at exactly PERIOD.
The clever part is the "X*100 + remainder 100-199" because it means that the end of PERIOD can can never conflict with the TMR0 interrupt! This is because subtracting 100-199 will always result in a legal TMR0 count that will be corrected on the next int. So the result is that you can just #define PERIOD and it will automatically generate an exact jitter free period with no messy timing conflicts.
# Note! If you wanted to use the code below to generate other xtal-locked frequencies, you just need to change the PERIOD value (and maybe the xtal);
# toggle PERIOD = (xtal / 4 / freq / 2)
# 1 second; 4MHz xtal, PERIOD = 500000
# 50 Hz; 8MHz xtal; PERIOD = 20000
# 60 Hz; 6MHz xtal, PERIOD = 12500
# 60 Hz; 12MHz xtal, PERIOD = 25000
# 1 second; 8.867238MHz cheap TV xtal, PERIOD = (8867238 / 4 / 2)
Here is the code to generate 50Hz with a PIC 12F675 4MHz xtal.
Code:
/******************************************************************************
ZeroJitter.c Generates zero-error and zero jitter interrupt period.
Open-source - 21 Nov 2009 - www.RomanBlack.com/one_sec.htm
PIC 12F675, 4MHz xtal.
This is like my zero-error 1 second timing system, that uses a convenient
constant to set ANY period (with 1 timer tick resolution).
However this system has zero jitter!
Can be used to generate 1 second period, or 50Hz freq output etc.
******************************************************************************/
// PERIOD sets the pin toggle freq; toggle PERIOD = (xtal / 4 / freq / 2)
#define PERIOD 10000 // (xtal 4Mhz) TMR0 1MHz, 10000 = 100Hz toggle (50Hz output)
#define PER_COUNTS ((PERIOD / 100) - 1) // don't edit this!
#define PER_REMAINDER (PERIOD - (PER_COUNTS * 100)) // don't edit this!
unsigned int pcount; // used in interrupt to count PER_COUNTS
//-----------------------------------------------------------------------------
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void interrupt()
{
//-----------------------------------------------------
// this is the TMR0 overflow interrupt.
// Note! TMR0 has a 3 tick write latency, writes must be -3
//-----------------------------------------------------
// check if time to toggle the output pin
if(!pcount)
{
asm {
movlw 0x01 ; // mask for pin 0
xorwf GPIO,f ; // toggle PIC pin GPIO.0
}
pcount = (PER_COUNTS+1); // how many delays to make total
TMR0 -= (PER_REMAINDER-3); // first delay will be ==remainder
}
// else make a normal delay
else
{
TMR0 -= (100-3); // make another 100 tick delay
}
pcount--;
//-----------------------------------------------------
// clear the TMR0 overflow flag and exit
INTCON.T0IF = 0;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//=============================================================================
// MAIN
//=============================================================================
void main ()
{
//-----------------------------------------------------
// PIC 12F675 setup ports
ANSEL = 0; // ADC off
CMCON = 0x07; // comparators off
GPIO = 0b00000000; // clear GPIO
TRISIO = 0b00000000; // All outputs
WPU = 0b00000000; // pin pullups; 1 = pullup on (for button)
//-----------------------------------------------------
// timer setup etc
OPTION_REG = 0b00001000; // TMR0 on, 1:1 prescale
pcount = 0;
INTCON = 0b10100000; // GIE on, T0IE on (turn interrupt on)
//-----------------------------------------------------
// main run loop here
while(1)
{
continue; // loop and do nothing, just let the interrupt happen
}
}
//-----------------------------------------------------------------------------
This can be used on even the smallest cheapest PICs, I deliberately chose TMR0 for this reason. ROM needed is about 54, RAM needed is 2.
Code was programmed and tested out perfectly, all values of PERIOD >=100.
There is more info here;
https://www.romanblack.com/one_sec.htm
Last edited: