При разработке аппаратной части комплекса REDD, описанного в этой статье, мы рассматривали различные варианты реализации. PSoC рассматривался, так как для него имеется готовый относительно стандартизованный, пусть и де-факто, вариант переходника USB-I2C. К сожалению, по причинам, описанным в статье про DMA, сделать что-то сложное для данного конкретного комплекса на PSoC не удалось, а простое — экономически нецелесообразно. Оказалось, дешевле взять микросхемы от FTDI. Но пока велись эксперименты с PSOC, вскрылись интересные подробности, которые имеет смысл опубликовать.
Основной опыт
Сделаем простейший проект. Настроим тактирование его блоков следующим образом:
У PLL выбрана минимально возможная частота (меньше не даст среда разработки). Шина тактируется ею же. Это сделано умышленно. Результаты работы будут контролироваться осциллографом, а в комментариях к этой статье я показал, что лучше не приближаться к верхней границе полосы пропускания, особенно, если осциллограф китайский: фронты будут так завалены, что в измерениях можно допустить ошибку. Так что лучше взять частоту пониже. Минимум — это 24 МГц, его и берём.
Схема проекта тривиальна. Два источника тактовых импульсов, подключённые к ножкам микросхемы.
Документ AN60631 говорит, что частоты источников Clock_1 и Clock_2 система будет делать из базовой, пропуская через делители:
На ножку Pin_1 в нашем проекте всегда будем подавать сигнал с частотой 24 МГц, а на Pin_2 попробуем подать сигнал меньшей частоты. Сначала всё идёт предсказуемо. При желаемой частоте от 23 до 18 МГц, получаем достижимую, равной 24.
Снизив желаемую частоту до 17 МГц, получаем достижимую 12. Всё логично. Делитель — не PLL. Константа деления должна быть целой. Просто убедились, что никаких сюрпризов нет.
Устанавливаем желаемую частоту, равной 12 МГц. Собираем проект (код при этом писать никакой не требуется) и смотрим на результат.
Жёлтый луч — базовая частота, голубой — делённая. Снова никаких подвохов. Так ради чего задумана статья? Мы как раз подбираемся к самому интересному. Какой следующий коэффициент деления? Тройка. Следующая достижимая частота равна 24/3=8 МГц. Меняем настройки проекта, «прошиваем», смотрим…
Прошу любить и жаловать, на голубом луче виден тактовый сигнал со скважностью, отличной от 50%. Ждёт ли простой программист, что источник тактового сигнала выдаст ему такое? Вряд ли. А вот выдал.
Деление на 4 предсказуемо красивое. Проверяем деление на 5 (желаемая частота 4.8 МГц):
Тенденция ясна. В роли делителя явно выступает ШИМ. Чем выше нечётный коэффициент деления, тем ближе скважность будет к 50%, но в целом, всё-таки будут некоторые несоответствия положительного и отрицательного полупериода. Если схема тактируется только положительными фронтами, то это не страшно. Но если разработчик сделал какой-то свой компонент, в котором используются как положительные, так и отрицательные фронты тактового сигнала, возможны нюансы, причём иногда — плавающие сбои.
В целом, про это дело более-менее рассказывается в TRM на рисунке 14-12, так что опять же, никто ничего не скрывает:
Но что-то мне подсказывает, что мало кто станет изучать этот рисунок до того, как поймает соответствующую картинку на осциллографе. А поймает он её только после длительных попыток найти, почему сбоит система. Поэтому считаю нужным предупредить о данной особенности компонента Clock у PSoC.
Дополнительные сведения о тактовых частотах PSoC
Зависимость частоты внутреннего генератора от температуры
Получилось как-то совсем коротко. Давайте попутно исследуем ещё один вопрос, связанный с тактовой частотой. Давным-давно я делал один проект на AtMega8. Для удешевления системы, тактирование было взято от внутреннего генератора. Проект был отлажен на стенде, но после этого выяснилось, что когда плата попадает в целевую среду, она корректно работает только после включения питания. Через пару минут всё нагревается, частота уплывает и принимаемые последовательные данные начинают декодироваться неверно. А если подогнать времянки под этот режим — всё врёт до прогрева. В том проекте всё решилось благополучно: данные были в манчестерском коде, а он самосинхронизирующийся. Я просто сделал синхронизацию не от старта посылки, а от каждого бита. Но на будущее усвоил, что при использовании внутренних генераторов в контроллерах, надо проверять их термостабильность. Проверим её у PSoC, благо на имеющейся макетке нет кварцевого резонатора, поэтому система тактируется от внутреннего генератора, расположенного в контроллере. Сам контроллер у меня при моих задачах пока не греется, но его могут прогревать компоненты, находящиеся на той же плате.
На частоте 24 МГц фронты довольно округлые, можно ошибиться. Возьмём для опытов уже полученную частоту f/5.
Кстати, это не совсем 4.8, а скорее 4.78 МГц. Не беда! Генератор можно откалибровать! В AN60631 сказано, что в целом за это отвечает 11-битный регистр, размещённый в портах IMO_TR0 и IMO_TR1. Как автоматически вычислить оптимальное его значение, пользуясь внешним опорным генератором, рассказано в документе CE219322. К тому документу даже прилагается пример. Но на имеющейся у меня макетной плате нет отдельного генератора, поэтому для одного экземпляра мне было проще подобрать значение опытным путём, ориентируясь на показания осциллографа. Добавив в функцию main() такой код (шаг приращения равен 0x20, так как младшие 5 бит не используются):
volatile uint16_t* ptr = (uint16_t*) CYREG_IMO_TR0;
ptr[0] += 20 * 0x20;
я добился вполне приличного результата:
Подержим плату на балконе, где сегодня около нуля. Частота чуточку уплыла, но на имеющемся осциллографе это даже сложно измерить. Скорее видно на глазок (по точке пересечения левого курсора с жёлтым лучом).
Теперь нагреем плату на батарее. Тоже по прибору отличий не видно.
Так что в PSoC генератор вполне себе термостабилен. Бешеных уходов частоты, при которой работающая система начинает давать большие ошибки, от него ожидать не стоит.
Зависимость частоты внутреннего генератора от питающего напряжения
Я уже написал эту статью и отдал её на черновое прочтение, как всплыл ещё один интересный фактор, связанный с тактовыми частотами. На одном проекте измерение частоты шло с ошибкой около 2%, что существенно для той задачи. Причём логика, реализованная в UDB, была реализована верно. Ошибок в логике было не найти. Контролируя уже всё осциллографом, я заметил, что опорная частота врёт как раз на те 2%.
Но почему? Всё же было замечательно! Тут-то я и вспомнил о черновике статьи. Зависимость бывает не только от температуры, но и от питающего напряжения. А я в определённый момент снизил его с 5 до 3.3 вольт. Откалибровал частоту генератора, ошибка ушла.
Но после этого возникло желание найти зависимости в документации. Оказывается, они все приведены в документе DataSheet на конкретную микросхему. Вот зависимость ошибки генератора от температуры
Мой график синий. В целом, всё соответствует практическим результатам. А вот зависимость от напряжения:
Здесь требуемый график почему-то красный. На два процента он явно не тянет, но линейный рост погрешности налицо.
Заключение
При использовании стандартного компонента Clock в PSoC Creator, следует быть готовым к тому, что скважность импульсов там будет не 50%. Это важно, если проект использует не только фронты, но и срезы сигнала. Для борьбы с этим эффектом следует делить базовую частоту на чётные коэффициенты.
Для чувствительных к погрешности частоты применений внутренний тактовый генератор (IMO) рекомендуется использовать только со стабилизированным напряжением питания, при этом для каждого конкретного изделия после сборки рекомендуется произвести калибровку частоты. Если предполагается батарейное нестабилизированное питание, лучше использовать внешний кварцевый резонатор.