📄 voice_recorder.c
字号:
__data16_write_addr((unsigned short)&DMA2DA, Memstart2);
// Dst address = Flash memory,
// Use intrinsic to ensure single-
// access to control register
DMA2SZ = (Memend2 - Memstart2) >> 1; // Size in words
// Setup and erase Flash memory
// (Rem.: This time is also used to wait for
// the voltages getting stabilized)
FCTL2 = FWKEY + FSSEL1 + FN1; // SMCLK/3 = ~333kHz
FCTL3 = FWKEY; // Unlock Flash memory for write
Erase(); // Call Flash erase subroutine
FCTL1 = FWKEY + WRT; // Enable Flash write for recording
// Update LCD
LCDM8 = SEG_A + SEG_B + SEG_C + SEG_E + SEG_F + SEG_G; // "R"
LCDM7 = SEG_A + SEG_D + SEG_E + SEG_F + SEG_G; // "E"
LCDM6 = SEG_A + SEG_D + SEG_E + SEG_F; // "C"
LCDM5 = 0x00; // " "
LCDM4 = 0x00; // " "
// Start recording
P1OUT |= 0x01; // LED#4 on
TBCTL |= MC0; // Start Timer_B in UP mode
// (counts up to TBCL0)
// Activate LPM during DMA recording, wake-up when finished
__bis_SR_register(LPM0_bits + GIE); // Enable interrupts, enter LPM0
__disable_interrupt(); // Disable interrupts
// Deactivate Flash memory write access
FCTL1 = FWKEY; // Disable Flash write
FCTL3 = FWKEY + LOCK; // Lock Flash memory
// Power-down MSP430 modules
ADC12CTL1 &= ~CONSEQ_2; // Stop conversion immediately
ADC12CTL0 &= ~ENC; // disable ADC12 conversion
ADC12CTL0 = 0; // Switch off ADC12 & ref voltage
TBCTL = 0; // Disable Timer_B
OA0CTL0 = 0; // Disable OA0
P2OUT &= ~0x08; // Mic supply off
P5OUT &= ~0x02; // LED#4 off
// Update LCD
LCDM8 = 0x00; // " "
LCDM7 = 0x00; // " "
LCDM6 = 0x00; // " "
}
//------------------------------------------------------------------------------
// Playback audio data stored in Flash memory using the integrated
// DMA controller and DAC12 module.
//------------------------------------------------------------------------------
void Playback(void)
{
volatile unsigned int i;
// Update LCD
LCDM8 = SEG_A + SEG_B + SEG_E + SEG_F + SEG_G; // "P"
LCDM7 = SEG_D + SEG_E + SEG_F; // "L"
LCDM6 = SEG_A + SEG_B + SEG_C + SEG_E + SEG_F + SEG_G; // "A"
LCDM5 = SEG_B + SEG_C + SEG_F + SEG_G; // "Y"
LCDM4 = 0x00; // " "
// Power-up external hardware
P5OUT |= 0x02; // LED#4 on
// Setup DAC12_0 = Offset for OA2 gain state
DAC12_0CTL = DAC12IR + DAC12AMP_2 + DAC12ENC + DAC12OPS;
DAC12_0DAT = 0x057F; // Offset level
// Setup OA1 = S-K Output filter for DAC12_1
// OA1+ = P6.4/OA1I0
// OA1- = R_Bottom (internal)
// OA1OUT = P6.3/A3/OA1O, R_Bottom (internal)
OA1CTL0 = OAPM_3 + OAADC1; // Select inputs, power mode
OA1CTL1 = OAFC_1 + OARRIP; // Unity Gain, rail-to-rail inputs
// Setup OA2 = Gain stage
// OA2+ = DAC12_0OUT
// OA2- = OA1OUT
// OA2OUT = P6.5/OA2O
OA2CTL0 = OAN_2 + OAP_2 + OAPM_3 + OAADC1;// Select inputs, power mode
OA2CTL1 = OAFC_6 + OAFBR_2 + OARRIP; // Invert. PGA, OAFBRx sets gain
// Setup DAC12_1 module
ADC12CTL0 = REFON + REF2_5V; // ADC12 ref needed for DAC12s
DAC12_1CTL = DAC12IR + DAC12AMP_7 + DAC12LSEL_3 + DAC12ENC;
// Configure DAC12
// latch data on pos. Timer_B.OUT2
for (i = 0; i < 0x3fff; i++); // Wait until voltages have stab.
// Steps executed for automated Flash-to-DAC12 transfer
// everything without CPU intervention
//
// (1) Timer_B.CCIFG2 triggers DMA transfer
// (2) Timer_B.OUT2 triggers DAC12 data latch
// (3) Goto (1) until DMA0SZ = 0
// Setup Timer_B for playback
TBCTL = TBSSEL_2; // Use SMCLK as Timer_B source
TBCCR0 = SamplePrd; // Initialize TBCCR0 w/ sample prd
TBCCR2 = SamplePrd >> 1; // EQU2 will trigger DMA
TBCCTL2 = OUTMOD_7; // Reset OUT2 on EQU2, set on EQU0
// Setup the DMA controller
//
// To allow for playback from the whole device memory without CPU
// interaction, all three DMA channels are used in a daisy-chained fashion.
//
// (1) DMA0 reads one block of MSP430 Flash memory
// (2) After this, DMA1 loads the control register of DMA2
// (3) DMA2 reads another block of MSP430 Flash memory
// Configure DMA triggers first
DMACTL0 = DMA2TSEL_2 + // Timer_B.CCIFG2 triggers DMA2
DMA1TSEL_14 + // DMA0IFG triggers DMA1
DMA0TSEL_2; // Timer_B.CCIFG2 triggers DMA0
// Setup DMA0 for playback from first memory block
DMA0SA = Memstart; // Src address = Flash memory
DMA0DA = (unsigned int)&DAC12_1DAT; // Dst address = DAC12 module
DMA0SZ = (Memend - Memstart) >> 1; // DMA block size
DMA0CTL = DMASRCINCR1 + DMASRCINCR0 + DMAEN;
// Single transfer,
// increment source address,
// leave dest. address unchanged,
// src and dst are words size,
// edge sensitive DMA trigger,
// enable DMA
// Setup DMA1 for activating DMA2
DMA1SA = (unsigned int)&DMA2CTL_Const_P; // Src address = contents to load
DMA1DA = (unsigned int)&DMA2CTL; // Dst address = into DMA2CTL
DMA1SZ = 1; // 1 Transfer
DMA1CTL = DMAEN; // Single transfer, enable DMA
// Setup DMA2 for playback from second memory block
__data16_write_addr((unsigned short)&DMA2SA, Memstart2);
// Src address = Flash memory
// Use intrinsic to ensure single-
// access to control register
DMA2DA = (unsigned int)&DAC12_1DAT; // Dst address = DAC12 module
DMA2SZ = (Memend2 - Memstart2) >> 1; // DMA block size
// Start playback
TBCTL |= MC0; // Start Timer_B in UP mode
// (counts up to TBCCR0)
// Activate LPM during DMA playback, wake-up when finished
__bis_SR_register(LPM0_bits + GIE); // Enable interrupts, enter LPM0
__disable_interrupt(); // Disable interrupts
// Power-down MSP430 modules
TBCTL = 0; // Disable Timer_B
ADC12CTL0 = 0; // Switch off ADC12 ref voltage
DAC12_0CTL &= ~DAC12ENC; // Disable DAC12 conversion
DAC12_0CTL = 0; // Switch off DAC12
DAC12_1CTL &= ~DAC12ENC; // Disable DAC12 conversion
DAC12_1CTL = 0; // Switch off DAC12
OA1CTL0 = 0; // Disable OA1
OA2CTL0 = 0; // Disable OA2
P5OUT &= ~0x02; // LED#4 off
// Update LCD
LCDM8 = 0x00; // " "
LCDM7 = 0x00; // " "
LCDM6 = 0x00; // " "
LCDM5 = 0x00; // " "
}
//------------------------------------------------------------------------------
// Erase Flash memory for new recording
//------------------------------------------------------------------------------
void Erase(void)
{
unsigned int Ptr = Memstart; // Start of record memory array
unsigned long FarPtr = Memstart2;
// Update LCD
LCDM8 = SEG_A + SEG_D + SEG_E + SEG_F + SEG_G; // "E"
LCDM7 = SEG_E + SEG_G; // "R"
LCDM6 = SEG_A + SEG_B + SEG_C + SEG_E + SEG_F + SEG_G; // "A"
LCDM5 = SEG_A + SEG_C + SEG_D + SEG_F + SEG_G; // "S"
LCDM4 = SEG_A + SEG_D + SEG_E + SEG_F + SEG_G; // "E"
// Erase memory block from 'Memstart' to 'Memend'
do
{
if (Ptr & 0x1000) // Use bit 12 to toggle LED#4
P5OUT |= 0x02;
else
P5OUT &= ~0x02;
FCTL1 = FWKEY + ERASE;
*(unsigned char *)Ptr = 0x00; // Dummy write to activate
// segment erase
Ptr += 0x0200; // Point to next segment
} while (Ptr < Memend);
// Erase memory block from 'Memstart2' to 'Memend2'
do
{
if (FarPtr & 0x1000) // Use bit 12 to toggle LED#4
P5OUT |= 0x02;
else
P5OUT &= ~0x02;
FCTL1 = FWKEY + ERASE;
__data20_write_char(FarPtr, 0x00); // Dummy write to activate
// segment erase
FarPtr += 0x0200; // Point to next segment
} while (FarPtr < Memend2);
}
//------------------------------------------------------------------------------
// PORT1 interrupt handler
//------------------------------------------------------------------------------
#pragma vector=PORT1_VECTOR
__interrupt void Port1_ISR (void)
{
P1IE &= ~0x03; // Disable button interrupts
__bic_SR_register_on_exit(LPM4_bits); // Exit LPM4 on reti to
// Activate voice recorder
}
//------------------------------------------------------------------------------
// DMA interrupt handler
//------------------------------------------------------------------------------
#pragma vector=DMA_VECTOR
__interrupt void DMA_ISR(void)
{
DMA2CTL &= ~DMAIFG; // Clear DMA2 interrupt flag
__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0 on reti
}
//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -