📄 voice_recorder.c
字号:
//******************************************************************************
// MSP430FG4618/F2013 Experimenter's Board - Voice Recorder Demo
//
// This software demonstrates voice recording and playback using an
// MSP430FG4618 MCU. Audio is recorded and stored using in-system self-
// programming into Flash memory until the entire device memory is
// filled with audio data. Both recording and playback are implemented
// using the DMA controller - allowing the CPU to be switched off (LPM0)
// during this entire process.
//
// ACLK = 32.768kHz, MCLK = SMCLK = DCO = default FLL = 1.048576MHz
//
// MSP430FG4618
// ------------------
// /|\| XIN|-
// | | | 32kHz
// --|RST XOUT|-
// | |
// Audio Out<--|P6.5/OA2O P5.1|-->LED
// Sallen-Key <--|P6.7/DAC1 |
// Low-Pass Filter <--|P6.3/OA1O S4|--> +-------------+
// Circuitry -->|P6.4/OA1I0 ...|--> | LCD DISPLAY |
// | S25|--> +-------------+
// VCC_Mic<--|P2.3 |
// Microphone -->|P6.0/OA0I0 P1.0|<--SW1 (Record Button)
// Circuitry -->|P6.2/OA0I1 P1.1|<--SW2 (Playback Button)
// <--|P6.1/OA0O |
//
// NOTE: Refer to the MSP430FG4618/F2013 Experimenter's Board schematic
// for details on the external circuitry.
//
// A. Dannenberg
// Texas Instruments Inc.
// Ver 1.00 - October 2006
// Built with IAR Embedded Workbench Version: 3.42A
//******************************************************************************
#include "msp430xG46x.h"
//------------------------------------------------------------------------------
// Voice-recorder memory definitions
//
// Two memory ranges are defined for voice recording. The MSP430FG4618 device
// memory is split into to regions as the device's interrupt vectors are
// located in the middle of the MSP430FG4618 Flash memory and must not be
// overwritten.
//
// ATTN: Care must be taken not to conflict with memory used by the program
// code. Also both addresses need to be integer multipliers of 0x0200
// due to the Flash memory segmenting.
//------------------------------------------------------------------------------
#define Memstart 0x6000 // Memory range to be filled with
#define Memend 0xfc00 // sampled data for voice recorder
#define Memstart2 0x10000 // Memory range to be filled with
#define Memend2 0x20000 // sampled data for voice recorder
#define SamplePrd 118 // Record&playback sample period
// SampleR = 1MHz / SamplePrd
//------------------------------------------------------------------------------
// LCD segment definitions
//------------------------------------------------------------------------------
#define SEG_A 0x01
#define SEG_B 0x02
#define SEG_C 0x04
#define SEG_D 0x08
#define SEG_E 0x40
#define SEG_F 0x10
#define SEG_G 0x20
#define SEG_H 0x80
//------------------------------------------------------------------------------
// The following two variables contain the control register settings for DMA2
// for the record and playback. DMA1 is used to transfer these control register
// values into the control register of DMA2 to start the DMA2 operation.
//
// Note that the value for record is kept in RAM to allow accessing it while
// a Flash write operation is pending. This is not needed for playback.
// Also, the modifier '__root' is used to prevent any compiler optimization.
//------------------------------------------------------------------------------
__root unsigned int DMA2CTL_Const_R = DMADSTINCR_3 + DMAEN + DMAIE;
// Single transfer,
// increment dest. address,
// leave source address unchanged,
// src and dst are words size,
// edge sensitive DMA trigger,
// enable DMA, enable DMA int
__root const unsigned int DMA2CTL_Const_P = DMASRCINCR_3 + DMAEN + DMAIE;
// Single transfer,
// leave dest. address unchanged,
// increment source address,
// src and dst are words size,
// edge sensitive DMA trigger,
// enable DMA, enable DMA int
//------------------------------------------------------------------------------
// Function prototypes
//------------------------------------------------------------------------------
void Record(void);
void Playback(void);
void Erase(void);
//------------------------------------------------------------------------------
void main(void)
{
volatile unsigned int i;
// WDT+ & LFXT1
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
FLL_CTL0 |= XCAP14PF; // Configure load caps
// LFXT1 startup delay
do
{
IFG1 &= ~OFIFG; // Clear OSCFault flag
for (i = 0x47FF; i > 0; i--); // Time for flag to set
}
while (IFG1 & OFIFG); // OSCFault flag still set?
// Ports
P1OUT = 0; // All P1.x reset
P1IE = 0x03; // P1.0, P1.1 Interrupt enabled
P1IES = 0x03; // P1.0, P1.1 hi/low edge
P1DIR = 0xFC; // P1.0/1 = input (switches)
P2OUT = 0; // All P2.x reset
P2DIR = 0xDF; // UCA0RXD = inp
P3OUT = 0x20; // All P3.x reset (3.5 = buzzer)
P3DIR = 0xF9; // I2C pins = inp
P4OUT = 0; // All P4.x reset
P4DIR = 0xFF; // All P4.x outputs
P5OUT = 0; // All P5.x reset
P5SEL = 0x1C; // P5.2/3/4 = LCD COM lines
P5DIR = 0xFF; // All P5.x outputs
P6OUT = 0; // All P6.x reset
P6SEL = 0xBF; // All but P6.6 analog funct.
P6DIR = 0xFF; // All P6.x outputs
P7OUT = 0; // All P7.x reset
P7DIR = 0xFF; // All P7.x outputs
P8OUT = 0; // All P8.x reset
P8DIR = 0xFF; // All P8.x outputs
P9OUT = 0; // All P9.x reset
P9DIR = 0xFF; // All P9.x outputs
P10OUT = 0; // All P10.x reset
P10DIR = 0xFF; // All P10.x outputs
// LCD_A
for (i = 19; i > 0; i--) LCDMEM[i] = 0; // Clear LCD
LCDACTL = LCDON + LCD4MUX + LCDFREQ_128; // 4mux LCD, ACLK/128
LCDAPCTL0 = 0x7E; // Segments 4-27
while (1) // Repeat forever
{
P1IFG &= ~0x03; // Clear pending button interrupts
P1IE |= 0x03; // Enable interrupts for buttons
// Wait for event, hold CPU in low-power mode 4
__bis_SR_register(LPM4_bits + GIE);
__disable_interrupt();
// Process key-press event
if (P1IFG & 0x02) // Record button SW2 pressed?
Record();
else if (P1IFG & 0x01) // Playback button SW1 pressed?
Playback();
}
}
//------------------------------------------------------------------------------
// Record audio data and store into Flash memory using the ADC12 module and
// the integrated DMA controller.
//------------------------------------------------------------------------------
void Record(void)
{
// Power-up external hardware
P5OUT |= 0x02; // LED#4 on
P2OUT |= 0x08; // Mic supply on
// Setup OA0 = Microphone pre-amplifier
// OA0+ = P6.2/OA0I1
// OA0- = P6.0/OA0I0
// OA0OUT = P6.1/OA0O, A1 (internal)
OA0CTL0 = OAP_1 + OAPM_3; // Select inputs, power mode
OA0CTL1 = OARRIP; // General purp., rail-to-rail inp.
// Setup ADC12 module
ADC12CTL0 = ADC12ON; // Turn on ADC12, S&H in sample
// ADC12 Clock=ADC12OSC
ADC12CTL1 = SHS_3 + CONSEQ_2; // S&H src select: Timer_B.OUT1,
// rep. single channel
ADC12IFG = 0x00; // Clear ADC12 interrupt flag reg
ADC12MCTL0 = 0x0001; // Input channel A1
ADC12CTL0 |= ENC; // Enable conversion
// Steps executed for automated ADC12-to-Flash transfer
// everything without CPU intervention
//
// (1) Timer_B.OUT1 triggers ADC12 conversion
// (2) ADC12IFGx triggers DMA transfer
// (3) Goto (1) until DMA0SZ = 0
// Setup Timer_B for recording
TBCTL = TBSSEL_2; // Use SMCLK as Timer_B source
TBR = 0;
TBCCR0 = SamplePrd; // Initialize TBCCR0
TBCCR1 = SamplePrd - 20; // Trigger for ADC12 SC
TBCCTL1 = OUTMOD_7; // Reset OUT1 on EQU1, set on EQU0
// Setup the DMA controller
//
// To allow for recording into the whole device memory without CPU
// interaction, and without overwriting the interrupt vectors, all three
// DMA channels are used in a daisy-chained fashion.
//
// (1) DMA0 fills up one block of MSP430 Flash memory
// (2) After this, DMA1 loads the control register of DMA2
// (3) DMA2 fills another block of MSP430 Flash memory
// Configure DMA triggers first
DMACTL0 = DMA2TSEL_6 + // ADC12IFGx triggers DMA2
DMA1TSEL_14 + // DMA0IFG triggers DMA1
DMA0TSEL_6; // ADC12IFGx triggers DMA0
// Setup DMA0 for recording to first memory block
DMA0SA = (unsigned int)&ADC12MEM0; // Src address = ADC12 module
DMA0DA = Memstart; // Dst address = Flash memory
DMA0SZ = (Memend - Memstart) >> 1; // Size in words
DMA0CTL = DMADSTINCR1 + DMADSTINCR0 + DMAEN;
// Single transfer,
// increment dest. address,
// leave source address unchanged,
// src and dst are words size,
// edge sensitive DMA trigger,
// enable DMA
// Setup DMA1 for activating DMA2
DMA1SA = (unsigned int)&DMA2CTL_Const_R; // 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 recording to second memory block
DMA2SA = (unsigned int)&ADC12MEM0; // Src address = ADC12 module
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -