At least you're being real, I admire that. I wish others could acknowledge my algorithm.Sorry don't know anything about programming with the PICKIT3.
At least you're being real, I admire that. I wish others could acknowledge my algorithm.Sorry don't know anything about programming with the PICKIT3.
From the 150 Hz output you can implement a small bit of code that counts to 75, which is half of 150 and toggles another GPIO pin. you'll get 75 cycles where the selected GPIO pin is high and 75 where it is low. I know you are having difficulty at the moment, but I encourage to keep coming back to things you don't understand. I promise that one day an imaginary light bulb will illuminate, and you will finally understand what is going on. If it will help, I can provide a clean version of the ISR and the initialization for you to study instead of telling you what changes to make.OK, thank you for your effort to make me understand--although I don't. I need both the 1hz and ~150hz outputs.
#include <xc.h>
/*
* Modify for 150 Hz Output
* Timer 1 Reload value changes from 0x3CB0 (decimal 15536) to 0xFD65 (decimal 667)
*/
// Configuration Bits: 16MHz HS Crystal, Watchdog Off, MCLR On, LVP Off
#pragma config FOSC = HS, WDTE = OFF, PWRTE = ON, MCLRE = ON, BOREN = OFF, LVP = OFF, CPD = OFF, CP = OFF
#define _XTAL_FREQ 16000000 // 16 MHz Crystal
#define CLOCK_OUT PORTBbits.RB0
unsigned int timer_counter = 0;
void __interrupt() isr(void) {
if (PIR1bits.TMR1IF) { // Check Timer 1 Overflow Flag
// Preload Timer 1 for 100ms delay:
// Instruction frequency = 16MHz / 4 = 4MHz
// Timer 1 with 1:8 Prescaler = 500kHz (2us per tick)
// 100ms / 2us = 50,000 ticks.
// Preload value = 65536 - 50000 = 15536 (0x3CB0)
TMR1H = 0xFD;
TMR1L = 0x65;
timer_counter++;
if (timer_counter >= 5) { // 10 * 100ms = 1 second
CLOCK_OUT = ~CLOCK_OUT; // Toggle the pin
timer_counter = 0;
}
PIR1bits.TMR1IF = 0; // Clear interrupt flag
}
}
void main(void) {
CMCON = 0x07; // Disable comparators to use PORTA/B as digital I/O
TRISBbits.TRISB0 = 0; // Set RB0 as output
CLOCK_OUT = 0;
// Timer 1 Configuration
T1CONbits.T1CKPS = 0b11; // 1:8 Prescaler
T1CONbits.TMR1CS = 0; // Internal clock (Fosc/4)
TMR1H = 0x3C; // Initial preload
TMR1L = 0xB0;
// Interrupt Configuration
PIE1bits.TMR1IE = 1; // Enable Timer 1 interrupt
INTCONbits.PEIE = 1; // Enable peripheral interrupts
INTCONbits.GIE = 1; // Enable global interrupts
T1CONbits.TMR1ON = 1; // Start Timer 1
while (1) {
// Main loop remains empty; logic is handled in ISR
}
}
With TMR1H = 0xFD; and TMR1L = 0x65;, according to my oscilloscope, I get 74.67hz--half of what I wanted.Here is the modification for doing 150 Hz
The modifed lines are numbers 23 & 24 and the comment/description of what I did is on lines 3 thru 6. Let me know if this helps. If it does, I'll try to add a 1 HZ. option on another GPIO pin. If this does not help you then, sorry, but I have little to no clue what will be helpful.Code:#include <xc.h> /* * Modify for 150 Hz Output * Timer 1 Reload value changes from 0x3CB0 (decimal 15536) to 0xFD65 (decimal 667) */ // Configuration Bits: 16MHz HS Crystal, Watchdog Off, MCLR On, LVP Off #pragma config FOSC = HS, WDTE = OFF, PWRTE = ON, MCLRE = ON, BOREN = OFF, LVP = OFF, CPD = OFF, CP = OFF #define _XTAL_FREQ 16000000 // 16 MHz Crystal #define CLOCK_OUT PORTBbits.RB0 unsigned int timer_counter = 0; void __interrupt() isr(void) { if (PIR1bits.TMR1IF) { // Check Timer 1 Overflow Flag // Preload Timer 1 for 100ms delay: // Instruction frequency = 16MHz / 4 = 4MHz // Timer 1 with 1:8 Prescaler = 500kHz (2us per tick) // 100ms / 2us = 50,000 ticks. // Preload value = 65536 - 50000 = 15536 (0x3CB0) TMR1H = 0xFD; TMR1L = 0x65; timer_counter++; if (timer_counter >= 5) { // 10 * 100ms = 1 second CLOCK_OUT = ~CLOCK_OUT; // Toggle the pin timer_counter = 0; } PIR1bits.TMR1IF = 0; // Clear interrupt flag } } void main(void) { CMCON = 0x07; // Disable comparators to use PORTA/B as digital I/O TRISBbits.TRISB0 = 0; // Set RB0 as output CLOCK_OUT = 0; // Timer 1 Configuration T1CONbits.T1CKPS = 0b11; // 1:8 Prescaler T1CONbits.TMR1CS = 0; // Internal clock (Fosc/4) TMR1H = 0x3C; // Initial preload TMR1L = 0xB0; // Interrupt Configuration PIE1bits.TMR1IE = 1; // Enable Timer 1 interrupt INTCONbits.PEIE = 1; // Enable peripheral interrupts INTCONbits.GIE = 1; // Enable global interrupts T1CONbits.TMR1ON = 1; // Start Timer 1 while (1) { // Main loop remains empty; logic is handled in ISR } }
That is interesting. I might need to start drawing better pictures for myself. I cannot be there to look over your shoulder to find the discrepancy, I'll try to go over my figures to see if I can find the problem.With TMR1H = 0xFD; and TMR1L = 0x65;, according to my oscilloscope, I get 74.67hz--half of what I wanted.
#include <xc.h>
/*
* Modify for 150 Hz Output
* Timer 1 Reload value changes from 0x3CB0 (decimal 15536) to 0xFEB3 (decimal 333)
*/
// Configuration Bits: 16MHz HS Crystal, Watchdog Off, MCLR On, LVP Off
#pragma config FOSC = HS, WDTE = OFF, PWRTE = ON, MCLRE = ON, BOREN = OFF, LVP = OFF, CPD = OFF, CP = OFF
#define _XTAL_FREQ 16000000 // 16 MHz Crystal
#define CLOCK_OUT PORTBbits.RB0
unsigned int timer_counter = 0;
void __interrupt() isr(void) {
if (PIR1bits.TMR1IF) { // Check Timer 1 Overflow Flag
// Preload Timer 1 for 100ms delay:
// Instruction frequency = 16MHz / 4 = 4MHz
// Timer 1 with 1:8 Prescaler = 500kHz (2us per tick)
// 100ms / 2us = 50,000 ticks.
// Preload value = 65536 - 50000 = 15536 (0x3CB0)
TMR1H = 0xFE;
TMR1L = 0xB3;
timer_counter++;
if (timer_counter >= 5) { // 10 * 100ms = 1 second
CLOCK_OUT = ~CLOCK_OUT; // Toggle the pin
timer_counter = 0;
}
PIR1bits.TMR1IF = 0; // Clear interrupt flag
}
}
void main(void) {
CMCON = 0x07; // Disable comparators to use PORTA/B as digital I/O
TRISBbits.TRISB0 = 0; // Set RB0 as output
CLOCK_OUT = 0;
// Timer 1 Configuration
T1CONbits.T1CKPS = 0b11; // 1:8 Prescaler
T1CONbits.TMR1CS = 0; // Internal clock (Fosc/4)
TMR1H = 0xFE; // Initial preload
TMR1L = 0xB3;
// Interrupt Configuration
PIE1bits.TMR1IE = 1; // Enable Timer 1 interrupt
INTCONbits.PEIE = 1; // Enable peripheral interrupts
INTCONbits.GIE = 1; // Enable global interrupts
T1CONbits.TMR1ON = 1; // Start Timer 1
while (1) {
// Main loop remains empty; logic is handled in ISR
}
}
you could just make a loop and use a pause timer / counter150 Hz. cannot be achieved using integer multiples of the basic time unit. That would require 1666.6666... ticks of 2 µs each. Your choices would be 1666 or 1667
\( 1666\times\;2\;\mu\text{sec}\;=\;300.120048\;\text{ Hz.} \)
\( 1667\times\;2\;\mu\text{sec}\;=\;299.940012\;\text{ Hz.} \)
Choose either one of those preload values for Timer 1 and you will be close. I would choose 1667 since it is closer to 300 than choosing 1666.
The conversion is:
1666 = 0x0682, and
1667 = 0x683
The code would be
TMR1H = 0x06;
TMR1L = 0x82;
or
TMR1H = 0x06;
TMR1L = 0x83;
It looks like things are OK now--I get 148.98hz on my oscilloscope. It sounds that way too on the headphones. I clocked one of my clocks externally with it and the minutes are switching at a nominal rate so I know from intuition the frequency is right.WBahn has a mantra about checking the units in a calculation. Doing that I found my mistake in converting "time" with units of seconds into "time" with units of clock ticks. In our case a click tic is 2 µsec in duration. Here is the revised code for 150 Hz.
Code:#include <xc.h> /* * Modify for 150 Hz Output * Timer 1 Reload value changes from 0x3CB0 (decimal 15536) to 0xFEB3 (decimal 333) */ // Configuration Bits: 16MHz HS Crystal, Watchdog Off, MCLR On, LVP Off #pragma config FOSC = HS, WDTE = OFF, PWRTE = ON, MCLRE = ON, BOREN = OFF, LVP = OFF, CPD = OFF, CP = OFF #define _XTAL_FREQ 16000000 // 16 MHz Crystal #define CLOCK_OUT PORTBbits.RB0 unsigned int timer_counter = 0; void __interrupt() isr(void) { if (PIR1bits.TMR1IF) { // Check Timer 1 Overflow Flag // Preload Timer 1 for 100ms delay: // Instruction frequency = 16MHz / 4 = 4MHz // Timer 1 with 1:8 Prescaler = 500kHz (2us per tick) // 100ms / 2us = 50,000 ticks. // Preload value = 65536 - 50000 = 15536 (0x3CB0) TMR1H = 0xFE; TMR1L = 0xB3; timer_counter++; if (timer_counter >= 5) { // 10 * 100ms = 1 second CLOCK_OUT = ~CLOCK_OUT; // Toggle the pin timer_counter = 0; } PIR1bits.TMR1IF = 0; // Clear interrupt flag } } void main(void) { CMCON = 0x07; // Disable comparators to use PORTA/B as digital I/O TRISBbits.TRISB0 = 0; // Set RB0 as output CLOCK_OUT = 0; // Timer 1 Configuration T1CONbits.T1CKPS = 0b11; // 1:8 Prescaler T1CONbits.TMR1CS = 0; // Internal clock (Fosc/4) TMR1H = 0xFE; // Initial preload TMR1L = 0xB3; // Interrupt Configuration PIE1bits.TMR1IE = 1; // Enable Timer 1 interrupt INTCONbits.PEIE = 1; // Enable peripheral interrupts INTCONbits.GIE = 1; // Enable global interrupts T1CONbits.TMR1ON = 1; // Start Timer 1 while (1) { // Main loop remains empty; logic is handled in ISR } }
// PIC16F627A Configuration Bit Settings
// 'C' source line config statements
// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
#pragma config BOREN = ON // Brown-out Detect Enable bit (BOD enabled)
#pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = ON // Data EE Memory Code Protection bit (Data memory code-protected)
#pragma config CP = ON // Flash Program Memory Code Protection bit (0000h to 03FFh code-protected)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#include <stdint.h>
#define _XTAL_FREQ 16000000
#define ONE_HZ_PIN PORTBbits.RB0
#define OHF_HZ_PIN PORTBbits.RB3
volatile uint16_t s1 = 0;
volatile uint8_t s2 = 0;
volatile uint8_t one_Hz_flag = 0;
volatile uint8_t ohf_Hz_flag = 0;
const uint8_t tmr1_h = 254;
const uint8_t tmr1_l = 112;
/*
*
*/
void mcu_Init(void)
{
CMCONbits.CM = 0b111;
PORTA = 0xFF;
PORTB = 0xFF;
TRISA = 0x00;
TRISB = 0x00;
}
/*
* http://eng-serve.com/pic/pic_timer.html
*/
void isr_Init(void)
{
//Timer1 Registers Prescaler= 1 - TMR1 Preset = 65136 - Freq = 10000.00 Hz - Period = 0.000100 seconds
T1CONbits.T1CKPS1 = 0b0; // bits 5-4 Prescaler Rate Select bits
T1CONbits.T1CKPS0 = 0b0; // bit 4
T1CONbits.T1OSCEN = 0b1; // bit 3 Timer1 Oscillator Enable Control bit 1 = on
T1CONbits.nT1SYNC = 0b1; // bit 2 Timer1 External Clock Input Synchronization Control bit...1 = Do not synchronize external clock input
T1CONbits.TMR1CS = 0b0; // bit 1 Timer1 Clock Source Select bit...0 = Internal clock (FOSC/4)
T1CONbits.TMR1ON = 0b1; // bit 0 enables timer
TMR1H = tmr1_h; // preset for timer1 MSB register
TMR1L = tmr1_l; // preset for timer1 LSB register
// Interrupt Registers
INTCON = 0; // clear the interrpt control register
INTCONbits.TMR0IE = 0b0; // bit5 TMR0 Overflow Interrupt Enable bit...0 = Disables the TMR0 interrupt
PIR1bits.TMR1IF = 0b0; // clear timer1 interupt flag TMR1IF
PIE1bits.TMR1IE = 0b1; // enable Timer1 interrupts
INTCONbits.TMR0IF = 0b0; // bit2 clear timer 0 interrupt flag
INTCONbits.GIE = 0b1; // bit7 global interrupt enable
INTCONbits.PEIE = 0b1; // bit6 Peripheral Interrupt Enable bit...1 = Enables all unmasked peripheral interrupts
}
/*
*
*/
void main(void)
{
mcu_Init();
isr_Init();
while(1)
{
if(one_Hz_flag == 1)
{
ONE_HZ_PIN ^= 0b1;
one_Hz_flag = 0;
}
if(ohf_Hz_flag == 1)
{
OHF_HZ_PIN ^= 0b1;
ohf_Hz_flag = 0;
}
}
}
/*
* http://eng-serve.com/pic/pic_timer.html
*/
void interrupt ISR(void)
{
// Timer1 Interrupt - Freq = 10000.00 Hz - Period = 0.000100 seconds
if(PIR1bits.TMR1IF == 0b1) // timer 1 interrupt flag
{
if(s1++ > 4200)
{
one_Hz_flag = 1;
s1 = 0;
}
if(s2++ > 26)
{
NOP();
NOP();
NOP();
ohf_Hz_flag = 1;
s2 = 0;
}
PIR1bits.TMR1IF = 0b0; // interrupt must be cleared by software
PIE1bits.TMR1IE = 0b1; // reenable the interrupt
TMR1H = tmr1_h; // preset for timer1 MSB register
TMR1L = tmr1_l; // preset for timer1 LSB register
}
}
/*----------------------------------------------------------------------------*/
Since I'm satisfied with the ~150hz, what about the 1hz output in addition.? Can you show me what the code is and where to add it in the program? I should mention that my original code caused a 1 second per day slowdown of the 1hz. I'm thinking of using a 32,768 hz crystal in the future.If you care to experiment, you can add or subtract 1 from the Timer 1 reload value; local variations in crystal frequency and temperature can be corrected for in this fashion. Raising the reload valu by 1 to 0xFEB4 should raise the frequency and lowering it to 0xFEB2 should lower it a bit.
This program will provide 1hz and ~150hz outputs?Its ok, for simulation.
Code:// PIC16F627A Configuration Bit Settings // 'C' source line config statements // CONFIG #pragma config FOSC = HS // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled) #pragma config MCLRE = OFF // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD) #pragma config BOREN = ON // Brown-out Detect Enable bit (BOD enabled) #pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming) #pragma config CPD = ON // Data EE Memory Code Protection bit (Data memory code-protected) #pragma config CP = ON // Flash Program Memory Code Protection bit (0000h to 03FFh code-protected) // #pragma config statements should precede project file includes. // Use project enums instead of #define for ON and OFF. #include <xc.h> #include <stdint.h> #define _XTAL_FREQ 16000000 #define ONE_HZ_PIN PORTBbits.RB0 #define OHF_HZ_PIN PORTBbits.RB3 volatile uint16_t s1 = 0; volatile uint8_t s2 = 0; volatile uint8_t one_Hz_flag = 0; volatile uint8_t ohf_Hz_flag = 0; const uint8_t tmr1_h = 254; const uint8_t tmr1_l = 112; /* * */ void mcu_Init(void) { CMCONbits.CM = 0b111; PORTA = 0xFF; PORTB = 0xFF; TRISA = 0x00; TRISB = 0x00; } /* * http://eng-serve.com/pic/pic_timer.html */ void isr_Init(void) { //Timer1 Registers Prescaler= 1 - TMR1 Preset = 65136 - Freq = 10000.00 Hz - Period = 0.000100 seconds T1CONbits.T1CKPS1 = 0b0; // bits 5-4 Prescaler Rate Select bits T1CONbits.T1CKPS0 = 0b0; // bit 4 T1CONbits.T1OSCEN = 0b1; // bit 3 Timer1 Oscillator Enable Control bit 1 = on T1CONbits.nT1SYNC = 0b1; // bit 2 Timer1 External Clock Input Synchronization Control bit...1 = Do not synchronize external clock input T1CONbits.TMR1CS = 0b0; // bit 1 Timer1 Clock Source Select bit...0 = Internal clock (FOSC/4) T1CONbits.TMR1ON = 0b1; // bit 0 enables timer TMR1H = tmr1_h; // preset for timer1 MSB register TMR1L = tmr1_l; // preset for timer1 LSB register // Interrupt Registers INTCON = 0; // clear the interrpt control register INTCONbits.TMR0IE = 0b0; // bit5 TMR0 Overflow Interrupt Enable bit...0 = Disables the TMR0 interrupt PIR1bits.TMR1IF = 0b0; // clear timer1 interupt flag TMR1IF PIE1bits.TMR1IE = 0b1; // enable Timer1 interrupts INTCONbits.TMR0IF = 0b0; // bit2 clear timer 0 interrupt flag INTCONbits.GIE = 0b1; // bit7 global interrupt enable INTCONbits.PEIE = 0b1; // bit6 Peripheral Interrupt Enable bit...1 = Enables all unmasked peripheral interrupts } /* * */ void main(void) { mcu_Init(); isr_Init(); while(1) { if(one_Hz_flag == 1) { ONE_HZ_PIN ^= 0b1; one_Hz_flag = 0; } if(ohf_Hz_flag == 1) { OHF_HZ_PIN ^= 0b1; ohf_Hz_flag = 0; } } } /* * http://eng-serve.com/pic/pic_timer.html */ void interrupt ISR(void) { // Timer1 Interrupt - Freq = 10000.00 Hz - Period = 0.000100 seconds if(PIR1bits.TMR1IF == 0b1) // timer 1 interrupt flag { if(s1++ > 4200) { one_Hz_flag = 1; s1 = 0; } if(s2++ > 26) { NOP(); NOP(); NOP(); ohf_Hz_flag = 1; s2 = 0; } PIR1bits.TMR1IF = 0b0; // interrupt must be cleared by software PIE1bits.TMR1IE = 0b1; // reenable the interrupt TMR1H = tmr1_h; // preset for timer1 MSB register TMR1L = tmr1_l; // preset for timer1 LSB register } } /*----------------------------------------------------------------------------*/
now do ypu understand how the interupt code works ?It looks like things are OK now--I get 148.98hz on my oscilloscope. It sounds that way too on the headphones. I clocked one of my clocks externally with it and the minutes are switching at a nominal rate so I know from intuition the frequency is right.
how are you aiming to use a 32.768 Khz crystal?Since I'm satisfied with the ~150hz, what about the 1hz output in addition.? Can you show me what the code is and where to add it in the program? I should mention that my original code caused a 1 second per day slowdown of the 1hz. I'm thinking of using a 32,768 hz crystal in the future.
I'm not inclined to learn about it because there's too much pessimism about my ability but eventually I may have to learn about it. If you ask me I think the logic of intelligence was changed by the Antichrist and I was not informed about it that is why it is difficult for me to learn. A new way of understanding was not programmed in my mind.now do ypu understand how the interupt code works ?
I plan to use the 32,768hz crystal with the same microcontroller and I'm planning to build another clock that is why I'm inquiring in the forum. Wouldn't this Crystal be more accurate for one hertz. ?how are you aiming to use a 32.768 Khz crystal?
what is this project were doing for you ?
You can get a precise signal by changing the values in the variables s1 and s2. Try it and write me the result.This program will provide 1hz and ~150hz outputs?
so your looking at replacing th 16 Mhz crystal with a 32.768 Khz crystal ?I plan to use the 32,768hz crystal with the same microcontroller and I'm planning to build another clock that is why I'm inquiring in the forum. Wouldn't this Crystal be more accurate for one hertz. ?