here is a simple 7-segment display with a pushbutton the problem is whenever I make the clock 1 MHZ the display doesn't run as expected but when I use 8 MHZ clock it works fine. here is the code:
#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++;
}
}
}
}
F_CPU
Should be the same as the hardware fuses configuration in proteus you could change them by double-click on atmega 16 and change CKSEL Fuses as following
_delay_ms()
It only west some CPU cycles depend on the required time by using F_CPU
in the calculation300ms
to make sure that program does not process the same click more than one and if you hold the key down it will increase in visual manner25ms
is a very short time ... a normal human click will take around 200-300ms
so in every click the microcontroller will consider it more than one
when I use 8 MHZ clock it works fine
when you change F_CPU
to 8MHZ the _delay_ms()
it make the calculation on this speed and will west more cycles ... while the actual speed is 1MHZ
this differance in speed (between F_CPU
and the actual speed) led to make 8 times slower delay ='25ms' *8 ='200 ms'
simple solution increase the _delay_ms(25)
to _delay_ms(200)
to make the same effect
_delay_ms
Is just LOOP to waste CPU cycles and it blocks the CPU from work
the frequency of the microcontroller is determined by the hardware fuses so you need to tell the software which frequency you use throw define F_CPU
so the software will know each cycle will take time = 1/F_cpu
when you need a delay, the software already know the amount of time taken by each clock so it will calculate the number of cycle to achieve the required delay time(if you need delay 1ms delay and each clock tack 1 us then you need to wait for 1000 cycles to achieve these delay)
in Assembly there is instruction called nop
take only 1 cycle to execute and do nothing
the following code is not correct but it makes something similar when the compiler translate _delay_ms()
in Assembly
for(int i=0;i<50;i++)nop;
this code will make 50 nop
and wast 50 cycles(actually more than 50 because access and increment variable 'i' will consume some cycles but neglect it to show the idea)
read more