Для всех желающих разобраться с прерываниями - под схему пылесоса написан небольшой код, иллюстрирующий их использование для задачи фазового регулятора.
Специально замечу, что высокий уровень на выходе RB4 - это отсутствие управляющего напряжения на симисторе, и наоборот - включение симистора осуществляется 0 на RB4.
Длительность включающего импульса - 0.64мс (соответствует осциллограмме).
Циклограмма работы:
Ждем фронт импульса синхронизации, сбрасываем таймер, выставляем значение задержки включения симистора.
Т.к. процессор ждет определенный фронт, каждый раз переключаем фронт на нужный.
Срабатывает таймер - включаем симистор, сбрасываем таймер, выставляем значение задержки выключения управляющего сигнала.
Срабатывает таймер - убираем управляющий сигнал, сбрасываем таймер и выставляем задержку на максимум (16мс), ждать новый импульс синхронизации ( <~10мс).
Код:
#if defined(__XC)
#include <xc.h> /* XC8 General Include File */
#elif defined(HI_TECH_C)
#include <htc.h> /* HiTech General Include File */
#endif
#include <stdint.h> /* For uint8_t definition */
#include <stdbool.h> /* For true/false definition */
#include "system.h" /* System funct/params, like osc/peripheral config */
uint8_t phase = 0xFF; //Force motor off by phase out of half-wave duration
//void interrupt isr(void)
void __interrupt () ISR (void) {
/* Determine which flag generated the interrupt and handle it */
// RB0/ExtINT interrupt
if(INTCONbits.INTF) {
INTCONbits.INTF = 0; /* Clear Interrupt Flag */
//Edge found. Switch to find next edge
if (OPTION_REGbits.INTEDG) { //Rising edge found
OPTION_REGbits.INTEDG = 0; //Now will wait for falling edge
}
else { //Falling edge found
OPTION_REGbits.INTEDG = 1; //Now will wait for rising edge
}
PR2 = phase; //Set TRIAC turn-on delay
TMR2 = 0; //Reset Timer2 state
PIR1bits.TMR2IF = 0; //Clear pending Timer2 IF
PORTBbits.RB4 = 1; //Disable TRIAC (force pin state)
}
//Timer2 PR2 match interrupt
if (PIR1bits.TMR2IF) {
PIR1bits.TMR2IF = 0; /* Clear Interrupt Flag */
if (PORTBbits.RB4 == 1) { //Triac pin is OFF
PORTBbits.RB4 = 0; //Set TRIAC ON
PR2 = 0x0A; //TRIAC on set for 10 * 64us = 0.64ms, next Timer2 interrupt will turn TRIAC pin OFF
}
else {
PORTBbits.RB4 = 1; //Set TRIAC OFF
PR2 = 0xFF; //PR2 should be set by edge, wait for sync.
}
TMR2 = 0; //Reset Timer2 state
}
}
void main(void) {
/* Initialize I/O and Peripherals for application */
PORTA = 0x04; //Turn off LED RA2
PORTB = 0x10; //Turn off TRIAC RB4
TRISA = 0x01; //RA0/AN0 - ADC input, RA2... outputs
TRISB = 0x0F; //RB0-RB3 inputs, RB4... outputs
OPTION_REG = 0x00; // RB0-interrupt on falling edge initially, Timer0/WDT not used
T1CON = 0x00; // Timer1 Fosc/4 clock; 1:1 prescale, Timer1 disabled
T2CON = 0x1F; // Timer2 Fosc/4 clock; 1:16 prescale, 1:4 postscaler, Timer2 enabled -- 4Mhz/16 = 62.5kHz = 16us/timer tick
// PR2 will set TMR2IE interrupt period as: PR2 * 4 * 16us
// For 50Hz 10ms half-period time, we can use values 0-156 as phase delay.
ADCON0 = 0xC0; // Use internal ADC RC oscillator, use AN0 input, ADC disabled (ADON=0)
ADCON1 = 0x04; // Vref=VDD, AN0,AN1,AN3 - as analog inputs (RA2 - LED)
PIR1 = 0; //Clear pending interrupt flags
PIE1 = 0x02; //Enable TMR2IE (PR2 matched) interrupt
INTCON = 0xD0; //Enable GIE (global interrupts) + PEIE (peripheral interrupts) + INTE (RB0/Ext INT)
while(1) {
phase = 0x75; // phase = 117; -- 7.5ms TRIAC phase delay, 25% of power.
}
}
Добавлено after 20 minutes 48 seconds:нет, это мне надо в томас прошивку написать, у них лоченые пики стоят. 12с509. если понадобиться, чтоб можно было код под любые порты любого пика написать. а тут от самсунга плата готовая лежит, потому на ней и хочу реализовать вначале
К сожалению, пример не особо поможет написать код под любые порты любого пика, хотя бы потому что упомянутый 12C(F)509 не умеет такой штуки как прерывания и код придется делать без них.