Ahoj,
na PB0 ( = ICP1) mám přivedeny impulsy signalizující průchod sítě nulou, na PB2 je připojen optotriak ( = OC1B). Taktování MCU je 4MHz
#define Global_Enable_Interrupts() __asm__ __volatile__ ("sei"::)
#define Global_Disable_interrupts() __asm__ __volatile__ ("cli"::)
#define TC_ON (1 << PORTB1)
#define PREDSTIH 2000 //predstih ukonceni ridiciho impulsu pred pruchodem site nulou
#include <avr/io.h>
#include <avr/interrupt.h>
int main(void)
{
DDRB = 0x04;
PORTB = ~0x04;
//nastavi casovac 1 a jeho preruseni
Global_Disable_interrupts();
TIMSK |= (1 << TICIE1);
OCR1B = 28000; //spozdeni
OCR1A = 30000; //max hodnota casovace, delka pulperiody - predstih cca 0.5 msec
TCCR1A |= (1 << COM1B0) | (1 << COM1B1) | (1 << WGM10) | (1 << WGM11); //Fast PWM Mode 15
TCCR1B |= (1 << WGM12) | (1 << WGM13);
TCCR1B |= (1 << CS10); //clock source /1
Global_Enable_Interrupts();
while(1)
{
}
}
ISR(TIMER1_CAPT_vect) //obsluha pruchodu site nulou
{
TCNT1 = 0;
}
Optotriak se zapne při shodě s OCR1B a řídící impuls se ukončí při shodě s OCR1A, pokud jsem dobře porozuměl popisu v datasheetu dojde současně k vynulování časovače (registru TCNT1). Program funguje na reálném hardware, má však vadu - čas ukončení řídícího impulsu je pevně dán a je vztažen k začátku půlperiody sítě. Předpokládal jsem, že v ICR1 zůstane zachycen čas od ukončení řídícího impulsu optotriaku do obsluhy přerušení a vynuceném vynulování TNCT1. Podle hodnoty v ICR1 jsem zkusil modifikovat OCR1A tak, aby řídící impuls končil vždy danou dobu před průchodem sítě nulou - makro PREDSTIH :
#define Global_Enable_Interrupts() __asm__ __volatile__ ("sei"::)
#define Global_Disable_interrupts() __asm__ __volatile__ ("cli"::)
#define TC_ON (1 << PORTB1)
#define PREDSTIH 2000 //predstih ukonceni ridiciho impulsu pred pruchodem site nulou
#include <avr/io.h>
#include <avr/interrupt.h>
int main(void)
{
DDRB = 0x04;
PORTB = ~0x04;
//nastavi casovac 1 a jeho preruseni
Global_Disable_interrupts();
TIMSK |= (1 << TICIE1);
OCR1B = 28000; //spozdeni
OCR1A = 30000; //max hodnota casovace, delka pulperiody - predstih cca 0.5 msec
TCCR1A |= (1 << COM1B0) | (1 << COM1B1) | (1 << WGM10) | (1 << WGM11); //Fast PWM Mode 15
TCCR1B |= (1 << WGM12) | (1 << WGM13);
TCCR1B |= (1 << CS10); //clock source /1
Global_Enable_Interrupts();
while(1)
{
}
}
ISR(TIMER1_CAPT_vect) //obsluha pruchodu site nulou
{
TCNT1 = 0;
OCR1A = (int)ICR1 - PREDSTIH + OCR1A;
}
Kód nefunguje, na výstupu je plné napětí. Bohužel k ATMEGA8A nelze připojit emulátor a zjistit, co v registrech opravdu je :(
hu