Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem sharing SPI #19

Closed
gioreva opened this issue Jan 18, 2020 · 28 comments
Closed

Problem sharing SPI #19

gioreva opened this issue Jan 18, 2020 · 28 comments

Comments

@gioreva
Copy link

gioreva commented Jan 18, 2020

SPI.begin();
flashDrive.init();
delay(1000);
if(flashDrive.checkDrive()) tft.println("Ch376 ok");
else tft.println("Ch376 fail");

If i add SPI.beghin() It does not work anymore
But if you do not add other devices do not work. SD, TFT, ecc.
Questo perchè uso i PIN SPI anche per IO Shif register.

void updateIO() // 74HC595 Output + 74HC165 Input
{
digitalWrite(latchPinI, LOW);
digitalWrite(latchPinO, LOW);
pinMode(clockPin, OUTPUT);
pinMode(dataPinO, OUTPUT);
shiftOut(dataPinO, clockPin, MSBFIRST, OutReg);
digitalWrite(latchPinO, HIGH);
SPI.begin();
}

@djuseeq
Copy link
Owner

djuseeq commented Jan 19, 2020

Hi. flashDrive.init() will also call SPI.begin() function and it's enough to call it once. Use this schematic? The shiftregister is on the SPI bus and in updateIO() function you communicate with it on softSPI way, what is probably not correct.

`void updateIO() // 74HC595 Output + 74HC165 Input
{

digitalWrite(latchPinI, LOW);

digitalWrite(latchPinO, LOW);

SPI.beginTransaction(SPISettings(hereWriteComSpeed, MSBFIRST, SPI_MODE0));

SPI.transfer(OutReg);//Transfer data

SPI.endTransaction();

digitalWrite(latchPinO, HIGH);

}`
and you can spare one extra pin if you attach 74HC165 output pin to MCU's MISO pin and then in the same time read inputs from 74hc165 and write to 74hc595, e.g.

`void updateIO() // 74HC595 Output + 74HC165 Input
{

digitalWrite(latchPinI, LOW);

digitalWrite(latchPinO, LOW);

SPI.beginTransaction(SPISettings(hereWriteComSpeed, MSBFIRST, SPI_MODE0));

InRegVariable = SPI.transfer(OutReg);//RW data

SPI.endTransaction();

digitalWrite(latchPinO, HIGH);

digitalWrite(latchPinI, HIGH);
}`

@djuseeq
Copy link
Owner

djuseeq commented Jan 19, 2020

If you use in your code the SPI.setDataMode(); SPI.setBitOrder(); SPI.setClockDivider(); functions then change them to SPI.beginTransaction() see here under description.

@gioreva
Copy link
Author

gioreva commented Jan 19, 2020

Yes, scheme is similar.
Output of 74hc165 is not trestate.
Always is on low impedance.
I can not connect with miso.
I could try using SPI. for 74hc595, it's definitely better of shiftOut, but not solve the problem.
Also SD and TFT call SPI.begin();

If i add SPI.begin(); at the end of my function, SD work, TFT work, but your library not work.
If i do not add SPI.begin();. your library work, but TFT and SD not work.

void updateOut() // 74HC595 Output
{
digitalWrite(latchPinO, LOW);
pinMode(clockPin, OUTPUT);
pinMode(dataPinO, OUTPUT);
shiftOut(dataPinO, clockPin, MSBFIRST, OutReg);
digitalWrite(latchPinO, HIGH);
SPI.begin();
}

void updateIn() // 74HC165 Input
{
pinMode(dataPinI, INPUT);
digitalWrite(clockPin, HIGH);
pinMode(clockPin, OUTPUT);
digitalWrite(latchPinI, LOW);
digitalWrite(latchPinI, HIGH);
InReg = shiftIn(dataPinI, clockPin, MSBFIRST );
SPI.begin();
}

void updateIO() // 74HC595 Output + 74HC165 Input
{
digitalWrite(latchPinI, LOW);
digitalWrite(latchPinO, LOW);
pinMode(clockPin, OUTPUT);
pinMode(dataPinO, OUTPUT);
shiftOut(dataPinO, clockPin, MSBFIRST, OutReg);
digitalWrite(latchPinO, HIGH);

pinMode(dataPinI, INPUT);
digitalWrite(clockPin, HIGH);
digitalWrite(latchPinI, HIGH);
InReg = shiftIn(dataPinI, clockPin, MSBFIRST );
SPI.begin();
}

@djuseeq
Copy link
Owner

djuseeq commented Jan 19, 2020

Sorry, you're right with 74HC165, i read it now. That is really interesting, i have to think about it.

@djuseeq
Copy link
Owner

djuseeq commented Jan 19, 2020

Try to use SPI.end() before you define SPI pins as OUTPUT/INPUT.

`void updateOut() // 74HC595 Output
{

SPI.end();

digitalWrite(latchPinO, LOW);

pinMode(clockPin, OUTPUT);

pinMode(dataPinO, OUTPUT);

shiftOut(dataPinO, clockPin, MSBFIRST, OutReg);

digitalWrite(latchPinO, HIGH);

SPI.begin();
}`

@gioreva
Copy link
Author

gioreva commented Jan 19, 2020

Adding SPI.end, TFT Stop Working

@gioreva
Copy link
Author

gioreva commented Jan 19, 2020

Indeed, adding SPI.end whole program crashes and does not proceed further.

@gioreva
Copy link
Author

gioreva commented Jan 19, 2020

Ok, solved prooblem of crash, but same, with SPI.end(), your library not work.

If i test SD then CH376, or first CH376 then SD, always SD work, TFT Work, CH376 Not Work.

//  TEST_SD  -  Write file on SD card.
  if(SD.begin(12))  tft.println("SD ok");
  else   tft.println("SD fail");
  
// Test Flash USB Writer
  SerialUSB.println(4);
  flashDrive.init();
  delay(1000);
  if(flashDrive.checkDrive())    tft.println("Ch376 ok");
  else    tft.println("Ch376 fail");

@gioreva
Copy link
Author

gioreva commented Jan 19, 2020

Same if i use
Ch376msc flashDrive(45, 1);
or
Ch376msc flashDrive(45);

But if i use
Ch376msc flashDrive(45, -1);
Program crash.

@gioreva
Copy link
Author

gioreva commented Jan 19, 2020

Working on simplified program, library stop working after pinMode(clockPin, OUTPUT);
I do not understand why.
First I thought it would stop working after SPI.init (), but I was wrong.
Only after I enable the line pinMode(clockPin, OUTPUT); it stops working.

#include <Ch376msc.h>
Ch376msc flashDrive(45); // chipSelect

#define latchPinO 6      //Pin connected to ST_CP of 74HC595 Output
#define clockPin 24      //Pin connected to SH_CP of 74HC595 Output of 74HC165 Input
#define dataPinO  23     //Pin connected to DS of 74HC595 Output
#define dataPinI 27      //Pin connected to DS of 74HC165 Input
#define latchPinI 2      //Pin connected to ST_CP of 74HC165 Input

byte OutReg = 0, InReg = 0;

void setup() {

  SerialUSB.begin(115200);
  while(!SerialUSB);

  SPI.end();
  digitalWrite(latchPinI, LOW);
  digitalWrite(latchPinO, LOW);
  pinMode(clockPin,  OUTPUT);   ### Here the problem
//  pinMode(dataPinO,  OUTPUT);  
//  shiftOut(dataPinO, clockPin, MSBFIRST, OutReg);
  digitalWrite(latchPinO, HIGH);
//  
//  pinMode(dataPinI,  INPUT);
//  digitalWrite(clockPin, HIGH);
//  digitalWrite(latchPinI, HIGH);
//  InReg = shiftIn(dataPinI, clockPin, MSBFIRST );
  SPI.begin();

  flashDrive.init();
  if(!flashDrive.checkDrive()) SerialUSB.println("fail");      
  else SerialUSB.println("Ok");
}

@djuseeq
Copy link
Owner

djuseeq commented Jan 20, 2020

Please use a dedicated pin for interrupt request from CH376! Ch376msc flashDrive(45); will not work in your code because the SPI bus is shared and in this case the library will configure the chip to use MISO pin as output(not in Z state), that means it blocks the communication with other devices. Ch376msc flashDrive(45, -1); will not work because -1 is not a valid pin on arduino. Instead -1 write a valid dedicated pin number what is used just for trigger INT request and it must to be connected phisically otherwise the MCU will not get the request and the communication with the CH376 will never happen.So in your case (more devices on SPI bus) will work just Ch376msc flashDrive(validChipSelectPin, validINTpin);

@djuseeq
Copy link
Owner

djuseeq commented Jan 20, 2020

Same if i use
Ch376msc flashDrive(45, 1);
or
Ch376msc flashDrive(45);

But if i use
Ch376msc flashDrive(45, -1);
Program crash.

In a first case Ch376msc flashDrive(45, 1); the chip's INT# pin is connected with arduino's pin 1?

@gioreva
Copy link
Author

gioreva commented Jan 20, 2020

I have no free pin for connect interrupt. But all other spi device work well.
Only this library not work.

It is not a problem if spi is used on special way during flash operation.

@djuseeq
Copy link
Owner

djuseeq commented Jan 20, 2020

The datasheet only describes this 2 mode with SPI(MISO as INT or dedicated INT), INT is always required. Possible to change 74HC165 chip with other type with 3state dataOut pin?e.g 74HC589 , etc.? Because then you get one extra pin what you using now like MISO2. Or to use shift register to query interrupt request from the chip? If it's possible then i can change the library to be able to use variable instead of physical pin for sensing interrupt request.

@gioreva
Copy link
Author

gioreva commented Jan 20, 2020

Yes, i can change IC.
I had tried a chip tristate but I had not found before.
Board already is on production, i try to stop it.

But before i try to connect INT for test.

@gioreva
Copy link
Author

gioreva commented Jan 20, 2020

Never print Init.
Do not like INT 27 ?

#include <Ch376msc.h>
Ch376msc flashDrive(45, 27); 

void setup() {
  SerialUSB.begin(115200);
  while(!SerialUSB);
  SerialUSB.println("Test");

  flashDrive.init();
  SerialUSB.println("Init");
 
  if(flashDrive.pingDevice()) SerialUSB.println("Chip Ok");      
  else SerialUSB.println("Chip fail");
  
  if(flashDrive.driveReady()) SerialUSB.println("driveReady Ok");      
  else SerialUSB.println("driveReady fail");
}

@djuseeq
Copy link
Owner

djuseeq commented Jan 20, 2020

That pin is not used elsewhere in your code? Or Serial2 is not initialized?
On AVRFreaks mention a trick to connect ~2k resistor to 74HC chip's dataOut pin. I don't know is that can work's.

@djuseeq
Copy link
Owner

djuseeq commented Jan 20, 2020

And put all the other devices chipSelect pins to high

@gioreva
Copy link
Author

gioreva commented Jan 21, 2020

Complicated to use HC589, has three control lines, I do not know if it can be reduced to one or two, I will buy someone to try.

But
Ch376msc flashDrive(45, 27);
flashDrive.init();

If no chip are not welded, alt the program, you have to add timeout.

@djuseeq
Copy link
Owner

djuseeq commented Jan 21, 2020

Please don't stick to this chip, that was just an example(quick pick from Google), please try the AVRFreaks solution first(this is also just an advice, it can only works if you plan to use just one 74HC165 on the MISO line). I put together an SD card+ SD lib., W5100 + Ethernet lib., CH376 + this lib.,Arduino Uno + IDE 1.8.10 and the code doesn't stuck , but if i don't connect a ethernet cable to eth.module then it get stuck(for 1 minute, timeout).

@djuseeq
Copy link
Owner

djuseeq commented Jan 21, 2020

I tried to totally disconnect the module or just int line and the code doesn't stuck. I can't reproduce this bug. My hardware environment is different from yours, this can be also

@gioreva
Copy link
Author

gioreva commented Jan 21, 2020

About Stuck I will do other tests.
About resistor, I realized only now, my English is horrible. I try now.
I could free up another pin, if I use the same pin as IN latch and OUT latch
Can SPI Hardware read and wrtite at same time ?

@djuseeq
Copy link
Owner

djuseeq commented Jan 21, 2020

No problem, yes it can, so in the same time you send out and read bit's.
inReg = SPI.transfer(outReg);

@gioreva
Copy link
Author

gioreva commented Jan 21, 2020

Using 1Kohm i can work at maximun frequency of 7Mhz, for securty i have set at 4 Mhz.
image

Using a single wire for Latch in and out, i read the Input at previews state.
I have to read tiwice for read the last state.

void updateIO() // 74HC595 Output + 74HC165 Input ONE WIRE
{
SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
InReg = SPI.transfer(OutReg);
digitalWrite(latchPinO, LOW);
digitalWrite(latchPinI, LOW);
digitalWrite(latchPinO, HIGH);
digitalWrite(latchPinI, HIGH);
}

void updateIO() // 74HC595 Output + 74HC165 Input TWO WIRE
{
digitalWrite(latchPinI, LOW);
digitalWrite(latchPinI, HIGH);
SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
InReg = SPI.transfer(OutReg);
digitalWrite(latchPinO, LOW);
digitalWrite(latchPinO, HIGH);
}

@djuseeq
Copy link
Owner

djuseeq commented Jan 21, 2020

The SPI.beginTransaction recommended to call before with the chipSelect pin you enable the chip itself.
SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
digitalWrite(latchPinO, LOW);//enable HC595
digitalWrite(latchPinI, LOW);//enable HC165
InReg = SPI.transfer(OutReg);//send and read
digitalWrite(latchPinO, HIGH);//disable HC595
digitalWrite(latchPinI, HIGH);//disable HC165
SPI.endTransaction();// Call this function when transaction is finished

I don't used these chip's so i'm not familiar with them.
Or if you can read just in second turn the HC165 then try

SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
digitalWrite(latchPinO, LOW);//enable HC595
digitalWrite(latchPinI, LOW);//enable HC165
SPI.transfer(OutReg);//send
digitalWrite(latchPinO, HIGH);//disable HC595
InReg = SPI.transfer(OutReg);//read in second transaction
digitalWrite(latchPinI, HIGH);//disable HC165
SPI.endTransaction();// Call this function when transaction is finished

@djuseeq
Copy link
Owner

djuseeq commented Jan 22, 2020

You can read issue #18 , maybe it can helps to you also this solution

@gioreva
Copy link
Author

gioreva commented Jan 23, 2020

But this is a problem.
If the type of key or formatting is not recognized, you can not completely stop the program.

@djuseeq
Copy link
Owner

djuseeq commented Jan 23, 2020

That's right i can reproduce, i open a new issue for this bug. If the SPI bus sharing issue is solved then we can close this issue. Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants