这代码真看不懂了,请老师教我-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 1917|回复: 5

[未解决] 这代码真看不懂了,请老师教我

[复制链接]
发表于 2021-11-8 21:49 | 显示全部楼层 |阅读模式
这是老外的代码,不明白为什么 startPlayback() 要在void setup()里,而void loop()里啥也没有????
请哪位老师教我
原贴https://playground.arduino.cc/Code/PCMAudio/


/*
* speaker_pcm
*
* Plays 8-bit PCM audio on pin 11 using pulse-width modulation (PWM).
使用脉宽调制 (PWM) 在引脚 11 上播放 8 位 PCM 音频。
  */

#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>

#define SAMPLE_RATE 8000

#include "sounddata.h"

int ledPin = 13;
int speakerPin = 11; // Can be either 3 or 11, two PWM outputs connected to Timer 2可以是3或11,两个PWM输出连接到定时器2
volatile uint16_t sample;
byte lastSample;

void stopPlayback()
{
    // Disable playback per-sample interrupt.禁用每个采样中断的播放。
    TIMSK1 &= ~_BV(OCIE1A);

    // Disable the per-sample timer completely.完全禁用每采样计时器。
    TCCR1B &= ~_BV(CS10);

    // Disable the PWM timer.禁用PWM定时器。
    TCCR2B &= ~_BV(CS10);

    digitalWrite(speakerPin, LOW);
}

// This is called at 8000 Hz to load the next sample.这在8000 Hz时调用,以加载下一个样本。
ISR(TIMER1_COMPA_vect) {
    if (sample >= sounddata_length) {
        if (sample == sounddata_length + lastSample) {
            stopPlayback();
        }
        else {
            if(speakerPin==11){
                // Ramp down to zero to reduce the click at the end of playback.渐变到零以减少播放结束时的单击。
                OCR2A = sounddata_length + lastSample - sample;
            } else {
                OCR2B = sounddata_length + lastSample - sample;               
            }
        }
    }
    else {
        if(speakerPin==11){
            OCR2A = pgm_read_byte(&sounddata_data[sample]);
        } else {
            OCR2B = pgm_read_byte(&sounddata_data[sample]);            
        }
    }

    ++sample;
}

void startPlayback()
{
    pinMode(speakerPin, OUTPUT);
    // Set up Timer 2 to do pulse width modulation on the speaker pin.设置定时器2对扬声器引脚进行脉宽调制。
    // Use internal clock (datasheet p.160)使用内部时钟(数据表第160页)
    ASSR &= ~(_BV(EXCLK) | _BV(AS2));
    // Set fast PWM mode  (p.157)设置快速PWM模式
    TCCR2A |= _BV(WGM21) | _BV(WGM20);
    TCCR2B &= ~_BV(WGM22);

    if(speakerPin==11){
        // Do non-inverting PWM on pin OC2A (p.155)
        // On the Arduino this is pin 11.
        TCCR2A = (TCCR2A | _BV(COM2A1)) & ~_BV(COM2A0);
        TCCR2A &= ~(_BV(COM2B1) | _BV(COM2B0));
        // No prescaler (p.158)
        TCCR2B = (TCCR2B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);

        // Set initial pulse width to the first sample.
        OCR2A = pgm_read_byte(&sounddata_data[0]);
    } else {
        // Do non-inverting PWM on pin OC2B (p.155)
        // On the Arduino this is pin 3.
        TCCR2A = (TCCR2A | _BV(COM2B1)) & ~_BV(COM2B0);
        TCCR2A &= ~(_BV(COM2A1) | _BV(COM2A0));
        // No prescaler (p.158)
        TCCR2B = (TCCR2B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);

        // Set initial pulse width to the first sample.
        OCR2B = pgm_read_byte(&sounddata_data[0]);
    }

    // Set up Timer 1 to send a sample every interrupt.

    cli();

    // Set CTC mode (Clear Timer on Compare Match) (p.133)
    // Have to set OCR1A *after*, otherwise it gets reset to 0!
    TCCR1B = (TCCR1B & ~_BV(WGM13)) | _BV(WGM12);
    TCCR1A = TCCR1A & ~(_BV(WGM11) | _BV(WGM10));

    // No prescaler (p.134)
    TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);

    // Set the compare register (OCR1A).
    // OCR1A is a 16-bit register, so we have to do this with
    // interrupts disabled to be safe.
    OCR1A = F_CPU / SAMPLE_RATE;    // 16e6 / 8000 = 2000

    // Enable interrupt when TCNT1 == OCR1A (p.136)
    TIMSK1 |= _BV(OCIE1A);

    lastSample = pgm_read_byte(&sounddata_data[sounddata_length-1]);
    sample = 0;
    sei();
}


void setup()
{
    pinMode(ledPin, OUTPUT);
    digitalWrite(ledPin, HIGH);
    startPlayback();    //????????????
}

void loop()
{
    while (true);        //???????????????????
}


发表于 2021-11-9 14:54 | 显示全部楼层
这不就一个AVR调用定时器。。。。
 楼主| 发表于 2021-11-21 11:26 | 显示全部楼层
XlinliY.Zhang 发表于 2021-11-9 14:54
这不就一个AVR调用定时器。。。。

是啊,可是看不懂,还在琢磨中,谢谢
发表于 2021-11-21 13:30 | 显示全部楼层
就是设置定时器,时间到中断触发执行。
发表于 2021-11-21 16:14 | 显示全部楼层
大散人 发表于 2021-11-21 11:26
是啊,可是看不懂,还在琢磨中,谢谢

数据手册,定时器部分,对于的寄存器的功能
 楼主| 发表于 2021-11-25 10:10 | 显示全部楼层
XlinliY.Zhang 发表于 2021-11-21 16:14
数据手册,定时器部分,对于的寄存器的功能

谢谢,这块有点复杂哦
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 19:44 , Processed in 0.072376 second(s), 16 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表