4053 multiplexer might limit SPI baudrate between ATMEGAs?

Go To Last Post
15 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, I am connecting ATMEGA88 and 128.
ATMEGA88 is using HEF4053BT that switches its MISO/MOSI between ISP and data bus coming to ATMEGA128.
The clocks at worktime are slightly rounded but still pretty square. Everything looks not very up to spec concerning risetime, and I cannot get more than 250baudrate from SPI ATMEGA128 master talking to ATMEGA88. The overall PCB design is very complex but I have well tested system, superb filtered powers supply etc. My only suspect is 4053, since I can get easily 4MHz transfer from ATMEGA128 to FM25, AT45, AT25 and SPI sensors.
Should I look for a special version for 4053 or get rid of it? What bandwidth you can achieve while using 4053 in the middle? Or maybe the layout of SCK/MOSI something is unfortunate? All working on 5V, AT88 at 20MHz, AT128 at 16MHz, both on quartz of course.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'd suggest trying a 74HC4053 first up. A 4053 is a bilaternal switch but the downside is that it has an on resistance of around 100ohms (off the top of my head). Depending on the capacitance, this may limit the maximum speed however 250kbits/s shouldn't be a problem.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you think the on resistance may be a problem, you can always try stacking several chips on top of each other, soldering pin for pin. That will parallel several switches and reduce the on resistance accordingly. I don't suggest it as a solution, just a diagnostic test. The 4053 itself doesn't have speed limitations, I've used them for video.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Likewise, I have used 4053 in video, though buffered (not in a 75 ohm system). Because of the 100 ohm-ish on resistance, capacitance on the load side is important.

There are a number of IC houses that make 405x pin-compatible muxes with much lower on resistance.

A little "rounding" on the rise and fall times should NOT hurt if, at the max bit rate you want to run, there are pretty flat tops and bottoms and the rise or fall time is less than, maybe, 20%, or so, of the PERIOD.

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just got rid of 4053 completely and soldered plain wires. The signals are ultra-pure, but still the same, 250KBps is max in atmega to atmega fight. There is something... More specific. Will inverstigate further. Some kind of jittery interrupt handling time dependency or so.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do you think this code is normal, SPI slave side?

inline void DRDY_setready()
{
	cbi(SCAP_DRDY_PORT, SCAP_DRDY_OUT);//SPI data READY, active low
}

inline void DRDY_setnotready()
{
	sbi(SCAP_DRDY_PORT, SCAP_DRDY_OUT);//SPI data NOT READY, inactive high
}

volatile uint16_t result_filtered[MAX_CHANNEL]={0};
// Channel 13 & 14 are ADC7, ADC8

volatile uint8_t spdrsend_lsb;

ISR(SPI_STC_vect)
{
	DRDY_setnotready();
	const uint8_t spdr_value=SPDR;
	if(spdr_value==0xF1)
	{
		SPDR=spdrsend_lsb;//During 0xF2 call, lsb will shift out
	}
	else if(spdr_value>8);//During 0xF1 call, msb will shift out
		spdrsend_lsb=(uint8_t)(temp);
	}
	DRDY_setready();
}

{main}
{

	// Setup SPI:
	cbi(DDRB, 2);//SS in
	sbi(PORTB, 2);//set pullup on SS
	cbi(DDRB, 3);//MOSI in
	sbi(DDRB, 4);//MISO out
	cbi(DDRB, 5);//SCK in

	SPCR=
		(1<<SPIE)|//Interrupt enable
		(1<<SPE)|//SPI enable
		(0<<DORD)|//MSB first
		(0<<MSTR)|//Slave
		(0<<CPOL)|
		(0<<CPHA)|
		(0<<SPR1)|//SCK freq is dont care for slave configuration
		(0<<SPR0)//SCK freq is dont care for slave configuration
		;
	cbi(SPSR, SPI2X);//SCK freq is dont care for slave configuration, but reading this clears interrupt flags
	DRDY_setnotready();
	//

}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

At what clockspeed are the AVR's running ?

A GIF is worth a thousend words   They are called Rosa, Sylvia, Tricia, and Ulyana. You can find them https://www.linuxmint.com/

Dragon broken ? http://aplomb.nl/TechStuff/Dragon/Dragon.html for how-to-fix tips

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Plons wrote:
At what clockspeed are the AVR's running ?

88 at 20MHz, 128 at 16MHz. 5V.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Master code:

void SCAP_init()
{
	sbi(DDRB, 0);//SS out
	sbi(PORTB, 0);//SS high
	sbi(DDRB, 1);//SCK out
	sbi(DDRB, 2);//MOSI out
	cbi(DDRB, 3);//MISO in // this is set as in by SPI enable in master mode...

	cbi(SCAP_DRDY_DDR, SCAP_DRDY);//SCAP DRDY IN
	cbi(SCAP_RXOVR_DDR, SCAP_RXOVR);//SCAP OVERRIDE IN
	sbi(SCAP_SS_DDR, SCAP_SS);//SCAP SS is out
	sbi(SCAP_DRDY_PORT, SCAP_DRDY);//SCAP dataready is pullup on
	sbi(SCAP_RXOVR_PORT, SCAP_RXOVR);//SCAP override is pullup on
	SCAP_SS_high();//Inactive
}

uint16_t SCAP_read_channel(uint8_t channel)
{
	cli();
	SCAP_setup_spi();
	SCAP_SS_low();// set SS = 0 (on)

	uint8_t errcode=SCAP_spi_write(channel);
	if(errcode==0xAA)
	{
		return 0;
	}
	sei();

	uint8_t outoftime=0xFF;
	while(SCAP_is_SPI_dataready()==false && --outoftime);
	if(!outoftime)
	{
		TIMING_PROBLEM|=64;
		return 0;
	}

	cli();
	SCAP_setup_spi();
	SCAP_SS_low();// set SS = 0 (on)
	const uint8_t msb=SCAP_spi_write(0xF1);
	SCAP_SS_high();// set SS = 1 (off)
	sei();

	outoftime=0xFF;
	while(SCAP_is_SPI_dataready()==false && --outoftime);
	if(!outoftime)
	{
		TIMING_PROBLEM|=64;
		return 0;
	}
	cli();
	SCAP_setup_spi();
	SCAP_SS_low();// set SS = 0 (on)
	const uint8_t lsb=SCAP_spi_write(0xF2);
	SCAP_SS_high();// set SS = 1 (off)
	sei();

	const uint16_t value=((uint16_t)msb<<8)|lsb;

	return value
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kbosak wrote:
Plons wrote:
At what clockspeed are the AVR's running ?

88 at 20MHz, 128 at 16MHz. 5V.

The slave can handle SPI at max F/4.
That implies that the data has to be fetched pretty quick, .... to prevent an overrun of the buffer. At max speed that is approx. 2us.

A GIF is worth a thousend words   They are called Rosa, Sylvia, Tricia, and Ulyana. You can find them https://www.linuxmint.com/

Dragon broken ? http://aplomb.nl/TechStuff/Dragon/Dragon.html for how-to-fix tips

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And that means no interrupts! I think the ISR response time is killing you. Your code cannot respond fast enough to prevent buffer over-run when it is done in an interrupt. If you want FAST SPI, then just sit in a tight loop, testing the byte complete flag. The code will only go through that loop once or twice.

Thinks about it. Max clock is Fsys/4. That means you can get 2-4 machine instructions per bit time. 8 bits means 16-32 instructions (probably upper 20s) between the start and when it HAS to be read. You simply cannot afford to do it by interrupt.

And, further, from the data sheet:

Quote:

The system is single buffered in the transmit direction and double buffered in the receive direction. This means that bytes to be transmitted cannot be written to the SPI Data Register before the entire shift cycle is completed. When receiving data, however, a received character must be read from the SPI Data Register before the next character has been completely shifted in. Otherwise, the first byte is lost.

This means that you HAVE to wait until the first byte is complete to read it. Subsequent bytes MUST be read between the time when that byte is complete and before the next byte is complete. You have no more time than that.

Jim
Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ouch the interrupt latency hint is golden. In fact the chip does PWM capture on 12 channels, I was so devoted to reduce teh PWM jitter that I forgot about calculating what should I need for SPI. I have no choice for polling since there is 'offline' calculation of the results (the PWM cap interrupt only copies 16bit register in specific place).

However, I believed that the whole DRDY machinery I implemented should provide enough delay to fetch the data into registers (the master must wait for a specific pin level before sending clocks). Of course making 4MHz then a long wait is wasteful, still, you need a few clocks for ISR and probably one to change DRDY pin so in theory it should work... At least around 1MHz. But it only does silly 250K.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Write the ISR in assembler, and get that if..else statement out of it! Stuff the data in a buffer somewhere and process it later, outside the ISR.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Like this?

volatile uint16_t result_filtered[MAX_CHANNEL]={0};
const uint8_t * const result_sendptr_beginning=(uint8_t*)&result_filtered[0];
volatile const uint8_t * result_sendptr=result_sendptr_beginning;

ISR(SPI_STC_vect)
{
	const uint8_t spdr_value=SPDR;
	SPDR=*result_sendptr++;
	if(spdr_value==0xCC)
	{
		result_sendptr=result_sendptr_beginning;
	}
}

It stinks because a half of the value might be updated so I need another mirror, 'ready to send array'.
But is the ISR minimal?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
But is the ISR minimal?

Who can tell? You wrote it in C. You have no idea how much baggage it's hauling. But I still see an IF statement in there. I'm curious to know why it's so important to reset the buffer pointer inside the ISR. Every transmitted byte carries the overhead of that test.