Длинная задержка с использованием функций задержки из библиотек C18 для PIC18
Я использую PIC18 с Fosc = 10 МГц. Поэтому, если я использую Delay10KTCYx(250), я получу 10 000 x 250 x 4 x (1/10e6) = 1 секунду.
Как использовать функции задержки в C18 для очень длительных задержек, скажем, 20 секунд? Я думал о том, чтобы просто использовать двадцать строк Delay10KTCYx(250). Есть ли еще более эффективный и элегантный способ?
Заранее спасибо!
2 ответа
Настоятельно рекомендуется избегать использования встроенных функций задержки, таких как Delay10KTCYx()
Почему вы можете спросить?
Эти функции задержки очень неточны, и они могут вызвать компиляцию вашего кода непредвиденными способами. Вот один из таких примеров, где использование функции Delay10KTCYx() может вызвать проблемы.
Допустим, у вас есть микропроцессор PIC18, который имеет только два аппаратных прерывания по таймеру. (Обычно их больше, но давайте просто скажем, что их всего два).
Теперь предположим, что вы вручную настроили первое аппаратное прерывание таймера, чтобы оно мигало с частотой один раз в секунду, чтобы активировать светодиодный индикатор пульса. И скажем, вы настроили второе аппаратное прерывание таймера так, чтобы оно прерывалось каждые 50 миллисекунд, потому что вы хотите получить какое-то цифровое или аналоговое считывание ровно за 50 миллисекунд.
Теперь, наконец, допустим, что в вашей основной программе вы хотите отложить 100 000 тактов. Итак, вы положили вызов Delay10KTCYx(10) в вашей основной программе. Как вы думаете, что происходит? Как PIC18 волшебным образом отсчитывает 100 000 тактов?
Произойдет одно из двух. Он может "перехватить" одно из ваших других аппаратных прерываний таймера, чтобы получить ровно 100 000 тактов. Это может привести к тому, что ваш датчик сердцебиения не будет работать ровно через 1 секунду, или к тому, что ваши цифровые или аналоговые показания будут происходить в какое-то время, отличное от каждых 50 миллисекунд.
Или, функция задержки просто вызовет группу Nop() и заявит, что 1 Nop() = 1 такт. Что не учитывается, так это "накладные расходы" внутри самой функции Delay10KTCYx(10). Он должен увеличивать счетчик, чтобы следить за вещами, и, конечно, для увеличения таймера требуется более 1 такта. Поскольку Delay10KTCYx(10) зацикливается вокруг и вокруг, он просто не способен дать вам ровно 100 000 тактов. В зависимости от многих факторов вы можете получить больше или меньше тактов, чем вы ожидали.
Delay10KTCYx(10) следует использовать только в том случае, если вам нужно "приблизительное" количество времени. И заранее установленные функции задержки не должны использоваться, если вы уже используете аппаратные прерывания таймера для других целей. Компилятор может даже не скомпилироваться успешно при использовании Delay10KTCYx(10) для очень длительных задержек.
Я настоятельно рекомендую вам установить одно из ваших прерываний по таймеру для прерывания работы вашего оборудования с известным интервалом. Скажем, 50000 тактов. Затем каждый раз, когда аппаратные прерывания, в вашем коде ISR для этого прерывания таймера, увеличивают счетчик и снова сбрасывают таймер до 0 циклов. Когда истечет 50 000 тактов, равных 20 секундам (или, другими словами, в вашем примере 200 прерываний по таймеру со скоростью 50 000 циклов на прерывание), сбросьте счетчик. По сути, мой совет заключается в том, что вы всегда должны обрабатывать время вручную в PIC и не полагаться на предварительно настроенные функции задержки, а скорее создавать собственные функции задержки, которые интегрируются в аппаратный таймер микросхемы. Да, это будет дополнительная работа - "но почему я не могу просто использовать эту простую и изящную встроенную функцию задержки, зачем им даже включать ее, если она испортит мою программу?" - но это должно стать второй натурой. Точно так же, как вы должны вручную настраивать КАЖДЫЙ ОДИН РЕГИСТР в вашем PIC18 при загрузке, используете ли вы его или нет, чтобы предотвратить непредвиденные события.
Вы получите намного более точные сроки и более предсказуемое поведение от вашего PIC18. Использование предварительно настроенных функций задержки - это путь к катастрофе... это может сработать... это может сработать в нескольких проектах... но рано или поздно ваш код будет работать с ошибками, и вам будет интересно, почему и Я гарантирую, что виновником будет заранее заданная функция задержки.
Для создания очень долгого времени используйте внутренний таймер. Это может помочь избежать блокировки в вашем приложении, и вы можете проверить время выполнения. Пожалуйста, обратитесь к спецификации PIC о том, как настроить таймер и его прерывание.
Если вам нужна очень высокая точность 1S, я предлагаю также рассмотреть внешнее устройство RTC или внутреннее устройство RTC, если оно есть у микроконтроллера.