f362dc_featuresdemo.c

来自「8051试验程序 基础教材」· C语言 代码 · 共 754 行 · 第 1/2 页

C
754
字号
//
//-----------------------------------------------------------------------------
void ADC0_Init (void)
{
   unsigned char SFRPAGE_save = SFRPAGE; // Save the current SFRPAGE

   SFRPAGE = CONFIG_PAGE;              // Switch to the necessary SFRPAGE

   ADC0CN = 0x02;                      // Disable ADC0
                                       // Normal Track Mode
                                       // Enable conversion on Timer2 overflow

   AMX0P = 0x06;                       // P1.6 is the positive input
   AMX0N = 0x1F;                       // GND is the negative input

   ADC0CF = (SYSCLK/ADC_CLOCK) << 3;   // ADC conversion clock <= 3MHz

   ADC0CF &= ~0x04;                    // Make ADC0 right-justified

   EIE1  |= 0x08;                      // Enable ADC0 conversion-complete
                                       // interrupts

   REF0CN = 0x0A;                      // VREF = VDD, bias generator is on.

   ADC0CN_bit.AD0EN = 1;                          // Enable ADC0

   SFRPAGE = SFRPAGE_save;             // Restore the SFRPAGE
}

//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// Configure the UART1 using Timer1, for <baudrate> and 8-N-1.
//
//-----------------------------------------------------------------------------
void UART0_Init (void)
{
   unsigned char SFRPAGE_save = SFRPAGE; // Save the current SFRPAGE

   SFRPAGE = CONFIG_PAGE;              // Switch to the necessary SFRPAGE

   SCON0 = 0x10;                       // SCON0: 8-bit variable bit rate
                                       //        level of STOP bit is ignored
                                       //        RX enabled
                                       //        ninth bits are zeros
                                       //        clear RI0 and TI0 bits
   if (SYSCLK/BAUDRATE/2/256 < 1) {
      TH1 = (0xFF-(SYSCLK/BAUDRATE/2))+1;
      CKCON &= ~0x0B;                  // T1M = 1; SCA1:0 = xx
      CKCON |=  0x08;
   } else if (SYSCLK/BAUDRATE/2/256 < 4) {
      TH1 = (0xFF-(SYSCLK/BAUDRATE/2/4))+1;
      CKCON &= ~0x0B;                  // T1M = 0; SCA1:0 = 01
      CKCON |=  0x09;
   } else if (SYSCLK/BAUDRATE/2/256 < 12) {
      TH1 = (0xFF-(SYSCLK/BAUDRATE/2/12))+1;
      CKCON &= ~0x0B;                  // T1M = 0; SCA1:0 = 00
   } else {
      TH1 = -(SYSCLK/BAUDRATE/2/48);
      CKCON &= ~0x0B;                  // T1M = 0; SCA1:0 = 10
      CKCON |=  0x02;
   }

   TL1 = TH1;                          // Init Timer1
   TMOD &= ~0xf0;                      // TMOD: timer 1 in 8-bit autoreload
   TMOD |=  0x20;
   TCON_bit.TR1 = 1;                   // START Timer1
   SCON0_bit.TI0 = 1;                  // Indicate TX0 ready

   SFRPAGE = SFRPAGE_save;             // Restore the SFRPAGE
}

//-----------------------------------------------------------------------------
// PCA0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// Configure Module0 to 8-bit PWM.  The duty cycle is initially set to 50%. The
// duty cycle will actually be determined by the value of the potentiometer.
//
// The PCA counter isn't started until the user switches to PWM mode.
//
//-----------------------------------------------------------------------------
void PCA0_Init (void)
{
   unsigned char SFRPAGE_save = SFRPAGE; // Save the current SFRPAGE

   SFRPAGE = CONFIG_PAGE;              // Switch to the necessary SFRPAGE

   // Configure PCA time base; overflow interrupt disabled
   PCA0CN = 0x00;                      // Stop counter; clear all flags
   PCA0MD = 0x08;                      // Use SYSCLK as time base

   PCA0CPM0 = 0x42;                    // Module 0 = 8-bit PWM mode

   // Configure initial PWM duty cycle = 50%
   PCA0CPH0 = 256 - (256 * 0.5);

   SFRPAGE = SFRPAGE_save;             // Restore the SFRPAGE
}

