Timer Attiny85在定时器中断中使用全局变量
我对Arduino编程相当陌生。然而,我已经编写了一段时间了。我目前正在尝试使用Arduino IDE和Digispark Attiny85开发板为复调钢琴编写代码。为了一次播放多个音符,我使用正弦表和快速PWM。这是我的代码:Timer Attiny85在定时器中断中使用全局变量,timer,arduino,global-variables,interrupt,attiny,Timer,Arduino,Global Variables,Interrupt,Attiny,我对Arduino编程相当陌生。然而,我已经编写了一段时间了。我目前正在尝试使用Arduino IDE和Digispark Attiny85开发板为复调钢琴编写代码。为了一次播放多个音符,我使用正弦表和快速PWM。这是我的代码: int val=1; uint8_t C=0; uint8_t D=0; uint8_t E=0; uint8_t F=0; uint8_t G=0; uint8_t A=0; uint8_t B=0; 静态uint8_t sinu_C[123]={16,16,17,1
int val=1;
uint8_t C=0;
uint8_t D=0;
uint8_t E=0;
uint8_t F=0;
uint8_t G=0;
uint8_t A=0;
uint8_t B=0;
静态uint8_t sinu_C[123]={16,16,17,18,19,20,20,21,22,23,23,24,25,25,26,27,27,28,28,29,29,30,30,30,31,31,31,31,31,31,31,31,31,31,31,31,31,31,30,30,30,29,29,28,28,27,27,26,25,25,24,23,23,22,21,20,20,19,18,17,16,16,15,14,13,12,11,11,10,9,8,8,7,6,6,5,4,4,3,3,2,2,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,2,2,3,3,4,4,5,6,6,7,8,8,9,10,11,11,12,13,14,15,15};
10,19,20,20,20,20,20,20,20,20,20,20,20,20,20,26,26,26,26,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,18,18,17,17,17,17,17,17,17,10,10,10,10,10,10,10,10 10,10,10,10 10,10,10 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,101,1,1,1,2,2,3,3,4,5,6,7,8,8,9,10,11,12,13,14,15};
目前,,20,20,20,20,20,20,20,20,20,20,20,20,20,10,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,7,7,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10 10,10,10,10,10 10,6,7,8,8,9,10,11,12,13,14,15};
1,20,20,20,20,20,20,20,20,20,20,20,20,20,10,10,7,27,27,27,27,27,7,7,77,7,27,27,27,27,27,27,27,28,27,28,7,28,7,28,7,28,28,28,7,28,28,7,28,7,7,28,28,28,7,7 7,7,28,7,7,7 10,28,28,28,28,28,7,7,7,28,7,7,28,28,28,28,28,7 11,12,13,14,15};
静态uint8_t sinu G[82]={16,17,18,19,20,22,23,24,25,26,27,28,28,29,30,30,31,31,31,31,31,31,31,30,31,29,31,30,29,29,28,27,26,25,24,16,15,12,11,10,9,8,7,6,5,4,3,2,2,1,1,0,0,0,29,29,28,28,20,22,22,21,20,20,20,20,17,17,17,16,15,15,11,11,10,9,8,8,7,6,6,5,4,0,0,0,2,0,0,0,2,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0;
静态uint8_t sinu_A[73]={16,17,18,20,21,22,24,25,26,27,28,29,29,30,31,31,31,31,30,32,31,31,31,31,31,31,30,29,28,27,26,25,24,22,21,20,18,17,14,11,10,9,7,6,5,4,3,2,2,1,0,0,0,0,0,0,1,2,2,3,3,4,5,6,10,10,10,11,15,14};
静态uint8_t sinu B[65]={16,17,19,20,22,23,24,26,27,28,29,30,30,31,31,32,31,31,30,30,29,28,27,26,24,22,20,19,17,16,14,12,11,9,8,7,5,4,3,2,1,0,0,0,0,0,1,2,3,4,5,7,8,9,11,15};
行业特殊报告员(计时器公司){
C++;
D++;
E++;
F++;
G++;
A++;
B++;
如果(C>122){
C=0;
}
如果(D>109){
D=0;
}
如果(E>97){
E=0;
}
如果(F>91){
F=0;
}
如果(G>81){
G=0;
}
如果(A>72){
A=0;
}
如果(B>64){
B=0;
}
int值[7]={sin_C[C],sin_D[D],sin_E[E],sin_F[F],sin_G[G],sin_A[A],sin_B[B]};
OCR0A=值[val];
}
无效设置(){
DDRB |=(1使用全局变量是在主程序循环和中断处理程序之间进行数据通信的唯一方法
编写此响应时,我发现您应该真正考虑在正弦表中使用带符号的值。需要签名添加才能使数学正确工作。
这一行:
OCR0A = values[val];
只能产生单声道声音
您正走在正确的道路上:
int values[7] = {sin_C[C],sin_D[D],sin_E[E],sin_F[F],sin_G[G],sin_A[A],sin_B[B]};
不过
因此,是的,另一个全局var应该可以做到这一点:
unsigned char notes_played; // bits 0-7 map C-D notes
在您的ISR中:
ISR(TIMER0_COMPA_vect)
{
//...
int values[7] = {sin_C[C],sin_D[D],sin_E[E],sin_F[F],sin_G[G],sin_A[A],sin_B[B]};
int ocr_value = 0;
for (unsigned char mask = 1, i = 0; mask < 0x80; mask <<= 1, ++i)
{
if (mask & note_played)
ocr_value += (signed char)(values[i] - 16); // hints that using signed values
// in sine tables may be more
// efficient.
}
// need to 'clip' OCR here?
if (ocr_value < -(OCR_RANGE / 2))
ocr_value = -(OCR_RANGE / 2);
if (ocr_value > (OCR_RANGE / 2))
ocr_value = (OCR_RANGE / 2);
OCRA0 = (unsigned char)((ocr_value + OCR_ZERO) & 0xFF);
}
使正弦表尽可能大,中断尽可能快,确实可以在音质上产生很大的差异。在任何人询问之前,我已经尝试添加volatile标记,它不会改变任何东西。
unsigned char notes_played; // bits 0-7 map C-D notes
ISR(TIMER0_COMPA_vect)
{
//...
int values[7] = {sin_C[C],sin_D[D],sin_E[E],sin_F[F],sin_G[G],sin_A[A],sin_B[B]};
int ocr_value = 0;
for (unsigned char mask = 1, i = 0; mask < 0x80; mask <<= 1, ++i)
{
if (mask & note_played)
ocr_value += (signed char)(values[i] - 16); // hints that using signed values
// in sine tables may be more
// efficient.
}
// need to 'clip' OCR here?
if (ocr_value < -(OCR_RANGE / 2))
ocr_value = -(OCR_RANGE / 2);
if (ocr_value > (OCR_RANGE / 2))
ocr_value = (OCR_RANGE / 2);
OCRA0 = (unsigned char)((ocr_value + OCR_ZERO) & 0xFF);
}
static uint8_t sin_B[65] = //... This gets store in data space, which is limited
static const uint8_t sin_B[65] = //... This gets stored on flash, which has plenty of room.