USART TX Interrupt problem. (DT_INTS)


Closed Thread
Results 1 to 12 of 12
  1. #1
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521

    Default USART TX Interrupt problem. (DT_INTS)

    Hello everyone,

    I've got a bit of a problem getting my USART TX interrupt working correctly (using DT_INTS), something that I've done numerous times before. This is on a 18F25K20 (on the AMICUS 18 board) and here the piece of code I'm using as a base for testing:
    Code:
    DEFINE OSC 64
    DEFINE LOADER_USED 1            ' We're using a bootloader.
    DEFINE HSER_RCSTA 90h           ' Enable serial port & continuous receive
    DEFINE HSER_TXSTA 24h           ' Enable transmit, BRGH = 1
    DEFINE HSER_CLROERR 1           ' Clear overflow automatically
    DEFINE HSER_SPBRG 138           ' 115200 Baud @ 64MHz, -0,08%
     
    SPBRGH = 0
    BAUDCON.3 = 1                   ' Enable 16 bit baudrate generator
     
    INCLUDE "DT_INTS-18.bas"        ' Include Darrels interrupt engine.
    INCLUDE "ReEnterPBP-18.bas"     ' And the stub needed for interrupts in PBP 
     
    ASM                             ; Set up the USART transmit interrupt.
    INT_LIST  macro     ; IntSource,   Label,    Type, ResetFlag?
            INT_Handler    TX_INT,   _USART_TX,   PBP,    no
        endm
        INT_CREATE                  ; Creates the interrupt processor
    ENDASM
     
    String_1    VAR BYTE 50       ' Array to hold string.
    TXPointer   VAR BYTE           ' Pointer into array
     
    HSEROUT["Program start",13,13]
     
    ArrayWrite String_1, ["This is the content of String_1",13,0]
     
    '-------------------------------------------------------------------
    HSEROUT["First test:  "]
    HSEROUT[STR String_1]
    Pause 200
    '-------------------------------------------------------------------
     
    '-------------------------------------------------------------------
    HSEROUT["Second test: "]
    TxPointer = 0
    While String_1[TxPointer] <> 0
      HSEROUT[String_1[TXPointer]]
      TxPointer = TxPointer + 1
    WEND
    Pause 200
    '-------------------------------------------------------------------
     
    '-------------------------------------------------------------------
    HSEROUT["Third test:  "]
    TxPointer = 0
    @  INT_ENABLE TX_INT
    Pause 200
    '-------------------------------------------------------------------
     
    '-------------------------------------------------------------------
    HSEROUT["Fourth test: "]
    TxPointer = 0
    While String_1[TxPointer] <> 0
      HSEROUT[String_1[TXPointer]]
      TxPointer = TxPointer + 1
    WEND
    Pause 200
    '-------------------------------------------------------------------
     
    END
     
    '-- Interrupt service rotuine for USART TX Interrupt ---------------
    USART_TX:
      TXReg = String_1[TxPointer]       ' Load character from array into USART TX register
      If String_1[TxPointer] = 0 then   ' If that character was a NULL we're done so we.....
    @   INT_DISABLE  TX_INT             ; ...disable the any further USART TX interrupts.
      ELSE                              ' If the character was not a CR we.....
        TxPointer = TxPointer + 1       ' ...increase the pointer, prepare to send the next character.
      ENDIF                             ' As soon as the TX-reg is empty the interrupt will fire again. (~1ms at 9600baud)
    @ INT_RETURN
    As you can see I load an array with a short string and then I send it out using various methods. This works exactly as I want, on the serial terminal I get the following, each time I reset the device:
    Program start

    First test: This is the content of String_1
    Second test: This is the content of String_1
    Third test: This is the content of String_1
    Fourth test: This is the content of String_1
    However, if I now increase the size of the array to 100 it messes up and I get this instead:
    Program start

    First test: This is the content of String_1
    Second test: This is the content of String_1
    Third test: TFourth test: T
    As you can see something is now messed up and I don't understand what and why. The interrupt routine seems to disable the interrupt after the first character and then, what previously worked fine in Test2, no longer works either. As if the array got corrupted.

    As a debug aid I then added a fifth output as follows:
    Code:
    HSEROUT[13, "Fifth test",13]
    For TXPointer = 0 to 35
      HSEROUT [DEC TXPointer,": ", DEC String_1[TXPointer],13]
    NEXT
    Pause 200
     
    END
    The output of this clearly shows why the interrupt routine (and the following WHILE-WEND routine) stops sending - there's now a NULL at location 1 in the array - the array has somehow gotten corrupted:
    First test: This is the content of String_1
    Second test: This is the content of String_1
    Third test: TFourth test: T
    Fifth test
    0: 84
    1: 0
    2: 0
    3: 115
    4: 32
    5: 133
    6: 0
    7: 32
    8: 116
    9: 104
    10: 0
    The 25K20 used here has 1536 bytes of RAM so I can't imagine it's running out of room - in which case I should've gotten a message about it not being able to fit the array, which I don't.

    This was initially with 2.60A but I've tried with 3.01 and I get the same results.

    I've tried declaring the array as various sizes. At 50 bytes everything works, so does 63 but at 64 bytes it "starts" to fall apart, the output then becomes:
    First test: This is the content of String_1
    Second test: This is the content of String_1
    Third test: This is the content of String_1
    `Fourth test: This is the content of String_1
    `
    What am I doing wrong here? Why is the ISR corrupting my array? I've got the ISR declared as type PBP so it's not that. What is that I'm not seeing here?

    /Henrik.

  2. #2


    Did you find this post helpful? Yes | No

    Default Re: USART TX Interrupt problem. (DT_INTS)

    Hi,
    may need a different pointer for TX int if you are using that one for HSER also. I think they will get intertwined !?

    don

  3. #3
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: USART TX Interrupt problem. (DT_INTS)

    Thanks don,
    I was actually trying some things with regards to your latest thread when I stumbled across this.

    You have a good point. However, I don't think different pointers will make any difference in this case. Here's the reason(s) for my statement.

    1) I have a Pause 500 after enabling the interrupt, that's more than enough to send the string out. This means that TXPointer is free to use when "test 4" begins.

    2) If that was the case then the size of the array wouldn't matter. Note that I'm not changing the amount of data actually written to the array, I just change the declared size of it. 50 works, 100 doesn't.

    3) When test 5 is executed it shows that the actuall content of the array is changed. I forgot to mention this is in first post but I initially used another pointer variable (not TXPointer) in Test5 and it gave the same result as when using TXPointer - ie, it shows that the array is corrupted.

    /Henrik.

  4. #4


    Did you find this post helpful? Yes | No

    Default Re: USART TX Interrupt problem. (DT_INTS)

    OK then,

    This puts a byte at location 50 (dec) in ram
    Code:
    String_1    VAR BYTE 50       ' Array to hold string.
    this puts array of 50 where PBasic puts it
    Code:
    String_1    VAR BYTE  [50]             ' Array to hold string.
    this puts array of 50 at location $100, (100hex, 256 dec)
    Code:
    String_1    VAR BYTE  [50]              $100     ' Array to hold string.

    At the bottom of the generated LIST file is a listing of the mem locations for ram and prog mem
    there you can see the var's location and alotted space left between arrays.

    Name:  Capture2.JPG
Views: 551
Size:  120.8 KB

    Don
    Last edited by amgen; - 16th August 2011 at 13:39.

  5. #5
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: USART TX Interrupt problem. (DT_INTS)

    That's it, thank you!
    It was all in the declaration, I had forgot the brackets!

    Can't belive I didn't think of that - the number of times I've been there and changed the value and missed the missing brackets. Guess, since it worked with an imiginary lenght of 50 it was harder to see.

    Thanks again!

    /Henrik.

  6. #6


    Did you find this post helpful? Yes | No

    Default Re: USART TX Interrupt problem. (DT_INTS)

    that will be $1 or cup of coffee or credit for my future dumb stuff

    don

  7. #7
    Join Date
    Mar 2003
    Location
    Commerce Michigan USA
    Posts
    1,166


    Did you find this post helpful? Yes | No

    Default Re: USART TX Interrupt problem. (DT_INTS)

    Henerik, Why are you using HSEROUT when you have the interrupt all setup?
    Dave Purola,
    N8NTA
    EN82fn

  8. #8
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: USART TX Interrupt problem. (DT_INTS)

    Because the interrupt messed up my array of data and the HSEROUT statements helped me show what was going on. Which turned out to be that I hadn't declared the array properly.

  9. #9
    Join Date
    Mar 2003
    Location
    Commerce Michigan USA
    Posts
    1,166


    Did you find this post helpful? Yes | No

    Default Re: USART TX Interrupt problem. (DT_INTS)

    Yeah, I understand that but, Why don't you just load the array with your message and then enable the interrupt? You have the code there already.. The interrupt will disable it when the message is sent... I have used this methode for the last few years but not with the ARRAYREAD or ARRAYWRITE statements... Just loose the HSEROUT stuff.... THat way it's all done in the background...
    Dave Purola,
    N8NTA
    EN82fn

  10. #10
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: USART TX Interrupt problem. (DT_INTS)

    Dave,
    That was the purpose all along and that is exactly what I did - but it didn't work, it just gave me garbage as you can see in my first post. So I added the HSEROUT statements to help debug the problem which, again, was my erronous array declaration. Now when teh problem is found and fixed the HSEROUT statements are gone.

    The code isn't "production code" it's code to illustrate the problem I had with the interrupt routine corrupting my array.

    /Henrik.

  11. #11
    Join Date
    Mar 2003
    Location
    Commerce Michigan USA
    Posts
    1,166


    Did you find this post helpful? Yes | No

    Default Re: USART TX Interrupt problem. (DT_INTS)

    Henrik, Yes I understand now. However if you are going to use this routine:
    '-- Interrupt service rotuine for USART TX Interrupt ---------------
    USART_TX:
    TXReg = String_1[TxPointer] ' Load character from array into USART TX register
    If String_1[TxPointer] = 0 then ' If that character was a NULL we're done so we.....
    @ INT_DISABLE TX_INT ; ...disable the any further USART TX interrupts.
    ELSE ' If the character was not a CR we.....
    TxPointer = TxPointer + 1 ' ...increase the pointer, prepare to send the next character.
    ENDIF ' As soon as the TX-reg is empty the interrupt will fire again. (~1ms at 9600baud)
    @ INT_RETURN

    I would check for the end of the string before I send the a character, That way you won't be sending the null character from the end of the array. You will get an interrupt when the last character is sent and at that time you don't want to be sending any more, just disable the interrupt and leave.... just change the routine to read:

    '-- Interrupt service rotuine for USART TX Interrupt ---------------
    USART_TX:
    If String_1[TxPointer] = 0 then ' If that character was a NULL we're done so we.....
    @ INT_DISABLE TX_INT ; ...disable the any further USART TX interrupts.
    ELSE ' If the character was not a CR we.....
    TXReg = String_1[TxPointer] ' Load character from array into USART TX register
    TxPointer = TxPointer + 1 ' ...increase the pointer, prepare to send the next character.
    ENDIF ' As soon as the TX-reg is empty the interrupt will fire again. (~1ms at 9600baud)
    @ INT_RETURN
    Dave Purola,
    N8NTA
    EN82fn

  12. #12
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: USART TX Interrupt problem. (DT_INTS)

    Hi Dave,
    Good point! I cut and pasted the routine from a working program in which I used 13 as the string terminator - which I did want to send. With NULL as the terminator checking it first is of course better.

    /Henrik.

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts