📄 f411_vr.c
字号:
//-----------------------------------------------------------------------------
// PCA_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configure PCA0 modules 0 and 1 to 8-bit PWM mode using the system clock.
//
void PCA_Init (void)
{
PCA0MD = 0x88; // set PCA to use system clock, disable
// idle mode
// PCA0 (for LED1)
PCA0CPM0 = 0x42; // set PCA0 for 8-bit PWM mode
PCA0CPH0 = 0x00; // set LED to off originally
// PCA1 (for LED0)
PCA0CPM1 = 0x42; // set PCA1 for 8-bit PWM mode
PCA0CPH1 = 0x00; // set LED to off originally
// add another PCA module for another LED here, if desired
PCA0CN = 0x40; // turn on the PCA timer/counter
}
//-----------------------------------------------------------------------------
// SPI0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configure the SPI to run in 4-wire master mode at SYSCLK / 4 (1.53 MHz)
// using clock phase 0 and clock polarity 0 to interface with the SST Flash
// memory.
//
void SPI0_Init (void)
{
SPI0CFG = 0x40; // set the master mode, polarity and
// phase
// set the SPI frequency to SYSCLK / 2*(1+1) = SYSCLK / 4
SPI0CKR = 0x01;
SPI0CN = 0x0C; // clear flags, turn off NSS
// set the 4-wire mode
SPIEN = 1; // enable the SPI
}
//-----------------------------------------------------------------------------
// Timer0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters :
// 1) int period - number of timer counts to generate the desired period
// range is postive range of integer: 0 to 32767
//
// Configure Timer0 to 16-bit mode. Timer0 is used to control the load
// time of the PCA PCA0CPHn registers, which changes the PWM intensity of the
// LEDs.
//
// The input parameter can be calculated as follows:
// (Oscillator (Hz) / 4) / Desired_Freq (Hz) = Timer Ticks
//
void Timer0_Init (int period)
{
TMOD |= 0x01; // set Timer 0 to mode 1 (16 bit)
CKCON |= 0x04; // use the system clock
ET0 = 1; // enable Timer 0 interrupts
PT0 = 1; // set Timer 0 interrupts to high
// priority (has to interrupt T1)
TL0 = (-period) & 0x00FF; // set the desired period
TH0 = ((-period) & 0xFF00) >> 8;
TR0 = 0; // keep Timer 0 off (LED
// functions will turn it on)
}
//-----------------------------------------------------------------------------
// Timer1_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters :
// 1) int period - number of timer counts to generate the desired period
// range is postive range of integer: 0 to 32767
//
// Configure Timer1 to 16-bit mode. Timer1 controls the switch polling.
//
// To calculate:
// (Oscillator (Hz) / 4) / 48 / Desired_Freq (Hz) = Timer Ticks
//
// NOTE - the extra 48 in this equation is present because of the settings
// in CKCON.
//
void Timer1_Init (int period)
{
TMOD |= 0x10; // set Timer 1 to mode 1 (16 bit)
CKCON |= 0x02; // use the system clock / 48
ET1 = 1; // enable Timer 1 interrupts
TL1 = (-period) & 0x00FF; // set the desired period
TH1 = ((-period) & 0xFF00) >> 8;
TR1 = 0; // keep Timer 1 off until needed
}
//-----------------------------------------------------------------------------
// Timer2_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters :
// 1) int period - number of timer counts to generate the desired period
// range is postive range of integer: 0 to 32767
//
// Configure Timer2 to 16-bit auto reload mode. Timer2 controls the ADC0
// start-of-conversion rate.
//
// To calculate:
// (Oscillator (Hz) / 4) / Desired_Freq (Hz) = Timer Ticks
//
void Timer2_Init (int period)
{
CKCON |= 0x10; // use the system clock
TMR2CN = 0x00; // 16-bit auto-reload mode
ET2 = 0; // disable T2 interrupts (use ADC
// conversion complete interrupt)
TMR2RL = -period; // set the desired period
TMR2 = -period; // initialize the timer
TR2 = 0; // keep Timer 2 off until the RECORD
// function is used
}
//-----------------------------------------------------------------------------
// Timer3_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters :
// 1) int period - number of timer counts to generate the desired period
// range is postive range of integer: 0 to 32767
//
// Configure Timer3 to 16-bit auto reload mode. Timer3 controls the DAC output
// rate.
//
// To calculate:
// (Oscillator (Hz) / 4) / Desired_Freq (Hz) = Timer Ticks
//
void Timer3_Init (int period)
{
CKCON |= 0x40; // use the system clock
TMR3CN = 0x00; // 16-bit auto-reload mode
EIE1 |= 0x80; // enable Timer 3 interrupts
EIP1 |= 0x80; // set Timer 3 interrupts to high
// priority
TMR3RL = -period; // set the desired period
TMR3 = -period; // initialize the timer
TMR3CN = 0x00; // keep Timer 3 off until the PLAY
// function is used
}
//-----------------------------------------------------------------------------
// RTC_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Enable the RTC so it doesn't cause a wake-up from suspend mode.
//
void RTC_Init (void)
{
RTC0KEY = 0xA5; // unlock the RTC interface
RTC0KEY = 0xF1;
RTC0ADR = 0x06; // point to RTC0CN
RTC0DAT = 0x80; // enable the RTC
}
//-----------------------------------------------------------------------------
// Recording_Search
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Search for a recording already residing in memory on power-up and set the
// rec_end_addr accordingly.
//
void Recording_Search(void)
{
unsigned long address = 0x00000000;
bit end_flag = 0;
// indicate to the user that the microcontroller is not ready to record
// or playback
LED_DCH = &LED0_DC;
Brighten_LED ();
LED_DCH = &LED1_DC;
Brighten_LED ();
// search through the SST flash until a series of 0xFF is found, indicating
// cleared memory
while (end_flag != 1)
{
if (Read_MEM_Init (address) == 0xFF)
{
// double-check that the 0xFF found is not just a data byte of 0xFF
if (Read_MEM_Init (address+10) == 0xFF)
{
if (Read_MEM_Init (address+40) == 0xFF)
{
end_flag = 1;
}
}
}
address++;
if (address == MAX_MEM_ADDR)
{
end_flag = 1;
}
}
rec_end_addr = address-1; // set the recording ending address
// turn off the LEDs so the user knows the recording search has ended
LED_DCH = &LED0_DC;
Dim_LED ();
LED_DCH = &LED1_DC;
Dim_LED ();
}
////////////////////////// INTERRUPT SERVICE ROUTINES /////////////////////////
//-----------------------------------------------------------------------------
// Timer0_ISR
//-----------------------------------------------------------------------------
//
// Handle the 76Hz (13ms) Timer 0 interrupt.
//
// Timer 0 controls the rate at which the microcontroller changes the duty
// cycle of the PCA controlling the LEDs
//
// The LEDs are updated periodically, even if the LED PWM hasn't changed.
// By using the pointer (which is set before calling the LED functions) and
// updating all LEDs in the ISR every time, the same functions can be used for
// any number of LEDs. To add an LED, simply set-up another PCA channel,
// point to that LED before calling the LED functions, and update the LED in
// the ISR.
//
void Timer0_ISR (void) interrupt 1 using 1
{
*LED_DCH += ADJ; // calculate the new duty cycle based
// on the values set by the LED
// functions
PCA0CPH1 = LED0_DC; // load all LEDs with the possibly
PCA0CPH0 = LED1_DC; // updated value
// add another LED update here, if desired
TL0 = (-LED_PWM) & 0x00FF; // wait the time specified by the
TH0 = ((-LED_PWM) & 0xFF00) >> 8; // calling LED function
LED_PWM += LED_PWM_CHANGE; // change the interrupt rate, if
// necessary
}
//-----------------------------------------------------------------------------
// Timer1_ISR
//-----------------------------------------------------------------------------
//
// Handle the 64 Hz (15.63 ms) Timer 1 interrupt.
//
// Timer 1 controls the rate at which the microcontroller checks the switches
// for activity while in full power mode.
//
// for RECORD - press and hold REC_PLAY button, release stops recording
// for PLAYBACK - press and release REC_PLAY button, press and release again
// to stop
//
void Timer1_ISR (void) interrupt 3 using 0
{
// interrupt again in 15.63 ms, unless a switch is pressed
unsigned short reload_value = POLLING;
static unsigned char record_counter = 0;
static unsigned short suspend_counter = 0;
bit switch_pressed_flag = 0;
// REC_PLAY button pressed
if (REC_PLAY == 0)
{
switch_pressed_flag = 1; // record the user interaction
// check if the recording time ran out, and stop any interaction
// from the switch until the switch is released and pressed again
if ((system_state & END_MEM) != END_MEM)
{
// the REC_PLAY button must be pressed and held for a period of time
// in order to start the RECORD function
record_counter++;
// check if the REC_PLAY button was held down long enough to begin
// recording (7 x 150 ms = 1.5 seconds)
// ignore the ERASED and END_MEM state bits, check if the system is
// idle and can start recording
if ((record_counter > 7) && ((system_state & 0x03) == IDLE))
{
TR2 = 1; // turn on the RECORD timer
system_state |= RECORDING; // start recording
LED_DCH = &LED0_DC; // point to the record LED's duty cycle
// address
Brighten_LED(); // ramp on the record LED
record_counter = 0; // reset the counter
reload_value = PRCHANGE*2; // give a longer time period to check
// the button (effectively debouncing)
}
// check if the recording time is running out (button must be held
// to continue recording)
if (TR2 == 1)
{
if (MEM_END_NEAR_FLAG == 1)
{
LED_DCH = &LED0_DC;
Flutter_LED (); // indicate to the user that time is
// almost out
}
}
else
{
// check if end of the memory has been reached
if (MEM_END_FLAG == 1)
{
// stop recording
system_state = IDLE | END_MEM; // indicate that the end of
// memory was reached
MEM_END_FLAG = 0;
LED_DCH = &LED0_DC; // point to the record LED's duty cycle
// address
Dim_LED (); // dim off the record LED
}
}
}
}
else
{
// check if the switch was pressed, but not long enough to start
// recording
if (record_counter > 0)
{
switch_pressed_flag = 1; // record the user interaction
// the system is currently playing - stop playing
// ignore the ERASED and END_MEM state bits
if ((system_state & 0x03) == PLAYING)
{
system_state &= ~PLAYING; // clear the PLAYING state bit
DAC_STOP_FLAG = 1;
IDA0DAT = 0x0800;
LED_DCH = &LED1_DC; // point to the play LED's duty cycle
// address
Dim_LED (); // dim off the play LED
}
else
{
// the system is idle - start playing
// ignore the ERASED and END_MEM state bits
if ((system_state & 0x03) == IDLE)
{
system_state |= PLAYING;
TMR3CN = 0x04; // start the timer controlling the DAC
REC_END_FLAG = 0; // reset the "end of recording" flag
DAC_STOP_FLAG = 0;
LED_DCH = &LED1_DC; // point to the play LED's duty cycle
// address
Brighten_LED (); // ramp on the play LED
}
}
record_counter = 0; // switch-press registered, reset
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -