UART as SPI on mega, work with SD-card via UART

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

Hi!

What AVR mega's mcu can use UART as SPI?

It's possible to work wih SD-card using UART instead of SPI (working project for AVR Studio for working with SD FAT FS will be great).

Thank you :)

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

The models that have MSPIM in their datasheet can do SPI Master using USART.

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

Quote:

The models that have MSPIM in their datasheet can do SPI Master using USART.


LOL--how about the models with >>this<< in the datasheet?!?
Quote:
20. USART in SPI Mode

But unless a true 'Freak OP doesn't have the datasheets for all AVR models on the local hard drive. Short answer: "Modern" ATmega (or equivalent) models.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Ok with SPI by UART.

Does any body have working project for AVR Studio for working with SD FAT FS? :)

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

Can any body help porting code for work SD via SPI to UART?

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

I presume it is Chan's FatFs that you are using. Surely this is as simple as just modifying the routines in mmc.c where all the existing SPI stuff is isolated?

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

clawson - yes, its :)

my first questions:

1. what speed I need setup for UART (what value for BAUD)
2. what PINs I need to configure (except XCK)
3. I need connect RX with DO and TX with DI?

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

1 FatFs uses SPI in a low speed mode during initialisation then speeds it up once the init has succeeded.

2 SPI consists of SCK (XCK), MISO (RXD) and MOSI (TXD)

3 that sounds right

BTW which AVR is this and why are you forced to use USART in SPI mode rather than using the real SPI interface? You do know that a "real" SPI can actually connect to several devices? (it's just that you can only chip/slave select one at a time).

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

yes, I know, SPI can connect several devices, but I'd like use UART instead :)

is this ok for setting BAUD and init?

#define	SYSCLK			4000000UL
#define SD_UART_BAUDRATE	100000L
#define SD_UART_BAUD (SYSCLK/(2*SD_UART_BAUDRATE))-1

#define SD_PORT PORTD
#define	SD_DDR	DDRD
#define	SD_XCK  4
...

UBRR0 = 0;
SD_DDR |= (1<<SD_XCK);

UCSR0C = (1<<UMSEL01)|(1<<UMSEL00)|(0<<UCPHA0)|(0<<UCPOL0);
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
UBRR0 = SD_UART_BAUD;

P.S. mega328, 4MHz

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

Do you have it working on SPI already? If not I'd do that first or else you are going to have too many variables in the system and will not be able to isolate faults when it doesn't work.

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

With SPI as default in library, it works

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

Any sugg? :)

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

Quote:

Any sugg?

What's the question? I think so far you've established that you have Fats working with SPI so now all you need is to provide a replacement mmc.c that uses UART-SPI instead of true SPI. As there are only about 10 lines actually interfacing with SPI in mmc.c then it should be a fairly easy port shouldn't it?

(maybe start in isolation with a simple test program just to make sure you can independently send/receive using UART-SPI - maybe test the output with a scope and make sure it "looks" like the normal SPI)

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

The question is that I need help. My project include diskio.c, not mmc.c, where SPI is used. With original SPI it works fine.

comments of diskio.c:

/*-----------------------------------------------------------------------*/
/* MMCv3/SDv1/SDv2 (in SPI mode) control module  (C)ChaN, 2010           */
/*-----------------------------------------------------------------------*/
/* Only sd_rcvr(), xmit_spi(), disk_timerproc() and some macros         */
/* are platform dependent.                                               */
/*-----------------------------------------------------------------------*/

Please look at my privios post about USART init. I don't know what value for SD_UART_BAUDRATE I need to set up and if my USART init is right for SD.

thank :)

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

Since it works with true SPI, why bother with SPI_UART ?

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

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

Because I'd like use UART instead SPI :)

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

How this function will look for SPI in USART mode?

static BYTE sd_rcvr(void)
{
 SPDR = 0xFF;
 loop_until_bit_is_set(SPSR, SPIF);
 return SPDR;
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why are you attempting this if you cannot understand basic details in the datasheet? A typical datasheet (m164/324/644) shows this for initialisating MPSIM mode:

void USART_Init( unsigned int baud )
{
  UBRRn = 0;
  /* Setting the XCKn port pin as output, enables master mode. */
  XCKn_DDR |= (1<<XCKn);
  /* Set MSPI mode of operation and SPI data mode 0. */
  UCSRnC = (1<<UMSELn1)|(1<<UMSELn0)|(0<<UCPHAn)|(0<<UCPOLn);
  /* Enable receiver and transmitter. */
  UCSRnB = (1<<RXENn)|(1<<TXENn);
  /* Set baud rate. */
  /* IMPORTANT: The Baud Rate must be set after the transmitter is enabled 
  */
  UBRRn = baud;
}

and this to send a byte:

unsigned char USART_Receive( unsigned char data )
{
  /* Wait for empty transmit buffer */
  while ( !( UCSRnA & (1<<UDREn)) );
  /* Put data into buffer, sends the data */
  UDRn = data;
  /* Wait for data to be received */
  while ( !(UCSRnA & (1<<RXCn)) );
  /* Get and return received data from buffer */
  return UDRn;
}

I've corrected the latter to take "data" as a parameter as they were using it globally.

This second routine is close to the routine you describe except that it sends "data" not a fixed 0xFF. To use it in that way then call with:

USART_Receive(0xFF);

(as it's both a send and receive routine the name _Receive is a misnomer and perhaps should be something like _Transfer() ? Also, to avoid confusion I would put SPI in these function names somewhere to show the UART is actually being used in SPI mode)

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

Thank, I have read initialisating MPSIM mode in Datasheet long ago. Init and sample send/receive work fine, but in project with SD it send/receive data not like when using SPI.

The other question I don't know is what will be BAUD value for USART speed 100 and 400 kHz. (in project with SPI author using this speed for SPI)

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

See ffsample.zip. It's designed for about 10MHz (9.something in fact) and it does this:

E:\ffsample\avr>grep SPCR mmc.c
#define FCLK_SLOW()     SPCR = 0x52             /* Set slow clock (100k-400k) */
#define FCLK_FAST()     SPCR = 0x50             /* Set fast clock (depends on the CSD) */ // cliff change 50 to 52
        SPCR = 0x52;                    /* Enable SPI function in mode 0 */
        SPCR = 0;                               /* Disable SPI function */

Looking at the mega64 datasheet (the chip this was written for) this shows that in "slow" mode while the card is initialised it is running at 10M/64 = 156,250 and in fast it is 10M/4 = 2.5M

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

Yes, it is good for SPI, and what will be BAUD for USART for 100k-400k?

in copy I found in internet of mmc.c in sd_poweron:
SPSR = 0x01
that mean SPI2x,
SPI2x=1 and SPR1=1 and SPR0=0 => Fosc/32 (SPCR=0x52)

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

This from the mega164/324/644 datasheet:

Quote:
The function and bit description of the baud rate registers in MSPI mode is identical to normal USART operation. See ”UBRRnL and UBRRnH – USART Baud Rate Registers” on page 193.

The implication is that the usual:

BAUD = F_CPU/(16 * (UBRR + 1))

applies.

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

Can you share your copy of ffsample? thank

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

Eh? It's on Chan's website?!? (my local copy has edits for my own use)

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

Hi! Coud somebody check transformation from SPI to USART in SPI mode:

== SPI ==

#define CS_LOW()	PORTB &= ~1
#define CS_HIGH()	PORTB |= 1

#define xmit_spi(dat) 	SPDR=(dat); loop_until_bit_is_set(SPSR,SPIF)

#define rcvr_spi_m(dst)	SPDR=0xFF; loop_until_bit_is_set(SPSR,SPIF); *(dst)=SPDR

static void IoInit ()
{
 PORTB = 0b10110000;
 DDRB  = 0b11000000;
}

static int power_status(void)
{
 return (PORTE & 0x80) ? 0 : 1;
}

static BYTE rcvr_spi (void)
{
 SPDR = 0xFF;
 loop_until_bit_is_set(SPSR, SPIF);
 return SPDR;
}

static void power_on (void)
{
 // PORTE &= ~0x80; 	/* Socket power on */
 for (Timer1 = 2; Timer1; );	/* Wait for 20ms */
 PORTB = 0b10110101; 	/* Enable drivers */
 DDRB  = 0b11000111;
 SPCR = 0x52;		/* Enable SPI function in mode 0 */
 SPSR = 0x01;		/* SPI 2x mode */
}

static int wait_ready (void)
{
 BYTE d;
 Timer2 = 50;
 do
  d = rcvr_spi();
 while (d != 0xFF && Timer2);
 return (d == 0xFF) ? 1 : 0;
}

== USART in SPI ==

#define SD_PORT	PORTD
#define SD_DDR	DDRD

#define SD_CS   2
#define SD_XCK 4

#define FCLK_FAST() 
#define FCLK_SLOW() 

#define xmit_usart(dat)	while (!(UCSR0A & (1<<UDRE0))); UDR0=dat;
#define rcvr_usart_m(dst) 	UDR0=0xFF; while (!(UCSR0A & (1<<RXC0))); *(dst)=UDR0; 

#define SD_CS_LOW()	SD_PORT &= ~(1<<SD_CS)	/* MMC CS = L */
#define SD_CS_HIGH()	SD_PORT |= (1<<SD_CS)	/* MMC CS = H */

static void IoInit ()
{
 // PORTB = 0b10110000;   // PORT: SS,SCK,MISO,MOSI=0
 // DDRB  = 0b11000000;  // DDR: SS,SCK,MISO,MOSI=0
 // WP and POWER flags don't using
 SD_DDR = 0;
 SD_PORT= 0;
}

static int power_status(void)
{
 return 1;
}

static BYTE rcvr_usart(void)
{
 while (!(UCSR0A & (1<<UDRE0)));
 UDR0=0xFF;
 while (!(UCSR0A & (1<<RXC0)));
 return UDR0;
}

static void power_on (void)
{

 //PORTB = 0b00000101;  // CS=1,SCK=0,MOSI=1,MISO=0
 //DDRB  = 0b00000111; // CS=1,SCK=1,MOSI=1,MISO=0
 // WP and POWER flags don't using
 // PB0 - SS / CS  
 // PB1 - SCK / XCK
 // PB2 - MOSI / TX
 // PB3 - MISO / RX

 SD_DDR = (1<<SD_XCK)|(1<<SD_CS);	
 SD_PORT = (1<<SD_XCK)|(1<<SD_CS);

 // SPI mode 0
UCSR0C = (1<<UMSEL01)|(1<<UMSEL00)|(0<<UDORD0)|(0<<UCPOL0)|(0<<UCPHA0);
UCSR0B = (1<<RXEN0)|(1<<TXEN0);

 UBRR0 = 100000;
}

static int wait_ready(void)
{
 int timer = 0;
 rcvr_usart();
 do
  {
   if (rcvr_usart() == 0xFF) return 1;
   _delay_ms(30); 
   timer++;
  }
 while (timer<50);
 return 0;
}

thank you! :)

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

Surely the proof of whether you have done it properly is whether it works? If it doesn't dig out you JTAG and your oscilloscope and determine why.

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

before check all HW, it would be great if somebody check if my translation from HW SPI to USART in SPI is done properly :)

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

Is there somebody real AVR professionals?

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

In the preceding 56 days since this thread started have you tried simple test cases (ignoring the SD for the time being) and just proved you can make the same pulses occur for the UART acting as SPI as the real SPI? Once you are over that hurdle it's just a "slot in" solution isn't it?