📄 f411_vr.c
字号:
//-----------------------------------------------------------------------------
// 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 + -