проблемы с часами при 7-сегментном дисплее в протеусе

Вот простой 7-сегментный дисплей с кнопкой. Проблема в том, что всякий раз, когда я делаю часы на 1 МГц, дисплей работает не так, как ожидалось, но когда я использую часы на 8 МГц, он работает нормально. вот код:

#define  F_CPU 1000000L

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
    DDRD &= ~(1<<PD4);
    DDRC |= (1<<PC0) | (1<<PC1) | (1<<PC2) | (1<<PC3);
    PORTC = 0;
    while (1) 
    {
        if(PIND & (1<<PD4)){
            _delay_ms(25);
            if(PIND & (1<<PD4)){
                PORTC++;
            }
        }
    }
}

введите здесь описание изображения


person Ali El-Boghdady    schedule 15.11.2020    source источник


Ответы (1)


F_CPU Должны быть такими же, как конфигурация аппаратных предохранителей в proteus, вы можете изменить их, дважды щелкнув на atmega 16 и измените предохранители CKSEL следующим образом.

введите здесь описание изображения

некоторая информация может помочь

  1. _delay_ms() Только некоторые циклы ЦП зависят от требуемого времени, используя F_CPU в расчетах.
  2. Вам нужно увеличить эту задержку до 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' потребует несколько циклов, но пренебрегает этим, чтобы показать идею)

читать далее

  1. Используют ли функции задержки AVR таймеры?< /а>
  2. как сделать задержку в сборке AVR
person Ibram Reda    schedule 15.11.2020
comment
спасибо за ваш отличный и пояснительный ответ, он сработал после того, как я увеличил задержку, у меня уже есть протеус атмега на 1 МГц, мне нужно лучше понять, как работают часы в этих расчетах, если вы можете мне это объяснить или отправьте мне ссылку было бы здорово - person Ali El-Boghdady; 16.11.2020
comment
@AliEl-Boghdady Пожалуйста, я обновил пост и добавил информацию о задержке. - person Ibram Reda; 17.11.2020