Как я могу добавить задержку в 90 минут, когда порт изменился с 0 на 1? - PullRequest
1 голос
/ 10 мая 2019

У меня есть PIC12F1822, в котором есть светодиод и реле в качестве выхода и триггер в качестве входа.

Когда триггер равен единице, я бы хотел, чтобы светодиод и реле оставались включенными в течение 90 минут.

Проблема в том, что я не могу использовать задержку, так как __delayms имеет ограничение.

Как это можно сделать?

#include <xc.h>

#define _XTAL_FREQ 4000000

#define LED PORTAbits.RA5
#define RELAY PORTAbits.RA4
#define TRIGGER PORTAbits.RA2

int main()
{

//  OSCCON = 0b01101000 ;
    OSCCONbits.IRCF = 0b1101 ;

  TRISAbits.TRISA5 = 0; //LED Output PIN
  TRISAbits.TRISA4 = 0; //Output for Relay
  TRISAbits.TRISA2 = 1; //INPUT trigger from comparator

  while(1)
  {
      if (TRIGGER == 1)
      { 
          LED = 1;  // LED ON
          __delay_ms(1000); // 1 Second Delay
          LED = 0;  // LED OFF
          __delay_ms(1000); // 1 Second Delay

       }

      else

      {
       LED = 0;  // LED OFF   
      }

  }
  return 0;
}

Ответы [ 3 ]

2 голосов
/ 10 мая 2019

почему бы не перенести задержку в 1 с в функцию, обеспечивающую delay_s(uint32_t seconds), и в функцию, обеспечивающую delay_m(uint32_t minutes)

void delay_s(uint32_t seconds)
{
  while(seconds){
    __delay_ms(1000);
    seconds--;
  }
}

void delay_m(uint32_t minutes)
{
  while(minutes){
    delay_s(60);
    minutes--;
  }
}

Но:
Вы должны знать, что это полностью блокирует ваши микроСпрограмма.Он не будет реагировать на нажатие клавиш.Это может быть хорошо, но, возможно, вы хотите, чтобы задержка была сброшена до 90 минут, если во время задержки будет нажата клавиша.

Я бы предложил реализовать все это с прерываниями и таймерами.Установите таймер, который будет запускаться один раз в секунду, и обратный отсчет глобальной переменной (volatile!) Внутри isr, который был установлен вашим основным циклом.Если счетчик достигает 0, ваш isr может отключить ваш выход.

Таким образом, ваш микроконтроллер может обрабатывать другие объекты в главном цикле и не блокируется функцией __delay.

1 голос
/ 10 мая 2019

Simple. Конечные автоматы и Таймер прерывает и отсчет минут. Как то так:

Отказ от ответственности - закодировано вслепую

#define MINUTES_90 5400UL /* 90 seconds */

typedef enum
{
    /** Code operational */
    p_state_idle,
    /** Code waiting for 90 minutes */
    p_state_waiting
}p_state_t;

static unsigned long gSecondsRemaining = MINUTES_90;

int main()
{
    p_state_t gState = p_state_running;

    OPTION_REGbits.PSA = 0; /* Prescaler assigned */
    OPTION_REGbits.PS = 0b111; /* 256 prescaler */
    OPTION_REGbits.TMR0CS = 0; /* Fosc / 4 */
    INTCONbits.TMR0IE = 1; /* Timer 0 interrupt enabled */
    INTCONbits.PEIE = 1; /* Peripheral interrupts enabled */
    INTCONbits.GIE = 1; /* Global interrupts enabled */

    /** Default LED off */
    LED = 0;

    while (1)
    {
        switch (gState)
        {
        case p_state_idle:
            if (TRIGGER == 1)
            {
                LED = 1;  // LED ON
                gSecondsRemaining = MINUTES_90; /* Reset timer countdown */
                gState = p_state_waiting;
            }
            break;
        case p_state_waiting:
            /** can sleep here */
            if (gSecondsRemaining == 0)
            {
                gState = p_state_idle;
                LED = 0;
            }
            break;
        }
    }
}

void interrupt ISR()
{
    static unsigned char gSecond = 15;

    /** approx 15 Hz ? */
    if (INTCONbits.TMR0IF)
    {
        INTCONbits.TMR0IF = 0;

        if (gSecond > 0)
            gSecond--;

        if (gSecond == 0)
        {
            if (gSecondsRemaining > 0)
                gSecondsRemaining--;

            gSecond = 15;
        }
    }
}
0 голосов
/ 13 мая 2019

Вы можете решить эту проблему с помощью встроенной функции сборки с некоторыми циклами.Посмотрите здесь: пример: 30 минутная задержка

...