📄 common.c
字号:
//-----------------------------------------------------------------------------
// common.c
//-----------------------------------------------------------------------------
// Copyright 2002 Cygnal Integrated Products, Inc.
//
// AUTH: FB
// DATE: 18 SEP 02
//
// This example shows how to set up a code banking project using the Cygnal
// IDE and the KEIL development tools. It uses Timer3 and Timer4 interrupts
// to blink the LED and output a 1 kHz sine wave on DAC1, respectively. The
// code that blinks the LED is located in Bank 3 and the code that outputs a
// sine wave based on a 256 entry sine table is located in Bank 2. Since
// interrupts must be located in the Common area, both interrupts call
// a function in one of the banks to perform the desired task.
//
// The project should be configured for code banking as shown in AN030 before
// this project is built.
//
// This program uses the the 24.5 MHz internal oscillator multiplied by two
// for an effective SYSCLK of 49 MHz. This program also initializes UART1
// at <BAUDRATE> bits per second.
//
//
// Target: C8051F12x
// Tool chain: KEIL C51 6.03 / KEIL EVAL C51
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <c8051f120.h> // SFR declarations
#include <stdio.h> // printf() and getchar()
//-----------------------------------------------------------------------------
// 16-bit SFR Definitions for 'F12x
//-----------------------------------------------------------------------------
sfr16 DP = 0x82; // data pointer
sfr16 ADC0 = 0xbe; // ADC0 data
sfr16 ADC0GT = 0xc4; // ADC0 greater than window
sfr16 ADC0LT = 0xc6; // ADC0 less than window
sfr16 RCAP2 = 0xca; // Timer2 capture/reload
sfr16 RCAP3 = 0xca; // Timer3 capture/reload
sfr16 RCAP4 = 0xca; // Timer4 capture/reload
sfr16 TMR2 = 0xcc; // Timer2
sfr16 TMR3 = 0xcc; // Timer3
sfr16 TMR4 = 0xcc; // Timer4
sfr16 DAC0 = 0xd2; // DAC0 data
sfr16 DAC1 = 0xd2; // DAC1 data
sfr16 PCA0CP5 = 0xe1; // PCA0 Module 5 capture
sfr16 PCA0CP2 = 0xe9; // PCA0 Module 2 capture
sfr16 PCA0CP3 = 0xeb; // PCA0 Module 3 capture
sfr16 PCA0CP4 = 0xed; // PCA0 Module 4 capture
sfr16 PCA0 = 0xf9; // PCA0 counter
sfr16 PCA0CP0 = 0xfb; // PCA0 Module 0 capture
sfr16 PCA0CP1 = 0xfd; // PCA0 Module 1 capture
//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------
#define TRUE 1
#define FALSE 0
#define INTCLK 24500000 // Internal oscillator frequency in Hz
#define SYSCLK 49000000 // Output of PLL derived from (INTCLK*2)
#define BAUDRATE 115200 // Baud rate of UART in bps
#define SAMPLE_RATE_DAC 100000L // DAC sampling rate in Hz
#define PHASE_PRECISION 65536 // range of phase accumulator
sbit LED = P1^6; // LED='1' means ON
sbit SW2 = P3^7; // SW2='0' means switch pressed
#define FREQUENCY 1000 // frequency of output waveform in Hz
// <phase_add> is the change in phase
// between DAC1 samples; It is used in
// the set_DAC1 routine in bank2
unsigned int phase_add = FREQUENCY * PHASE_PRECISION / SAMPLE_RATE_DAC;
//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------
// Common area functions
void main(void);
void SYSCLK_Init(void);
void PORT_Init(void);
void UART1_Init (void);
void DAC1_Init (void);
void Timer3_Init(int counts);
void Timer4_Init(int counts);
// code bank 2 functions
extern void set_DAC1(void);
// code bank 3 functions
extern void toggle_LED(void);
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------
void main (void)
{
WDTCN = 0xde; // disable watchdog timer
WDTCN = 0xad;
PORT_Init (); // initialize crossbar and GPIO
SYSCLK_Init (); // initialize oscillator
UART1_Init (); // initialize UART1
DAC1_Init (); // initialize DAC1
Timer3_Init(SYSCLK/12/1000); // initialize Timer3 to overflow
// every millisecond
Timer4_Init(SYSCLK/SAMPLE_RATE_DAC);// initialize Timer4 to overflow
// <SAMPLE_RATE_DAC> times per
// second
EA = 1; // enable global interrupts
while(1);
}
//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Timer3_ISR
//-----------------------------------------------------------------------------
// This routine changes the state of the LED whenever Timer3 overflows 250 times.
//
// NOTE: The SFRPAGE register will automatically be switched to the Timer 3 Page
// When an interrupt occurs. SFRPAGE will return to its previous setting on exit
// from this routine.
//
void Timer3_ISR (void) interrupt 14
{
static int i; // software interrupt counter
TF3 = 0; // clear Timer3 overflow flag
i++; // increment software counter
// toggle the LED every 250ms
if (i == 250) {
toggle_LED(); // toggle the green LED
i = 0; // clear software counter
}
}
//-----------------------------------------------------------------------------
// Timer4_ISR -- Wave Generator
//-----------------------------------------------------------------------------
//
// This ISR is called on Timer4 overflows. Timer4 is set to auto-reload mode
// and is used to schedule the DAC output sample rate in this example.
// Note that the value that is written to DAC1 during this ISR call is
// actually transferred to DAC1 at the next Timer4 overflow.
//
void Timer4_ISR (void) interrupt 16
{
TF4 = 0; // clear Timer4 overflow flag
set_DAC1();
}
//-----------------------------------------------------------------------------
// Initialization Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
//
// This routine initializes the system clock to use the internal oscillator
// at 24.5 MHz multiplied by two using the PLL.
//
void SYSCLK_Init (void)
{
int i; // software timer
char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page
SFRPAGE = CONFIG_PAGE; // set SFR page
OSCICN = 0x83; // set internal oscillator to run
// at its maximum frequency
CLKSEL = 0x00; // Select the internal osc. as
// the SYSCLK source
//Turn on the PLL and increase the system clock by a factor of M/N = 2
SFRPAGE = CONFIG_PAGE;
PLL0CN = 0x00; // Set internal osc. as PLL source
SFRPAGE = LEGACY_PAGE;
FLSCL = 0x10; // Set FLASH read time for 50MHz clk
// or less
SFRPAGE = CONFIG_PAGE;
PLL0CN |= 0x01; // Enable Power to PLL
PLL0DIV = 0x01; // Set Pre-divide value to N (N = 1)
PLL0FLT = 0x01; // Set the PLL filter register for
// a reference clock from 19 - 30 MHz
// and an output clock from 45 - 80 MHz
PLL0MUL = 0x02; // Multiply SYSCLK by M (M = 2)
for (i=0; i < 256; i++) ; // Wait at least 5us
PLL0CN |= 0x02; // Enable the PLL
while(!(PLL0CN & 0x10)); // Wait until PLL frequency is locked
CLKSEL = 0x02; // Select PLL as SYSCLK source
SFRPAGE = SFRPAGE_SAVE; // Restore SFR page
}
//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// This routine configures the crossbar and GPIO ports.
//
void PORT_Init (void)
{
char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page
SFRPAGE = CONFIG_PAGE; // set SFR page
XBR0 = 0x00;
XBR1 = 0x00;
XBR2 = 0x44; // Enable crossbar and weak pull-up
// Enable UART1
P0MDOUT |= 0x01; // Set TX1 pin to push-pull
P1MDOUT |= 0x40; // Set P1.6(LED) to push-pull
SFRPAGE = SFRPAGE_SAVE; // Restore SFR page
}
//-----------------------------------------------------------------------------
// UART1_Init
//-----------------------------------------------------------------------------
//
// Configure the UART1 using Timer1, for <baudrate> and 8-N-1.
//
void UART1_Init (void)
{
char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page
SFRPAGE = UART1_PAGE;
SCON1 = 0x10; // SCON1: mode 0, 8-bit UART, enable RX
SFRPAGE = TIMER01_PAGE;
TMOD &= ~0xF0;
TMOD |= 0x20; // TMOD: timer 1, mode 2, 8-bit reload
if (SYSCLK/BAUDRATE/2/256 < 1) {
TH1 = -(SYSCLK/BAUDRATE/2);
CKCON |= 0x10; // T1M = 1; SCA1:0 = xx
} else if (SYSCLK/BAUDRATE/2/256 < 4) {
TH1 = -(SYSCLK/BAUDRATE/2/4);
CKCON &= ~0x13; // Clear all T1 related bits
CKCON |= 0x01; // T1M = 0; SCA1:0 = 01
} else if (SYSCLK/BAUDRATE/2/256 < 12) {
TH1 = -(SYSCLK/BAUDRATE/2/12);
CKCON &= ~0x13; // T1M = 0; SCA1:0 = 00
} else {
TH1 = -(SYSCLK/BAUDRATE/2/48);
CKCON &= ~0x13; // Clear all T1 related bits
CKCON |= 0x02; // T1M = 0; SCA1:0 = 10
}
TL1 = TH1; // initialize Timer1
TR1 = 1; // start Timer1
SFRPAGE = UART1_PAGE;
TI1 = 1; // Indicate TX1 ready
SFRPAGE = SFRPAGE_SAVE; // Restore SFR page
}
//-----------------------------------------------------------------------------
// DAC1_Init
//-----------------------------------------------------------------------------
//
// Configure DAC1 to update on Timer4 overflows and enable the the VREF buffer.
//
//
void DAC1_Init(void){
char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page
SFRPAGE = DAC1_PAGE;
DAC1CN = 0x94; // Enable DAC1 in left-justified mode
// managed by Timer4 overflows
SFRPAGE = LEGACY_PAGE;
REF0CN |= 0x03; // Enable the internal VREF (2.4v) and
// the Bias Generator
SFRPAGE = SFRPAGE_SAVE; // Restore SFR page
}
//-----------------------------------------------------------------------------
// Timer3_Init
//-----------------------------------------------------------------------------
//
// Configure Timer3 to auto-reload mode and to generate interrupts
// at intervals specified by <counts> using SYSCLK/12 as its time base.
//
//
void Timer3_Init (int counts)
{
char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page
SFRPAGE = TMR3_PAGE;
TMR3CN = 0x00; // Stop Timer; Clear overflow flag;
// Set to Auto-Reload Mode
TMR3CF = 0x00; // Configure Timer to increment;
// Timer counts SYSCLKs/12
RCAP3 = -counts; // Set reload value
TMR3 = RCAP3; // Initialize Timer to reload value
EIE2 |= 0x01; // enable Timer3 interrupts
TR3 = 1; // start Timer
SFRPAGE = SFRPAGE_SAVE; // Restore SFR page
}
//-----------------------------------------------------------------------------
// Timer4_Init
//-----------------------------------------------------------------------------
// Configure Timer4 to auto-reload mode and to generate interrupts
// at intervals specified in <counts> using SYSCLK as its time base.
//
void Timer4_Init (int counts)
{
char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page
SFRPAGE = TMR4_PAGE;
TMR4CN = 0x00; // Stop Timer4; Clear overflow flag (TF4);
// Set to Auto-Reload Mode
TMR4CF = 0x08; // Configure Timer4 to increment;
// Timer4 counts SYSCLKs
RCAP4 = -counts; // Set reload value
TMR4 = RCAP4; // Initialzie Timer4 to reload value
EIE2 |= 0x04; // enable Timer4 interrupts
TR4 = 1; // start Timer4
SFRPAGE = SFRPAGE_SAVE; // Restore SFR page
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -