Newbie Problem with Blinky C8051F340

Lee Noack
2008-12-01
2013-03-12
  • Lee Noack
    Lee Noack
    2008-12-01

    Hi,
    Below is the code I modified for the F340 and while it seems to compile and load OK, it doesn't seem to work. I am using the SDCC header and yes this is my first attempt with SDCC. Can someone point out the error of my ways.

    //------------------------------------------------------------------------------------
    // Blinky.c
    //------------------------------------------------------------------------------------
    //
    // This program flashes the green LED on the C8051F020 target board about five times
    // a second using the interrupt handler for Timer3.
    //
    // Target: C8051F340
    //
    // Date: 23 MAY 05
    //
    // Tool chain: SDCC 'c'
    //
    // Release 1.1
    //
    // Change Log:
    //
    // Revisions from 1.0 to 1.1:
    // Changed LED = ~LED; to LED = !LED; because using the ~ operator causes SDCC
    // to upcast to INT which leads to an incorrect result (always 1)
    //------------------------------------------------------------------------------------
    // Includes
    //------------------------------------------------------------------------------------
    #include <C8051F340.h> // SFR declarations
    //------------------------------------------------------------------------------------
    // Global CONSTANTS
    //------------------------------------------------------------------------------------
    #define SYSCLK 1200000 // approximate SYSCLK frequency in Hz
    sbit at 0xA2 LED; // green LED: '1' = ON; '0' = OFF  P2_2 on F340 board
    //------------------------------------------------------------------------------------
    // Function PROTOTYPES
    //------------------------------------------------------------------------------------
    void PORT_Init (void);
    void Timer3_Init (int counts);
    void Timer3_ISR (void) interrupt 14;
    //------------------------------------------------------------------------------------
    // MAIN Routine
    //------------------------------------------------------------------------------------
    void main (void) {
    // disable watchdog timer
    //WDTCN = 0xde;
    //WDTCN = 0xad;
    PCA0MD &= ~0x40;                    // WDTE = 0 (clear watchdog timer enable)
    OSCICN |=0xC3;

    PORT_Init ();
    Timer3_Init (SYSCLK / 12 / 10); // Init Timer3 to generate interrupts
    EA = 1; // enable global interrupts

    while (1) { // spin forever
    }
    }
    //------------------------------------------------------------------------------------
    // PORT_Init
    //------------------------------------------------------------------------------------
    //
    // Configure the Crossbar and GPIO ports
    //
    void PORT_Init (void)
    {
    XBR2 = 0x40; // Enable crossbar and weak pull-ups
    P2MDOUT |= 0x04; // enable P2_2 (LED) as push-pull output
    }
    //------------------------------------------------------------------------------------
    // Timer3_Init
    //------------------------------------------------------------------------------------
    //
    // Configure Timer3 to 16 bit auto-reload and generate an interrupt at interval
    // specified by <counts> using SYSCLK/12 as its time base.
    //
    void Timer3_Init (int counts)
    {
    TMR3CN = 0x00; // Stop Timer3; Clear TF3, use SYSCLK/12 as timebase
    TMR3RLH = (-counts) >> 8; // Init reload values
    TMR3RLL = (-counts); // Init reload values
    TMR3H = 0xff; // set to reload immediately
    TMR3L = 0xff; // set to reload immediately
    EIE2 |= 0x80; // enable Timer3 interrupts:-changed for F340
    TMR3CN |= 0x04; // start Timer3
    }
    //------------------------------------------------------------------------------------
    // Interrupt Service Routines
    //------------------------------------------------------------------------------------
    //------------------------------------------------------------------------------------
    // Timer3_ISR
    //------------------------------------------------------------------------------------
    // This routine changes the state of the LED whenever Timer3 overflows.
    //
    void Timer3_ISR (void) interrupt 14
    {
    TMR3CN &= ~(0x80); // clear TF3
    LED = !LED; // change state of LED
    }

     
    • Maarten Brock
      Maarten Brock
      2008-12-01

      I think XBR2 should be XBR1.

      Maarten

       
    • Lee Noack
      Lee Noack
      2008-12-02

      Hi Maarten,

      Thanks, I overlooked that when changing the code from the original AN-198. The Led now turns on but stays on, so I guess the ISR isn't working or the Timer counts value is incorrect. I couldn't see a frequency with the cro so I'm guessing the problem is with the ISR.

      Cheers,
      Lee.

       
    • Lee Noack
      Lee Noack
      2008-12-02

      Hi, Timer2 nowworks but still having problems with Timer3. I've tried keeping the code as close as possible but the TMR3CN register is not bit addressable like TMR2CN????

      #include <C8051F340.h> // SFR declarations
      //------------------------------------------------------------------------------------
      // Global CONSTANTS
      //------------------------------------------------------------------------------------
      #define SYSCLK 1500000 // approximate SYSCLK frequency in Hz
      #define BLINK_RATE   2                // Timer2 Interrupts per second
      sbit at 0xA2 LED1; // green LED: '1' = ON; '0' = OFF  P2_2 on F340 board
      sbit at 0xA3 LED2;
      //------------------------------------------------------------------------------------
      // Function PROTOTYPES
      //------------------------------------------------------------------------------------
      void PORT_Init (void);
      void Timer2_Init (int counts);
      void Timer2_ISR (void) interrupt 5;
      void PORT_Init (void);
      void Timer3_Init (int counts);
      void Timer3_ISR (void) interrupt 14;
      //------------------------------------------------------------------------------------
      // MAIN Routine
      //------------------------------------------------------------------------------------
      void main (void) {
      // disable watchdog timer

      PCA0MD &= ~0x40;                    // WDTE = 0 (clear watchdog timer enable)
      OSCICN = 0x80;                         //Oscillator at slowest speed OSC/8 = 1.5MHz

      PORT_Init ();
      Timer2_Init (SYSCLK/12/BLINK_RATE ); // Init Timer2 to generate interrupts
      Timer3_Init (SYSCLK/12/BLINK_RATE ); // Init Timer2 to generate interrupts
      EA = 1; // enable global interrupts

      while (1) { // spin forever
      }
      }
      //------------------------------------------------------------------------------------
      // PORT_Init
      //------------------------------------------------------------------------------------
      //
      // Configure the Crossbar and GPIO ports
      //
      void PORT_Init (void)
      {
      XBR0 = 0x00;
      XBR1 = 0xC0; // Enable crossbar and disable weak pull-ups
      P2MDOUT |= 0xFF; // enable P2 as push-pull outputs
      }

      //------------------------------------------------------------------------------------
      // Timer3_Init
      //------------------------------------------------------------------------------------
      //
      // Configure Timer3 to 16 bit auto-reload and generate an interrupt at interval
      // specified by <counts> using SYSCLK/12 as its time base.
      //
      void Timer3_Init (int counts)
      {
         TMR3CN  = 0x00;                     // Stop Timer3; Clear TF3;
         TMR3RL  = -counts;                  // Init reload values
         TMR3    = 0xffff;                   // Set to reload immediately
         EIE1 |= 0x80;                       // Enable Timer3 interrupts
         TMR3CN  &= 0x04;                      // Enable  Timer 3
      }
      //------------------------------------------------------------------------------------
      // Interrupt Service Routines
      //------------------------------------------------------------------------------------
      //------------------------------------------------------------------------------------
      // Timer3_ISR
      //------------------------------------------------------------------------------------
      // This routine changes the state of the LED whenever Timer3 overflows.
      //
      void Timer3_ISR (void) interrupt 14
      {
        TMR3CN &= 0x7F;                      // Clear Timer3 interrupt flag
        LED2 = !LED2; // change state of LED

      }

      //-----------------------------------------------------------------------------
      // Timer2_Init
      //-----------------------------------------------------------------------------
      //
      // Return Value : None
      // Parameters   :
      //   1)  int counts - calculated Timer overflow rate
      //                    range is postive range of integer: 0 to 32767
      //
      // Configure Timer2 to 16-bit auto-reload and generate an interrupt at
      // interval specified by <counts> using SYSCLK/48 as its time base.
      //
      //-----------------------------------------------------------------------------
      void Timer2_Init (int counts)
      {
         TMR2CN  = 0x00;                     // Stop Timer2; Clear TF2;
                                             // Use SYSCLK/12 as timebase
         //CKCON  &= ~0x60;                    // Timer2 clocked based on T2XCLK;

         TMR2RL  = -counts;                  // Init reload values
         TMR2    = 0xffff;                   // Set to reload immediately
         ET2     = 1;                        // Enable Timer2 interrupts
         TR2     = 1;                        // Start Timer2
      }

      //-----------------------------------------------------------------------------
      // Interrupt Service Routines
      //-----------------------------------------------------------------------------

      //-----------------------------------------------------------------------------
      // Timer2_ISR
      //-----------------------------------------------------------------------------
      //
      // This routine changes the state of the LED whenever Timer2 overflows.
      //
      //-----------------------------------------------------------------------------
      void Timer2_ISR (void) interrupt 5
      {
         TF2H = 0;                           // Clear Timer2 interrupt flag
         LED1 = !LED1;                       // Change state of LED

       
      • Maarten Brock
        Maarten Brock
        2008-12-02

        TMR3CN &= 0x04; // Enable Timer 3

        This does not enable timer3.

         
    • Lee Noack
      Lee Noack
      2008-12-02

      Hi Maaten, Thanks for that. TMR3CN |= 0x04; // Enable Timer 3  is correct.  Can you explain why the use of the -ve counts.  Don't Timers count from the reload value to oxFFFF. Is this possibly to give a greater range of counts??

      Cheers,
      Lee.