我是靠谱客的博主 伶俐羽毛,最近开发中收集的这篇文章主要介绍Arduino基础学习-声音信号输出,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述


通过Arduino生成声音或者模拟电压,这个教学将介绍如何下面将教你如何建立一个基本的数字模拟转换器,然后你就可以是通过Arduino一些数字信号管脚的不同波形和波长的信号转换为模拟信号。(这篇文章我写的另一片文章“如何传输音频信号给Arduino”的姊妹篇;点击链接就可以了) 

以下是我的一些想法:

取样的音乐器材:保存样本文件在Arduino或者SD卡中用按键触发器或其他控制器件控制,我用Arduino电子鼓作为范例。

数字信号合成:产生锯齿波,正弦波,三角波,方波或者其他任意波形都可以通过信号发生器来生成。

使用MIDI控制电压模块/MIDIf仿真:接收MIDI信号然后转化为电压信号,所以用来控制模拟信号,或者也可以使用MIDE数据来输出一定频率的音频信号。

模拟信号输出:你可能需要用Arduino生成模拟信号,来与模拟设备连接。

音响/数字信号处理:与麦克风或者音响连接可以演示所以种类的数字信号,然后将音频传送到扬声器。可以用我的作为范例。

音频播放设备:使用你的iPod(或其他MP3)添加一张SD卡,现在你可以制作你的Arduino MP3 播放器了。(检查波形记录的启动代码),这里的电路和代码都是以SPI传输模式提供的。

自由发挥创意,一起参加这个有趣的DIY Audio CONTEST ,他们会提供一个HDTV,一些DSLR 摄像头,还有其他等等。

器件:

9个1/4W的20K电阻,

7个1/4W的10k电阻,

2个TS922N,

1个10k的电位器,

1个0.01uF电容,

1个200uF电容,

1个0.1uF电容,

1个1/4W的3K电阻,

1个1/4W的10欧电阻,

额外器件有:

1个USB转接线,

1和面包板,

一些跳线


第一步:数字信号与模拟信号转换

DAC(digital to analog coverter)Arduino 不能产生模拟信号,我们需要使用DAC来转换数字数据(numbers,ints,bytes)为模拟信号(电压)。一个简单方便的方法是使用R2R电阻网络。本质上,他也是讲数字信号bits(Arduino的0V和5V)分析权重,求和产生0到5V(见图 from wikipedia resistor laddrt page)你可以将其视为多重电位分割器件。

本教程中将展示的电阻梯是8位DAC,这意味着它可以在0和5v之间产生256(2 ^ 8)个不同的电压电平我将每个数字引脚0-7连接到我的8位DAC中的每个8个连接点(如图1和图3所示)。我喜欢使用这些电阻梯DAC,因为我总是有材料,它们便宜且有趣,但是它们不会给你最高质量的音频您可以购买一个与R2R DAC完全相同的芯片(并且可以使用所有代码),但具有内部,高度匹配的电阻,以获得更好的音频质量,我喜欢这个BC它运行单个5V电源(您甚至可以使用立体声音频),但还有更多可用的,寻找“输入,8位,DAC芯片”。

或者,存在采用串行数据来执行数模转换的芯片。这些芯片通常具有更高的保真度(更好的电阻梯形DAC的质量),它们只使用两个或三个的Arduino的输出引脚(与8相反)。它的缺点是编程更具挑战性,更昂贵,并且无法使用此“可教导”中的代码,尽管我确信还有其他教程可用。在digikey(原文购买电子器件的网站,单个买的话,国外的比较贵)快速搜索之后,对于Arduino的来说,这些芯片看起来不错,尝试找到一个支持5V电源的器件。还有一个注意事项 - 似乎有一种误解约8位音频 - 它总是听起来像马里奥游戏的声音效果 - 但8bit音频与这个真正基本的DAC实际上可以很好地复制人们的声音和乐器的声音,我总是惊讶于可以来自一堆电阻的声音质量。

第二步:建立DAC电路,测试





原理图如图8所示。下面是生成图4-7所示波形的几个示例代码。 在以下代码段中,当我要将数据发送到DAC时,我会在0到255之间发送一个值到“PORTD”,如下所示:4


PORTD = 125;//send data t DAC

这被称为直接寻址端口。 在Arduino上,数字引脚0-7都在Atmel328芯片的端口d上。 PORTD命令让我们告诉引脚0-7在一行中变为HIGH或LOW(而不是使用八次digitalWrite())。 这不仅更容易编码,而且Arduino处理速度要快得多,引脚可以同时更改,而不是逐个更改(您只能使用digitalWrite()一次只能与一个引脚通信)。 由于端口d上有八个引脚(数字引脚0-7),我们可以发送2 ^ 8 = 256个可能值(0-255)中的一个来控制引脚。

 例如,如果我们写下列行:

PORTD=0;

这个命令会使0~7管脚低电平,模拟信号会输出0V,

例如,如果我们写下列行:

PORTD=255;

这个命令会使0·7管脚高电平,模拟信号会输出5V,同样我们也可以输出0到5U之间的电压,只要使用以下命令就可以了:

PORTD=125;

125=01111101这将引脚7设置为低电平(msb为0),引脚6-2为高电平(接下来的5位为1),引脚1为低电平(下一位为0),引脚0为高电平(lsb为1)。 你可以阅读更多关于这是如何工作的。 为了计算从DAC输出的电压,我们使用以下公式:

voltage output from DAC = [ (value sent to PORTD) / 255 ] * 5V

所以PORTD=125:

电压=(125/255)*5=2.45u

下面的代码发出了0到5V之间的几个电压,并且保持每个电压很短的时间来演示上面描述的概念。 在我写的main loop()函数中:

  PORTD = 0;//send (0/255)*5 = 0V out DAC
  delay(1);//wait 1ms
  PORTD = 127;//send (127/255)*5 = 2.5V out DAC
  delay(2);//wait 2ms
  PORTD = 51;//send (51/255)*5 = 1V out DAC
  delay(1);//wait 1ms
  PORTD = 255;//send (255/255)*5 = 5V out DAC
  delay(3);//wait 3ms

输出显示在图4中的示波器上。示波器上的中心水平线表示0V,每条水平线表示2V的电压增加/减小。 图4中的图像注释显示了上述每行代码的输出,点击图像查看图像注释。


//Analog out
//by Amanda Ghassaei
//https://www.instructables.com/id/Arduino-Audio-Output/
//Sept 2012

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
*/

void setup(){
  //set digital pins 0-7 as outputs
  for (int i=0;i<8;i++){
    pinMode(i,OUTPUT);
  }
}

void loop(){
  PORTD = 0;//send (0/255)*5 = 0V out DAC
  delay(1);//wait 1ms
  PORTD = 127;//send (127/255)*5 = 2.5V out DAC
  delay(2);//wait 2ms
  PORTD = 51;//send (51/255)*5 = 1V out DAC
  delay(1);//wait 1ms
  PORTD = 255;//send (255/255)*5 = 5V out DAC
  delay(3);//wait 3ms
}
以下代码输出从0到5V的斜坡图样,在loop()函数中,变量“a”从0增加到255.每次递增,“a”的值被发送到PORTD。 在发送新值“a”之前,此值保持为50us。 一旦“a”达到255,它将重置为0.此斜坡的每个周期的时间(也称为周期)需要:

period = (duration of each step) * (number of steps)
period = 50us * 256 = 12800us = 0.0128s

所以周期是74hz.

DAC在示波器上面的图像可以在图五,(当然,图片,我没有转来)

/Ramp out
//by Amanda Ghassaei
//https://www.instructables.com/id/Arduino-Audio-Output/
//Sept 2012

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
*/

void setup(){
  //set digital pins 0-7 as outputs
  for (int i=0;i<8;i++){
    pinMode(i,OUTPUT);
  }
}

void loop(){
  for (int a=0;a<256;a++){
    PORTD = a;//send out ramp to digital pins 0-7
    delayMicroseconds(50);//wait 50us
  }
}

命令会输出2.5u左右的电压,最低5u最低0u,在loop()程序中,变量t是在0到100 之间变化,时间增加,表达式是

127+127*sin(2*3.14*t/100)

被发送到PORTD。 在“t”再次递增之前,此值保持为50us,并将新值发送到PORTD。 一旦“t”达到100,则将其重置为0.该正弦波的周期应为


period = (duration of each step) * (number of steps)
period = 50us * 100 = 5000us = 0.005s

周期是200hz

//Sine out
//by Amanda Ghassaei
//https://www.instructables.com/id/Arduino-Audio-Output/
//Sept 2012

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
*/

void setup(){
  //set digital pins 0-7 as outputs
  for (int i=0;i<8;i++){
    pinMode(i,OUTPUT);
  }
}

void loop(){
  for (int t=0;t<100;t++){//increment "t"
    PORTD = 127+127*sin(2*3.14*t/100);//send sine wave to DAC, centered around (127/255)*5 = 2.5V
    delayMicroseconds(50);//wait 50us
  }
}

但是不是这样,DAC的输出如图6所示。如图所示,它没有频率为200hz,频率更像45hz。这是因为行:
PORTD = 127 + 127 * sin(2 * 3.14 * t / 100);
花费很长时间来计算。在一般乘法/除数与十进制数和sin()函数使Arduino执行很多时间。
一个解决方案是提前计算正弦值,并将其存储在Arduino的记忆中。那么当Arduino草图运行时,Arduino所要做的就是记忆这些值(Arduino的一个非常简单和快速的任务)。我运行了一个简单的Python脚本(下面)来生成100个值127 + 127 * sin(2 * 3.14 * t / 100):
导入数学对于范围内的x(0,100):
print str(int(127 + 127 * math.sin(2 * math.pi * x * 0.01)))+ str(“,”),
我将这些值存储在下面的Arduino草图中的一个名为“sine”的数组中。然后在我的循环中,对于“t”的每个值,我向PORTD发送了一个正弦[]的元素:
PORTD = sine [t];
该草图的该DAC的输出如图7所示。您可以看到,如预期的那样,它输出200hz的正弦波。


//Sine out with stored array
//by Amanda Ghassaei
//https://www.instructables.com/id/Arduino-Audio-Output/
//Sept 2012

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
*/

byte sine[] = {127, 134, 142, 150, 158, 166, 173, 181, 188, 195, 201, 207, 213, 219, 224, 229, 234, 238, 241, 245, 247, 250, 251, 252, 253, 254, 253, 252, 251, 250, 247, 245, 241, 238, 234, 229, 224, 219, 213, 207, 201, 195, 188, 181, 173, 166, 158, 150, 142, 134, 127, 119, 111, 103, 95, 87, 80, 72, 65, 58, 52, 46, 40, 34, 29, 24, 19, 15, 12, 8, 6, 3, 2, 1, 0, 0, 0, 1, 2, 3, 6, 8, 12, 15, 19, 24, 29, 34, 40, 46, 52, 58, 65, 72, 80, 87, 95, 103, 111, 119,};

void setup(){
  //set digital pins 0-7 as outputs
  for (int i=0;i<8;i++){
    pinMode(i,OUTPUT);
  }
}

void loop(){
  for (int t=0;t<100;t++){//increment "t"
    PORTD = sine[t];//send sine wave to DAC, centered around (127/255)*5 = 2.5V
    delayMicroseconds(50);//wait 50us
  }
}


第三步:DAC缓冲


现在我们有一个很好的信号从Arduino出来,我们需要保真。 R2R DAC对其上的任何负载非常敏感,因此试图直接从DAC驱动扬声器将会大大扭曲信号。 在做任何事情之前,您需要设置某种缓冲电路。 我在TS922双运放封装中设置了一个运算放大器作为电压跟随器,用于从我的电路的其余部分缓冲我的DAC(见图6中的原理图,请务必使用5V和地线为运算放大器供电)。
一旦这样设置,我在运算放大器的输出和地之间串联一个LED和220欧姆电阻。 下面的草图输出缓慢的DAC输出,所以您可以看到LED随着斜坡增加电压而变得更亮。 坡道的时期是:
周期=(每个步骤的持续时间)*(步数)
周期= 5ms * 256 = 1280ms = 1.28s
所以LED需要1.28秒才能从关闭到全亮。

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
*/

void setup(){
  //set digital pins 0-7 as outputs
  for (int i=0;i<8;i++){
    pinMode(i,OUTPUT);
  }
}

void loop(){
  for (int a=0;a<256;a++){
    PORTD = a;//send out ramp to digital pins 0-7
    delay(5);//wait 5ms
  }
}


第四步:低通

点击打开链接低通滤波器的目的是平滑DAC的输出以减少噪声。通过对信号使用低通滤波器,您可以平滑波形中的“步进”,同时保持波形的整体形状不变(参见图4)。我使用一个简单的RC 滤波电路来实现这一点:电阻和电容串联到地。将电阻连接到输入信号和电容接地,来自这两个组件之间的结点的信号将被低通滤波。我将这个滤波后的信号发送到另一个缓冲电路(我在一个电压跟随器配置中连接一个运算放大器),以保护滤波信号免受电路中的任何负载的影响。有关更多信息,请参见图5中的原理图。

您可以根据以下公式计算低通滤波器所需的电容和电阻值:
截止频率= 1 /(2 * pi * R * C)
奈奎斯特的Theroum指出,对于采样率为x Hz的信号,可以产生的最高频率为x / 2Hz。您应该将您的截止频率设置为x / 2Hz(或者根据您喜欢的方式可能略低)。因此,如果采样率为40kHz(大多数音频的标准),则可以再现的最大频率为20kHz(可听频谱的上限),低通滤波器的截止频率应在20kHz左右。
对于截止频率为20,000Hz和1kΩ电阻:
20000 = 1 /(2 * 3.14 * 1000 * C)
C =〜8nF
由于8nF电容器难以达到,因此可以达到0.01uF。这给出约16kHz的截止频率。你可以选择你喜欢的值,我倾向于filter heavier(我不会翻译了,过滤更多的意思吧),因为它会消除更多的不必要的噪音。

第五步:波幅


接下来我增加了一个电位器来控制我的信号幅度(音量)。为此我有线输出第二电压跟随一个10kΩ的电位器一侧。我把另一边连接到地上。从中间出来的信号有一个可调幅度(介于0和2.5V)这取决于电位器的转向。见示意图(图7)更多信息。您可以看到输出信号之前,电位器和电位器后(当转向中点)图6 

Step 6: Amplifier放大器






很多时候当我们谈论到放大器,我们想到的是增加信号的振幅。在这里,我会增加信号的电流,以便它可以驱动负载(如扬声器)。在这一阶段的电路我设置运算放大器在ts922包并联电压跟随器。意思是我把输出从振幅器的非反相输入到两个运算放大器。然后,我连接两个运算放大器作为voltage follwer(电压跟随器)连接他们的输出给对方。由于每个运放可以80ma电流源,电流源应该是160ma。 

Step 7: DC Offset直流漂移



在发送一个信号到扬声器,你要确保它是振荡为0V左右(典型的音频信号)。到目前为止,Arduino的DAC输出我们定在2.5V。为此我们可以用一个大电容器。在示意图中显示,我使用220uF电容直流偏移我的信号,振荡为0V左右,直流偏移信号输出(蓝色)和联合偏移信号(黄色)两种不同的振幅可以在图2和图3。 

