Так вот, весь механизм фиксации открытия/закрытия клапана построен на 7 ключевых точках, в которых мониторятся определенные состояния и производятся определенныедействия. Компаратор настроен так:
Код
TRISAbits.RA4 = 0; // установить порт RА4 на выход (выход компаратора)
PORTAbits.RA4 = 0;
CM1CON0bits.C1POL = 0; // логика на C1OUT не инвертирована
CM1CON0bits.C1SP = 0; // компаратор работает в режиме малой мощности и низкой скорости
CM1CON0bits.C1R = 0;
CM1CON0bits.C1CH = 1; // выставить канал компаратора на верхний предел
IPR2bits.C1IP = 1; // приоритет прерываний от компаратора C1 высокий
PORTAbits.RA4 = 0;
CM1CON0bits.C1POL = 0; // логика на C1OUT не инвертирована
CM1CON0bits.C1SP = 0; // компаратор работает в режиме малой мощности и низкой скорости
CM1CON0bits.C1R = 0;
CM1CON0bits.C1CH = 1; // выставить канал компаратора на верхний предел
IPR2bits.C1IP = 1; // приоритет прерываний от компаратора C1 высокий
И обработчик его прерывания:
Код
void high_isr()
{
if (PIR2bits.C1IF) // прерывание от компаратора
{
if ((PIE2bits.C1IE) && (T3CONbits.TMR3ON == 0)) // если прерывания от компаратора разрешены и таймер TMR3 свободен
FFComparator1Interrupt(); // войти в обработчик прерываний компаратора
CM1CON0bits.C1OUT = 0; // выставить 0 на выходе компаратора
PIR2bits.C1IF = 0; // сбросить флаг прерывания
}
}
{
if (PIR2bits.C1IF) // прерывание от компаратора
{
if ((PIE2bits.C1IE) && (T3CONbits.TMR3ON == 0)) // если прерывания от компаратора разрешены и таймер TMR3 свободен
FFComparator1Interrupt(); // войти в обработчик прерываний компаратора
CM1CON0bits.C1OUT = 0; // выставить 0 на выходе компаратора
PIR2bits.C1IF = 0; // сбросить флаг прерывания
}
}
Все начинается с состояния PPR_CLOSE:
Код
void FFComparator1Interrupt()
{
switch(PPR.State)
{
case PPR_CLOSE:
DelayInterrupt = 0; //исключаем пересечения
if (CM1CON0bits.C1CH == 1) // если компаратор переключен на верхний порог (т.е. фиксируем движение клапана)
{
PPR.State = PPR_START_OPEN; // изменить состояния клапана на "Начал открываться"
PIE2bits.C1IE = 0; // отключить прерывания от компаратора
PORTAbits.RA4 = 1; // поднять уровень сигнала на линии TAU
CM1CON0bits.C1OE = 0; // отключить выход компаратора (не реагировать на изменения на выходе)
timer3Delay(2); // установить задержку в 2мс
DelayInterrupt = 1; // выставить флаг для обработчика прерываний таймера TMR3
}
else
{
CM1CON0bits.C1CH = 1; // переключить компаратор на верхний порог
}
break;
}
return;
}
{
switch(PPR.State)
{
case PPR_CLOSE:
DelayInterrupt = 0; //исключаем пересечения
if (CM1CON0bits.C1CH == 1) // если компаратор переключен на верхний порог (т.е. фиксируем движение клапана)
{
PPR.State = PPR_START_OPEN; // изменить состояния клапана на "Начал открываться"
PIE2bits.C1IE = 0; // отключить прерывания от компаратора
PORTAbits.RA4 = 1; // поднять уровень сигнала на линии TAU
CM1CON0bits.C1OE = 0; // отключить выход компаратора (не реагировать на изменения на выходе)
timer3Delay(2); // установить задержку в 2мс
DelayInterrupt = 1; // выставить флаг для обработчика прерываний таймера TMR3
}
else
{
CM1CON0bits.C1CH = 1; // переключить компаратор на верхний порог
}
break;
}
return;
}
В следующем же состоянии PPR_START_OPEN:
Код
void FFTimerEvent()
{
switch(PPR.State)
{
case PPR_START_OPEN:
if (CM1CON0bits.C1CH == 1) // если компаратор переключен на верхний порог
{
if (CM1CON0bits.C1OUT == 1) // если клапан действительно открывается
{
timer3Delay(40); // установить задержку в 40мс для исключения дребезга
DelayInterrupt = 1; // выставить флаг для обработчика прерываний таймера TMR3
PPR.State = PPR_PRE_OPEN;// изменить состояния клапана на "Почти открылся"
StateChanged = 1; // выставить флаг о смене состояния клапана
}
else // иначе это был дребезг
{
PPR.State = PPR_CLOSE;
CM1CON0bits.C1OE = 1; // подключить выход компаратора
PIR2bits.C1IF = 0; // сбросить флаг прерывания компаратора
PIE2bits.C1IE = 1; // включить прерывания от компаратора
}
}
else
{
CM1CON0bits.C1CH = 1; // переключить компаратор на верхний порог
timer3Delay(1); // установить задержку в 1мс
DelayInterrupt = 1; // выставить флаг для обработчика прерываний таймера TMR3
}
break;
}
}
{
switch(PPR.State)
{
case PPR_START_OPEN:
if (CM1CON0bits.C1CH == 1) // если компаратор переключен на верхний порог
{
if (CM1CON0bits.C1OUT == 1) // если клапан действительно открывается
{
timer3Delay(40); // установить задержку в 40мс для исключения дребезга
DelayInterrupt = 1; // выставить флаг для обработчика прерываний таймера TMR3
PPR.State = PPR_PRE_OPEN;// изменить состояния клапана на "Почти открылся"
StateChanged = 1; // выставить флаг о смене состояния клапана
}
else // иначе это был дребезг
{
PPR.State = PPR_CLOSE;
CM1CON0bits.C1OE = 1; // подключить выход компаратора
PIR2bits.C1IF = 0; // сбросить флаг прерывания компаратора
PIE2bits.C1IE = 1; // включить прерывания от компаратора
}
}
else
{
CM1CON0bits.C1CH = 1; // переключить компаратор на верхний порог
timer3Delay(1); // установить задержку в 1мс
DelayInterrupt = 1; // выставить флаг для обработчика прерываний таймера TMR3
}
break;
}
}
При попытке разобраться возникли спорные моменты: подскажите, пожалуйста
1. зачем по окончании обработки прерывания компаратора выставляется CM1CON0bits.C1OUT = 0 ?
2. зачем в след. за первым состоянием мониторится CM1CON0bits.C1OUT == 1, когда только что был CM1CON0bits.C1OUT = 0 ? Что мы просто мониторим в данном случае, и что сейчас на выходе компаратора реально?
3. действие PORTAbits.RA4 = 1 в первом состоянии не идентично CM1CON0bits.C1OUT = 1? Просто по даташиту Pin #6 = RA4 (C1OUT, SRQ, CCP5, T0CKI) Связаны ли эти два действия вообще друг с другом и как?
И если кому то интересно, то вот изображение самого сигнала (измеряемый промежуток находится между вертикальными пунктирными линиями):
Нажмите для просмотра прикрепленного файла