📄 exercise-7.c
字号:
/* Exercise 7
An extension of the simple voice recorder from exercise 6, to use DMA for the record and replay.
The DMA code is based on the following examples:
fet430_dma_03.c
fet430_dma_07.c
*/
#include <stdint.h>
#include <msp430xG43x.h>
#define AUDIO_MEM_START 0x2000
#define AUDIO_MEM_END 0xFE00
void record(void)
{
long int i;
int16_t *ptr;
/* Set up timer A to kick the ADC at 6.5536kHz, which will be our audio
* sampling rate. */
TAR = 0;
TACCR0 = 5 - 1;
TACCR1 = 5 - 2;
TACCTL0 = 0;
TACCTL1 = OUTMOD_3;
TACTL = TACLR | MC_1 | TASSEL_1;
/* Make the earpiece pins outputs driven to 0, to power the mic */
P6SEL &= ~(BIT5 | BIT3);
P6DIR |= (BIT5 | BIT3);
P6OUT &= ~(BIT5 | BIT3);
/* Set up the mic amp */
/* Input 0 is the mic signal.
* Output goes to the feedback resistor.
* We want a general purpose amp.
* We want DAC1 to bias the +ve input of the amp.
* We want the amp in high performance mode. */
P6SEL |= (BIT1 | BIT0);
OA0CTL0 = OAN_0 | OAP_3 | OAPM_3 | OAADC1;
OA0CTL1 = OAFC_0;
/* Second amplifier stage */
OA1CTL0 = OAN_2 | OAP_3 | OAPM_3 | OAADC0; // -ve=OA1I0, +ve=DAC1
OA1CTL1 = OAFC_6 | OAFBR_4;
/* Must disable conversion while reprogramming the ADC */
ADC12CTL0 &= ~ENC;
ADC12CTL0 = ADC12ON | SHT0_4 | REFON | REF2_5V; // Turn on the ADC12, and set the sampling time
ADC12CTL1 = SHP | SHS_1 | CONSEQ_2; // Use sampling timer, single sample repeating, TA1 trigger
ADC12MCTL0 = INCH_13 | SREF_1; // ref += Vref, channel = A13 = OA1
ADC12IE = 0;
ADC12IFG = 0x00;
/* Configure DAC 1 to provide bias for the mic amplifier */
P6SEL |= BIT7;
DAC12_1CTL = DAC12CALON | DAC12IR | DAC12AMP_7 | DAC12ENC;
DAC12_1DAT = 0x800;
/* Based on example fet430_dma_07.c - getting ADC data to flash
Change the memory address and the transfer length. */
DMA0SA = (int) &ADC12MEM0; // Src address = ADC12 module
DMA0DA = (int) AUDIO_MEM_START; // Dst address = Flash memory
DMA0SZ = (AUDIO_MEM_END - AUDIO_MEM_START) >> 1; // Size in words
DMACTL0 = DMA0TSEL_6; // ADC12IFGx triggers DMA0
DMACTL1 = DMAONFETCH; // Required for proper Flash write
DMA0CTL = DMADSTINCR_3 | DMAIE | DMAEN; // Config
for (ptr = (int16_t *) AUDIO_MEM_START; ptr != (int16_t *) AUDIO_MEM_END; ptr += 0x100)
{
FCTL3 = FWKEY; /* Lock = 0 */
FCTL1 = FWKEY | ERASE;
*ptr = 0; /* Erase flash segment */
FCTL1 = FWKEY; /* Erase, write = 0 */
FCTL3 = FWKEY | LOCK;
}
/* Set the flash clock to a sensible value for the DMA writes to work properly */
FCTL2 = FWKEY | FSSEL_2 | 23; /* Clk src = SMCLK / 24 (~350KHz) */
/* Wait for the mic amp to settle */
for (i = 150000; i > 0; i--)
_NOP();
/* Unlock the flash memory for writing */
FCTL3 = FWKEY;
FCTL1 = FWKEY | WRT;
/* Set the recording off, and wait in LPM0 for it to complete */
_EINT();
P1OUT |= BIT0; /* Turn on the LED */
ADC12CTL0 |= ENC;
_BIS_SR(LPM0_bits);
ADC12CTL0 &= ~ENC;
P1OUT &= ~BIT0; /* Turn off the LED */
/* Lock the flash memory for writing */
FCTL1 = FWKEY;
FCTL3 = FWKEY | LOCK;
_DINT();
}
void play(void)
{
/* Ensure the ADC12 is not running, but is providing the reference
voltage for the DAC12. */
ADC12CTL0 &= ~ENC;
ADC12CTL0 = ADC12ON | REFON | REF2_5V;
ADC12IE = 0;
ADC12CTL0 |= ENC;
/* Set up timer A to kick the DAC at 6.5536kHz, which will be our audio
sampling rate. */
TAR = 0;
TACCR0 = 5 - 1;
TACCR1 = 5 - 2;
TACCTL0 = 0;
TACCTL1 = OUTMOD_3;
TACTL = TACLR | MC_1 | TASSEL_1;
/* Make a differential drive for the earpiece */
P6SEL |= (BIT5 | BIT3);
/* Chain two amps to make an inverting buffer with a gain of one */
OA0CTL0 = OAP_2 | OAPM_3;
OA0CTL1 = OAFC_1;
OA1CTL0 = OAN_2 | OAP_3 | OAPM_3 | OAADC1;
OA1CTL1 = OAFC_6 | OAFBR_2;
/* Use the third amp as a non-inverting buffer with a gain of one */
OA2CTL0 = OAP_2 | OAPM_3 | OAADC1;
OA2CTL1 = OAFC_1;
/* Configure DAC0 to provide the audio signal for the earpiece amp.
The data will be latched by TACCR1 */
DAC12_0CTL = DAC12CALON | DAC12IR | DAC12AMP_7 | DAC12ENC | DAC12LSEL_2;
DAC12_0DAT = 0x800;
/* Configure DAC1 to provide a bias signal for the inverting PGA */
DAC12_1CTL = DAC12CALON | DAC12IR | DAC12AMP_7 | DAC12ENC;
DAC12_1DAT = 0x800;
/* Based on example fet430_dma_03.c - feeding a string to a USART port.
Changed to use TACCR0 instead of TACCR2
Changed to use word-to-word operations
Changed to use the relevant memory and device addresses */
DMA0SA = (int) AUDIO_MEM_START; // Source audio address
DMA0DA = (int) &DAC12_0DAT; // Destination single address
DMA0SZ = (AUDIO_MEM_END - AUDIO_MEM_START) >> 1;
DMACTL0 = DMA0TSEL_7; // TACCR0 is the trigger
DMA0CTL = DMADT_4 | DMASRCINCR_3 | DMASWDW | DMAEN; // Rpt, inc src
/* Don't bother turning on interrupts - we won't get any */
for (;;)
{
_BIS_SR(LPM0_bits);
_NOP();
}
}
void main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
SCFI0 = FN_3 | FLLD_4;
FLL_CTL0 = XCAP18PF; // set load capacitance for xtal
SCFQCTL = 64 - 1; // 256*32768Hz = 8.388608MHz
FLL_CTL0 |= DCOPLUS;
P1DIR = 0xE7; // All P1.x outputs
P1OUT = 0; // All P1.x reset
P2DIR = 0x00; // All P2.x outputs
P2OUT = 0; // All P2.x reset
P3DIR = 0xFF; // All P3.x outputs
P3OUT = 0; // All P3.x reset
P4DIR = 0xFF; // All P4.x outputs
P4OUT = 0; // All P4.x reset
P5DIR = 0xFF; // All P5.x outputs
P5OUT = 0; // All P5.x reset
P6DIR = 0xFF; // All P6.x outputs
P6OUT = 0; // All P6.x reset
/* Configure UART0 */
UCTL0 = CHAR; /* 8-bit character */
UTCTL0 = SSEL1; /* UCLK = SMCLK */
UBR00 = 72; /* 115200 bps, based on the 256*32768Hz clock */
UBR10 = 0;
UMCTL0 = 0x7F;
P2SEL |= (BIT5 | BIT4);
U0ME |= UTXE0; /* Enable only USART0 TXD */
record();
for (;;)
play();
_NOP();
}
#pragma vector=DAC12_DMA_VECTOR
__interrupt void dma_interrupt(void)
{
DMA0CTL &= ~DMAIFG; /* Clear DMA0 interrupt flag */
_BIC_SR_IRQ(LPM0_bits);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -