Connect with us

Problem with serial shift registers

Discussion in 'Microcontrollers, Programming and IoT' started by Anard, Mar 30, 2018.

Scroll to continue with content
  1. Anard

    Anard

    47
    1
    Feb 21, 2018
    Hi.
    I encounter an issue with 7 serial 74HC595 that I can't understand.
    I talk with them with a PIC18F26K22 in SPI mode. Here is my configuration :
    Fosc = 16MHz, 64MHz with PLL activated.
    SSP1STAT = 0x40 and SSP1CON1 = 0x20, so
    • Input data sampled at middle of data output time
    • Transmit occurs on transition from active to Idle clock state
    • No collision, no overflow
    • Idle state for clock is a low level
    • MasterMode, clock = Fosc/4
    In my code, I first set a global char array variable arrOuts[7][8] when I need a modification. First searching the correct bit to modify and then applying :
    Code:
    static
    char Modif_Output(unsigned char pos, char bOnOff) {
        int iOutGroup, iOutBit;
        iOutGroup = pos / 8;
        iOutBit = pos % 8;
        // set and clear corresponding output
        arrOuts[iOutGroup][iOutBit] = bOnOff;
        return 1;
    }
    Next, I send it to shift registers as it :
    Code:
    uint8_t interface_tx(uint8_t data) {
       spi_buff = data;
       while (!spi_bufFull);
       return (spi_buff);
    }
    void Out_Refresh(void) {
        signed char iOutGroup, iOutBit;
        Out_CS = 0;
        // send 7 x 8 bits one after the other
        for (iOutGroup = 6; iOutGroup >= 0; iOutGroup--) {
            iOut = 0x00;
            for (iOutBit = 7; iOutBit >= 0; iOutBit--) {
                iOut <<= 1;
                iOut |= arrOuts[iOutGroup][iOutBit];
            }
            interface_tx(iOut);
        }
        Out_CS = 1;
    }
    It works well but for some bits, I have also to modify previous one. So I do :
    Code:
    void Prepare_Output(void) {
        unsigned char outSelect = 0;
        char bModif;
    
        // search right output
        while (outSelect<cNbOuts) {
            if (outToModify == arrOutPosition[outSelect]) {
                bModif = Modif_Output(outSelect, bOnOff);
                if (associatedOutput) bModif += Modif_Output(outSelect, bOnOff);
                break;
            }
            else outSelect++;
        }
        if (bModif > 0) Out_Refresh();
    }

    With this associated output, in any cases, it opens the 2 to 6 first outputs of the first shift register while it should not.
    If associatedOutput is always 0, it seems to work fine.

    I first thought to a memory problem which could modify my array arrOuts during a function call but after many tries, I can't confirm. Working in debug mode with data breakpoints on writing to arrOuts[0][0], it never stops.
    I tried not using PLL to run at 16MHz and setting SSP1CON1 to 0x22 for reducing SPI speed to 250Hz with no effects.
    There is a 74HC244 activated by Out_CS after the µC to drive the signal after what one connector and the first ShiftRegister.

    I've no more ideas about where could be my problem. Could you help me to understand where it could be ?
    Maybe modifying the clock polarity, clock edge or data input sample phase but I don't know precisely what should be the effect of these parameters.

    Thanks so much for your advices.
     
    Last edited: Mar 30, 2018
  2. Anard

    Anard

    47
    1
    Feb 21, 2018
    Anything I can't understand.
    Shift registers are updated on a rising edge of the clock.
    In my configuration, idle state is a low level and transmit occurs on transition from active to idle state. So, transmit occurs on a falling edge of clock. It seems to be wrong, however it's in this configuration it works better. If I set SSP1STAT to 0x00, transmit would occur on transition from idle to active but all my outputs are shifted by 1 bit. What did I not understand ?
    Do we agree that the input data sample have influence on receipt data from slave, so have no influence when working with shift registers ?

    My english is very poor, so I don't understand precisely technical documentations...
     
  3. Harald Kapp

    Harald Kapp Moderator Moderator

    11,440
    2,627
    Nov 17, 2011
    Salut Anard.

    It will be a great help seeing the schematic of the relevant part of your circuit: how is the shift register connected to the controller?
    It may also help to simplify the program to get things started (pseudocode as I do not program for PICs):
    Code:
    Initialize SPI         // where's that part in your code?
    uint8_t value;
    while (1) {
       for (value = 0x00; value <= 0xff; value++) {
          send_spi(value);
          delay(500ms);
       }
    }
    This will allow you to monitor the shift register's action with the naked eye (provided each shift register output drives an LED).
     
  4. Anard

    Anard

    47
    1
    Feb 21, 2018
    Hello.
    I searched everywhere in software and made different tests, but still can't find any error. I tried every configuration possibilities for SPI module without results.
    So I think to a hardware problem but I'm really newbie in electronics...

    During my tests, it seems like if clock signal wasn't clean on the first shift registers. I think to ringing problems due to unterminated lines.

    Here is a shematics of my connectings, every chip have 100nF decoulpling capacitors between Vcc and Ground :
    SPI.jpg

    The problem appears in the left-side's 595 of this diagram. In any cases, the first outputs are open while they shouldn't, in other cases, outputs are shifted by 1 or 2 bits. Reducing clock frequency never improved the problem. On the right-side, I have never seen any problem.

    Do you think that leaving clock line floating in the end of left-side registers could be an explanation ?
    And if so, assuming that boards are ever printed and mounted, how would you suggest me to improve my signal ? I can read on web to put any "termination resistor" on clock lines but I don't know precisely where neither what range of values ?

    Thanks so much for your help.
     
  5. Harald Kapp

    Harald Kapp Moderator Moderator

    11,440
    2,627
    Nov 17, 2011
    Possible. 70 cm is rather long for an unterminated TTL signal. Do you have an oscilloscope to verify this idea?
    You may try to add series resistors at the outputs of the leftmost 74HC244. Use 100 Ω for starters. This is not an ideal termination, but the resistance in conjunction with the capacity of the long line helps to slow the edges, thus reducing the high frequency content of the signals and making it less susceptible to ringing. You may experiment with the resistor's values. 33 Ω, 47.5 Ω 120 Ω may work differently - better or worse.

    Another improvement of signal quality can be achieved by using separate drivers for the left section of the shift register and the right section. Thus any distortion on the signals leading to one section is not seen by the other section.

    As a third measure you can improve signal quality by using Schmitt-Trigger gates to reduce sensitivity to noise. A 74HC14 contains 6 inverting Schmitt-Trigger gates. Use them in pairs (e.g. connect pins 2 and 3, use 1 as input, 4 as output) to create a non-inverting Schmittt-Trigger buffer. Each 74HC14 chip will thus give you 3 drivers. place these drivers at the start of each shift register section (one chip fir the left sectiom one chip for the right section).
     
  6. Anard

    Anard

    47
    1
    Feb 21, 2018
    Thanks for your answer.
    The 70cm cable is the reason why I add the second 74HC244 (on right side), and signal seems good on this side.
    Do you think though it could be the origin of my problem on left side caused by the created "antenna", even if shift registers are not connected on this side.
    Sorry for these questions, but I'm discovering this kind of effects which weren't expected...
     
    Last edited: Apr 11, 2018
  7. Harald Kapp

    Harald Kapp Moderator Moderator

    11,440
    2,627
    Nov 17, 2011
    Not by an antenna effect but by reflections from the long end.
     
  8. Anard

    Anard

    47
    1
    Feb 21, 2018
    Hi.
    So, I tried first to place 100Ω resistors just near the outputs of the 74HC244 (before my connector), serial on clock and data lines. It was worse, so I replaced it by 50Ω resistors and find the same result than with no resistors (little worse ?).
    Then, I placed another 100Ω serial resistor on ChipSelect line on the same location, result was nonsense, so I replaced it by a 50Ω too. Difficult to say if it's better or worse than when there was no resistors at all.

    Anyway, I also tried in software to wait a 1ms delay after clearing ChipSelect and before sending data to shift registers and it's much better. Below 1ms, I still have some shifted bits in my results. So it's like if CS took about 1ms to fall correctly, explaining the origin of my problems.

    I took a probe on clock line (on the first shift register pin), with these three 50Ω resistors. My scope is very simple and I can't compare to another line in real time.
    It's very "round"…

    12042018601.jpg

    I don't know if you think it would be better to try other resistors values. Next, I'd have 7Ω, 15Ω or 220Ω to work with 3 single resistors.
     
  9. Harald Kapp

    Harald Kapp Moderator Moderator

    11,440
    2,627
    Nov 17, 2011
    The scope signal as shown doesn't look very nice but neither is it too bad. A Schmitt-Trigger as suggested will restore a clean square signal from this.
    What is your SPI frequency? Have you tried a slower SPI clock rate?
     
    Last edited: Apr 12, 2018
  10. Anard

    Anard

    47
    1
    Feb 21, 2018
    Yes, in future, I'll use a Schmitt-Trigger just before the left-side serie of shift registers. But in this case, it'd impose to rebuild circuit boards, what is difficult today...

    Right now, SPI works at 16MHz (64MHz/4) with 16MHz quartz and PLL (4xFosc) activated. I tried to stop PLL and/or reducing SPI speed to Fosc/16 and Fosc/64, with no difference at all.
     
  11. Harald Kapp

    Harald Kapp Moderator Moderator

    11,440
    2,627
    Nov 17, 2011
    With 70 cm of cable you should not exceed 1 MHz SPI clock frequency.
    Difficult, but not impossible with a steady hand. Use the dead bug solder technique. Glue the Schmitt-Trigger IC on top of the bus driver IC. Lift off the input signals of the bus driver IC from the PCB. Make the necessary changes using thin magnet wire.
    I once added 16 * 20 pin memory chips to my ATARI computer this way to double memory capacity.

    Maybe this tutorial can help you?
     
  12. Anard

    Anard

    47
    1
    Feb 21, 2018
    I didn't know this technique… not sure it's up to my skills ! Also, I haven't 74HC14 right here.
    So, following you (but with my skills :D), I'm trying to draw a new PCB for inserting another 74HC244 just before the first left-side 74HC595. I have just enough space to place the PCB above the chip, with side header connections.
    Do you think that could work ?

    About frequency, I'll try with this new configuration, but for the moment, I tried lots of times to decrease it but have never seen the slightest difference... For each new try, I still test with lower frenquencies.

    Anyway, thanks a lot for your advises.
     
  13. Harald Kapp

    Harald Kapp Moderator Moderator

    11,440
    2,627
    Nov 17, 2011
    Make that one for each bus driver (both sides).
    If your little scope has more than one channel, it will help to see a photo of both clock and data to see the correct timing relationship.

    Also you should permanently enable the two bus drivers. Remove chip select from the enable input, tie enable to gnd. You can do this comparatively easily on the existing PCB. As it is, during chip select = high the outputs of the bus drivers are tri-state adn the corresponding inputs of the shift registers are floating. The inputs to CMOS gates should never be left floating. This may be the root cause of your problem. Sorry I didn't see this in the first place.
     
    Anard likes this.
  14. Anard

    Anard

    47
    1
    Feb 21, 2018
    I have ever one just before the right-side shift registers. So, we agree I have just 1 to add ?

    I use the first driver because I also have 2 other slaves on the same SPI module (a LCD and a SD card), for isolating each slave one by one. I connected Enable pin to ChipSelect to prevent shift registers to be active when I talk to another slave.
    I'll have so 3 driver : 1 on the output of the MCU and one before each serie of shift registers.

    Do you mean I should so enable permanently these 3 enable inputs or just for the 2 that are just before the shift registers series ?
    Sorry for this newbie question, but I have never understood clearly the differences between TTL and CMOS (and what it concretely implies).

    Unfortunately not…
     
  15. Harald Kapp

    Harald Kapp Moderator Moderator

    11,440
    2,627
    Nov 17, 2011
    One for each bus driver. If there is already a Schmitt-Trigger before the right side, you add one for the left side.
    This may, however, not be necessary when you ensure defined logic levels on the signal lines, see below.

    In that case add pull-up or pull-down resistors at the output of the bus drivers to ensure a defined logic level when the drivers are inactive. Chose the same logic level as the idle state of the SPI signals. Then you can continue using the existing enable scheme.
     
    Anard likes this.
  16. Anard

    Anard

    47
    1
    Feb 21, 2018
    :D:D:D IT WORKS !!!

    I just replaced my serial resistors by thin wires (residual components pins) as you show me above and pulled the Enable pin of the first 74HC244 to ground without other changes and it's all OK !
    I'll make the same for the second driver (on right side) for security but it seems to work fine as it. So I think it's not necessary to add the third driver before left side shift registers.

    Thank you so much for your help ! I don't know how to tell you my gratitude, it was searching for this fu..ing novice error since at least 3 weeks and was totally desperate.

    So now, when my MCU is talking to SD card or LCD screen, serial registers are internally updated "randomly" according to data sent to the other slave, but as CS line of shift registers remain high, outputs aren't updated. When I need to update it, I send all outputs, thus we can't note this fact.
    But do you think that shifting registers without updating outputs, when talking to another slave, could be a source of undesirable current consumption ? I don't see any information about it in datasheet.

    PS : is there a way to indicate "FIXED" in the title of this thread ?
     
  17. Harald Kapp

    Harald Kapp Moderator Moderator

    11,440
    2,627
    Nov 17, 2011
    Only marginally.

    We do not have (or at least do not use) this feature in this forum.
     
  18. Anard

    Anard

    47
    1
    Feb 21, 2018
    I rejoiced a little early...
    Before, right side was always OK, left side sometimes opened random wrong outputs.
    I have just connected Enable pin of the drivers to ground, and now, left side is always OK... but randomly, some outputs of right side stay closed whereas they shouldn't (but no wrong outputs) !
    I also tried to reduce SPI speed to 1MHz, without effect.

    Next step will be too add the 3rd driver just before left side registers, but not very optimistic…
     
    Last edited: Apr 13, 2018
  19. Harald Kapp

    Harald Kapp Moderator Moderator

    11,440
    2,627
    Nov 17, 2011
    Why worry about the left side when the problem is with the right side?
    As of now I'm a bit confused about your actual setup. Could you update the schematic, s'il-vous-plait?
     
  20. Anard

    Anard

    47
    1
    Feb 21, 2018
    Hi.
    Here is the new shematic, I also tried to match reality : I have 3 registers on left side and 4 on right side. Also, after right's driver, data bus goes first to the last shift register to come back to the nearest.
    So there is about 20cm track between right's 74HC244 DataOut and first 74HC595 DataIn.

    SPI.jpg

    Anyway, I could notice anything else about this new problem. After reset, every outputs work fine.
    But after any tries, the last shift register (in serie, the top right one on shematic) seems entirely (and permanently) deactivated, as if it's OE pin was set while it's not. Also, all OE inputs are linked, so I can't believe that one is set while others are cleared.
    For both sides, I use a temporisation to clear shift register's OE after about 10ms, letting MCU to clear all outputs before enabling it : OEpins.jpg
    When stabilized, OE is about 0.4V, datasheet preconize 1.35Vmax for a low level. So I think that problem isn't here insomuch as it worked before pulling driver's enable pins to ground.

    What's strange is it doesn't happen always on the same situation. I tried to open outputs one after one and it's not always the same one that desactivate the last shift register.

    When I shut off the system and reboot, it works again… until next error. Maybe this fact could help to identify the problem.
     
    Last edited: Apr 14, 2018
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day

-