This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Problem while trying to write to Serial Window #1 at regular intervals

Hi All,
I'm trying to write to the Serial Window #1 at regular interval of time (But not successful yet). To generate the time interval i'm using timer0 of 8051 in 16 Bit Timer Mode 0x01
The values are initialized as shown below
TH0 = 0xFF
TL0 = 0x00
In the given program below, if I comment all the printf statements It works fine, generates accurate delay as needed (as seen in Debug Session). i.e. TL0 starts incrementing for every clock tick and when it reaches 0xFF, the next clock tick sets the overflow flag which in turn calls the ISR (Interrupt_Service_Routine0), wherein I again set the timer's TH0 and TL0 value.
But if I uncomment the printf statements in the program (Func1 and Func2), I don't get accurate time delay (as seen in Debug Session). when control reaches Func1 and passes ahead of printf statement the TH0 and TL0 value changes to 0x06 and 0x52 respectively.
As I have understood the timer 0 values should be between FF00 to FFFF (as initialized in the Timer_0_Init and Interrupt_Service_Routine0)
Please do correct me if my understanding is not correct

Using Keil IDE uVision2 V2.38a
Have selected ,b>Generic->8052 (all variants),/b> in the Options for Target in Project Menu
The program is as shown below:

/*------------------------------------------------------------------------------
HELLO.C

Copyright 1995-1999 Keil Software, Inc.
------------------------------------------------------------------------------*/

#include <REG52.H>                /* special function register declarations   */
                                  /* for the intended 8051 derivative         */
#include <stdio.h>                /* prototype declarations for I/O functions */


#ifdef MONITOR51                         /* Debugging with Monitor-51 needs   */
char code reserve [3] _at_ 0x23;         /* space for serial interrupt if     */
#endif                                   /* Stop Exection with Serial Intr.   */
                                         /* is enabled                        */
#define FUNC1           3
#define FUNC2           2

sbit Port1Pin0 = P1^0;
sbit Port1Pin1 = P1^1;
sbit Port1Pin2 = P1^2;
sbit Port1Pin3 = P1^3;

unsigned short myFlag = 0;
unsigned short count = 0;

/* --------------------------------------------------------- */
//Functions (Func1 and Func2)to be called from ISR
void Func1() {
//      printf("Func1\n");

        Port1Pin0 = 1;
        Port1Pin1 = 0;
        Port1Pin2 = 1;
        Port1Pin3 = 0;
}

void Func2() {
//      printf("Func2\n");

        Port1Pin0 = 1;
        Port1Pin1 = 0;
        Port1Pin2 = 0;
        Port1Pin3 = 0;
}

/* --------------------------------------------------------- */
//Initializing TImer0
void Timer_0_Init(void)
{
        TMOD |= 0x01;

        TL0 = 0x00;
        TH0 = 0xFF;

        ET0 = 1;
        TR0 = 1;
        EA = 1;
}

/*----------------------------------------------------------*/
//ISR for Timer 0
void Interrupt_Service_Routine0(void) interrupt 1
{
        TR0 = 0;                //Deactivate Timer 0
        TL0 = 0x00;             //Setting timer Initial value again
        TH0 = 0xFF;             //Setting timer Initial value again
        TF0 = 0;                //Set Timer Overflow Flag to 0
        TR0 = 1;                //Activate Timer 0

        ++count;
        if (myFlag == 0 && count > FUNC1) {
                //Call Func1
                Func1();
                myFlag = 1;
                count = 0;
        }
        else if (myFlag == 1 && count > FUNC2) {
                //Call Func2
                Func2();
                myFlag = 0;
                count = 0;
        }
}

/*------------------------------------------------------------*/
void main(void)
{
/*------------------------------------------------
Setup the serial port for 1200 baud at 16MHz.
------------------------------------------------*/
#ifndef MONITOR51
    SCON  = 0x50;                       /* SCON: mode 1, 8-bit UART, enable rcvr      */
    TMOD |= 0x20;               /* TMOD: timer 1, mode 2, 8-bit reload        */
    TH1   = 221;                /* TH1:  reload value for 1200 baud @ 16MHz   */
    TR1   = 1;                  /* TR1:  timer 1 run                          */
    TI    = 1;                  /* TI:   set TI to send first char of UART    */
#endif

        Timer_0_Init();
        while(1) {
                //Do Nothing, wait for Timer overflow which inturn calls ISR
                ;
        }
}

Thanks for your Time and Help

Parents
  • .... had I coded something and asked someone (no web) "what is wrong" and been told "You can successfully do this" I would have persisted up the road I was travelling and lost a lot of time.

    I'm afraid that's your inability to read and understand things in context coming to the fore.

    When you make statements that are FALSE in 99.9% of the cases DO NOT DO SO WITHOUT stating all ramifications of doing so or you will lead many down the garden path.

    I pointed out that there were considerations. As one of the regular proponents of making people think rather than presenting them with a complete package I thought you'd approve.

    How can you (in sardinespeak) state "You can successfully printf() from an ISR" without knowing if the OPs UART is interrupt driven or not?

    How can you (in sardinespeak) state "You can successfully printf() from an ISR" without knowing the OPs program timnings?

    How can you (in sardinespeak) state "You can successfully printf() from an ISR" without knowing the OPs printf frequency?

    That information is all readily available in the code the OP posted. However, these details are irrelevant - none of those things prevent one from being able to successfully printf() from an ISR.

    YES an advanced user may be able to pull some rabbits out of the hat, but to avoid misunderstandings either state the 99% truism or give ALL EACH and EVERY ramification of doing it

    I wouldn't have described calling printf() from an ISR as "pulling rabbits out of the hat", more a question of understanding the implications and consequences of doing so. Given that you view this as a magic trick only achieveble by an advanced user it would be a useful educational exercise for you to research and list the ramifications yourself.

Reply
  • .... had I coded something and asked someone (no web) "what is wrong" and been told "You can successfully do this" I would have persisted up the road I was travelling and lost a lot of time.

    I'm afraid that's your inability to read and understand things in context coming to the fore.

    When you make statements that are FALSE in 99.9% of the cases DO NOT DO SO WITHOUT stating all ramifications of doing so or you will lead many down the garden path.

    I pointed out that there were considerations. As one of the regular proponents of making people think rather than presenting them with a complete package I thought you'd approve.

    How can you (in sardinespeak) state "You can successfully printf() from an ISR" without knowing if the OPs UART is interrupt driven or not?

    How can you (in sardinespeak) state "You can successfully printf() from an ISR" without knowing the OPs program timnings?

    How can you (in sardinespeak) state "You can successfully printf() from an ISR" without knowing the OPs printf frequency?

    That information is all readily available in the code the OP posted. However, these details are irrelevant - none of those things prevent one from being able to successfully printf() from an ISR.

    YES an advanced user may be able to pull some rabbits out of the hat, but to avoid misunderstandings either state the 99% truism or give ALL EACH and EVERY ramification of doing it

    I wouldn't have described calling printf() from an ISR as "pulling rabbits out of the hat", more a question of understanding the implications and consequences of doing so. Given that you view this as a magic trick only achieveble by an advanced user it would be a useful educational exercise for you to research and list the ramifications yourself.

Children
  • Can somebody please quickly elaborate on the ramifications of calling printf from an ISR mentioned in this thread?

  • How can you (in sardinespeak) state "You can successfully printf() from an ISR" without knowing if the OPs UART is interrupt driven or not?

    ..... these details are irrelevant - none of those things prevent one from being able to successfully printf() from an ISR.

    since when ?

    One example of a relevant detail is that if putchar is ISR driven you can't. DO NOTE the MCU: above.

    In most cases printf() from an ISR will lead to some other ISR not being serviced in a timely fashion or the ISR with the printf being constantly seviced i.e. it takes so long to execute that it is activated again before it is done.

    Putting a printf in an ISR is an abhorrent violation if the KISS principle (keep ISRs short & simple)

    One point to the above is that the problems can show up in an intermittent way making the debugging (of what is wrong in the first place) virtually impossible.

    Erik

  • I'm afraid that's your inability to read and understand things in context coming to the fore.
    so, you are back to your old tricks, when you can not see a technical reason you go personal.

    Erik

  • printf is not reentrant of a C51 (as far as I know).

  • How can you (in sardinespeak) state "You can successfully printf() from an ISR" without knowing if the OPs UART is interrupt driven or not?

    That information is all readily available in the code the OP posted. However, these details are irrelevant - none of those things prevent one from being able to successfully printf() from an ISR.

    since when ?

    The first 'C' compiler for the 8051.

    One example of a relevant detail is that if putchar is ISR driven you can't. DO NOTE the MCU: above.

    Well, it is possible that the variant is specified somewhere in this thread and I've missed it, but I'm assuming that it's a pretty straightforward 8051.

    I'm interested in your idea of an "ISR driven" putchar(). Here's a fairly generic putchar() implementation for interrupt driven serial communications:

    /*------------------------------------------------------------------------------
    ------------------------------------------------------------------------------*/
    #pragma disable
    
    char com_putchar (
      unsigned char c)
    {
    /*------------------------------------------------
    If the buffer is full, return an error value.
    ------------------------------------------------*/
    if (com_tbuflen () >= TBUF_SIZE)
      return (-1);
    
    /*------------------------------------------------
    Add the data to the transmit buffer.  If the
    transmit interrupt is disabled, then enable it.
    ------------------------------------------------*/
    tbuf [t_in & (TBUF_SIZE - 1)] = c;
    t_in++;
    
    if (ti_restart)
      {
      ti_restart = 0;
      TI = 1;               /* generate transmit interrupt */
      }
    
    return (0);
    }
    

    Could you give me some idea of how putchar() might be "ISR driven" and how that would prevent one from successfully calling printf() from an ISR?

    In most cases printf() from an ISR will lead to some other ISR not being serviced in a timely fashion or the ISR with the printf being constantly seviced i.e. it takes so long to execute that it is activated again before it is done.

    Ok, there's ramification number 1 for your list.

    Putting a printf in an ISR is an abhorrent violation if the KISS principle (keep ISRs short & simple)

    Last time I heard KISS it meant 'Keep It Simple Stupid' which seemed rather more snappy.

    One point to the above is that the problems can show up in an intermittent way making the debugging (of what is wrong in the first place) virtually impossible.

    This is why one needs to be aware of the ramifications.

  • I'm afraid that's your inability to read and understand things in context coming to the fore.

    so, you are back to your old tricks, when you can not see a technical reason you go personal.

    You quote what I say removing the context, then comment on your interpretation of what is left. Either this is wilfull misquoting or it it a deliberate attempt to distract attention from your technical shortcomings.

    I was giving you the benefit of the doubt, but there you go.

  • Could you give me some idea of how putchar() might be "ISR driven" and how that would prevent one from successfully calling printf() from an ISR?
    ... then each and every point you have made is moot

    Erik

  • Either this is wilfull misquoting or it it a deliberate attempt to distract attention from your technical shortcomings

    it is pointing out that because of YOUR "technical shortcomings" (re the '51 and C51)you resort to personal attacks.

    Erik

  • Could you give me some idea of how putchar() might be "ISR driven" and how that would prevent one from successfully calling printf() from an ISR?

    ... then each and every point you have made is moot

    Is that really your best attempt at answering the question?

  • Is that really your best attempt at answering the question?

    attempt, no, but if you do not know how printf/putchar can be ISR driven, then your postings in this thread are invalid.

    Of course, if you are one of those that can only work with waitI/O, then I understand your problem.

    Erik

  • Either this is wilfull misquoting or it it a deliberate attempt to distract attention from your technical shortcomings

    it is pointing out that because of YOUR "technical shortcomings" (re the '51 and C51)you resort to personal attacks.

    You see? You've done it again. You've removed the sentence before the one you've quoted which contains the information to which the quote refers, then tried to use the remainder as an opportunity to complain that being shown to be wrong is a personal attack.

    You really do need to either make more of an effort to post correct information or grow a thicker skin.

  • attempt, no, but if you do not know how printf/putchar can be ISR driven, then your postings in this thread are invalid.

    Of course, if you are one of those that can only work with waitI/O, then I understand your problem.

    In a sane interrupt driven serial comms implementation neither printf() nor putchar() are interrupt driven. printf() calls putchar(), and putchar() places the character passed to it in a buffer. If necessary putchar() sets TI to stimulate the first serial interrupt. That's it - neither printf() nor putchar() are driven by an ISR nor does this prevent printf() being called from an ISR.

    If you think you can show otherwise please do.

  • In a sane interrupt driven serial comms implementation neither printf() nor putchar() are interrupt driven. printf() calls putchar(), and putchar() places the character passed to it in a buffer. If necessary putchar() sets TI to stimulate the first serial interrupt. That's it - neither printf() nor putchar() are driven by an ISR nor does this prevent printf() being called from an ISR.

    I am SOOOOO sorry, what you write I can ONLY read as "printf/putchar can be ISR driven", if you want me to convert to your verbiose babbeling style, I refuse.

    Erik

  • If necessary putchar() sets TI to stimulate the first serial interrupt.

    I am SOOOOO sorry, what you write I can ONLY read as "printf/putchar can be ISR driven", if you want me to convert to your verbiose babbeling style, I refuse.

    Your attempts to get out of this one with your skin intact are becoming increasingly amusing. By your argument this:

    void main(void)
    {
       EA=1;
       ES=1;
       TI=1;
    
       while(1);
    }
    

    is an interrupt driven main.