F_CPU
Должны быть такими же, как конфигурация аппаратных предохранителей в proteus, вы можете изменить их, дважды щелкнув на atmega 16 и измените предохранители CKSEL следующим образом.
некоторая информация может помочь
_delay_ms()
Только некоторые циклы ЦП зависят от требуемого времени, используя F_CPU
в расчетах.
- Вам нужно увеличить эту задержку до
300ms
, чтобы убедиться, что программа не обрабатывает один и тот же щелчок более одного раза, и если вы удерживаете клавишу нажатой, она будет увеличиваться визуально.
анализ неправильного поведения
25ms
- это очень короткое время... обычный человеческий щелчок занимает около 200-300ms
, поэтому каждый щелчок микроконтроллер будет учитывать более чем один раз.
когда я использую часы 8 МГц, все работает нормально
когда вы меняете F_CPU
на 8MHZ, _delay_ms()
делает расчет на этой скорости и будет больше циклов на запад ... в то время как фактическая скорость 1MHZ
эта разница в скорости (между F_CPU
и фактической скоростью) привела к тому, что задержка = '25 мс' * 8 = '200 мс' стала в 8 раз медленнее.
Простое решение: увеличьте _delay_ms(25)
до _delay_ms(200)
, чтобы получить тот же эффект
обновление (информация о том, как работает задержка)
_delay_ms
Это просто LOOP, чтобы тратить циклы ЦП и блокировать работу ЦП.
частота микроконтроллера определяется аппаратными предохранителями, поэтому вам нужно сообщить программному обеспечению, какую частоту вы используете, бросив определение F_CPU
, чтобы программное обеспечение знало, что каждый цикл займет время = 1 / F_cpu
когда вам нужна задержка, программное обеспечение уже знает количество времени, затрачиваемое каждым тактовым генератором, поэтому оно рассчитает количество циклов для достижения требуемого времени задержки (если вам нужна задержка 1 мс и каждый такт 1 мкс, тогда вы нужно подождать 1000 циклов для достижения этой задержки)
в ассемблере есть инструкция под названием nop
, выполнение которой занимает всего 1 цикл и ничего не делается.
следующий код неверен, но он делает что-то похожее, когда компилятор переводит _delay_ms()
в сборку
for(int i=0;i<50;i++)nop;
этот код сделает 50 nop
и потратит 50 циклов (на самом деле больше 50, потому что переменная доступа и приращения 'i' потребует несколько циклов, но пренебрегает этим, чтобы показать идею)
читать далее
- Используют ли функции задержки AVR таймеры?< /а>
- как сделать задержку в сборке AVR
person
Ibram Reda
schedule
15.11.2020