我正在尝试完成一项任务,要求我使用MSP430微处理器和Launchpad套件制作音乐播放器。我让播放器完全正常工作,但出于某种原因,当我尝试播放某个音符以上时,它会输出快速点击而非音调。
我知道扬声器可以产生更高的音调,所以我相当肯定这是我的软件的问题,可能会产生某种数学错误。这是我的代码(至少是处理笔记的部分):
asm(" .length 10000");
asm(" .width 132");
#include "msp430g2553.h"
//-----------------------
// define the bit mask (within P1) corresponding to output TA0
#define TA0_BIT 0x02
// define the port and location for the button (this is the built in button)
// specific bit for the button
#define BUTTON_BIT 0x04
#define PLUS_BUTTON 0x08 //Defines the "GO FASTER" button to P1.3
#define MINUS_BUTTON 0x10 //Defines the "SLOW DOWN" button to P1.4
#define SHIFT 0x20
//----------------------------------
// Some global variables (mainly to look at in the debugger)
volatile unsigned halfPeriod; // half period count for the timer
volatile unsigned long intcount=0; // number of times the interrupt has occurred
volatile unsigned soundOn=0; // state of sound: 0 or OUTMOD_4 (0x0080)
volatile int noteCount = 0;
volatile int noteLength = 0;
volatile int deltaHP=1; // step in half period per half period
volatile unsigned int plus_on;
volatile unsigned int minus_on;
volatile double speed = 1;
volatile int shiftkey = 0;
static const int noteArray[] = {800, 1000, 900, 800}; //THESE ARE THE NOTES
static const int noteLengths[] = {200, 500, 500, 500};
void init_timer(void); // routine to setup the timer
void init_button(void); // routine to setup the button
// ++++++++++++++++++++++++++
void main(){
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
BCSCTL1 = CALBC1_1MHZ; // 1Mhz calibration for clock
DCOCTL = CALDCO_1MHZ;
//halfPeriod=noteArray[0]; // initial half-period at lowest frequency
init_timer(); // initialize timer
init_button(); // initialize the button
_bis_SR_register(GIE+LPM0_bits);// enable general interrupts and power down CPU
}
// +++++++++++++++++++++++++++
// Sound Production System
void init_timer(){ // initialization and start of timer
TA0CTL |=TACLR; // reset clock
TA0CTL =TASSEL1+ID_0+MC_2; // clock source = SMCLK, clock divider=1, continuous mode,
TA0CCTL0=soundOn+CCIE; // compare mode, outmod=sound, interrupt CCR1 on
TA0CCR0 = TAR+noteArray[0]; // time for first alarm
P1SEL|=TA0_BIT; // connect timer output to pin
P1DIR|=TA0_BIT;
}
// +++++++++++++++++++++++++++
void interrupt sound_handler(){
TACCR0 += (noteArray[noteCount]); // advance 'alarm' time
if (soundOn){ // change half period if the sound is playing
noteLength++;
if (noteLength >= (speed* noteLengths[noteCount])) {
noteLength=0;
noteCount++;
if (noteCount == sizeof(noteArray)/sizeof(int)) {
//halfPeriod += deltaHP;
noteCount = 0;
//deltaHP=-deltaHP;
}
}
}
TA0CCTL0 = CCIE + soundOn; // update control register with current soundOn
++intcount; // advance debug counter
}
ISR_VECTOR(sound_handler,".int09") // declare interrupt vector
目前我只有4个随机音符,有4个随机长度来演示错误。奇怪的咔嗒噪声发生在介于800和900之间的某个值之间。我只是在代码中遗漏了一些会产生小于8xx的数字错误的东西吗?我没有看到任何划分错误或类似的点,但我可能是错的。 谢谢。
另外:我应该注意,当错误发生时,点击持续很长时间,比该音符的相应长度长得多,但它不是永久性的。最终玩家继续前进到下一个音符并正常播放,只要它大于900左右。
答案 0 :(得分:1)
如果中断处理程序执行速度不够快,则下一个事件(TACCR0 += noteArray[...]
)的设置将来得太晚,即在达到该计时器值之后。所以下一个定时器中断不会在800个滴答之后但在2 16 +800滴答之后触发。
您可以尝试优化中断处理程序功能。
特别是,浮点仿真可能需要数百个周期;删除speed
。
但是,不是在软件中切换输出,而应利用硬件功能,并使用PWM功能生成波形:在向上模式下运行定时器,在第二个CCR中使用置位/复位输出模式(参见用户指南的第12.2.5.2节。 (这意味着您只需要定时器中断来启动/停止音符,因此为了适应2 16 限制,您可能希望使用基于更慢时钟的第二个定时器。)