Задержка на PIC18F

Я использую PIC18F14K50 с компилятором HiTech ANSI C и MPLAB v8.43. Мой PIC-код, наконец, запущен и работает, за исключением функции задержки. Это очень важно для моего приложения — мне нужно, чтобы оно находилось в определенных состояниях в течение заданного количества миллисекунд, секунд или минут.

Я пытался найти решение для этого около 2 недель, но пока безуспешно. Я сдался и написал свою собственную функцию задержки с asm("nop"); в цикле, но это дает очень непредсказуемые результаты. Если я скажу ему подождать полсекунды или 5 секунд, он работает достаточно точно. Но как только я говорю ему подождать дольше - например, 10 минут, задержка длится всего около 10-20 секунд, а 2 минуты и более - это мигание короче, чем задержка в 500 мс.

Вот мои предохранители конфигурации и функция wait():

#include <htc.h>

__CONFIG(1, FOSC_IRC   & FCMEN_OFF & IESO_OFF & XINST_OFF);
__CONFIG(2, PWRTEN_OFF & BOREN_OFF & WDTEN_OFF);
__CONFIG(3, MCLRE_OFF);
__CONFIG(4, STVREN_ON  & LVP_OFF   & DEBUG_OFF);
__CONFIG(5, 0xFFFF);
__CONFIG(6, 0xFFFF);
__CONFIG(7, 0xFFFF);

void wait(int ms)
{
  for (int i = 0; i < ms; i++)
    for (int j = 0; j < 12; j++)
      asm("nop");
}

Как я уже сказал, если я позвоню wait(500) до wait(30000), то я получу задержку от полсекунды до 30 секунд в пределах интересующего меня допуска, однако, если я позвоню wait(600000), я не получу 10-минутную задержку, как я ожидал. , а около 10-15 секунд, а wait(120000) дает не 2-минутную задержку, а быстрое мигание.

В идеале я хотел бы, чтобы встроенная функция __delay_ms() работала и вызывалась из моего wait(), однако мне это не удалось. Если я попытаюсь #include <delay.h>, то мой MPLAB жалуется, что такого файла или каталога нет. Если я посмотрю на delay.h в своих образцах HiTech, то у меня есть DelayUs(unsigned char) определенный и extern void DelayMs(unsigned char), который я не пробовал, однако, когда я пытаюсь поместить extern непосредственно в свой код C, я получаю ошибку неопределенного символа при связывании .

Несоответствие между короткими и средними задержками и длинными задержками не имеет смысла. Единственное объяснение, которое у меня есть, это то, что компилятор оптимизировал NOP или что-то в этом роде.

Как я уже сказал, это PIC18F14K50 с указанными выше предохранителями. У меня нет большого опыта работы с PIC, но я предполагаю, что при такой настройке он работает на частоте 4 МГц.

Меня устраивает внешняя функция из библиотеки или макроса, либо написанная от руки функция с NOP. Все, что мне нужно, это точность в пределах пары секунд в минуту или около того.


person Ozzah    schedule 12.04.2012    source источник


Ответы (3)


Является ли PIC 16-битным микроконтроллером? Я предполагаю, что вы получаете переполнение для значения ожидания, которое переполнится после 2 ^ 15 (32 767 - максимальное значение 16-битного целого числа со знаком).

person Tim    schedule 12.04.2012
comment
Это звучит очень правдоподобно! Я обновлю код и посмотрю, что произойдет. - person Ozzah; 12.04.2012
comment
Спасибо. Я написал wait_sec(int sec), который просто перебирает и выполняет wait(1000); несколько раз. :) - person Ozzah; 12.04.2012

Если вы измените свои переменные int на unsigned, вы можете увеличить время до 65535 мс. Чтобы пойти дальше, вам нужно использовать long в качестве типа параметра и вкладывать циклы еще глубже.

person Gabe    schedule 12.04.2012

Лучшим долгосрочным решением было бы написать функцию задержки, которая использует один из встроенных аппаратных таймеров, которые есть в вашем чипе. Ваша задержка NOP не будет точной в течение длительных периодов времени, если у вас есть такие вещи, как срабатывание других прерываний и использование некоторых циклов ЦП.

person TJD    schedule 12.04.2012