⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lab-02-mucic.c

📁 这写C源代码是MSP430单片机的应用程序
💻 C
字号:
//******************************************************************************
//  MSP430FG4619/F2013 Experimenter's Board - Voice Recorder Demo
//
//  This software demonstrates voice recording and playback using an
//  MSP430FG4619 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
//
//                             MSP430FG4619
//                           ------------------
//                       /|\|               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 MSP430FG4619/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"

#define Memstart             0x6000         // Memory1 起始地址
#define Memend               0xfc00         // Memory1 结束地址
#define Memstart2            0x10000        // Memory2 起始地址
#define Memend2              0x20000        // Memory2 结束地址
#define SamplePrd            118            // 设置录音时间
                                             

#define SEG_A       0x01                    // LCD段码定义
#define SEG_B       0x02
#define SEG_D       0x04
#define SEG_G       0x08
#define SEG_C       0x10
#define SEG_F       0x20
#define SEG_H       0x40
#define SEG_E       0x80

__root unsigned int DMA2CTL_Const_R = DMADSTINCR_3 + DMAEN + DMAIE;
                                            // 单一传输模式 ,目的地址增加
                                            // 边沿触发 使能DMA
__root const unsigned int DMA2CTL_Const_P = DMASRCINCR_3 + DMAEN + DMAIE;
                                            // S单一传输模式 源地址增加
                                            //边沿触发  使能DMA  

void Record(void);
void Playback(void);
void Erase(void);

void main(void)
{
  volatile unsigned int i;
  WDTCTL = WDTPW + WDTHOLD;                 // 关看门狗
  FLL_CTL0 |= XCAP14PF;                     // 设置匹配电容
  do
  {
    IFG1 &= ~OFIFG;                         // 清晶振失效标志位
    for (i = 0x47FF; i > 0; i--);           // 延时
  }
  while (IFG1 & OFIFG);                     // 晶振失效标志位仍存在?

  P1OUT = 0;                                // 所有 P1.x 输出低
  P1IE = 0x03;                              // P1.0, P1.1 中断使能
  P1IES = 0x03;                             // P1.0, P1.1 下降沿触发
  P1DIR = 0xFC;                             // P1.0/1 输入
  P2OUT = 0;                                // 所有 P2.x 输出低
  P2DIR = 0xDF;                             // UCA0RXD  
  P3OUT = 0x20;                             // P3.5 接蜂鸣器
  P3DIR = 0xF9;                             // I2C  
  P4OUT = 0;                                // 所有 P4.x 输出低
  P4DIR = 0xFF;                             // P4.x 输出方向
  P5OUT = 0;                                // 所有 P5.x 输出低
  P5SEL = 0x1C;                             // P5.2/3/4 = LCD COM 
  P5DIR = 0xFF;                             // P5.x 输出方向
  P6OUT = 0;                                // 所有 P6.x 输出低
  P6SEL = 0xBF;                             // P6.6 OA
  P6DIR = 0xFF;                             // P6.x 输出方向
  P7OUT = 0;                                // 所有 P7.x 输出低
  P7DIR = 0xFF;                             // P7.x 输出方向
  P8OUT = 0;                                // 所有 P8.x 输出低
  P8DIR = 0xFF;                             // P8.x 输出方向
  P9OUT = 0;                                // 所有 P9.x 输出低
  P9DIR = 0xFF;                             // P9.x 输出方向
  P10OUT = 0;                               // 所有 P10.x 输出低
  P10DIR = 0xFF;                            // P10.x 输出方向

  for (i = 19; i > 0; i--) LCDMEM[i] = 0;   // 清 LCD
  LCDACTL = LCDON + LCD4MUX + LCDFREQ_128;  // 4mux LCD, ACLK/128
  LCDAPCTL0 = 0x7E;                         // 段 S4-S27

  while (1)                                 
  {
    P1IFG &= ~0x03;                         // 清中断标志
    P1IE |= 0x03;                           // 中断使能
    __bis_SR_register(LPM4_bits + GIE);
    __disable_interrupt();
    if (P1IFG & 0x02)                       // S1按下
      Record();
    else if (P1IFG & 0x01)                  // S2按下
      Playback();
  }
}

void Record(void)
{

  P5OUT |= 0x02;                            // LED4 亮
  P2OUT |= 0x08;                            // 麦克风
  OA0CTL0 = OAP_1 + OAPM_3;                 // 反向输入, fast模式
  OA0CTL1 = OARRIP;                         // 输入信号范围有限
  
  ADC12CTL0 = ADC12ON;                      // 打开 ADC12 
  ADC12CTL1 = SHS_3 + CONSEQ_2;             // Timer_B.OUT1触发,单通道序列采样
  ADC12IFG = 0x00;                          // 清ADC12 中断标志位
  ADC12MCTL0 = 0x0001;                      // 输入通道 A1
  ADC12CTL0 |= ENC;                         // 使能转换
  TBCTL = TBSSEL_2;                         // SMCLK 作为 Timer_B时钟源
  TBR = 0;
  TBCCR0 = SamplePrd;                       // 初始化 TBCCR0
  TBCCR1 = SamplePrd - 20;                  // 触发 ADC12 
  TBCCTL1 = OUTMOD_7;                       // 复位/置位
  DMACTL0 = DMA2TSEL_6 +                    // ADC12IFGx 触发 DMA2
            DMA1TSEL_14 +                   // DMA0IFG 触发 DMA1
            DMA0TSEL_6;                     // ADC12IFGx 触发 DMA0
  DMA0SA = (unsigned int)&ADC12MEM0;        // DMA操作起始地址
  DMA0DA = Memstart;                        // DMA操作结束地址
  DMA0SZ = (Memend - Memstart) >> 1;        // 长度
  DMA0CTL = DMADSTINCR1 + DMADSTINCR0 + DMAEN;
                                            // 单一传输 目的地址增加
                                            // 边沿触发 使能 DMA
  DMA1SA = (unsigned int)&DMA2CTL_Const_R;  // 源地址
  DMA1DA = (unsigned int)&DMA2CTL;          //目的地址
  DMA1SZ = 1;                               // 长度
  DMA1CTL = DMAEN;                          // 单一传输 使能DMA
  DMA2SA = (unsigned int)&ADC12MEM0;        // 源地址
  __data16_write_addr((unsigned short)&DMA2DA, Memstart2);
                                            // 目的地址
  DMA2SZ = (Memend2 - Memstart2) >> 1;       
  FCTL2 = FWKEY + FSSEL1 + FN1;             // 时钟 SMCLK/3 = ~333kHz
  FCTL3 = FWKEY;                            // 写操作
  Erase();                                  // 调用写flash程序
  FCTL1 = FWKEY + WRT;                      // 写flash

  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;                                           // " "

  P1OUT |= 0x01;                            // LED4 亮
  TBCTL |= MC0;                             //  Timer_B 增计数模式
  __bis_SR_register(LPM0_bits + GIE);       // 中断使能 ,进入LPM0
  __disable_interrupt();                    // 关中断
  
  FCTL1 = FWKEY;                            // 结束写flash操作
  FCTL3 = FWKEY + LOCK;                     // 锁flash
  ADC12CTL1 &= ~CONSEQ_2;                   // 立即停止ADC采样
  ADC12CTL0 &= ~ENC;                        // 禁止ADC12转换
  ADC12CTL0 = 0;                            // 关 ADC12 、参考电压
  TBCTL = 0;                                // 关 Timer_B
  OA0CTL0 = 0;                              // 关 OA0

  P2OUT &= ~0x08;                           // 关麦克风
  P5OUT &= ~0x02;                           // LED4 灭
  LCDM8 = 0x00;                             // " "
  LCDM7 = 0x00;                             // " "
  LCDM6 = 0x00;                             // " "
}

void Playback(void)
{
  volatile unsigned int i;
  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_D + SEG_F + SEG_G;          // "Y"
  LCDM4 = 0x00;                                           // " "
  P5OUT |= 0x02;                            // LED4 亮
  DAC12_0CTL = DAC12IR + DAC12AMP_2 + DAC12ENC + DAC12OPS;
  DAC12_0DAT = 0x057F;                  
  OA1CTL0 = OAPM_3 + OAADC1;                // Sfast模式
  OA1CTL1 = OAFC_1 + OARRIP;                // rail-to-rail 输入
  OA2CTL0 = OAN_2 + OAP_2 + OAPM_3 + OAADC1;// Sfast模式  内部DAC0
  OA2CTL1 = OAFC_6 + OAFBR_2 + OARRIP;      // 反向比例放大
  ADC12CTL0 = REFON + REF2_5V;              // ADC12 参考电压2.5V
  DAC12_1CTL = DAC12IR + DAC12AMP_7 + DAC12LSEL_3 + DAC12ENC;
                                            // 设置 DAC12T   imer_B.OUT2
  for (i = 0; i < 0x3fff; i++);             // 等待参考电压稳定
  TBCTL = TBSSEL_2;                         // SMCLK 作为 Timer_B 时钟源
  TBCCR0 = SamplePrd;                       // 初始化 TBCCR0  
  TBCCR2 = SamplePrd >> 1;                  // EQU2 触发 DMA
  TBCCTL2 = OUTMOD_7;                       // 复位/置位
  DMACTL0 = DMA2TSEL_2 +                    // Timer_B.CCIFG2 触发 DMA2
            DMA1TSEL_14 +                   // DMA0IFG 触发 DMA1
            DMA0TSEL_2;                     // Timer_B.CCIFG2 触发 DMA0
  DMA0SA = Memstart;                        // 源地址 
  DMA0DA = (unsigned int)&DAC12_1DAT;       // 目的地址
  DMA0SZ = (Memend - Memstart) >> 1;        // DMA 大小
  DMA0CTL = DMASRCINCR1 + DMASRCINCR0 + DMAEN;
                                            // 单一传输 源地址增加 使能DMA
  DMA1SA = (unsigned int)&DMA2CTL_Const_P;  // 源地址
  DMA1DA = (unsigned int)&DMA2CTL;          // 目的地址
  DMA1SZ = 1;                               // 长度
  DMA1CTL = DMAEN;                          // 使能DMA
  __data16_write_addr((unsigned short)&DMA2SA, Memstart2);
  DMA2DA = (unsigned int)&DAC12_1DAT;         
  DMA2SZ = (Memend2 - Memstart2) >> 1;       
  TBCTL |= MC0;                             // Timer_B 增计数模式
  __bis_SR_register(LPM0_bits + GIE);       // 中断使能 进入 LPM0
  __disable_interrupt();                    // 关中断

  TBCTL = 0;                                // 关 Timer_B
  ADC12CTL0 = 0;                            // 关ADC12  
  DAC12_0CTL &= ~DAC12ENC;                  // 禁止 DAC12 转换
  DAC12_0CTL = 0;                           // 关 DAC12
  DAC12_1CTL &= ~DAC12ENC;                  // 禁止 DAC12 转换
  DAC12_1CTL = 0;                           // 关 DAC12
  OA1CTL0 = 0;                              // 关 OA1
  OA2CTL0 = 0;                              // 关 OA2
  P5OUT &= ~0x02;                           // LED4 灭
  LCDM8 = 0x00;                             // " "
  LCDM7 = 0x00;                             // " "
  LCDM6 = 0x00;                             // " "
  LCDM5 = 0x00;                             // " "
}

void Erase(void)
{
  unsigned int Ptr = Memstart;             
  unsigned long FarPtr = Memstart2;
  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"
  do
  {
    if (Ptr & 0x1000)                       
      P5OUT |= 0x02;
    else
      P5OUT &= ~0x02;
    FCTL1 = FWKEY + ERASE;
    *(unsigned char *)Ptr = 0x00;           // 空写 段擦除                                            
    Ptr += 0x0200;                          //指向下一段
  }
  while (Ptr < Memend);
  do
  {
    if (FarPtr & 0x1000)                  
      P5OUT |= 0x02;
    else
      P5OUT &= ~0x02;

    FCTL1 = FWKEY + ERASE;
    __data20_write_char(FarPtr, 0x00);      //空写 段擦除 
    FarPtr += 0x0200;                       // 指向下一段
  } 
  while (FarPtr < Memend2);
}
 
#pragma vector=PORT1_VECTOR
__interrupt void Port1_ISR (void)
{
  P1IE &= ~0x03;                            // 关中断
  __bic_SR_register_on_exit(LPM4_bits);     //退出低功耗
}

#pragma vector=DMA_VECTOR
__interrupt void DMA_ISR(void)
{
  DMA2CTL &= ~DMAIFG;                       // 清 DMA2 中断标志
  __bic_SR_register_on_exit(LPM0_bits);     // 退出低功耗
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -