• AVR Freaks

Hot!PIC18F45K42 UART1 setting DMX Address U1P2 U1P3 registers

Author
team_king
New Member
  • Total Posts : 6
  • Reward points : 0
  • Joined: 2018/11/16 15:13:14
  • Location: 0
  • Status: offline
2019/02/25 09:37:28 (permalink)
0

PIC18F45K42 UART1 setting DMX Address U1P2 U1P3 registers

I'm having an issue writing the U1P2 and U1P3 registers for UART1 to set the DMX base address and end addresses.
My code works fine up to the first 8 bits of a DMX address, but is not recognizing the 9th address bit in U1P2H register.
Example if trying to set the DMX address to channel 321 (0x141), then subtract 1 from the address per the PIC18F45K42 manual, then write 0x140 to U1P2 should set the correct byte to grab from the DMX stream. However, it will not respond to a DMX transmit on channel 321, but rather on channel 65. Note that 321 - 65 = 256, which is the missing 9th bit in the address.
Using PICKIT3 debug, shows the U1P2L and U1P2H registers are correctly set at 0x40 and 0x01 respectfully.
Using MPLAB X v5.10 XC8 v2.00
Currently loaded firmware on PICkit 3
Firmware Suite Version.....01.54.00
Firmware type..............Enhanced Midrange
Target voltage detected
Target device PIC18F45K42 found.
Device Revision ID = a001
 
If I "hard code" the DMX address by
U1P2L = 0x40;
U1P2H = 0x01;
The code will work properly and respond the a DMX transmission on channel 321 as expected.
 
However, if I try to set the DMX address at runtime like below, it behaves as though that 9th bit is not set, even though the debug says it is. (which brings another question: Does the Debug actually read that register? Or just calculate what it should be?)
 
(The DMX_BASE_ADDRESS is set from user input in another block of code. Debug is showing correct values are stored.)
 
uint16_t DMX_BASE_ADDRESS;
 
PIE3bits.U1RXIE = 0;//disable uart interrupts - is this needed??
U1CON1bits.ON = 0;//stop uart to write U1P2 --do we need to stop it??
U1P2 = DMX_BASE_ADDRESS;
U1P3 = DMX_BASE_ADDRESS;
U1CON1bits.ON = 1;//start uart after writing U1P2
PIE3bits.U1RXIE = 1;//re-enable the uart interrupts
 
I have also tried it this way:
U1P2L = (DMX_BASE_ADDRESS & 0xFF);//only lower byte
U1P2H = (DMX_BASE_ADDRESS >>8);//only want upper byte (bit 9) from the 16 bit var.
U1P3L = (DMX_BASE_ADDRESS & 0xFF);
U1P3H = (DMX_BASE_ADDRESS >>8);
 
Any of the above ways, using PICKIT3 debug, will show the correct values in the registers.
 
I'm sure it is something simple, as it usually is, but I'm not seeing it. After many hours of trying things and searching forums, I need some help.
 
More hours of trying things and testing 20190226.
This works fine if I set it to a number in code:
U1P2 = 0x0140;//start address for DMX
U1P3 = 0x0140;//end address for DMX
 
Note this will not work:
U1P2 = 0x140; //it must have the leading "0"
 
And for some reason? This will not work:
U1P2L = 0x40; //lower byte of DMX start address
U1P2H = 0x01;//high byte of DMX start address
 
I have also put 8 LEDs on PORTD to read the registers
LATD = U1P2L;
//1 second delay here for testing
LATD = U1P2H;
 
Now consider this...EVERY VARIATION OF CODE I HAVE TRIED TO SET THESE REGISTERS WILL READ CORRECTLY IN DEBUG AND ON LATD AFTER READING THE REGISTERS.
 
I have a solid electronics background. Started using latches and Gates back in the 70's. What I want to know here is if these address latches hold the correct set bits, whether I load them by U1P2 = 0x0140: or separately as U1P2L = 0x40; and U1P2H = 0x01; why does the silicon behave differently? One way it will read the DMX and the other it will not? No other code changed. Only the setting of the registers as shown above. I first thought it was a compiler issue, but reading the registers into LATD and lighting the LEDs proves the registers are holding the correct bits, no matter which way I load them. 
 
I see I've contradicted myself - at the start of this post I said this works:
U1P2L = 0x40;
U1P2H = 0x01;
But today it is not working. So did I mis-state earlier or what? That's what 10 hours on one little detail will do to you!
 
I just tried adding some delay between, in case it is a propagation issue in the silicon:
U1P2L = 0x40;
__delay_ms(5);
U1P2H = 0x01;
Still does not work.
 
Let's try setting the high register first:
U1P2H = 0x01;
U1P2L = 0x40;
U1P3H = 0x01;
U1P3L = 0x40;
(Expletive!) That works ok!
Why does this order matter? (keep in mind reading the registers always show right on LATD)
Perhaps at the top of this post I had the order reversed?
 
Then I wonder why the compiler will allow
U1P2 = 0x0140; and work ok
 
BUT NOT work with
DMX_BASE_ADDRESS = 0x0140;
U1P2 = DMX_BASE_ADDRESS;//DMX_BASE_ADDRESS is a uint16_t
even though LATD says the U1P2 and U1P3 registers are set the same in both cases? WHY microchip?
 
Other perhaps relevant information:
PICIT3 is always connected, but PC and PD are not shared with other parts of the circuit. I am using the PPS feature to re-map the serial ports.
Sometimes I need to re-boot the PCBA after changing the registers, to get the DMX to work, even thought LATD says the registers are set right.
This is not on a breadboard, but on a nice prototype PCBA so electrical connections are good.
When I said a way worked or did not work above - I loaded the code to the PIC 5 times and tested each time to rule out glitches.
I also tested with 2 different copies of the PCBA with same results.
 
I've done a fair amount of programming over many years, although only PIC in last couple years. This new gen K42 is new to me, however, so I may be doing something idiotic. I welcome you to point out my idiocy and tell me what I am doing wrong here. Does LATD lie? OR is something not propagating from U1P2 and U1P3 registers to where it counts? (pun intended)
post edited by team_king - 2019/02/27 08:37:28

Attached Image(s)

#1

8 Replies Related Threads

    team_king
    New Member
    • Total Posts : 6
    • Reward points : 0
    • Joined: 2018/11/16 15:13:14
    • Location: 0
    • Status: offline
    Re: PIC18F45K42 UART1 setting DMX Address U1P2 U1P3 registers 2019/02/27 13:42:03 (permalink)
    0
    20190227 more testing
    This seems very intermittent, as to if it will read the DMX address or not.
    I dis-connected the PICKIT3 then did several power cycles / re-boots. It is not consistent.
    Sometimes can re-boot it 3 times in a row and will read properly, then it may not for a few boots.
    When it does boot and read the DMX address, it will continue to read every time I send a DMX command. I can "beat on" the PCBA and connections and it still receives. I can leave it for an hour powered on, come back and it still receives the correct DMX address / byte.
    I have verified the voltage is good at 5.01 Volts. (using Fluke DVM only)
    The UART is not initialized until after the user (me) enters the DMX address, so all should be stable inside before these registers are written. 
    And to repeat myself, reading the DMX address from U1P2L and U1P2H to LATD output to 8 LEDs shows the correct address is in the registers, even when it will not receive.
    I added a picture of the PIC in case the markings can help Microchip know the die, if there is an internal issue. I have entered a support ticket.
     
    I suppose I should look at the possibility that the UART1 is just stopping for some reason? OR the DMA transfer is stopping?
    I did model from this code for UART1 and DMA: 
    https://mplabxpress.microchip.com/mplabcloud/example/details/382
     
    #2
    team_king
    New Member
    • Total Posts : 6
    • Reward points : 0
    • Joined: 2018/11/16 15:13:14
    • Location: 0
    • Status: offline
    Re: PIC18F45K42 UART1 setting DMX Address U1P2 U1P3 registers 2019/02/28 09:13:34 (permalink)
    0
    More testing 20190228
    I left it in a "working" state overnight. It still responds to DMX commands fine.
    It appears if it does load correctly (after an address input from user) it will keep running just fine.
     
    Next I tried inputting several addresses in the lower byte only, U1P2L, and all seemed to go well. As I changed the input DMX address, the UART1 did grab the correct DMX address byte and pass on to my other functions.
     
    Then I tried using that 9th bit, that gets set in U1P2H, and had no good response. It did not retrieve a DMX byte on the input address. I went further and sent a DMX command on all 512 channels. The UART1 did not grab any of them.
     
    Looked at my code and was going to add some LATD output indicators to let me know if the UART1 is running and if the DMA transfer is running. Before I changed any code I decided to single-step debug, from the point of retrieving the DMX address from the eeprom, through initializing the UART1, initializing the DMA, up to the point where it will grab DMX byes. IT WORKED OK! It is grabbing the correct DMX address byte using the 9th bit, in fact all 9 bits at address 511.
     
    Then I exited Debug and loaded the program to the PIC. One try, two tries, three tries - none worked. The 4th try it worked!
     
    Next I tried Debug mode single stepping again. It works sometimes, and sometimes not.
     
    Next I did about 8 normal loads of the program to the PIC, before I got a "good one" working. Again, every load is showing the correct  values are in U1P2L and U1P2H, according to a read to LATD, and output to 8 LEDs. Once working, I can change the DMX data value byte (staying in the same DMX address channel) and everything works as expected, just fine. I power-cycled the PIC, and now not working.
     
    I should also mention that through all of the testing up to now, the DMX Master transmitter is always connected to my PCBA and transmitting continuously as DMX calls for. So between Debug, loading the program, power-cycling etc, it is always sending data to my PCBA. Can that be causing an issue?
     
    YES IT WAS!  Unplugged the DMX input to the PCBA before applying power, and it worked ok. Tried it 20 times to be sure. (Yes I did 20 times to eliminate random chance) Sorry Microchip, my apologies. It appears the silicon is ok. But why is there only issues when using that 9th bit, using U1P2H, using some address over 255? That 255 may be a clue. Perhaps the UART1 receive buffer? The DMA transfer? I need to go look, study, and test those areas.
    #3
    qhb
    Superb Member
    • Total Posts : 9999
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: PIC18F45K42 UART1 setting DMX Address U1P2 U1P3 registers 2019/02/28 12:34:56 (permalink)
    0
    Just a guess.
    Maybe try a short (1ms?) delay after disabling the USART before changing the U1P2L & U1P2H registers.
    Maybe it's taking a bit clock to fully disengage, and something is getting out of synch if you change before it is fully idle.
     

    Nearly there...
    #4
    Danno
    Super Member
    • Total Posts : 272
    • Reward points : 0
    • Joined: 2005/09/07 10:12:10
    • Status: offline
    Re: PIC18F45K42 UART1 setting DMX Address U1P2 U1P3 registers 2019/02/28 13:23:17 (permalink)
    0
    Glad you figured it out.
    #5
    team_king
    New Member
    • Total Posts : 6
    • Reward points : 0
    • Joined: 2018/11/16 15:13:14
    • Location: 0
    • Status: offline
    Re: PIC18F45K42 UART1 setting DMX Address U1P2 U1P3 registers 2019/03/02 09:54:21 (permalink)
    0
    Thanks for the idea qhb. I did try adding a delay between setting the U1P2L & U1P2H registers before with no luck.
    I did this to make it start every time:
    I set the enable pin on the 485 receiver IC last, just before the DMA will grab a byte. So no data flows to the UART1 until we are good and ready for it.
     
    But I am still wondering what exactly was causing the issue? I had thought 2 days ago that maybe it was the UART1 rx ring buffer, and the uint8_t  uart1RxCount counter (1 byte = 256 count), getting lost with overflowed input before it was read out of the buffer.
     
    The standard rx buffer code:
    uint8_t UART1_Read(void)
    {
    uint8_t readValue = 0;

    while(0 == uart1RxCount)
    {
    }
    readValue = uart1RxBuffer[uart1RxTail++];
    if(sizeof(uart1RxBuffer) <= uart1RxTail)
    {
    uart1RxTail = 0;
    }
    PIE3bits.U1RXIE = 0;
    uart1RxCount--;
    PIE3bits.U1RXIE = 1;
    return readValue;
    }
     
    However this is the fist time I've used DMA transfers. By reading more this morning and commenting out parts of my code, it turns out that that rx read code UART1_Read is never used! Nor is the interrupt routine for UART1!
    This PIE3bits.U1RXIE (UART1 receive interrupt enable) does not need be enabled. This line in the DMA initialize code will grab the rx bytes from the buffer as they arrive: DMA1SIRQ = 27;//DMA start trigger - U1RX
     
    Here is the DMA code, again from thee Microchip example:
    void DMA_Initialize()
    {

    //DMA Control Register 1
    //DMODE = 00 - Destination pointer remains unchanged after every transfer
    //DSTP = 1 - SIRQEN bit is cleared when the destination counter reloads
    //SMR = 00 - Points to SFR/GPR
    //SMODE = 00 - Source pointer remains unchanged after every transfer
    //SSTP = 0 - SIRQEN bit is not cleared when the source counter reloads
    DMA1CON1 = 0b01000000;

    //DMA start trigger - U1RX
    DMA1SIRQ = 27;
    //DMA Source size
    DMA1SSZH = 0x00;
    DMA1SSZL = 0x01;
    // DMA destination size
    DMA1DSZH = 0x00;
    DMA1DSZL = 0x04;// (my note): Also works ok at 0x02. 0r 0x06 or 0x08 or 0xFE**??
    //DMA Source address
    DMA1SSA = &U1RXB;

    //DMA destination address
    DMA1DSA = &DMX_DATA;
    asm("BANKSEL PRLOCK");
    asm("MOVLW 0x55");
    asm("MOVWF PRLOCK");
    asm("MOVLW 0xAA");
    asm("MOVWF PRLOCK");
    asm("BSF PRLOCK, 0");
    asm("BANKSEL DMA1CON1");
    DMA1CON0bits.EN = 1;
    DMA1CON0bits.SIRQEN = 1;
    }
     
    At this point I need to study the DMA process more. At first glance it appears to me that setting that DMA Destination Size register DMA1DSZL = 0x04 to 4, may only pass data from  1 out of 4 DMX frames that are received.
     
    The code below is started when the Destination Counter register reaches zero. So it appears there are 4 counts (DMA1DSZL = 0x04) before the received data byte is processed. So we just skip 3 DMX frames and read the 4th?
    I tried it at 0xFE, and it takes about 3 second to respond now, so I think it is skipping 253 (0xFD) DMX frames now. (My DMX control transmitter is sending at 40 Hz - 40 frames per second) Interesting. Perhaps the Microchip example code using DMA1DSZL = 0x04 is to capture 3 or 4 channels of DMX from a DMX frame. Then setting the U1P3L/H DMX end address registers to a number greater than U1P2L/H start address registers will fill the array DMX_DATA[ ] ---And not skip DMX frames.
     
    I need to Google a bit and study the DMA process more. Perhaps someone experienced in the DMA workings can jump in and comment on this.  
     
    while (1)//keep looping in while
    {
    if(DMA1DCNTIF)//DMA Destination Counter interrupt set. Received a byte from UART1
    //The DMAxDCNTIF destination count interrupt flag is
    //set every time the DMAxDCNT<11:0> reaches zero
    //and is reloaded to its starting value.
    //with DMA1SSZ = 0x01 source size and DMA1DSZL = 0x04 destination size
    //does that infer we are only reading every 4th byte received from the UART1?
    {
    DMA1DCNTIF = 0;//clear the Destination Count interrupt flag
    DMX_New_Value = (DMX_DATA[1]); //,DMX_DATA[2],DMX_DATA[3]);

    if (DMX_New_Value != DMX_Value) //if new value then proceed
    {
    switch (DMX_New_Value)
     
    I hope all of this writing helps someone else one of these days.
    #6
    team_king
    New Member
    • Total Posts : 6
    • Reward points : 0
    • Joined: 2018/11/16 15:13:14
    • Location: 0
    • Status: offline
    Re: PIC18F45K42 UART1 setting DMX Address U1P2 U1P3 registers 2019/03/26 11:24:23 (permalink)
    0
    I had to stop working on this project for 2 weeks due to a trade show. I plan to do more testing in this area of the program soon. I'll post what I find / learn to hopefully help others.
    #7
    PRWiley
    New Member
    • Total Posts : 22
    • Reward points : 0
    • Joined: 2019/07/04 06:16:51
    • Location: Lewisburg PA USA
    • Status: offline
    Re: PIC18F45K42 UART1 setting DMX Address U1P2 U1P3 registers 2019/07/17 07:54:19 (permalink)
    0
    team_king
     
    Did you ever solve the issues? I am working on a DMX project and the answer might help me a great deal.
     
    Thx.
    #8
    team_king
    New Member
    • Total Posts : 6
    • Reward points : 0
    • Joined: 2018/11/16 15:13:14
    • Location: 0
    • Status: offline
    Re: PIC18F45K42 UART1 setting DMX Address U1P2 U1P3 registers 2019/07/21 10:53:55 (permalink)
    0
    Hello PRWiley,
     
    I do have it working fine, however I still need to study up on the DMA workings. I have two Switch / Case in my program for the DMX receive:
    Case 1) grabs only one byte of data at the specified channel number from the DMX frame to control my MedeaWiz Sprite video player.
    Case 2) grabs 9 bytes of data starting at the specified channel number from the DMX frame to control my MedeaWiz Sprite video player plus 8 sinking outputs. (on / off only, no dimming)
     
    I am actually still working on other parts of the project since the DMX part is working ok. I have not looked at that code for many weeks since I bounce from one fire to another.
     
    I was chasing all sorts of things around in my program as you can see if you read this thread, but this was the thing that fixed my issue:
    I set the enable pin on the 485 receiver IC last, just before the DMA will grab a byte. (from the DMX frame)
     
    I've never used DMA before this project, and I am by no means an expert programmer!
     
    Here is a remark / note in my code for me to study the DMA process:
     
    U1P3 = U1P2 + 10;//this works to add channels**
    //4 works for 4 outputs. 10 works for 8 outputs. why??
     
    That sets the end channel or number of channels to grab from the frame after the start channel.
    I still need to understand how that is working because logically if 4 works for 4 channels, then 8 should work for 8.
    Maybe it's in the way the DMA maps to memory?
    Or I still have some gremlin - But it works flawlessly.
     
    For the single channel case, is simply U1P3 = U1P2
     
    If you can tell me more about what you are doing and where you are having trouble, I will try to help you, if I can.
    #9
    Jump to:
    © 2019 APG vNext Commercial Version 4.5