News:

PROTON pic BASIC Compilers for PIC, PIC24, dsPIC33

Main Menu

UART problem with dsPIC33CK256MP505

Started by charliecoutas, Nov 26, 2021, 10:17 PM

Previous topic - Next topic

charliecoutas

This is driving me nuts. I can't get the UART1 to work on the above chip. I have carved the code right down to leave just the basics.


    Device = 33CK256MP505
    Declare Xtal = 200

    Declare Hserial1_Baud = 9600
    Symbol    led             PORTC.12
    Symbol    U1RXIF          IFS0.11                                   ;UART1 int flag
    Symbol    U1RXIE          IEC0.11                   

    $define IPC2bits_U1RXIP0 IPC2.12
    $define IPC2bits_U1RXIP1 IPC2.13
    $define IPC2bits_U1RXIP2 IPC2.14   
 
    IntOsc_200MHz()                                                     ;set the device to operate at 200MHz with its internal oscillator 
 
$define PPS_OutPin_RB14 cOut_Pin_RP46
$define PPS_InPin_RB15 cIn_Pin_RP47
 
    PPS_Unlock()                                                        ;unlock the PPS peripheral
    PPS_Output(PPS_OutPin_RB14, cOut_Fn_U1TX)                           ;set the appropriate PPS pin for the USART1 peripheral TX
    PPS_Input(PPS_InPin_RB15, cIn_Fn_U1RX)                              ; ..  ..  input  on R15

       ANSELB = 0
       ANSELC = 0
       TRISC.12 = 0
       TRISB.15 = 1

       led = 1                                                          ;show that we're running
       DelayMS 100
       led = 0

       IPC2bits_U1RXIP0 = 1                            ' \
       IPC2bits_U1RXIP1 = 1                            ' | USART1 RX interrupt priority
       IPC2bits_U1RXIP2 = 1                            ' /
       
       U1RXIF = 0                                                       ;avoid false int at start
       U1RXIE = 1                                                       ;allow UART to interrupt

       HRSOut "Hello"
       
       INTCON2.15 = 1                                                   ;allow interrupts   

       While
       Wend

Isr U1RXInterrupt                                                       ;async channel 1 - a char has arrived                                                   
      While
        DelayMS 100
        Toggle led
      Wend         
EndIsr

Proc IntOsc_200MHz()
    CLKDIV = $3001          ' FRCDIV FRC/1, PLLPRE 1, DOZE 1:8
    PLLFBD = 100
    OSCTUN = %00011 ;$00
    PLLDIV = $21            ' POST1DIV 1:2, VCODIV FVCO/4, POST2DIV 1:1
    ACLKCON1 = $0101        ' FRCSEL FRC, APLLPRE 1:1
    APLLFBD1 = $C8
    APLLDIV1 = $42          ' APOST1DIV 1:4, APOST2DIV 1:2, AVCODIV FVCO/4*)

    Write_OSCCONH($01)
    Write_OSCCONL($01)

    While OSCCONbits_OSWEN <> 0 : Wend  ' Wait for the clock switch to occur
EndProc

    Config FSEC     = BWRP_OFF, BSS_DISABLED, BSEN_OFF, GWRP_OFF, GSS_DISABLED, CWRP_OFF, CSS_DISABLED, AIVTDIS_OFF
    Config FOSCSEL  = FNOSC_FRC, IESO_OFF
    Config FOSC     = POSCMD_NONE, OSCIOFNC_ON, FCKSM_CSECMD, PLLKEN_OFF, XTCFG_G0, XTBST_ENABLE
    Config FWDT     = SWDTPS_PS2147483648, RCLKSEL_LPRC
    Config FPOR     = BISTDIS_DISABLED
    Config FICD     = ICS_PGD1, JTAGEN_OFF, NOBTSWP_DISABLED
    Config FDMT     = DMTDIS_OFF
    Config FDEVOPT  = 0xF8FF ''ALTI2C1_OFF, ALTI2C2_OFF, ALTI2C3_OFF, SMBEN_STANDARD, SPI2PIN_PPS  mod by diebobo - Bob
;    Config FDEVOPT  = ALTI2C1_ON, ALTI2C2_ON, ALTI2C3_ON, SMBEN_STANDARD, SPI2PIN_PPS
    Config FALTREG  = CTXT1_OFF, CTXT2_OFF, CTXT3_OFF, CTXT4_OFF 

It starts, flashes the led once, sends "Hello" to the HC-12 (which is sent OK), then does nothing. I transmit characters with another HC-12 and I can see them arriving on pin 2 of the chip (PORTB.15) but it never enters the interrupt routine.  I tried Les's example of interrupt driven UART and that wouldn't work either.

Any ideas?

Charlie

diebobo

I got it working charlie will send example when home tonight.. compared to 24fj devices it has some more "rules" before it behaves as wanted

charliecoutas

Trying to get something working would be almost impossible without help like this.
Many thanks Bob.

Charlie

top204

#3
Within your RX interrupt, you should read the RX buffer to move it, and usually clear the RX flag:

IFS0bits_U1RXIF = 0  ' Clear the interrupt request flag

On some devices this is not required and reading the buffer auto clears it, but these days you can never tell what is actually required, and it may wait until teh buffer is full before it is cleared, so better safe than sorry.

Here is a complete serial interrupt buffer for the dsPIC33CK devices, tested on a dsPIC33CK128MP202, so it should work with other dsPIC33xxCK devices, but you can never tell these days with Microchip. The AVR and ARM users are in for a big shock when they use the new devices that Microchip are in charge of now. Things will change for the sake of change and what used to work on them for many years, and were standards on them, will need re-writing. :-) I wrote the following code to test the interrupt mechanism on the dsPIC33xxCK devices and it works well.

I, personally, think you chose the wrong dsPIC33xxCK device to start writing for a new type Charlie. The larger devices are always more complex with all the PIC families, and have more peripherals to cater for, or switch off etc... You should have started with one of the smaller devices that have what is required for tests, but not all the rest of the "not required" peripherals, then move up when the code is working and you are confident with the device's specs.

Below are the library routines that replaces the compiler's HRsin/HSerin commands with and without timeouts:

$ifndef _USART1_Buffer33CK_inc_
$define _USART1_Buffer33CK_inc_
'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Buffered USART receiver that replaces the compiler's Hrsin1 command library routines, both with and without timeout
' Written specifically for dsPIC33xxCK devices.
'
' Written for the Positron16 compiler by Les Johnson
'
' The compiler will produce the following hooks for use with #ifSym:
' __SYSCOM_HRSIN1_REQ_      for the HRSIn command without timeout
' __SYSCOM_HRSIN1_TO_REQ_   for the HRSIn command with timeout
'
    #Disable HRSIn1, HRsin1To                               ' Disable the compiler's Hrsin1 (with and without timeout) library routines
'
' Default size of the RX buffer
'
$ifndef cUSART_RXBufferSize
    $define cUSART_RXBufferSize 64
    $SendWarning "$define cUSART_RXBufferSize missing, so using an RX buffer size of 64 bytes"
$endif
'
' Create some variables for use with the interrupt RX buffer
'
    Dim _USART1_bRxBuffer[cUSART_RXBufferSize] As Byte          ' The RX buffer array
    Dim _USART1_wRxIndexIn  As Word                             ' RX Data in pointer
    Dim _USART1_wRxIndexOut As Word                             ' RX Data out pointer
    Dim USART1_tRxOverrun   As Bit                              ' RX Buffer Overrun flag

$define cHrsin1_TimeoutPadding $eval (((80 * _xtal) / 2) - 1)  ' Hrsin1 timeout delay padding

$ifndef False
    $define False 0
$endif
$ifndef True
    $define True 1
$endif

'-------------------------------------------------------------------------------------------
$define USART1_Isr_RxEnable()  IEC0bits_U1RXIE = 1  ' Enable the USART1 RX Interrupt
$define USART1_Isr_RxDisable() IEC0bits_U1RXIE = 0  ' Disable the USART1 RX interrupt

'-------------------------------------------------------------------------------------------
' IPC2 Bits
'
$ifndef IPC2bits_U1RXIP0
    $define IPC2bits_U1RXIP0 IPC2.12
    $define IPC2bits_U1RXIP1 IPC2.13
    $define IPC2bits_U1RXIP2 IPC2.14
$endif

'-------------------------------------------------------------------------------------------
' Reset the buffer variables
' Input     : None
' Output    : None
' Notes     : None
'
Proc USART1_BufferReset()
    USART1_Isr_RxDisable()                          ' Disable the USART1 RX interrupt
    USART1_tRxOverrun = False                       ' Reset the Overrun flag
    Clear _USART1_bRxBuffer                         ' Clear the RX buffer array
    _USART1_wRxIndexIn = 0                          ' \
    _USART1_wRxIndexOut = 0                         ' / Reset the RX data in and out pointers
    IFS0bits_U1RXIF = 0                             ' Clear the interrupt request flag
    USART1_Isr_RxEnable()                           ' Enable the USART1 RX interrupt
EndProc

'-------------------------------------------------------------------------------------------
' Initialise the buffer and the USART1 RX interrupt handler
' Input     : None
' Output    : None
' Notes     : The procedure also contains the interrupt handler
'
Proc USART1_Init()
    USART1_Isr_RxDisable()                          ' Disable the USART1 RX interrupt
    PinInput __HRSIN1_Port.__HRSIN1_Pin             ' Make the Hrsin1 pin an input
    USART1_tRxOverrun = False                       ' Reset the RX Overrun flag
    Clear _USART1_bRxBuffer                         ' Clear the RX buffer array
    _USART1_wRxIndexIn = 0                          ' \
    _USART1_wRxIndexOut = 0                         ' / Reset the RX data in and out pointers
    IPC2bits_U1RXIP0 = 1                            ' \
    IPC2bits_U1RXIP1 = 1                            ' | USART1 RX interrupt priority
    IPC2bits_U1RXIP2 = 1                            ' /
    IFS0bits_U1RXIF = 0                             ' Clear the RX interrupt request flag
    USART1_Isr_RxEnable()                           ' Enable the USART1 RX interrupt
    ExitProc
'
' USART1 RX interrupt handler to buffer incoming data
'
Isr U1RXInterrupt                                   ' USART1 RX interrupt
    #ifSym __SYSCOM_HSERIAL1_CLEAR_REQ_             ' Has the Hserial_Clear declare been used in the program?
        If U1STAbits_OERR = 1 Then                  ' Yes. So is there an overrun error?
            U1STAbits_OERR = 0                      ' Yes. So clear it
            GoTo Exit_Interrupt                     ' And exit the interrupt
        EndIf
    #endIfSym
    _USART1_bRxBuffer[_USART1_wRxIndexIn] = U1RXREG ' Read a data byte from USART1
    Inc _USART1_wRxIndexIn                          ' Move up the buffer
    If _USART1_wRxIndexIn > cUSART_RXBufferSize Then    ' Has the buffer been filled?
        _USART1_wRxIndexIn = 0                      ' Yes. So reset the in pointer
    EndIf
Exit_Interrupt:
    IFS0bits_U1RXIF = 0                             ' Clear the interrupt request flag
EndIsr                                              ' Exit the interrupt handler
EndProc

'----------------------------------------------------------------------------
' Jump over the replacement library subroutines (if they are enabled)
'
#ifSym __SYSCOM_HRSIN1_REQ_, __SYSCOM_HRSIN1_TO_REQ_
    GoTo _BufferedHrsin1_Main
#endIfSym

'----------------------------------------------------------------------------
' Hrsin1 replacement code with timeout
' Input     : PRTA1 = timeout value
' Output    : WREG0.Byte0
'           : Carry flag clear if timed out
' Notes     : Follows exactly the method used by the compiler's library routine
'
#ifSym __SYSCOM_HRSIN1_TO_REQ_
__hrsin1__to:
    Push.d WREG2                                ' Save WREG2 and WREG3 on the stack
    WREG2 = PRTA1                               ' Move the timeout value (passed from the command) to WREG2
    WREG3 = 0                                   ' Clear the timeout loop counter
    Do                                          ' Create an infinite loop
        DelayCS 1                               ' Padding for 1 cycle
        If _USART1_wRxIndexIn <> _USART1_wRxIndexOut Then ' Is there any data in the buffer?
            Pop.d WREG2                         ' Yes. So restore WREG2 and WREG3
            GoTo __hrsin1__getbyte              ' Get the byte from USART1, and exit the routine from there
        EndIf
        WREG0 = 0
        Dec WREG3                               ' Decrement the inner loop counter
        If SRbits_C = 1 Then Continue           ' Continue if gone below zero
        Dec WREG2                               ' Decrement the outer loop counter
        If SRbits_C = 0 Then                    ' Is the carry flag clear?
            Pop.d WREG2                         ' Yes. So restore WREG2 and WREG3 from the stack
            Return                              ' Exit the subroutine
        EndIf
        WREG3 = cHrsin1_TimeoutPadding          ' Reload the timout padding into WREG3
    Loop                                        ' Look again
#endIfSym
'
'----------------------------------------------------------------------------
' Hrsin1 replacement code without timeout
' Input     : None
' Output    : WREG0.Byte0
' Notes     : None
'
#ifSym __SYSCOM_HRSIN1_REQ_
__hrsin1:
    While _USART1_wRxIndexIn = _USART1_wRxIndexOut      ' \ Wait for data in the buffer
    Wend                                                ' /
'
' Fall through to __hrsin1__getbyte
'
#endIfSym
'----------------------------------------------------------------------------
' Get a single byte from the buffer and place it into WREG0.Byte0
'
#ifSym __SYSCOM_HRSIN1_REQ_, __SYSCOM_HRSIN1_TO_REQ_
__hrsin1__getbyte:
    WREG2.Byte0 = _USART1_bRxBuffer[_USART1_wRxIndexOut]    ' Place a buffer byte into WREG2.Byte0
    Inc _USART1_wRxIndexOut                                 ' Move up the buffer
    If _USART1_wRxIndexOut > cUSART_RXBufferSize Then       ' Is the out index over-running the buffer size?
        _USART1_wRxIndexOut = 0                             ' Yes. So reset it
    EndIf
    WREG0.Byte0 = WREG2.Byte0                               ' Transfer the byte from the buffer to WREG0
    Set SRbits_C                                            ' Set the carry flag to indicate byte received
    Return                                                  ' Exit the subroutine
#endIfSym

'----------------------------------------------------------------------------
_BufferedHrsin1_Main:

$endif  ' _USART1_Buffer33CK_inc_

Name the file created from the above code listing; "USART1_Buffer33CK.inc"

Below is the demo to test the library above:

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Demonstrate the buffered USART library that replaces the routines used by the Hrsin1 and HSerin1 commands
' The demo will receive bytes from a serial terminal and echo them back
'
' Written for the Positron16 compiler by Les Johnson
'
    Device = 33CK128MP202
    Declare Xtal = 160
'
' USART1 setup
'
    Declare Hserial_Baud = 9600
    Declare HRSOut1_Pin = PORTB.0
    Declare HRSIn1_Pin  = PORTB.1

$define cUSART_RXBufferSize 128
   
    Include "USART1_Buffer33CK.inc"                   ' Load the buffered Hrsin routines into the program
'
' PPS output defines
'
$define PPS_OutPin_RB0  cOut_Pin_RP32
$define PPS_OutPin_RB1  cOut_Pin_RP33
$define PPS_OutPin_RB2  cOut_Pin_RP34
$define PPS_OutPin_RB3  cOut_Pin_RP35
$define PPS_OutPin_RB4  cOut_Pin_RP36
$define PPS_OutPin_RB5  cOut_Pin_RP37
$define PPS_OutPin_RB6  cOut_Pin_RP38
$define PPS_OutPin_RB7  cOut_Pin_RP39
$define PPS_OutPin_RB8  cOut_Pin_RP40
$define PPS_OutPin_RB9  cOut_Pin_RP41
$define PPS_OutPin_RB10 cOut_Pin_RP42
$define PPS_OutPin_RB11 cOut_Pin_RP43
$define PPS_OutPin_RB12 cOut_Pin_RP44
$define PPS_OutPin_RB13 cOut_Pin_RP45
$define PPS_OutPin_RB14 cOut_Pin_RP46
$define PPS_OutPin_RB15 cOut_Pin_RP47
'
' PPS input defines
'
$define PPS_InPin_RB0  cIn_Pin_RP32
$define PPS_InPin_RB1  cIn_Pin_RP33
$define PPS_InPin_RB2  cIn_Pin_RP34
$define PPS_InPin_RB3  cIn_Pin_RP35
$define PPS_InPin_RB4  cIn_Pin_RP36
$define PPS_InPin_RB5  cIn_Pin_RP37
$define PPS_InPin_RB6  cIn_Pin_RP38                                                                                                                                             
$define PPS_InPin_RB7  cIn_Pin_RP39
$define PPS_InPin_RB8  cIn_Pin_RP40
$define PPS_InPin_RB9  cIn_Pin_RP41
$define PPS_InPin_RB10 cIn_Pin_RP42
$define PPS_InPin_RB11 cIn_Pin_RP43
$define PPS_InPin_RB12 cIn_Pin_RP44
$define PPS_InPin_RB13 cIn_Pin_RP45
$define PPS_InPin_RB14 cIn_Pin_RP46
$define PPS_InPin_RB15 cIn_Pin_RP47
'
' Create a variable for the demo
'   
    Dim MyByte As Byte

'----------------------------------------------------------------------------
Main: 
    IntOsc_160MHz()                                     ' Set the device to operate at 160MHz with its internal oscillator
   
    USART1_Init()                                       ' Initialise the USART1 buffer interrupt
   
    PPS_Unlock()                                        ' Unlock the PPS peripheral
    PPS_Output(PPS_OutPin_RB0, cOut_Fn_U1TX)            ' Set the appropriate PPS pin for the USART1 peripheral TX
    PPS_Input(PPS_InPin_RB1, cIn_Fn_U1RX)               ' Set the appropriate PPS pin for the USART1 peripheral RX
   
    HRSOutLn "Start"
      
    Do                                                  ' Create a loop
        Do                                              ' Create a loop
            MyByte = HRSIn1, {5000, TimeOutLabel}       ' Receive a serial byte with timeout
            DelayMS 500                                 ' Create a large delay between reception and transmission to test the buffer
            HRSOut1 MyByte                              ' Transmit what was received
        Loop                                            ' Close the loop
'
' Come here if a timeout occurs
TimeOutLabel: 
        HRSOutLn "\r** Timed Out **"
    Loop                                            ' Look for more serial bytes

'----------------------------------------------------------------------------------
' Set the internal oscillator to 160MHz
' Input     : None
' Output    : None
' Notes     : None
'
Proc IntOsc_160MHz()
    CLKDIV = %0011000000000001
    PLLFBD = 160                   
    OSCTUN = $00                   
    PLLDIV = %0000000001000001
    ACLKCON1 = $0101               
    APLLFBD1 = 150
    APLLDIV1 = $41
    Write_OSCCON($0101)
'
' Wait for clock switch to finish
'
    While OSCCONbits_OSWEN <> 0 : Wend
    While OSCCONbits_LOCK <> 1 : Wend
EndProc

'----------------------------------------------------------------------------------    
' Set the fuses for internal oscillator on a dsPIC33CK128MP202 Device
'   
    Config FSEC     = BWRP_OFF, BSS_DISABLED, BSEN_OFF, GWRP_OFF, GSS_DISABLED, CWRP_OFF, CSS_DISABLED, AIVTDIS_OFF  
    Config FOSCSEL  = FNOSC_FRC, IESO_OFF   
    Config FOSC     = POSCMD_NONE, OSCIOFNC_ON, FCKSM_CSECMD, PLLKEN_OFF, XTCFG_G0, XTBST_ENABLE   
    Config FWDT     = SWDTPS_PS2147483648, RCLKSEL_LPRC   
    Config FPOR     = BISTDIS_DISABLED  
    Config FICD     = ICS_PGD1, JTAGEN_OFF, NOBTSWP_DISABLED
    Config FDMT     = DMTDIS_OFF
    Config FDEVOPT  = ALTI2C1_ON, ALTI2C2_ON, ALTI2C3_ON, SMBEN_STANDARD, SPI2PIN_PPS
    Config FALTREG  = CTXT1_OFF, CTXT2_OFF, CTXT3_OFF, CTXT4_OFF

charliecoutas

Thanks Les. I chose this device because you recommended it. But with your and Bob's help I am almost there.
I already tried your demonstration buffered UART and it wouldn't work. But I'll try again with the code in your last post.

I have got it driving a power transistor driving a low resistance load and the waveforms look good. I tried a MOSFET but there was a real big overshoot on the leading edge. Like I say, it's looking very promising.

Charlie

charliecoutas

Just tried your code and it worked. Now I can find out why my code doesn't. Cheers Les!

charliecoutas

Nailed it! I hadn't set the three interrupt priority bits to a non-zero value. I've set them to 7, same as you do Les.

Then, in the UART setup:

$ifndef IPC2bits_U1RXIP0
    $define IPC2bits_U1RXIP0 IPC2.12
    $define IPC2bits_U1RXIP1 IPC2.13
    $define IPC2bits_U1RXIP2 IPC2.14
$endif

    IPC2bits_U1RXIP0 = 1                            ' \
    IPC2bits_U1RXIP1 = 1                            ' | USART1 RX interrupt priority
    IPC2bits_U1RXIP2 = 1                            ' /

diebobo

Charlie,

I see you are already covered.. Anyway, my routines that workes for me :

Proc USART1_Init()
    IPC2.12 = 1 ' Prio 5.. 7 is t hoogst
    IPC2.13 = 0
    IPC2.14 = 1

    IFS0bits_U1RXIF = 0;
    IEC0.11 = 1;   _U1RXInterrupt Enable

    U1MODEbits_UARTEN = 1; //enable uart
    U1modebits_UTXEN = 1; //transmitter enabled
    U1modebits_URXEN = 1; //Receiver enabled
    Main_Byte = u1rxreg ' USART Buffer uitlezen, zit altijd iets in na reboot en anders triggered interrupt niet.
    IFS0bits_U1RXIF = 0;
EndProc

