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 + -
显示快捷键?