It's a prototype for a triac phase control circuit. The zero crossing signal triggers INT which starts a variable hold-off timer on TMR1. When TMR1 overflows, an output is switched on, triggering the triac, and TMR0 is enabled. When TMR0 overflows, the trigger output is switched off. ADC is for set point.
Setting OPTION_REG.T0CS = 0 causes the following code to crash when INT is triggered. The easypic board has buttons pulled up to VCC and port B pulled down.
Sorry the code is a bit long, I'm ex-pascal
Can anyone see what the problem is?
Code: Select all
unsigned int temp_set;
void interrupt() {
if (INTCON.TMR0IF) { // This is the triac trigger turn off. It does not get reset.
TMR0 = 235;
INTCON.T0IE = 0; // mask the interrupt
INTCON.T0IF = 1; // clear the flag
// PORTC.F0 = 1; // switch the triac trigger off
}
else if (INTCON.INTF) { // zero crossing - Start the triac trigger delay
INTCON.INTF = 0; // clear the INTCON INTF bit
PORTC = ~PORTC;
// PIR1.TMR1ON = 1; // Start the delay timer
}
else if (PIR1.TMR1IF) { // delay after zero crossing
PIR1.TMR1IF = 0; // reset the interrupt flags
PIR1.TMR1IE = 1; // unmask the interrupt
PIR1.TMR1ON = 0;
TMR1H = 0x80; // reload the start count
TMR1L = 0x00;
// PORTC.F0 = 0; // fire the triac
// start the triac turnoff counter
}
}
void setup_ports() {
ADCON1 = 0x80; // Configure analog inputs, all inputs, internal Vref
ADCON1.ADFM = 1 ; // Set ADC output to right justified
TRISA = 0x1F; // PORTA is input, AD for pot and thermistors
TRISB = 0x01; // PORTB supports zero cross RB0 and lcd RB2-7
PORTB = 0xFE;
OPTION_REG.INTEDG = 0; // Pin RB0 is interrupt, triggered on falling edge for zero crossing
INTCON.GIE = 1; // Enable General Interrupt Enable
INTCON.INTE = 1; // Enable RB0 Extrenal Interrupt Edge
TRISC = 0; // RC0 is triac trigger, serial comms and spi/i2c, initially used for testing leds
// PORTC = 0x1; // set the triac trigger high
PORTC = 0;
TRISD = 0; // PORTD is output, leds at the moment
PORTD = 0xFF;
INTCON.PEIE = 1; // Enable peripheral interrupts
T1CON = 0;
T1CON.T1CKPS1 = 0; // Timer 1 is timer with 1:2 prescale
T1CON.T1CKPS0 = 1;
T1CON.T1OSCEN = 0; // Timer 1 oscillator is off
T1CON.TMR1CS = 0; // Timer 1 internal oscillator
TMR1H = 0x80; // Load an initial value for the timer
TMR1L = 0x00;
T1CON.TMR1ON = 0; // Disable the trigger delay timer
OPTION_REG.NOT_RBPU = 1; // Disable weak pull-ups
OPTION_REG.T0CS = 0; // Internal Clock - setting to zero fails, rc0 is high
OPTION_REG.T0SE = 0;
OPTION_REG.PSA = 1; // prescaler assigned to watchdog, ie no prescale
OPTION_REG.PS2 = 0;
OPTION_REG.PS1 = 0;
OPTION_REG.PS0 = 0;
TMR0 = 235; // Timer0 initial value
INTCON.T0IE = 1; // Enable TMRO interrupt
}
void main() {
setup_ports();
do {
temp_set = ADC_Read(0); // Get 10-bit results of AD conversion
PORTD = temp_set; // Send lower 8 bits to PORTD PORTB = temp_res >> 2; // Send 2 most significant bits to RB7, RB6
PORTB.F7 = ~PORTB.F7; // run indicator
Delay_ms(500);
} while(1);
}