Принятый ответ jfpoilpret очень хорошо написан, совершенно действителен, и в 99% случаев я буду делать именно то, что он объясняет. Его решения находятся в пределах ваших определенных параметров, поэтому они должны работать очень хорошо. Но что лучше, чем « очень хорошо »? Совершенство! В конце концов, вопрос в том, чтобы получить точное значение. Как уже говорилось, достаточно близко в большинстве случаев хорошо (возможно, во всех), и даже при работе с чем-то вроде часов, когда 1 секунда должна быть 1 секунда, вы все равно должны страдать от недостатков унаследованных частей.
То, что я предлагаю, не всегда возможно. В некоторых случаях это возможно, но с большим количеством хлопот и усилий, чем в этом случае. Стоит ли это зависеть от конкретного случая. Моя цель в основном показать альтернативу для будущих ссылок, которая лучше в несколько более отдаленных случаях. Это написано для начинающих пользователей Arduino, которые не имеют большого опыта в электронике.
Для более продвинутых людей это, вероятно, будет выглядеть слишком многословно и глупо. Но я верю, что те же самые люди, вероятно, уже знают это и не нуждаются в этом ответе. Это также применимо к каждому микроконтроллеру и каждому производителю и архитектуре. Но для других микроконтроллеров вам нужно будет обратиться к правильной таблице данных, чтобы выяснить правильные регистры и имена и значения перед масштабированием.
В вашем случае вам нужна конкретная частота, и самое приятное в этом то, что фактически 56 кГц можно достичь очень легко (не считая практических недостатков деталей). Так что это тоже идеальный пример.
Генерация сигнала зависит от таймеров и источника синхронизации микроконтроллера, что хорошо объяснено в jfpoilpret. Его ответ имеет дело только с проблемой одной точки зрения, которая связана с таймерами. Но вы также можете поиграть с источником тактовых импульсов, а еще лучше - и с синергией, и с потрясающими результатами. Изменяя параметры среды, в этом случае взламывая систему и заменяя источник тактовых импульсов, мы можем справиться с конкретной проблемой гораздо, гораздо проще и проще.
Для начала напомним, что из-за переключения состояния вывода необходимо выполнить ISR в два раза больше, чем частота сигнала. Это 112 000 раз в секунду. 56 000 и 16 000 000 не складываются очень хорошо, как уже отмечалось. Нам нужно изменить либо частоту сигнала, либо частоту тактов. Давайте разберемся с неизменной частотой сигнала и найдем лучшую тактовую частоту.
Было бы очень просто выбрать часы с некоторым порядком величины, превышающим 56 кГц (или 112 кГц, но это практически то же самое), так как вы добавляете только нули, и этот тип математики является самым простым для большинства людей. К сожалению, все в этом мире является своего рода компромиссом с чем-то. Не каждое значение будет работать.
Первый пример со слишком низкой скоростью тактового генератора.
Если вы выберете тактовую частоту 56 000 Гц, вы ничего не сможете сделать, так как вам нужно будет звонить в ISR каждый цикл и больше ничего не делать. Это совершенно бесполезно. Если вы выберете в 10 раз более высокую скорость (560 кГц), у вас будет 9 (10 циклов для достижения таймером максимального значения - один цикл для вызова функции ISR), чтобы микроконтроллер выполнял вашу работу, и этого вполне может быть недостаточно. Вам просто часто требуется больше вычислительной мощности.
Если вы выберете слишком большое значение с другой стороны, то при 56 МГц микроконтроллер просто не сможет с ним работать. Это слишком быстро. Таким образом, простой выбор самой большой цены в магазине также не снизит ее.
Оригинальные Arduino Uno R3 имеют штатные часы на 16 МГц, поэтому все, что работает медленнее, гарантированно будет работать. Следующее значение, которое на порядок больше 56 и ниже 16 МГц, составляет 5,6 МГц. Это позволит вызывать ISR каждые 50 циклов и создать идеальную частоту таймера 112000 Гц. И ваш сигнал будет ровно 56 кГц. У вас будет 49 циклов микроконтроллера для выполнения вашей программы между вызовами ISR, но она по-прежнему будет примерно на 1/3 скорости исходных часов. Можно использовать 112 в качестве базы и использовать тактовую частоту 11,2 МГц, и это даст около 2/3 стандартного резонатора 16 МГц. Функция ISR будет вызываться каждые 100 циклов и при этом генерировать идеальный сигнал 56 кГц.
Однако существуют две основные проблемы с этими значениями.
Первая проблема сильно зависит от ваших потребностей: вы жертвуете примерно 1/3 (с 11,2 МГц) своей максимальной вычислительной мощности, чтобы получить точную частоту сигнала, которая использует легко обнаруживаемое значение регистра (OCR iirc ). Вы можете быть в порядке с этим или нет.
Вторая проблема - это жесткая демонстрация : очень легко найти значения, но очень часто они просто не существуют как изготовленный источник часов. Это веб-страница резонатора Фарнелла, которой просто не хватает 5,6 МГц и 11,2 МГц.
Чтобы обойти это, мы можем посмотреть на доступные значения резонатора и найти что-то еще, что можно использовать для генерации точно желаемых значений. Если мы разделим 56 на 4, мы получим 14 и, к счастью, есть резонатор 14 МГц. Это дает нам гораздо более высокую скорость и большую мощность, а также одинаково легко найти значение регистра. Чтобы вызывать ISR 112 000 раз в секунду, нам нужно поместить десятичное значение 124 или шестнадцатеричное 0x7C в регистр OCR, поэтому, посчитав 124 цикла + 1 для вызова ISR, мы получим желаемое идеальное значение.
NB
- ISR - подпрограмма обработки прерываний (это код, который выполняется только для сгенерированных прерываний)
- Насколько большой может быть ваша программа, зависит от объема памяти! Это не имеет ничего общего с тактовой частотой и не имеет отношения к тому, как часто вы звоните ISR.
Когда микроконтроллер запускается с помощью команды программы, счетчик увеличивается. Если генерируется прерывание, вызывается ISR, и это значение сохраняется в специальном регистре. Когда код ISR завершается, значение счетчика программы восстанавливается из этого специального регистра, и программа продолжается с того места, где оно было прервано, как если бы это никогда не происходило.
Я приведу крайне тупой пример. Если вы пурист, я предупреждаю вас: может возникнуть кровотечение из носа и глаз.
Представьте, что вам нужно идти откуда-то куда-то. Пошаговые инструкции по маршруту - ваша основная программа и ее команды. Как быстро вы идете или бежите, зависит от вашей «тактовой частоты», но не от инструкций по маршруту (30 шагов вперед, 1 поворот 90 град. Влево, 10 шагов вперед, 45 град. Вправо и т. Д.) Они всегда одинаковы , Теперь представьте, что маленький ребенок или жадный коррумпированный местный политик время от времени развязывают ваши ботинки. Это событие, которое генерирует прерывание. Затем вы останавливаетесь после последнего шага, становитесь на колени и снова завязываете обувь. Это ваша программа ISR.
Затем вы продолжаете с того места, где остановились; Вы не начинаете с начала. Когда вы идете без заботы в мире и все время, вам все равно, даже если вы должны завязывать обувь каждый второй шаг. Однако, если вы делаете это с временными ограничениями, такими как бег на 100 метров на Олимпиаде (или бег от голодного хищника, питающегося мясом), остановка и завязывание вашей обуви могут иметь ужасные последствия. То же самое с микроконтроллерами. Даже если вы выполните только одну строку кода, ваша программа будет продолжаться, хотя и медленно. Если вам не важна скорость, это не будет проблемой. Если вам нужно выполнить какое-то время, например, используя другие действия, зависящие от таймера, помехи могут быть очень нежелательными и проблемными.
Меньше - больше! Более быстрые часы не всегда лучше. Устройства с меньшей тактовой частотой потребляют значительно меньше энергии. Это может быть решающим моментом в устройстве с батарейным питанием.
Необходимые циклы выводятся из следующих формул:
(тактовая частота / (предскалерное значение * необходимая частота вызовов ISR)) - 1