Перейти к содержанию

    

Компаратор в микроконтроллере PIC18F25K22

Добрый день. В данный момент у меня на руках плата с контроллером PIC18F25K22 и проект от предыдущего сотрудника. Если очень рассказать очень сжато суть проекта, то есть первичный преобразователь расхода, который состоит из магнито-механического клапана, поршня и катушки индуктивности, обеспечивающей индикацию перемещения поршня в клапане и частичное управление поршнем. При открытии клапана на катушке формируется положительный потенциал, что может быть установлено с помощью компаратора, настроенного на верхний предел (ножка RA4, она же C1OUT). При закрытии клапана на катушке формируется отрицательный потенциал, что приводит к срабатыванию компаратора, если он настроен на нижний предел.

 

Так вот, весь механизм фиксации открытия/закрытия клапана построен на 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 высокий

 

И обработчик его прерывания:

void high_isr()
{
     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;
}

 

В следующем же состоянии 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;
    }
}

 

При попытке разобраться возникли спорные моменты: подскажите, пожалуйста

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) Связаны ли эти два действия вообще друг с другом и как?

И если кому то интересно, то вот изображение самого сигнала (измеряемый промежуток находится между вертикальными пунктирными линиями):

post-83032-1501762904_thumb.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
Авторизация