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

📄 f411_vr.c

📁 用c8051f410和FLASH(SPI接口)实现的数字录音机。
💻 C
📖 第 1 页 / 共 3 页
字号:
//-----------------------------------------------------------------------------
// F411_VR.c
//-----------------------------------------------------------------------------
// Copyright 2006 Silicon Laboratories, Inc.
// http://www.silabs.com
//
// Program Description:
//
// This program uses the DPCM functions to encode voice samples and saves them
// to flash memory.  This program also interfaces with a speaker or headphones
// to play back the recorded voice.
//
// How To Use:    See Readme.txt
//
// FID:            41X000005
// Target:         C8051F411
// Tool chain:     Keil C51 7.50 / Keil EVAL C51
//                 Silicon Laboratories IDE version 2.6
// Project Name:   F411_VR
//
// Release 1.3
//    -All changes by TP
//    -02 Feb 2006
//    -minor changes in comments
//
// Release 1.2
//    -All changes by TP
//    -21 Nov 2005
//    -Revised for a 2-button version of the board with
//       volume wheel.
//
// Release 1.1
//    -All changes by TP
//    -16 Aug 2004
//    -project version updated, no changes to this file
//
// Release 1.0
//    -Initial Revision (TP)
//    -15 AUG 2004
//


//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <c8051f410.h>                 // SFR declarations
#include "F411_VR_DPCM.h"              // contains DPCM functions
#include "F411_VR_SSTFlash.h"          // contains functions to write to the
                                       // serial SST external 512 kb Flash
#include "F411_VR_LED.h"               // contains functions to control the
                                       // intensity of the LEDs

//-----------------------------------------------------------------------------
// 16-bit SFR Definitions for 'F411
//-----------------------------------------------------------------------------

// SFR16 Defintions (Timers, ADC, and DAC)
sfr16 TMR2RL = 0xCA;                   // Timer 2 Reload address
sfr16 TMR2 = 0xCC;                     // Timer 2 Counter address
sfr16 TMR3RL = 0x92;                   // Timer 3 Reload address
sfr16 TMR3 = 0x94;                     // Timer 3 Counter address
sfr16 ADC0DAT = 0xBD;                  // ADC 16-bit address
sfr16 IDA0DAT = 0x96;                  // IDAC 16-bit address

//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------

// General Constants
#define SYSCLK 6125000                 // system clock in Hz (24.5 MHz / 4)

// T1 runs at SYSCLK / 48
#define POLLING 1992                   // poll the switches at 64 Hz
#define PRCHANGE 20000                 // wait approx. 150ms after a button is
                                       // pressed to "debounce" the switches

#define SAMP_FREQ 764                  // use 8kHz sampling for both the ADC
                                       // and DAC

#define MAX_MEM_ADDR 0x0007FFFF        // 512K = 2^19 address bits
#define NEAR_END_ADDR 0x00065F55       // for every 4 samples, 3 bytes are
                                       // written to memory, so 10.67 kHz
                                       // ((8 kHz * 4)/3) writing time = 106666
                                       // addresses every 10 seconds, so give
                                       // about 10 seconds of warning

#define mid_range 2048                 // middle value of 12-bit ADC and DAC

// System States
#define IDLE 0x00                      // indicates no current action
#define RECORDING 0x01                 // indicates the device is recording
#define PLAYING 0x02                   // indicates the device is playing
#define END_MEM 0x04                   // flag used if the end of memory is
                                       // reached
#define ERASED 0x08                    // flag used if memory is erased

// Port Pin Definitions
sbit REC_PLAY = P1^7;
sbit ERASE = P1^6;
sbit TRANS = P1^3;
sbit LED0 = P2^1;
sbit LED1 = P2^0;

sbit SCK = P0^4;
sbit MISO = P0^5;
sbit MOSI = P0^6;
sbit NSS = P0^7;

//-----------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------

unsigned char system_state = IDLE;     // start in idle mode
                                       // bit 3 of the system_state indicates
                                       // if the end of memory has been
                                       // reached
                                       // bit 4 of the system_state indicates
                                       // if the memory has been erased since
                                       // the last action (1 = erased)


// Ending address of the recording in memory
unsigned long rec_end_addr = 0x00000000;

// flags to communicate between the T1 ISR and the ADC/DAC ISRs for various
// termination events
bit ADC_STOP_FLAG = 0;
bit MEM_END_NEAR_FLAG = 0;
bit MEM_END_FLAG = 0;
bit REC_END_FLAG = 0;
bit DAC_STOP_FLAG = 0;
bit ENTER_SUSPEND = 0;

//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------
// System and peripheral initialization functions
void System_Init (void);
void VDDMon_Init (void);
void Port_Init (void);
void ADC0_Init (void);
void DAC0_Init (void);
void PCA_Init (void);
void SPI0_Init (void);
void RTC_Init (void);
void Timer0_Init (int period);
void Timer1_Init (int period);
void Timer2_Init (int period);
void Timer3_Init (int period);
void Recording_Search (void);

// Interrupt service routines
void Timer0_ISR (void);                // LED updates
void Timer1_ISR (void);                // Switch polling
void ADC0_ISR (void);                  // Recording
void Timer3_ISR (void);                // Playback

//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------
void main (void)
{
   unsigned char i;

   // Watchdog timer disabled in VR_STARTUP.A51

   System_Init ();                     // Initialize system clock
   Port_Init ();                       // Initialize crossbar and GPIO
   ADC0_Init ();                       // Initialize ADC0 (microphone)
   DAC0_Init ();                       // Initialize DAC0 (speaker)
   PCA_Init ();                        // Initialize the PCA for 8-bit PWM
                                       // in modules 0, 1, and 2
   SPI0_Init();                        // Initialize the interface to the flash

   RTC_Init ();                        // Stop the RTC from causing a wake-up
                                       // from suspend

   Timer0_Init (LED_PWM);              // Initialize timer 0 to provide a
                                       // 76 Hz interrupt rate for the LEDs

   Timer1_Init (POLLING);              // Initialize timer 1 to provide a
                                       // 64 Hz interrupt rate for the switches

   Timer2_Init (SAMP_FREQ);            // Initialize the timer to provide an
                                       // 8KHz interrupt rate for sampling

   Timer3_Init (SAMP_FREQ);            // Initialize the timer to provide an
                                       // 8KHz interrupt rate for sampling

   EA = 1;                             // enable global interrupts

   SSTFlash_Init ();                   // disable the write protection in the
                                       // external SST flash memory
   Recording_Search ();                // search for a recording already
                                       // present in memory

   TR1 = 1;                            // start polling the switches

   // loop forever
   while (1)
   {
      if (ENTER_SUSPEND == 1)          // check if no interaction has occurred
      {                                // for some time
         // disable everything to save the most power and set everything to a
         // dormant state
         ENTER_SUSPEND = 0;

         TR1 = 0;                      // stop polling the switches

         EA = 0;                       // disable all interrupts

         XBR1 = 0x40;                  // disable the PCA
         XBR0 = 0x00;                  // disable the SPI

         SCK = 0;                      // drive the SPI pins low so the
         MISO = 0;                     // external Flash won't attempt to draw
         MOSI = 0;                     // current while unpowered

         IDA0CN &= ~0x80;              // disable DAC0
         REF0CN &= ~0x01;              // disable VREF

         LED0 = 1;                     // turn the LEDs off
         LED1 = 1;

         TRANS = 1;                    // turn off the external circuitry

         RSTSRC = 0x00;                // disable missing clock detector
         VDM0CN &= ~0x80;              // disable the VDD Monitor

         OSCICN |= 0x20;               // enter suspend mode and wait
                                       // until a port match event occurs

         // re-enable and reinitialize the system
         VDDMon_Init ();

         TRANS = 0;                    // turn on the external circuitry

         REF0CN |= 0x01;               // re-enable VREF
         IDA0CN |= 0x80;               // re-enable DAC0

         XBR0 = 0x02;                  // re-enable SPI
         XBR1 = 0x42;                  // re-enable PCA0_0 and PCA0_1

         // wait 10us until the Flash is ready to receive writes and reads
         for (i = 0; i < 64; i++);

         SSTFlash_Init ();             // re-initialize the SST flash

         EA = 1;                       // enable global interrupts

         // wait until the button that woke the system is released
         while ((REC_PLAY == 0) || (ERASE == 0));

         TR1 = 1;                      // begin polling the buttons again
      }
   }
}

/////////////////////////// INITIALIZATION ROUTINES ///////////////////////////

//-----------------------------------------------------------------------------
// System_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This routine initializes the system clock to use the internal 24.5MHz / 4
// oscillator as its clock source and enables the missing clock detector reset.
// Additionally, this routine sets up VREF, the internal regulator, and the
// VDD monitor.
//
void System_Init (void)
{
   OSCICN = 0x85;                      // configure internal oscillator打开内部24.5M振荡器并实行4分频
   RSTSRC = 0x04;                      // enable missing clock detector.如果丢掉时钟将引起复位

   REF0CN = 0x01;                      // set up and enable VREF pin 输出参考电压参考电压为1.5V

   REG0CN = 0x10;                      // set up and enable 2.5V VDD from the 开启内部VDD电压产生电路并设置电压为2.5V
                                       // internal regulator

   VDDMon_Init ();                     // initialize the VDD Monitor
}

//-----------------------------------------------------------------------------
// VDDMon_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This routine initializes the VDD Monitor and enables it as a reset source.
//
void VDDMon_Init (void)
{
   char i;

   VDM0CN = 0x80;                      // enable the VDD monitor              打开电压产生器
   for (i = 0; i < 80; i++);           // wait for the monitor to stabilize   延时等待初始化完毕(其实这些值都是内部默认的值,没有必要重值)
   RSTSRC = 0x06;                      // enable missing clock detector and   允许时钟出错复位和电源出错复位
                                       // VDD monitor as reset sources
}

//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// P0.0 = DAC0 (analog, skip)
// P0.1-3 = unused (skip)
// P0.4-7 = SPI interface (digital, do not skip)
// P1.0-1 = unused (skip)
// P1.2 = VREF (analog, skip)
// P1.3 = analog power-on transistor (digital, skip)
// P1.4 = unused (skip)
// P1.5 = ADC0 (analog, skip)
// P1.6-7 = REC_PLAY and ERASE switches (digital, skip)
// P2.0-1 = LED PCA outputs (digital, do not skip)
//
void Port_Init (void)
{
   P0MDIN = 0xFE;                      // make switch and SPI pins digital   //选择P0口是作为数字输入还是作为模拟输入
   P0MDOUT = 0xD0;                     // make SPI pins push-pull            //选择p0口是不是有上拉
   P1MDIN = 0xC8;                      // make trans and switches digital    //选择P1口是作为数字输入还是作为模拟输入 
   P1MDOUT = 0x08;                     // make trans pin push-pull           //选择p1口是不是有上拉
   P2MDIN = 0x03;                      // make PCA pins digital
   P2MDOUT = 0x03;                     // make PCA pins push-pull            //选择两个LED的驱动GPIO需要上拉.
   P0SKIP = 0x0F;                      // skip pins not belonging to SPI     //跳跃引脚  1为跳跃第二功能,0为可选择第二功能
   P1SKIP = 0xFF;                      // skip all P1 pins                 
   P2SKIP = 0xFC;                      // skip pins not belonging to LED PCA //将PCA的两个引脚跳开

   XBR0 = 0x02;                        // enable SPI                         //将SPI的信号线连接在IO上
   XBR1 = 0x42;                        // enable PCA0_0 and PCA0_1           //使能跳接开关并将CEX0,CEX1连接在IO口上

   TRANS = 0;                          // turn on the power to all analog    //
                                       // components

   P0MAT = 0x00;                       // the buttons will go low when pressed, //设置引脚中断功能
   P1MAT = 0xC0;                       // causing the port match event
   P0MASK = 0x00;                      // mask off all P0 and P1 pins except
   P1MASK = 0xC0;                      // the switches
   EIE2 = 0x00;                        // disable the port match interrupt
                                       // (not required to wake up the core)
}

//-----------------------------------------------------------------------------
// ADC0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// Configure ADC0 to update with a Timer 2 overflow using P1.5 as its positive
// input in post-tracking mode, enable burst mode, and use a repeat factor of
// 16.
//
void ADC0_Init (void)
{
   ADC0CN = 0x43;                      // ADC in low-power burst mode, use T2
                                       // overflow, right justify
   ADC0MX = 0x0D;                      // use P1.5 as the positive reference
   // set the ADC conversion about 5 MHz and use a repeat factor
   // of 16
   ADC0CF = (4 << 3) | (3 << 1);
   ADC0TK = 0xF4;                      // use post-tracking mode
   EIE1 |= 0x08;                       // enable the ADC conversion complete
                                       // interrupt
   EIP1 |= 0x08;                       // set the ADC convertion complete
                                       // interrupt to high priority
}

//-----------------------------------------------------------------------------
// DAC0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// Configure DAC0 to be right justified, update with a Timer 3 overflow, and
// use a full-scale 2 mA output current.
//
void DAC0_Init (void)
{
   IDA0CN = 0x70;                      // set the IDAC to update on a write
                                       // to IDA0DAT (initially only)
   IDA0CN |= 0x00;                     // set the IDAC to use a 0.25 mA current.
   IDA0CN |= 0x04;                     // set the IDAC to be right-justified
   IDA0CN |= 0x80;                     // enable the IDAC

   IDA0L = 0x00;                       // initialize the IDAC to be mid-scale
   IDA0H = 0x08;

   IDA0CN &= ~0x70;                    // set the IDAC to update on T3 overflow,
   IDA0CN |= 0x33;                     // and use a 2 mA full-scale current
}

⌨️ 快捷键说明

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