如何用 C 为时钟为 16MHz 的 ATMega8 计算时间
How to count time in C for ATMega8 with clock 16MHz
如何计算中断时间并设置为全局变量?
我的单片机是Atmega8,F_CPU是16MHz,编程语言是C。
我知道的很少,下面那行是时钟的初始化。
TCCR1B |= (1 << CS10);
这一行就是这样,全局变量 "a" 得到循环值除以 "xxx"。但是必须为 xxx 分配什么值?
a = TCNT1/xxx;
PS1: 我想计算我的螺旋桨在推进 LED 显示器中的最后一圈,并将这个值提供给下一个中断以正确的方式显示图像。
PS2:为了延迟,我使用函数:_delay_ms()。
首先使用 _delay_ms
不是正确计时的好方法。
我建议如下:
使用 timer1 测量转子的频率。
当您获得位置中断(假设每回合一个)时,将当前计时器值写入一个变量。在以下每个中断上计算循环计数器的差异(正确考虑溢出)。
现在你有了每转的循环数。我现在会以某种方式设置第二个计时器,计数器的最高值(CTC 模式)与测量的周期数除以显示器的 angular 分辨率相同。因此,在溢出中断中,您可以将新数据锁存到 LED。
一个例子:
preconditions/assumptions:
- F_CPU(和实际时钟)16MHz
- 显示分辨率:200 角度
- 旋翼转速:137Hz
- 定时器1预分频器=4(否则每转溢出多次)
有了这个值,您应该得到 29197 个计时器滴答的差异,这转化为 116788.3 CPU-每转周期。除以 200 行,每个部分有 583.94 个周期。这个数字对于 8 位计数器来说太大了。使用预分频器 2 得到 291.97 - 仍然太大。因此,您必须使用下一个更大的预分频器(希望如此)4 才能使值达到 145.98。
向上舍入为 146 和 -1,因为 0 也被计算在内。
所以我建议使用 145 作为这个计数器的最高值。这种考虑必须以编程方式实现。获取循环值并增加预分频器,只要它不适合您的 8 位即可。
整个程序如下所示:
volatile uint16_t oldTimer=0;
volatile uint16_t newTimer=0;
volatile uint8_t flag=0; // bit 1 = push new data, bit 2 = new revolution measurement
ISR(Postional Interupt){
oldTimer = newTimer;
newTimer = TCNT1;
flag |= 2;
}
ISR(timer2_overflow){
latchDataToOutput();
flag |= 1;
}
int main()
{
while(1){
if(flag & 2){
calcNewTimer2Timing();
flag &= ~2;
}
if(flag & 1){
OutputDataToShiftRegister();
flag &= ~1;
}
}
}
如何计算中断时间并设置为全局变量? 我的单片机是Atmega8,F_CPU是16MHz,编程语言是C。 我知道的很少,下面那行是时钟的初始化。
TCCR1B |= (1 << CS10);
这一行就是这样,全局变量 "a" 得到循环值除以 "xxx"。但是必须为 xxx 分配什么值?
a = TCNT1/xxx;
PS1: 我想计算我的螺旋桨在推进 LED 显示器中的最后一圈,并将这个值提供给下一个中断以正确的方式显示图像。
PS2:为了延迟,我使用函数:_delay_ms()。
首先使用 _delay_ms
不是正确计时的好方法。
我建议如下: 使用 timer1 测量转子的频率。 当您获得位置中断(假设每回合一个)时,将当前计时器值写入一个变量。在以下每个中断上计算循环计数器的差异(正确考虑溢出)。
现在你有了每转的循环数。我现在会以某种方式设置第二个计时器,计数器的最高值(CTC 模式)与测量的周期数除以显示器的 angular 分辨率相同。因此,在溢出中断中,您可以将新数据锁存到 LED。
一个例子:
preconditions/assumptions:
- F_CPU(和实际时钟)16MHz
- 显示分辨率:200 角度
- 旋翼转速:137Hz
- 定时器1预分频器=4(否则每转溢出多次)
有了这个值,您应该得到 29197 个计时器滴答的差异,这转化为 116788.3 CPU-每转周期。除以 200 行,每个部分有 583.94 个周期。这个数字对于 8 位计数器来说太大了。使用预分频器 2 得到 291.97 - 仍然太大。因此,您必须使用下一个更大的预分频器(希望如此)4 才能使值达到 145.98。 向上舍入为 146 和 -1,因为 0 也被计算在内。 所以我建议使用 145 作为这个计数器的最高值。这种考虑必须以编程方式实现。获取循环值并增加预分频器,只要它不适合您的 8 位即可。
整个程序如下所示:
volatile uint16_t oldTimer=0;
volatile uint16_t newTimer=0;
volatile uint8_t flag=0; // bit 1 = push new data, bit 2 = new revolution measurement
ISR(Postional Interupt){
oldTimer = newTimer;
newTimer = TCNT1;
flag |= 2;
}
ISR(timer2_overflow){
latchDataToOutput();
flag |= 1;
}
int main()
{
while(1){
if(flag & 2){
calcNewTimer2Timing();
flag &= ~2;
}
if(flag & 1){
OutputDataToShiftRegister();
flag &= ~1;
}
}
}