第八步:输出


最后,我用两根线连接1 / 4mono Jack连接器。我接地导致Arduino的地面和信号传到220UF和0.1UF的电容器负极导线。接地引脚通常是较大的针脚,与螺纹部分进行连接测试,以确保您正确地连接了接地引脚(见图5)。信号引脚将从mono Jack引出来(图5)。更多信息参见示意图。 

第9步:40KHZ的采样信号


如何产生音频在40kHz的采样,代码可以使用定时器中断。Arduino的定时器中断允许你暂停,你的loop()函数做跳到一个另外的进程,称为“中断”,一旦这个程序完成你回到loop()。你设置指定代码的setup()部分这些频率中断。你可以在这里设置中断的细节,但如果你只是想实现40khz中断,然后你可以复制下面的代码部分。

在setup()设定中断参数


cli();//disable interrupts
  //set timer0 interrupt at 40kHz
  TCCR0A = 0;// set entire TCCR0A register to 0
  TCCR0B = 0;// same for TCCR0B
  TCNT0  = 0;//initialize counter value to 0
  // set compare match register for 40khz increments
  OCR0A = 49;// = (16*10^6) / (40000*8) - 1 (must be <256)
  // turn on CTC mode
  TCCR0A |= (1 << WGM01);
  // Set CS11 bit for 8 prescaler
  TCCR0B |= (1 << CS11);
  // enable timer compare interrupt
  TIMSK0 |= (1 << OCIE0A);
  sei();//enable interrupts
中断功能在这个参数里实现
ISR(TIMER0_COMPA_vect){ //40kHz interrupt routine}

你想让中断程序尽可能短。你可以在loop()做你其他任务(检查按钮,打开灯,等等)。也请记住,设置中断可能会影响其他功能,如使用Arduino的analogwrite和delay的使用。

在下面的代码中,我使用的中断函数在40KHZ发送一个新的正弦sine[ ]值给PORTD,然后增加变量t。图1和图2显示(过滤)示波器上输出的代码。我们可以计算预期的频率如下:

 
frequency = (sampling frequency) / (steps per cycle)
frequency = 40,000 / 100 = 400hz

每一段所用时间为:

duration of each sample step = 1/(sampling frequency)
duration of each sample step = 1/40,000 = 25us

//Sine out w/ 40kHz sampling rate
//by Amanda Ghassaei
//https://www.instructables.com/id/Arduino-Audio-Output/
//Sept 2012


/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
*/


byte sine[] = {127, 134, 142, 150, 158, 166, 173, 181, 188, 195, 201, 207, 213, 219, 224, 229, 234, 238, 241, 245, 247, 250, 251, 252, 253, 254, 253, 252, 251, 250, 247, 245, 241, 238, 234, 229, 224, 219, 213, 207, 201, 195, 188, 181, 173, 166, 158, 150, 142, 134, 127, 119, 111, 103, 95, 87, 80, 72, 65, 58, 52, 46, 40, 34, 29, 24, 19, 15, 12, 8, 6, 3, 2, 1, 0, 0, 0, 1, 2, 3, 6, 8, 12, 15, 19, 24, 29, 34, 40, 46, 52, 58, 65, 72, 80, 87, 95, 103, 111, 119,};
int t = 0;//time


void setup(){
  //set digital pins 0-7 as outputs
  for (int i=0;i<8;i++){
    pinMode(i,OUTPUT);
  }
  
  cli();//disable interrupts
  //set timer0 interrupt at 40kHz
  TCCR0A = 0;// set entire TCCR0A register to 0
  TCCR0B = 0;// same for TCCR0B
  TCNT0  = 0;//initialize counter value to 0
// set compare match register for 40khz increments
  OCR0A = 49;// = (16*10^6) / (40000*8) - 1 (must be <256)
  // turn on CTC mode
  TCCR0A |= (1 << WGM01);
  // Set CS11 bit for 8 prescaler
  TCCR0B |= (1 << CS11); 
  // enable timer compare interrupt
  TIMSK0 |= (1 << OCIE0A);
  sei();//enable interrupts
  
}




ISR(TIMER0_COMPA_vect){ //40kHz interrupt routine
  PORTD = sine[t];//send sine wave to DAC, centered around (127/255)*5 = 2.5V
  t++;//increment t
  if (t > 99){//reset t to zero
    t = 0;
  }
}


void loop(){
  //do other stuff here
}






第十步:其他

该DAC采用一些Arduino的数字引脚,包括一些通常用于串行通信和PWM的引脚,所以这里有一些提示来帮助处理引脚冲突。

如果你想做串口通信:软件序列是一个Arduino库,允许你把任何的Arduino的引脚为串行引脚。通常当你做一个Arduino项目需要串口通信,可以避免使用数字引脚0和1因为他们需要空置来发送串行数据。我喜欢用8位DAC,因为引脚0-7部分均在PORTD上(Arduino的atmel328芯片),这使我能够解决所有问题,在一个单一的代码行。PORTB只有6引脚(数字引脚8-13),还能只有6个引脚(模拟引脚0-5),所以你不能建立这些端口的8位DAC。            

 如果您需要使用PWM引脚,或其他需要使用不同的引脚作为DAC:如果您必须使用的PWM引脚,您可以使用位操作释放引脚3,5,和6,并取代它们与引脚8,12和。说你想把36号PORTD。您可以使用以下行: 

//define variables:
boolean bit3state;
boolean bit5state;
boolean bit6state;


//in your main loop():

bit3state = (36 & B00001000)>>3;//get the third bit of 36
bit5state = (36 & B00100000)>>5;//get the fifth bit of 36
bit6state = (36 & B01000000)>>6;//get the sixth bit of 36


//send data to portd w/o disrupting pins 3, 5, and 6
PORTD |= (36&B10010111);//set high pins high using the number 36 with zeros replacing bits 3, 5, and 6
PORTD &= (36|B01101000);//set low pins low using the number 36 with ones replacing bits 3, 5, and 6

//send data to portb w/o disrupting pins 9, 10, and 11
PORTB |= 0 | (bit3state) | (bit5state<<4) | (bit6state<<5);//set high pins
PORTB &= 255 & ~(1-bit3state) & ~((1-bit5state)<<4) & ~((1-bit6state)<<5);//set low pins

一定要保持这些PORTD和PORTB线相互靠近,你想要的端口D和B口响应时间尽可能地快。

这里是从上一步的代码,可以编辑使它不使用任何PWM引脚。如图1所示,来自DAC的未经过滤的输出有许多由发送数据到端口D和端口B之间的滞后引起的不连续性,以及将引脚设置为高电平和低电平的命令。你可以用低通滤波器消除大部分这些不连续性(图2)。如果您想使用这种技术,您可能会考虑提高截止频率的低通滤波器。如果你想用好这个,你可以发送你的5个最重要的位端口D和你的3个最低有效位到端口B这将减少振幅的一些不连续性,减少噪音的大小。

//Sine out, 40kHz sampling rate, w/o using PWM pins
//by Amanda Ghassaei
//https://www.instructables.com/id/Arduino-Audio-Output/
//Sept 2012

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
*/

byte sine[] = {127, 134, 142, 150, 158, 166, 173, 181, 188, 195, 201, 207, 213, 219, 224, 229, 234, 238, 241, 245, 247, 250, 251, 252, 253, 254, 253, 252, 251, 250, 247, 245, 241, 238, 234, 229, 224, 219, 213, 207, 201, 195, 188, 181, 173, 166, 158, 150, 142, 134, 127, 119, 111, 103, 95, 87, 80, 72, 65, 58, 52, 46, 40, 34, 29, 24, 19, 15, 12, 8, 6, 3, 2, 1, 0, 0, 0, 1, 2, 3, 6, 8, 12, 15, 19, 24, 29, 34, 40, 46, 52, 58, 65, 72, 80, 87, 95, 103, 111, 119,};
int t = 0;//time

boolean bit3state;
boolean bit5state;
boolean bit6state;

void setup(){
  //set digital pins 0-13 as outputs
  for (int i=0;i<14;i++){
    pinMode(i,OUTPUT);
  }
  
  cli();//disable interrupts
  //set timer0 interrupt at 40kHz
  TCCR0A = 0;// set entire TCCR0A register to 0
  TCCR0B = 0;// same for TCCR0B
  TCNT0  = 0;//initialize counter value to 0
  // set compare match register for 40khz increments
  OCR0A = 49;// = (16*10^6) / (40000*8) - 1 (must be <256)
  // turn on CTC mode
  TCCR0A |= (1 << WGM01);
  // Set CS11 bit for 8 prescaler
  TCCR0B |= (1 << CS11); 
  // enable timer compare interrupt
  TIMSK0 |= (1 << OCIE0A);
  sei();//enable interrupts
  
}


ISR(TIMER0_COMPA_vect){ //40kHz interrupt routine
  bit3state = (sine[t] & B00001000)>>3;//get the third bit
  bit5state = (sine[t] & B00100000)>>5;//get the fifth bit
  bit6state = (sine[t] & B01000000)>>6;//get the sixth bit
  PORTD |= (sine[t]&B10010111);//set high pins high
  PORTD &= (sine[t]|B01101000);//set low pins low
  PORTB |= 0 | (bit3state) | (bit5state<<4) | (bit6state<<5);//set high pins
  PORTB &= 255 & ~(1-bit3state) & ~((1-bit5state)<<4) & ~((1-bit6state)<<5);//set low pins
  //PORTD = sine[t];//send sine wave to DAC, centered around (127/255)*5 = 2.5V
  t++;//increment t
  if (t > 99){//reset t to zero
    t = 0;
  }
}

void loop(){
  //do other stuff here
}



如果你的数字信号引脚用完了,可以将模拟信号引脚定义为数字信号引脚

digitalWrite(A0,HIGH);//set pin A0 high
digitalWrite(A0,LOW);//set pin A0 low
digitalRead(A0);//read digital data from pin A0

否则,尝试使用多路复用。如果你需要更多的数字输出,74HC595的允许你把三的Arduino的数字引脚8输出。你甚至可以连接多个75LS595的创造更多的输出引脚。如果你想要的话,你可以在这些芯片上安装一个DAC(虽然需要几行代码来处理它,而且可能会让你慢下来,以获得更高的采样率)。Arduino的网站是个不错的地方,开始学习如何使用595这样的芯片。

             如果你需要更多的数字输入,CD4021B 和74HC165可以将Arduino的3个数字引脚扩展为8输入。再安利一下,如果你想学习怎样使用芯片,Arduino的网站是个不错的地方。

       如果你想mega或其他板:在这个教程中我只讲了Arduino Uno与atmel328。同样的代码可以在有atmel328或atmel168芯片的板子运行。您也可以用mega实现相同的想法。你应该使你的DAC的任何端口有8个可用引脚,在UNO你就可以用这一行代码解决您的DAC地址定义“PORTD =“),唯一有有8个端口引脚是端口D.这张照片表明,mega有几个端口:8号指针的端口:a,b,c,l是显而易见的选择。如果你不关心浪费模拟引脚的问题,您也可以使用端口f或k。 



最后

以上就是伶俐羽毛为你收集整理的Arduino基础学习-声音信号输出的全部内容,希望文章能够帮你解决Arduino基础学习-声音信号输出所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(46)

评论列表共有 0 条评论

立即
投稿
返回
顶部