- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我制作了一个播放数组中保存的歌曲(使用蜂鸣器)的程序:
(...)
//function which plays a single note
void playNote(int8 wavelength, int duration) {
if (wavelength != 1) {
OCR0A = wavelength; /* set pitch */
SPEAKER_DDR |= (1 << SPEAKER); /* enable output on speaker */
}
while (duration) { /* Variable delay */
_delay_ms(1);
duration--;
}
SPEAKER_DDR &= ~(1 << SPEAKER); /* turn speaker off */
//function which plays song from array
void playSong( int8 *song,int tempo){
int length_16_note = tempo;
for( int8 i = 0;song[i]) ; i += 2){
playNote(song[i],song[i+1]*length_16_note);
_delay_ms(15);
}
}
int main(void){
//array of macros and lenghts of notes
int8 song1[] = {
C,4, E1,4, F1,3, E1,3, F1,2,
F1,2, F1, 2, B1,2, A1,2, G1,1, F1,2, G1,5,
G1,4, B1,4, C1,3, F1,3, E1,2,
B1,2, B1,2, G1,2, B1,2,
B1,3, C1,13, 0};
//initialize a timer
initTimer();
//play song
playSong(song1, 150)
}
我省略了其中的一些部分,但这段代码工作得很好。现在我想将我的歌曲保存到程序内存中,所以我更改:
#include <avr/pgmspace.h>
(...)
int8 song1[] PROGMEM = {...}
void playSong( int8 *song, int tempo){
int length_16_note = tempo;
for( int8 i = 0; pgm_read_byte(&(song[i])) ; i += 2){
playNote(pgm_read_byte(&(song[i])), pgm_read_byte(&(song[i+1]))*length_16_note);
_delay_ms(15);
}
}
当我在 Arduino 上运行该代码时,我会收到随机持续时间(比预期长得多)的随机蜂鸣声。看起来 pgm_read_byte(&(song[i]))
返回随机值。
我尝试将函数 playSong
中的代码提取到 main
中,以便不将数组作为参数传递给函数,但没有任何变化。那么这段代码有什么问题呢?
最佳答案
我不确定这就是原因,但我的第一个猜测是您的持续时间比预期更长,因为您的 for 循环如下所示:
for( int8 i = 0; pgm_read_byte(&(song[i])) ; i += 2)
这意味着每次执行for循环时,程序都会检查程序空间中的数据,因为这是循环条件。
avr-libc 用户手册中有一条关于在循环和函数中使用程序内存读取的警告,请参见下文。
The macros and functions used to retrieve data from the Program Space have to generate some extra code in order to actually load the data from the Program Space. This incurs some extra overhead in terms of code space (extra opcodes) and execution time. (...) But you should be aware of this so you can minimize the number of calls within a single function that gets the same piece of data from Program Space.
此外,您还可以在 for 循环内对程序闪存进行两次额外的调用。所有这些意味着,要更改音符,程序需要等待从程序存储器读取 3 个字节,并需要额外的 15 ms 延迟。结果,笔记比预期长得多。
我建议程序首先将整首歌曲读入 RAM 中的某种缓冲区,然后直接从 RAM 中播放。
关于c - pgm_read_ 和 PROGMEM - 意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47007018/
我制作了一个播放数组中保存的歌曲(使用蜂鸣器)的程序: (...) //function which plays a single note void playNote(int8 wavelength
我是一名优秀的程序员,十分优秀!