我正在编写代码,使一组五个LED看起来像来回“反弹”“Knight Rider”风格。当写入PORTB寄存器时,我注意到我插入LED的方式,不同的东西将是1,2,4,8,16。这些将转换相应的LED。所以我想通过使用pow
函数来循环使用将寄存器设置为2的值,将其提升到LED数字(0,1,2,3,4)。但它不能正常工作。
#include <avr/io.h>
#include <inttypes.h>
#include <math.h>
void delay(uint16_t x);
//void buttons(int b1, int b2);
int led = 0;
int inc = 1;
unsigned int ledpow = 0;
int main(void)
{
DDRB |= (1<<PORTB0); //Set PORTB0 (pin 8) as an output
DDRB |= (1<<PORTB1); //Set PORTB1 (pin 9) as an output
DDRB |= (1<<PORTB2); //Set PORTB2 (pin 10) as an output
DDRB |= (1<<PORTB3); //Set PORTB3 (pin 11) as an output
DDRB |= (1<<PORTB4); //Set PORTB4 (pin 12) as an output
DDRD &= ~(1<<PORTD3); //Set PORTD3 (pin 3) as an input
DDRD &= ~(1<<PORTD4); //Set PORTD4 (pin 4) as an input
PORTB = 0; //Disable Pull-up resistors for PORTB
PORTD = 0; //Disable Pull-up resistors for PORTD
while(1)
{
while((PIND & (1<<PORTD3)) != 0) {
//Do nothing, just pause the program
}
ledpow = pow(2,led);
PORTB = ledpow;
led = led + inc;
if ((led == 4) || (led==0)) {
inc = -inc;
}
if((PIND & (1<<PORTD4)) != 0) {
delay(50);
}
else {
delay(100);
}
}
}
void delay(uint16_t x)
{
uint16_t i,j;
for(i=0;i<x;i++)
for(j=0;j<1000;j++)
;
return;
}
为什么这不起作用?我使用了switch / case语句。我测试了pow
函数的工作原理是PORTB = pow(2,0);
以及变量“led”的其他功能。这工作正常。
答案 0 :(得分:1)
因为pow函数返回一个浮点数,它不是它应该表示的值的精确表示(并且数学函数也使用近似值)。所以也许pow(2, 3)
不会返回8而是7.99856或8.0000261等。在前一种情况下,你被搞砸了,因为当你将它分配给端口时,它被截断为一个整数(端口保持整数,对吧?并且失去其分数部分,形成7以点亮所有3个第一个LED。
对于整数运算,pow函数也是过期的,你在浪费你的机会。我想知道你为什么不使用PORTB = 1 << led;
而你用它来设置其他端口状态......
另外,你的延迟循环非常难以移植。潜入AVR-libc的文档,有两个延迟循环函数,提供几乎准确的时间延迟。您可以在我的AVR实用程序库中查看如何使用它们:http://github.com/H2CO3/libavrutil
答案 1 :(得分:1)
您不应该使用pow()
。您可以在pow()
at C++ Reference找到相关信息。
但是,基本上,整数没有pow()
签名:
double pow ( double base, double exponent ); long double pow ( long double base, long double exponent ); float pow ( float base, float exponent ); double pow ( double base, int exponent ); long double pow ( long double base, int exponent );
这意味着在运行时,它可能无法正常工作,因为它会使结果四舍五入。它需要浮点库(完全在AVR上的软件中实现) - 这很慢并占用空间。
PORTB = pow(2,0);
可能有效,因为它是constexpr
,因此可以在编译时进行评估。
相反,请尝试使用左移运算符,例如:
PORTB = 1 << led;
答案 2 :(得分:0)
你最好的方法是彻底避免战俘。而不是操纵端口用于digitalWrite功能。
void setup() {
for (uint8_t pin=0; pin<20; ++pin) {
pinMode(pin, OUTPUT);
}
}
void blink(const uint8_t pos) {
digitalWrite(pos, HIGH);
delay(200);
digitalWrite(pos, LOW);
}
void loop() {
for (uint8_t pos=0; pos<19; ++pos) {
blink(pos);
}
for (uint8_t pos=19; pos>0; --pos) {
blink(pos);
}
}
可以找到更复杂的骑士版本