我的一位同事向我提供了以下C AVR代码:
#include <avr/io.h>
#include <stdlib.h>
#define byte uint8_t
byte button[8];
byte play[8];
byte licz;
byte pind_in;
uint16_t freq[8]= {3822, 3405, 3033, 2863, 2551, 2272, 2024, 1911};
uint32_t count[8];
int main (void)
{
DDRD = 0;
PORTD = 0xff;
DDRB = 0b00000010;
while (1)
{
pind_in = PIND;
licz += 16;
for (byte i = 0; i < 8; i++)
{
button[i] = !(pind_in&(1<<i));
if ((button[i]) && (play[i] < 255))
play[i]++;
if ((!button[i]) && (!(licz)) && (play[i] > 0))
play[i]-- ;
count[i] += freq[i];
if ((count[i] & (0x4000)) && (play[i]))
PORTB = 0b00000010;
else
PORTB = 0;
}
}
}
我理解它是基于AVR微控制器的声音生成,但是我无法确定为什么licz + = 16在无限循环中使用,以及其余部分背后的算法是什么? 。这里有人能解密吗?
答案 0 :(得分:2)
我真的不知道你的AVR有什么联系,所以这只是受过教育的
在这里猜。
我们假设输出声音,而PORTB.2 == 1
则输出,否则静音。
此PORTB
位设置为play[i] > 0
。 play[i]
时会增加button[i]
play
已设置,可能是外部按钮或其他内容
类似。释放按钮后,licz
再次倒计时到零。
可能这会使声音比按下按钮的时间长一点。
licz
变量使得向下计数变慢。每个第16个循环(假设
该字节== 8位),play
将再次为零,并且会跳过递减的licz += 16;
。例如,如果您将licz += 128;
更改为{{1}},则会在每个第二个循环中跳过减少,使按钮释放后声音持续更长时间。
答案 1 :(得分:1)
我这样看:
#include <avr/io.h>
#include <stdlib.h>
#define byte uint8_t
// frequency table for each used HW button (scaled to main loop timing)
uint16_t freq[8]= {3822,3405,3033,2863,2551,2272,2024,1911};
byte button[8]; // HW button state
byte play[8]; // amplitude ... realy there is just single amplitude output but this makes time hysterezis of sound to filter out the glitches
uint32_t count[8]; // counter for frequency generation
byte licz; // just counter for hysterezis generation amplitude is increasing 16x faster then decreasing
byte pind_in; // variable for HW buttons/key-press detection
int main(void)
{
// probably configuration of IO port of the MCU (was not specified...)
DDRD= 0;
PORTD=0xff;
DDRB= 0b00000010;
// inf loop of main process
while(1)
{
pind_in=PIND; // read the HW buttons state
licz+=16;
for (byte i=0;i<8;i++) // loop through all buttons/frequencies
{
button[i]=!(pind_in&(1<<i)); // extract button state on/off
if (( button[i])&& (play[i]<255)) play[i]++; // if keypressed increase amplitude up to max
if ((!button[i])&&(!licz)&&(play[i]> 0)) play[i]--; // if not decrease amplitude until zero
count[i]+=freq[i]; // update frequency generator counter
// alternate the speaker/buzzer
if ((count[i]&(0x4000))&&(play[i])) PORTB=0b00000010; else PORTB=0;
}
}
}
}
此代码还有很多需要改进的地方