📄 msp430f2012playbackwav.c
字号:
//******************************************************************************
// MSP430F2012PlaybackWAV.c - This software is designed for eZ430-Speech
// hardware for audio Playback using PWM and
// external SPI-Flash
//
// MSP430F20xx
// -----------------
// /|\| |
// | | |
// --|RST |
// | |
// | TA1/TXD/P1.2|--------> PWM voice output
// | |
// | |
// | P1.0|---->/HOLD M25P64
// | |
// | P1.3|---->/S (Chip Select) M25P64
// | |
// | P1.5/SCLK|-------->
// | P1.6/SDO|--------> SPI master
// | P1.7/SDI|<--------
// | |
// | P1.0|--------> LED
// | |
// | P1.4|<-------- button
// | |
//
//
// P. Forstner
// Texas Instruments Inc.
// January 2009
// Built with IAR Embedded Workbench Version: v4.11
// Built with CCE Version: 3.1 Build 3.2.3.6.4
//******************************************************************************
#define SCLK 0x20 // SCLK on P1.5
#define SDO 0x40 // SDO on P1.6
#define SDI 0x80 // SDO on P1.7
#define FlashSelPOUT P1OUT
#define FlashSelPDIR P1DIR
#define FlashSelBIT BIT3 // P1.3 is M25P64 SELECT
#define LEDPOUT P1OUT
#define LEDPDIR P1DIR
#define LEDBIT BIT0 // LED indicator
#define ButtonPIN P1IN
#define ButtonPOUT P1OUT
#define ButtonPDIR P1DIR
#define ButtonPIFG P1IFG
#define ButtonPIES P1IES
#define ButtonPIE P1IE
#define ButtonPSEL P1SEL
#define ButtonPREN P1REN
#define ButtonBIT BIT4 // P1.4 is button input
#define PWM_POUT P1OUT
#define PWM_PDIR P1DIR
#define PWM_PSEL P1SEL
#define PWM_BIT BIT2
unsigned char TXDataUSI;
unsigned char RXDataUSI;
unsigned char USIcompleteRX;
unsigned int uAvgCntr;
unsigned int uAudioSample1;
unsigned int uAudioSample2;
int iAudioSampleDifference;
unsigned long lAudioSampleCnt;
unsigned long lAudioSampleLength;
unsigned char AudioFileNr;
void TX_USI (void);
#include <msp430x20x2.h>
void main (void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
__bis_SR_register(OSCOFF); // Turn LFXT1 off
P2SEL &= ~(BIT6 | BIT7); // LFXT1 pins are GPIOs
P2DIR |= BIT6 | BIT7; // LFXT1 GPIOs are outputs for low power!
// Control signals of external Flash
FlashSelPOUT |= FlashSelBIT;
FlashSelPDIR |= FlashSelBIT; // SPI-Flash SELECT = HIGH
LEDPOUT &= ~LEDBIT;
LEDPDIR |= LEDBIT; // LED turned off
ButtonPDIR &= ~ButtonBIT;
ButtonPOUT |= ButtonBIT;
ButtonPREN |= ButtonBIT; // Button input with pull-up
ButtonPIES |= ButtonBIT; // Interrupt on rising edge
ButtonPIE &= ~ButtonBIT; // Interrupt on rising edge
// Initialize Timer_A for PWM output
TACTL = TASSEL_2 | ID_1 | TACLR; // clock = SMCLK /2 = 16 MHz / 2
// overflow interrupt enabled
TACCTL1 = CM_0 | OUTMOD_0 | CCIE; // CM_0: Compare mode (no capture mode)
// OUTMOD_0 & BIT=0 : output=0
// CCIE: Compare Interrupt Enabled
TACCR0 = 0xFF; // 8-bit counter from 00h to FFh
// Initialize SPI master with USI
USICTL0 |= USIPE7 + USIPE6 + USIPE5 + USIMST + USIOE; // Init I/Os, SPI master
USICTL1 |= USICKPH; // sample on rising edge
USICKCTL = USIDIV_2 + USISSEL_2; // USICLK = SMCLK / 4 = 4MHz
USICTL0 &= ~USISWRST; // USI released for operation
USIcompleteRX = 0; // No RX transmission result
__delay_cycles(40000); // Time for VCC to rise to 3.3V
if ((CALDCO_16MHZ == 0xFF) || (CALBC1_16MHZ == 0xFF))
{
while(1) // Blink LED if calibration data
{ // missing
LEDPOUT ^= LEDBIT; // Toggle LED
__delay_cycles(60000);
}
}
DCOCTL = CALDCO_16MHZ; // DCO = 16MHz calibrated
BCSCTL1 = CALBC1_16MHZ; // DCO = 16MHz calibrated
__bis_SR_register(GIE); // Enable Interupts GIE
FlashSelPOUT &= ~FlashSelBIT; // SPI-Flash SELECT = LOW
TXDataUSI = 0x9F; // 0x9F: read ID
TX_USI(); // send TXDataUSI through SPI
while (USIcompleteRX == 0);
TXDataUSI = 0x00; // 0x9F: read ID
TX_USI(); // send TXDataUSI through SPI
while (USIcompleteRX == 0);
TX_USI(); // send TXDataUSI through SPI
while (USIcompleteRX == 0);
TX_USI(); // send TXDataUSI through SPI
while (USIcompleteRX == 0);
FlashSelPOUT |= FlashSelBIT; // SPI-Flash SELECT = HIGH
__delay_cycles(40000); // keep SEL a minimum time low
// Mainloop
AudioFileNr = 0;
while (1)
{
LEDPOUT |= LEDBIT; // LED turned on
FlashSelPOUT &= ~FlashSelBIT; // SPI-Flash SELECT = LOW
TXDataUSI = 0xAB; // 0x0AB: release from Deep Power-Down
TX_USI(); // send instruction 0x03
FlashSelPOUT |= FlashSelBIT; // SPI-Flash SELECT = HIGH
__delay_cycles(2500); // keep SEL a minimum time HIGH
FlashSelPOUT &= ~FlashSelBIT; // SPI-Flash SELECT = LOW
TXDataUSI = 0x03; // 0x03: read data bytes
TX_USI(); // send instruction 0x03
while (USIcompleteRX == 0);
TXDataUSI = AudioFileNr; // SPI-Flash start addr = 0xNR0000
TX_USI(); // send address byte 1
while (USIcompleteRX == 0);
TXDataUSI = 0x00; // SPI-Flash start addr = 0xNR0000
TX_USI(); // send address byte 2
while (USIcompleteRX == 0);
TX_USI(); // send address byte 3
while (USIcompleteRX == 0);
TX_USI(); // send dummy byte to receive data
while (USIcompleteRX == 0);
TX_USI(); // receive: size byte 0
*(((char*)(&lAudioSampleLength))+0) = RXDataUSI;
while (USIcompleteRX == 0);
TX_USI(); // receive: size byte 1
*(((char*)(&lAudioSampleLength))+1) = RXDataUSI;
while (USIcompleteRX == 0);
TX_USI(); // receive: size byte 2
*(((char*)(&lAudioSampleLength))+2) = RXDataUSI;
while (USIcompleteRX == 0);
TX_USI(); // receive: size byte 3
*(((char*)(&lAudioSampleLength))+3) = RXDataUSI;
while (USIcompleteRX == 0);
TX_USI(); // receive: first audio sample
while (USIcompleteRX == 0);
uAudioSample1 = RXDataUSI;
TX_USI(); // receive: second audio sample
while (USIcompleteRX == 0);
uAudioSample2 = RXDataUSI;
TACCTL1 &= ~(OUTMOD_7 | OUT); // PWM output = LOW
PWM_PDIR |= PWM_BIT; // P1.2/TA1/A2 is output
PWM_PSEL |= PWM_BIT; // P1.2/TA1/A2 is TA1 output
TACCTL1 |= OUTMOD_7; // outpode = RESET/SET
uAvgCntr = 0;
TACTL |= MC_1; // Start Timer_A in "up-mode"
for (lAudioSampleCnt = lAudioSampleLength-1; lAudioSampleCnt > 0; lAudioSampleCnt--)
{
__bis_SR_register(LPM0_bits + GIE); // LPM0: keep DCO running
TX_USI(); // receive: next audio sample
while (USIcompleteRX == 0);
uAudioSample1 = uAudioSample2;
uAudioSample2 = RXDataUSI;
}
TACTL &= ~MC_0; // Stop Timer_A
TACCTL1 &= ~(OUTMOD_7 | OUT); // PWM output = LOW
PWM_POUT &= ~PWM_BIT; // PWM GPIO-Pin = LOW
PWM_PDIR &= ~PWM_BIT; // P1.2/TA1/A2 is input
PWM_PSEL &= ~PWM_BIT; // P1.2/TA1/A2 is P1.2 input
FlashSelPOUT |= FlashSelBIT; // SPI-Flash SELECT = HIGH
FlashSelPOUT &= ~FlashSelBIT; // SPI-Flash SELECT = LOW
TXDataUSI = 0xB9; // 0xB9: go to Deep Power-Down
TX_USI(); // send instruction 0xB9
FlashSelPOUT |= FlashSelBIT; // SPI-Flash SELECT = HIGH
__delay_cycles(2500); // keep SEL a minimum time HIGH
AudioFileNr++; // point to next Audio File
AudioFileNr &= 0x03; // AudioFileNr Modulo 4
LEDPOUT &= ~LEDBIT; // LED turned off
ButtonPIFG &= ~ButtonBIT; // Clear pending button Interrupt
ButtonPIE |= ButtonBIT; // Enable button S1 Interrupts
__bis_SR_register(LPM4_bits + GIE); // LPM4: turn off
// and wait until putton pressed
}
}
//******************************************************************************
// Transmit byte with USI in SPI mode
//******************************************************************************
void TX_USI (void)
{
USISRL = TXDataUSI; // init-load data
USIcompleteRX = 0; // indicate transmission in progress
USICNT = 8; // init-load counter
USICTL1 |= USIIE; // Counter interrupt, flag remains set
}
//******************************************************************************
// Timer A1 interrupt service routine
//******************************************************************************
#pragma vector=TIMERA1_VECTOR
__interrupt void Timer_A1_ISR (void)
{ // Timer interupt (PWM, one sample)
switch (__even_in_range(TAIV,10))
{
case 2: // Vector 2: TACCR1
iAudioSampleDifference = (int) uAudioSample2 - (int) uAudioSample1;
if (iAudioSampleDifference > 68)
{
TACTL &= ~TAIFG; // clear overflow flag TAIFG IFG
TACTL |= TAIE; // enable overflow interrupt TAIFG
TACCTL1 &= ~CCIE; // turn off TACCR1 IFG
}
switch (__even_in_range(uAvgCntr,6))
{
case 0: TACCR1 = (uAudioSample1
+ uAudioSample1
+ uAudioSample1
+ uAudioSample2) >> 2;
break;
case 2: TACCR1 = (uAudioSample1
+ uAudioSample2) >> 1;
break;
case 4: TACCR1 = (uAudioSample1
+ uAudioSample2
+ uAudioSample2
+ uAudioSample2) >> 2;
break;
case 6: TACCR1 = uAudioSample2;
__bic_SR_register_on_exit(LPM4_bits);
// Clear all LPM bits from 0(SR)
// this restarts audio output loop
// and read next audio sample from
// SPI-Flash memory
break;
}
uAvgCntr+=2; // increment averaging counter (always by 2)
uAvgCntr = uAvgCntr & 0x06; // averaging counter range: 0, 2, 4, 6
break;
case 4: // Vector 4: TACCR2
break;
case 10: // Vector 10: TAIFG Flag
TACCTL1 &= ~CCIFG; // clear TACCR1 IFG
TACCTL1 |= CCIE; // enable TACCR1 IFG
TACTL &= ~TAIE; // turn off overflow interrupt TAIFG
break;
}
} // __interrupt void TimerA1 (void)
//******************************************************************************
// USI interrupt service routine
//******************************************************************************
#pragma vector=USI_VECTOR
__interrupt void universal_serial_interface(void)
{
USICTL1 &= ~USIIE; // Disable USI interrupts
RXDataUSI = USISRL; // store received data
USIcompleteRX = 1; // RX transmission result available
}
//******************************************************************************
// P1 interrupt service routine
//******************************************************************************
#pragma vector=PORT1_VECTOR
__interrupt void Port1 (void)
{
P1IFG = 0x00; // reset all interupt flags
ButtonPIE &= ~ButtonBIT; // Disable button S1
__bic_SR_register_on_exit(LPM4_bits); // Clear all LPM bits from 0(SR)
// this restarts main loop and
// starts next audio playback
__no_operation();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -