У меня есть плата с PIC16F18855, работающая на частоте 8 МГц от внешнего кристалла. Большую часть времени он работает нормально, но если его быстро отключить, он перезапустится на частоте 4 МГц. Основными симптомами этого являются такие вещи, как скорость передачи данных UART и частота PWM, падающая вдвое.
В частности, если я включу и выключу питание менее чем за ~ 2 секунды, он будет работать на более низкой частоте. Дольше и работает нормально. Когда я программирую плату, она перезагружается на частоте 4 МГц, а это означает, что мне нужно физически выключить и включить ее, прежде чем она заработает. Если я замкну контакт MCLR на землю, поведение будет непоследовательным - иногда он будет начинаться с 4 МГц, но обычно он начинается с 8 МГц.
У меня также был один случай, когда это занимало значительно больше времени, когда включение его в течение 10 минут после выключения заставляло его начинать с 4 МГц. Я не уверен, связана ли проблема, но я не могу воспроизвести эту ошибку в данный момент.
Изучая контакт OSC2/CLKOUT, я вижу, что сам кристалл все еще работает на частоте 8 МГц. С имеющимися у меня датчиками я не могу проверить контакт OSC1 без сброса микроконтроллера.
РЕДАКТИРОВАТЬ 1:
Когда плата работает на частоте 8 МГц, ее регистры OSCCONx:
OSCCON1: 0x70
OSCCON2: 0x70
OSCCON3: 0x10
и когда он работает на частоте 4 МГц, они:
OSCCON1: 0x70
OSCCON2: 0x60
OSCCON3: 0x00
Значит, он работает от внутреннего ВЧ-генератора. Посмотрим на это немного ближе. Зная это, я, возможно, смогу придумать обходной путь, но я бы предпочел выяснить причину проблемы.
OSCFRQ = 0x02
, что является настройкой для 4 МГц, так что это определенно то, что происходит. Ужасным обходным решением было бы установить OSCFRQ
регистр на значение 8 МГц, так что он работает одинаково в любом случае, но тогда я теряю точность кристалла. Это может не все испортить, но у меня есть некоторые чувствительные ко времени вещи, поэтому я предпочитаю использовать кристалл, если могу.
Это не объяснение того, почему это происходило, но я нашел исправление. Первое, что я попробовал, это установить фьюз-биты для RSTOSC_EXT (т.е. #pragma fuses HS, RSTOSC_EXT
) на основе того, что Спехро сказал в комментариях, но у меня это не сработало. Что я сделал, так это добавил следующее (обратите внимание, что OSCCON2 — это фактическая настройка, а OSCCON1 — это буфер):
if(OSCCON2 == 0x60){
OSCCON1 = 0x60;
OSCCON1 = 0x70;
}
Моя причина попробовать это: OSCCON2 является фактической настройкой и загрузит значение в OSCCON1, когда оно будет готово. Из моего предыдущего расследования я знал, что правильное значение было в OSCCON1, а OSCCON2 никогда его не загружал. Таким образом, предполагалось, что процесс загрузки где-то застрял, и загрузка значения из OSCCON2 в OSCCON1 заставит чип думать, что он загружен правильно. Это «отклеит» его, а затем позволит мне перезагрузить правильное значение без зависания.
Этот код находится в самом начале основной функции, после объявления переменных. Это решает проблему, но не объясняет, почему это происходит в первую очередь. Если кто-нибудь знает, что было причиной этого, и если есть лучшее решение, я все еще открыт для лучших ответов.
Спехро Пефхани
Побег
Спехро Пефхани
Дрю
Побег
Джон Биркхед