proteus中7段显示的时钟问题
clock problems with 7-segment display in proteus
这是一个带有按钮的简单 7 段显示,问题是每当我将时钟设置为 1 MHZ 时,显示并不像预期的那样 运行,但是当我使用 8 MHZ 时钟时,它工作正常。
这是代码:
#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
应该和proteus中的硬件保险丝配置一样你可以通过双击atmega 16来改变它们并改变CKSEL保险丝如下
一些信息可能有帮助
_delay_ms()
只需要CPU个周期就可以了F_CPU
计算需要的时间
- 您需要将此延迟增加到
300ms
以确保程序不会多次处理相同的点击,如果您按住该键,它会以视觉方式增加
错误行为分析
25ms
是一个非常短的时间...正常的人类点击大约需要 200-300ms
所以在每次点击中微控制器都会认为它不止一次
when I use 8 MHZ clock it works fine
当您将 F_CPU
更改为 8MHZ 时,_delay_ms()
会根据此速度进行计算,并将向西移动更多周期...而实际速度是 1MHZ
这种速度差异(在 F_CPU
和实际速度之间)导致延迟慢 8 倍 ='25ms' *8 ='200 ms'
简单的解决方案将 _delay_ms(25)
增加到 _delay_ms(200)
以达到相同的效果
更新(有关延迟如何工作的信息)
_delay_ms
只是浪费 CPU 周期的循环,它会阻止 CPU 工作
微控制器的频率由硬件保险丝决定,所以你需要告诉软件你使用哪个频率 throw define F_CPU
这样软件就会知道每个周期需要时间 = 1/F_cpu
当你需要延迟时,软件已经知道每个时钟所花费的时间,因此它会计算周期数以达到所需的延迟时间(如果你需要延迟1ms延迟和每个时钟调整 1 us 然后你需要等待 1000 个周期来实现这些延迟)
在 Assembly 中有一条指令叫做 nop
只需要 1 个周期来执行并且什么都不做
下面的代码不正确,但当编译器在汇编
中翻译_delay_ms()
时,它会产生类似的东西
for(int i=0;i<50;i++)nop;
此代码将生成 50 个 nop
并浪费 50 个周期(实际上超过 50 个,因为访问和递增变量 'i' 将消耗一些循环但忽略它以显示想法)
阅读更多
这是一个带有按钮的简单 7 段显示,问题是每当我将时钟设置为 1 MHZ 时,显示并不像预期的那样 运行,但是当我使用 8 MHZ 时钟时,它工作正常。 这是代码:
#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
应该和proteus中的硬件保险丝配置一样你可以通过双击atmega 16来改变它们并改变CKSEL保险丝如下
一些信息可能有帮助
_delay_ms()
只需要CPU个周期就可以了F_CPU
计算需要的时间- 您需要将此延迟增加到
300ms
以确保程序不会多次处理相同的点击,如果您按住该键,它会以视觉方式增加
错误行为分析
25ms
是一个非常短的时间...正常的人类点击大约需要 200-300ms
所以在每次点击中微控制器都会认为它不止一次
when I use 8 MHZ clock it works fine
当您将 F_CPU
更改为 8MHZ 时,_delay_ms()
会根据此速度进行计算,并将向西移动更多周期...而实际速度是 1MHZ
这种速度差异(在 F_CPU
和实际速度之间)导致延迟慢 8 倍 ='25ms' *8 ='200 ms'
简单的解决方案将 _delay_ms(25)
增加到 _delay_ms(200)
以达到相同的效果
更新(有关延迟如何工作的信息)
_delay_ms
只是浪费 CPU 周期的循环,它会阻止 CPU 工作
微控制器的频率由硬件保险丝决定,所以你需要告诉软件你使用哪个频率 throw define F_CPU
这样软件就会知道每个周期需要时间 = 1/F_cpu
当你需要延迟时,软件已经知道每个时钟所花费的时间,因此它会计算周期数以达到所需的延迟时间(如果你需要延迟1ms延迟和每个时钟调整 1 us 然后你需要等待 1000 个周期来实现这些延迟)
在 Assembly 中有一条指令叫做 nop
只需要 1 个周期来执行并且什么都不做
下面的代码不正确,但当编译器在汇编
中翻译_delay_ms()
时,它会产生类似的东西
for(int i=0;i<50;i++)nop;
此代码将生成 50 个 nop
并浪费 50 个周期(实际上超过 50 个,因为访问和递增变量 'i' 将消耗一些循环但忽略它以显示想法)
阅读更多