//-----------------------------------------------------------------------------
// INT0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// Configure /INT0 (P0.6) to be a level-sensitive interrupt pin.
// Starts active-low, but the INT0 ISR will switch this back and forth.
//
//-----------------------------------------------------------------------------
void INT0_Init (void)
{
   unsigned char SFRPAGE_save = SFRPAGE; // Save the current SFRPAGE

   SFRPAGE = CONFIG_PAGE;              // Switch to the necessary SFRPAGE

   IT01CF = 0x06;                      // Configure /INT0 to P0.6
                                       // Active High

   TCON_bit.IT0    = 0;                         // /INT0 is level sensitive

   IE_bit.EX0    = 1;                         // Enable /INT0 interrupts

   SFRPAGE = SFRPAGE_save;             // Restore the SFRPAGE
}


//-----------------------------------------------------------------------------
// 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)
{
   char SFRPAGE_save = SFRPAGE;

   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
      TMR3CN |= 0x04;                  // Start Timer3

	  SFRPAGE = CONFIG_PAGE;
      XBR1   &= ~0x01;                 // Remove CEX0 from Crossbar

   }
   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
      PCA0CN_bit.CR      = 1;          // Start PCA Counter

      SFRPAGE = CONFIG_PAGE;
      XBR1   |= 0x01;                  // Put CEX0 on Crossbar (P1.3)

   }

   SFRPAGE = SFRPAGE_save;
}

//-----------------------------------------------------------------------------
// 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 SYSCLK prescaler,
   // it is easier to use the prescaler only for Timer1 (UART) 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
         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;

   // The ADC, PCA, and TIMER registers are available on all SFR pages, so there
   // is no need to switch the SFR page before writing to these registers.

   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));
   }
   else
   {

      if (ADC_result == 0x03FF)        // Assume max reading indicates VDD
      {                                // and not (VDD - 1 LSB)
         percentage = 255;
         PWM_Duty_Cycle = 100;
      }
      else
      {
         percentage = (long) ADC_result * (long) 256;
         percentage = (long) percentage / (long) ADC_COUNTS;
         PWM_Duty_Cycle = (int) ( ((long)ADC_result * (long)100) / (long)ADC_COUNTS );
      }

      if (PWM_Duty_Cycle != PWM_Duty_Cycle_Old) {
         update = 1; }

      PWM_Duty_Cycle_Old = PWM_Duty_Cycle;

      // Set new PCA0 Module0 PWM duty cycle
      PCA0CPH0 = (char) percentage;
   }
}


//-----------------------------------------------------------------------------
// TIMER3_ISR
//-----------------------------------------------------------------------------
//
// This ISR is triggered upon a Timer3 overflow.  The ISR simply toggles
// the state of the LED and keeps track of the number of times the LED blinks.
//
//-----------------------------------------------------------------------------
#pragma vector = ET3_int
__interrupt void TIMER3_ISR (void)
{
   // The TMR3CN and Port registers are available on all SFR pages, so there
   // is no need to switch the SFR page before writing to these registers.

   TMR3CN &= ~0x80;                    // Clear Timer3 Flags

   LED = !LED;

   Num_LED_Flashes++;
}


//-----------------------------------------------------------------------------
// Support Functions
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Print_String
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   :
//         1) char pstring[] - null terminated character string
//
// Prints the strings stored in pstring to the UART.
//
//-----------------------------------------------------------------------------
void Print_String (char pstring[])
{
   // The SBUF0 register is available on all SFR pages, so there is no
   // need to switch the SFR page before calling putchar().

   unsigned char i = 0;
   while (pstring[i])
   {
      putchar(pstring[i++]);
   }
}

//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?