Isr U1RXInterrupt

    StrN Int_Serial_String = ""
    while U1STAH.1 = 0 or U1STAH.3 = 0 ' .1 is of RX Receiver bezig is met ontvangen en .3 is of er nog een byte in de buffer zit. IF Resetten heeft geen zin als er nog iets ontvangen KAN worden of er iets in de buffer zit. de IF triggered alleen vanuit 0  bytes in buffer
        HSerIn 1, Timeout_RCIF, [Int_Serial_Char]
        Int_Serial_String = Int_Serial_String + Int_Serial_Char
    wend

    Timeout_RCIF:

    IFS0bits_U1RXIF = 0   
   
    Serial_Ontvangen = 1

    If Serial_Buffer_1 = "" Then
        Serial_Buffer_1 = Int_Serial_String
    ElseIf  Serial_Buffer_2 = "" Then
        Serial_Buffer_2 = Int_Serial_String
    ElseIf  Serial_Buffer_3 = "" Then
        Serial_Buffer_3 = Int_Serial_String
    ElseIf  Serial_Buffer_4 = "" Then
        Serial_Buffer_4 = Int_Serial_String
    ElseIf  Serial_Buffer_5 = "" Then
        Serial_Buffer_5 = Int_Serial_String

    EndIf

EndIsr

And some stuff for in your main part :

Dim Main_Bit As Byte  ' Niet defineren als bit, blijft !! fout gaan met inlezen en of vergelijken.. NOOIT MEER BITS GEBRUIKEN
Dim Main_Byte As Byte
Dim Main_Word As Word

Dim Secs_From_Boot As dword

Dim Int_Serial_String   As String * 50 ' Hier word de complete seriele RX in opgeslagen
Dim Int_Serial_Char     As Byte

Dim Serial_Buffer_1        As String * 50 ' buffer regel 1
Dim Serial_Buffer_2        As String * 50
Dim Serial_Buffer_3        As String * 50
Dim Serial_Buffer_4        As String * 50
Dim Serial_Buffer_5        As String * 50

Dim Serial_Ontvangen As Byte

Setup:
'         5432109876543210
Ansela = %0000000000000001 ' Microfoon op AN0
TRISA  = %1111111111111111
AnselB = %0011110000000000
TRISB  = %1111111111111111 ' Button 1/2/3/4 op 10/11/12/13
CNPUb  = %0011110000000000 ' Interne pullups Buttons
Anselc = %0000000001000110 ' Analoge Inputs voor de LDR's en 5V USB meting
TRISc  = %1100111111111111
Anseld = %0000000000000000
TRISd  = %1111111111111111

Osc_200MHz_Init()

PPS_Unlock()

PPS_Output(cOut_Pin_RP46, cOut_Fn_U1TX)
PPS_input(cIn_Pin_RP47, cIn_Fn_U1RX)

USART1_Init()

Main:

If Serial_Ontvangen = 1 Then
     HSerOut ["*** Serieel ontvangen ***", 10]
    ' Process serial buffers in this part.   
     Serial_Ontvangen = 0
EndIf

GoTo Main

charliecoutas

Yes, and thanks for your help Bob. It was bugging me so I unpicked Les's code to see what he had done that I hadn't.
The priority bits were the difference. And they are not very well described in any of the Microchip documentation as far as I can see.

It's often a struggle with Microchip chips, but I wonder if other manufacturers have the same issues?

What is your application for the dsPIC33CK, if I may be so nosey?

Charlie

top204

#9
I always set all the priority bits of all interrupts high, because I do not fully understand the priority settings for the vector interrupts, so I set them so the default kicks in , and they have a natural priority via their positions in the vector table.

diebobo

Quote from: charliecoutas on Nov 27, 2021, 07:53 PMWhat is your application for the dsPIC33CK, if I may be so nosey?

You May :). I've designed a clock using this device with the folowing Peripials in use ( when it's done in the End :) ) :

- UART1 - CP2102 for PC Coms
- UART2 - ESP8266 Wifi Support, Plus control of local io like Reset and IO0 for firmware flashing.
- SPI1 - SPI Leds
- SPI2 - Flash Memory
- I2C - DS3231 Realtime Clock
- Analog In 4 x = 2 x LDR for Ligth Compensation , 1 x 5V USB voltage monitoring, 1 x Microphone / Opamp input for Equalizer function
- Some buttons for control.

charliecoutas

#11
Is that all? Wow, that sounds like a really good project. You obviously have a great deal of patience and skill. You are not using the microphone to interpret speech, are you?

But have you used the DAC? That was very simple to get going although the output voltage seems to wobble whenever the DAC is loaded with the same value.

Colin G3YHV

I had problems with "possible  Chinese fake" DS3231's not keeping time well.
So we used neo6m GPS modules instead  -  much better!
Colin G3YHV

top204

#13
In order to counteract that sort of problem Charlie, create a variable to hold the previous value sent to the DAC, and update it after the DAC has been loaded, and on the next iteration, if the current value and the previous value are the same, do not load the DAC with the value, because it is already at that state.

I often use the simple previous value method when updating displays or interfacing with PWM or loading peripherals etc, because the initial loading or setting up can cause the peripheral to jitter, unless it has a latch.

If the timing is critical, see how long it takes to interface to a peripheral and if the peripheral is not being interfaced with, add a small delay for the length of time it would have taken to be interfaced with. :-)

John Drew

Hi Charlie,
I use the "save last value" in other circumstances too.
E.g using a graphic display I send single bytes via I2C to a slave PIC which displays certain strings depending on the value received. By not resending duplicated bytes the graphic display updates a line only when needed.
Works a treat with noticeable speed improvements.
John

charliecoutas

Les, John: Yes, it was just a rough try to get the DAC running. I'll do the "only update if the value has changed" later.
I expect a problem with measuring V, and I, multiplying them together, to get power, then comparing that to the wanted value. I could probably use fancy DSP instructions for this but for now let's just get it working.

If I am too fast I expect the system to oscillate in the same way that a learner driver "kangeroos" at first by pressing too hard on the accelerator., then backing off as the car lurches forward.

It is doing a 12 bit ADC conversion in 1.2uS and the DAC changes after it's been loaded so I don't think speed will be a problem. Having never tried a closed-loop system like this using a DSP, it's an interesting ride. The "load" is effectively a resistive element that can/will change its resistance, hence the need for constant power. And I reckon that at 100MIPs I can be agile enough to follow the power changes very accurately.

top204

#16
You seem to be having fun with the new devices Charlie. Creating something that one has not created before is always fun isn't it?

To stop any oscillation, try a simple PID algorithm. As you probably already know, it is a simple mechanism that measures the amount of error and uses that value to stabilise the output, so it does not simply increment or decrement until it reaches the correct output level. Because it takes a few iterations to stabilise itself, that can get in the way of things, but with 100 MIPS and the architecture of the 16-bit devices, the stabilisation period will be very small, and tuning the PID makes the stabilisation period extremely small.

The Mathematic operations with the 16-bit devices are extremely fast because of both the compiler's code generation and the hardware features of the devices, such as hardware multiply, divide, single cycle multi-shifts, hardware Repeat loops, and of course, 16-bit operations in a single cycle. And the compiler makes use of all of those features whenever it can. I think you will be pleasantly surprised when you see how fast they operate on complex expressions.

charliecoutas

It keeps the little grey cells active, or so they say. A lot of head scratching but yes, a PID algorithm is a good idea. I hadn't thought of that.

As the load is mainly resistive, I don't think it will change resistance very rapidly. Thanks for the idea. I will have a rummage around in some PID algorithms. Cheers!

top204

#18
QuoteIt keeps the little grey cells active, or so they say.

I used to think that as well, until what happened to poor Terry Pratchett. His mind was constantly active and imaginative, but it did not stop the dreadful disease that slowly destroyed his brain cells. RIP. I just hope it does not happen to me because of where my injury is. :-( I know it is a possibility after a brain hemorage, and where it happened in my brain, but they still do not know what causes "it" to happen in all mammals.

With a slower moving load, you do not always need the full "PID", you can sometimes use "PI" instead. When controlling a motor, I have used PI instead of PID and it operates faster and has a faster stabilisation period. And is easier to tune. :-)