f330dc_featuresdemo.c
来自「8051试验程序 基础教材」· C语言 代码 · 共 667 行 · 第 1/2 页
C
667 行
//-----------------------------------------------------------------------------
// F330DC_FeaturesDemo.c
//-----------------------------------------------------------------------------
// Copyright 2006 Silicon Laboratories, Inc.
// http://www.silabs.com
//
// Program Description:
//
// This program demonstrates the features available on the ToolStick
// F330 Daughter Card.
//
// Based on the setting of a level-sensitive interrupt pin, the firmware
// will either blink the green LED or PWM the LED. The blinking speed
// or the PWM duty cycle is set based on the value of the potentiometer.
// Voltage across the potentiometer is measured using the on-chip 10-bit ADC.
//
// The program also outputs the status of the LED to the UART at a baud rate
// defined by <BAUDRATE>.
//
// How To Test:
// 1) Connect the ToolStickF330DC to the PC and download the code
// 2) Turn the potentiometer and see that the blink rate increases or decreases
// 3) Connect to the ToolStickF330DC using ToolStickTerminal and see that
// the UART output changes as the potentiometer is turned
// 4) In ToolStickTerminal, toggle GPIO0/RTS to force the firmware to
// switch modes.
// 5) Turn the potentiometer and see that the brightness of the LED changes
// and check that the output of the UART also changes.
//
//
// FID: 33X000030
// Target: ToolStickF330DC
// Tool chain: Keil C51 7.50 / Keil EVAL C51
// Silicon Laboratories IDE version 2.6
//
// Release 1.0
// -Initial Revision (GP)
// -06 AUG 2006
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <ioC8051F330.h> // SFR declarations
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
//-----------------------------------------------------------------------------
// 16-bit SFR Definitions
//-----------------------------------------------------------------------------
__sfr __no_init volatile unsigned short ADC0 @ 0xBD;
__sfr __no_init volatile unsigned short TMR3RL @ 0x92;
__sfr __no_init volatile unsigned short TMR2RL @ 0xCA;
__sfr __no_init volatile unsigned short TMR2 @ 0xCC;
__sfr __no_init volatile unsigned short TMR3 @ 0x94;
//-----------------------------------------------------------------------------
// SFR and Bit Definitions
//-----------------------------------------------------------------------------
#define LED P1_bit.P13 // LED='1' means ON
//-----------------------------------------------------------------------------
// Global Constants
//-----------------------------------------------------------------------------
#define SYSCLK 3000000L // SYSCLK frequency in Hz
#define BAUDRATE 115200 // Baud rate of UART in bps
#define PRINT_RATE 20 // Times per second to update on UART
#define OVERFLOWS_NEEDED (SYSCLK / 65536 / PRINT_RATE)
#define ADC_CLOCK 100000 // SAR clock
#define ADC_SAMPLE_RATE 100 // Timer 2 overflow rate in Hz
#define ADC_COUNTS 1024 // Number of ADC counts
#define MAX_BLINK_RATE 40 // Max blink rate in Hz for Timer mode
#define MIN_BLINK_RATE 1 // Min blink rate in Hz for Timer mode
#define BLINK_DIFF (MAX_BLINK_RATE - MIN_BLINK_RATE) // For easy calculations
// Firmware states
#define TIMER_MODE 0 // Uses the Timer to blink the LED
#define PWM_MODE 1 // Use a PCA channel to PWM the LED
//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------
void OSCILLATOR_Init (void);
void PORT_Init (void);
void TIMER0_Init (void);
void TIMER2_Init (int counts);
void TIMER3_Init (void);
void ADC0_Init (void);
void PCA0_Init (void);
void UART0_Init (void);
void INT0_Init (void);
void Print_String (char pstring[]);
// ISRs defined: INT0_ISR, TIMER0_ISR, TIMER3_ISR, ADC0_ISR.
//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
bool Blink_State = TIMER_MODE; // Starts with blinking the LED
int PWM_Duty_Cycle = 0; // Percentage from 0 to 100
int Blink_Rate = 0; // From MIN_BLINK_RATE to MAX_BLINK_RATE
bool update = 0; // Forces a UART update
long Num_LED_Flashes = 0; // Simply counts the number of times
// the LED blinks
//-----------------------------------------------------------------------------
// PUTCHAR Routine
//-----------------------------------------------------------------------------
int putchar(int ch)
{
if (ch == '\n') {
while (!SCON0_bit.TI0);
SCON0_bit.TI0 = 0;
SBUF0 = 0x0d; // output CR
}
while (!SCON0_bit.TI0);
SCON0_bit.TI0 = 0;
return (SBUF0 = ch);
}
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------
void main (void)
{
PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer
// enable)
OSCILLATOR_Init (); // Initialize system clock to 24.5 Mhz
PORT_Init (); // Initialize crossbar and GPIO
TIMER0_Init (); // Initialize Timer0 for UART update
TIMER2_Init (SYSCLK / 12 / ADC_SAMPLE_RATE); // Init Timer2 for ADC
TIMER3_Init (); // Init timer used to blink LED
PCA0_Init (); // Init PCA Module 0 to blink LED
ADC0_Init (); // Enable ADC0
INT0_Init (); // Enable /INT0
UART0_Init (); // Enable UART using global settings
IE_bit.EA = 1; // Enable global interrupts
while (1) {}
}
#pragma vector = TF2H_int
__interrupt void crap (void)
{
volatile int a;
a=5;
}
//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// INT0_ISR
//-----------------------------------------------------------------------------
//
// INT0_ISR is triggered upon a level transition on the /INT0 pin.
// If /INT0 is logic high, the firmware switches to a state that blinks the LED
// If /INT0 is logic low, the fimware applies PWM wave to the LED to control
// the brightness.
//
//-----------------------------------------------------------------------------
#pragma vector = IE0_int
__interrupt void INT0_ISR (void)
{
if (IT01CF & 0x08) // Currently active-high
{
IT01CF &= ~0x08; // Switch to active-low
Blink_State = TIMER_MODE; // State is now Timer mode
update = 1;
// Switch to Timer Mode
PCA0CN_bit.CR = 0; // Stop PCA Counter
XBR1 &= ~0x01; // Remove CEX0 from Crossbar
TMR3CN |= 0x04; // Start Timer3
}
else
{
IT01CF |= 0x08; // Switch to active-high
Blink_State = PWM_MODE; // State is now PWM mode
update = 1;
// Switch To PWM Mode
TMR3CN &= ~0x04; // Stop Timer3
XBR1 |= 0x01; // Put CEX0 on Crossbar (P1.3)
PCA0CN_bit.CR = 1; // Start PCA Counter
}
}
//-----------------------------------------------------------------------------
// TIMER0_ISR
//-----------------------------------------------------------------------------
//
// This ISR is triggered upon a Timer0 overflow. It is used to update the
// UART with the status of the LED.
//
//-----------------------------------------------------------------------------
#pragma vector = TF0_int
__interrupt void TIMER0_ISR (void)
{
static int overflows = 0;
// Timer0 is used to schedule the number of times per second the status is
// printed to the UART. Since Timer0 and Timer1 share a SYCLK prescaler, it
// is easier to use the prescaler only for Timer1 (UART baud rate) and run
// Timer0 from SYSCLK. Running Timer0 from SYSCLK requires keeping track
// of the number of Timer0 overflows to schedule a reasonable UART update
// rate. Updating on every Timer0 overflow would print too fast.
// The benefit is that there is more flexibility in scheduling the update
// rate as it is no longer any dependent on the fixed UART prescaler.
overflows++;
if (overflows == OVERFLOWS_NEEDED) // Time to print
{
if ((Blink_State == TIMER_MODE) & update) // Timer mode
{
putchar ('\f'); // Clear screen
Print_String ("LED Blink Rate: ");
// Add a hundreds digit if <MAX_BLINK_RATE> requires one
putchar ((Blink_Rate / 10) + 0x30); // Tens digit 30
putchar ((Blink_Rate % 10) + 0x30); // Ones digit
Print_String (" Hz\n");
update = 0;
}
else if ((Blink_State == PWM_MODE) & update) // PWM mode
{
putchar ('\f'); // Clear screen
Print_String ("LED PWM Duty Cycle: ");
putchar ((PWM_Duty_Cycle / 100) + 0x30); // Hundreds digit
putchar (((PWM_Duty_Cycle / 10) % 10) + 0x30); // Tens digit
putchar ((PWM_Duty_Cycle % 10) + 0x30); // Ones digit
Print_String (" %\n");
update = 0;
}
overflows = 0; // Reset the count
}
}
//-----------------------------------------------------------------------------
// ADC0_ISR
//-----------------------------------------------------------------------------
//
// ADC0_ISR is triggerered upon the completion of an ADC conversion. The ISR
// calculates the Blink_Rate or PWM_Duty_Cycle based on the voltage
// across the potentiometer.
//
// Blink mode:
// A full-scale reading will configure the Timer to blink the LED at
// <MAX_BLINK_RATE>
// A zero reading will configure the Timer the LED to blink at <MIN_BLINK_RATE>
//
// PWM mode:
// A full scale value will configure the PCA to use a duty cycle of 100%
// A zero reading will configure the PCA to use a duty cycle of 0%
//
//-----------------------------------------------------------------------------
#pragma vector = AD0INT_int
__interrupt void ADC0_ISR (void)
{
unsigned int ADC_result;
unsigned long reload_speed, percentage;
static int PWM_Duty_Cycle_Old = 0;
static int Blink_Rate_Old = 0;
ADC0CN_bit.AD0BUSY = 0; //DEBUG CODE
ADC0CN_bit.AD0INT = 0; // Clear conversion complete flag
ADC_result = ADC0;
if (Blink_State == TIMER_MODE)
{
if (ADC_result == 0x03FF) // Assume max reading indicates VDD
{ // and not (VDD - 1 LSB)
reload_speed = MAX_BLINK_RATE;
}
else
{
reload_speed = (long) (ADC_result * BLINK_DIFF);
reload_speed = reload_speed / ADC_COUNTS;
reload_speed += MIN_BLINK_RATE;
}
Blink_Rate = reload_speed; // Set global variable
if (Blink_Rate != Blink_Rate_Old) {
update = 1; }
Blink_Rate_Old = Blink_Rate;
TMR3RL = - ((unsigned int) (SYSCLK / 12 / reload_speed));
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?