CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Problem with 18F4550 to Atmel Dataflash Communication

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
karlfstborst



Joined: 11 Oct 2006
Posts: 4
Location: Darmstadt, Germany

View user's profile Send private message

Problem with 18F4550 to Atmel Dataflash Communication
PostPosted: Wed Oct 11, 2006 8:33 am     Reply with quote

I am trying to communicate with an Atmel Dataflash AT45DB041B using a PIC18F4550 microcontroller - I can't get it to work, I have tried everything and read through this whole forum for hours, but with no luck.

The Pic is connected to 5V and the Atmel to 3.3 Volts (from triple power supply) with the following pin-connections:

Code:

PIC-VCC --- 5V
PIC-SDO(C7) --- ATMEL-SI
PIC-SDI(B0)  --- ATMEL-SO
PIC-SCK(B1) --- ATMEL-SCK
PIC-B2 ---  ATMEL-CS
ATMEL-[RESET,WP,VCC] --- 3.3V
ATMEL-GND ---GND


I use the 3.249 CCS Compiler, the settings are the following (I have connected an external 20 MHz crystal to the PIC):

Code:

#device ADC=8
#fuses HS            /* High speed Osc (> 4mhz) */
#fuses PLL5          /* PLL5 Divide By 5(20MHz oscillator input) */ 
#fuses CPUDIV1      /* CPUDIV1 No System Clock Postscaler */
#fuses USBDIV      /* USB clock source comes from PLL divide by 2 */
#fuses VREGEN      /* USB voltage regulator enabled */
#fuses NOWDT        /* No Watch Dog Timer */
#fuses NOPROTECT    /* Code not protected from reading */
#fuses NOLVP        /* No low voltage prgming, B5 (PIC18) used for I/O */
#fuses NODEBUG      /* No Debug mode for ICD */ 
#fuses NOPBADEN    /* PORTB pins are configured as digital I/O on RESET */
#define MHZ(x) x##000000       
#use delay(clock=MHZ(20))


So, first I tried to use the hardware SPI module (after read/write failed, I thought just reading the status register would be the easiest test):

Code:

int8 read_statusreg(void)
{
   int8 reg;
   
   // SPI Mode 3:

   setup_spi(SPI_MASTER |
           SPI_H_TO_L |
           SPI_XMIT_L_TO_H |
           SPI_CLK_DIV_4 |
           SPI_SAMPLE_AT_END);
   
   printf("Reading Statusreg...");
   
   delay_us(50);
   output_high(EEPROM_SCK);
   output_low(EEPROM_CS);
   delay_cycles(15);
   spi_write(0x57);
   reg = spi_read(0);
   output_high(EEPROM_CS);   
   delay_cycles(15);
   printf("[Done]\r\n");
   
   return reg;
}


I've experimented alot with this, different delays etc., but the Flash is outputting nothing but zero. Also checked it on the scope - constant 0 all the time.

I then tried to modify an existing device file (provided by the ccs compiler) for a very similiar flash that don't use the hardware SPI module, it goes like this:

Code:

int8 ext_flash_getByte()
{
   int8 flashData;
   int i;
   for(i=0; i<8; ++i)                        // Get 8 bits of data
   {
      output_high(EEPROM_SCK);
      shift_left(&flashData, 1, input(EEPROM_SDI));
      output_low(EEPROM_SCK);
   }
   return flashData;
}

void ext_flash_sendData(int16 data, int8 size)
{
   int8 i;
   data <<= (16-size);
   for(i=0; i<size; ++i)
   {
      output_bit(EEPROM_SDO, shift_left(&data,2,0));    // Send a data bit
      output_high(EEPROM_SCK);                       // Pulse the clock
      output_low(EEPROM_SCK);
   }
}

int8 ext_flash_readStatus()
{
   int8 status;
   output_low(EEPROM_CS);                 // Enable select line
   ext_flash_sendData(0xD7, 8);              // Send status command
   status = ext_flash_getByte();             // Get the status
   output_high(EEPROM_CS);                // Disable select line

   return status;                            // Return the status
}


This didn't work either, I'm afraid. Then out of desperation, I tried to just stupidly code the low level bit timing diagram from the datasheet, also with no success:

Code:

int8 read_statusreg_lowlevel(void)
{
   int8 data;
   data = 0;

   output_high(EEPROM_CS);
   output_high(EEPROM_SCK);
   delay_cycles(10);
   output_low(EEPROM_CS);
   delay_cycles(1);
   output_low(EEPROM_SCK);
   output_low(EEPROM_SDO); // 0
   output_high(EEPROM_SCK);
   output_low(EEPROM_SCK);
   output_high(EEPROM_SDO);// 1
   output_high(EEPROM_SCK);
   output_low(EEPROM_SCK);
   output_low(EEPROM_SDO);// 0
   output_high(EEPROM_SCK);
   output_low(EEPROM_SCK);
   output_high(EEPROM_SDO);// 1
   output_high(EEPROM_SCK);
   output_low(EEPROM_SCK);
   output_low(EEPROM_SDO);// 0
   output_high(EEPROM_SCK);
   output_low(EEPROM_SCK);
   output_high(EEPROM_SDO);// 1
   output_high(EEPROM_SCK);
   output_low(EEPROM_SCK);
   output_high(EEPROM_SDO);// 1
   output_high(EEPROM_SCK);
   output_low(EEPROM_SCK);
   output_high(EEPROM_SDO);// 1
   output_high(EEPROM_SCK);
   output_low(EEPROM_SCK);
   output_high(EEPROM_SCK);
   data |= (input(EEPROM_SDI) << 8); // MSB
   output_low(EEPROM_SCK);
   output_high(EEPROM_SCK);
   data |= (input(EEPROM_SDI) << 7);
   output_low(EEPROM_SCK);
   output_high(EEPROM_SCK);
   data |= (input(EEPROM_SDI) << 6);
   output_low(EEPROM_SCK);
   output_high(EEPROM_SCK);
   data |= (input(EEPROM_SDI) << 5);
   output_low(EEPROM_SCK);
   output_high(EEPROM_SCK);
   data |= (input(EEPROM_SDI) << 4);
   output_low(EEPROM_SCK);
   output_high(EEPROM_SCK);
   data |= (input(EEPROM_SDI) << 3);
   output_low(EEPROM_SCK);
   output_high(EEPROM_SCK);
   data |= (input(EEPROM_SDI) << 2);
   output_low(EEPROM_SCK);
   output_high(EEPROM_SCK);
   data |= (input(EEPROM_SDI) << 1);
   output_low(EEPROM_SCK);
   output_high(EEPROM_SCK);
   data |= input(EEPROM_SDI);
   output_high(EEPROM_CS);
   delay_cycles(10);
   
   return data;   
}


So now I've really ran out of ideas. Does someone have an idea of what the problem could be? Of course it could be that the flash is damaged, but its brand new, so probably not (how could I test that by the way?).

I appreciate any comments on this, anything would be helpful.


Best Regards,
Andre Kvist Aronsen.
asmallri



Joined: 12 Aug 2004
Posts: 1634
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Oct 11, 2006 9:07 am     Reply with quote

Back to basics. I am assuming you have a pull up resistor on the SDO line from the Atmel otherwise you could not tell if you are reading a 0 level out of the flash or a floating output.) Ignoring the software, the hardware has one, possibly two problems.

Possible problem: Are the Atmel flash SDI, CS and SCK inputs +5v tolerant? If not latch up can occur and it will not work. This scenario could explain why the ATMEL puts out a continuous logic zero. If this is the case the easiest way around this problem is to add resistive voltage dividers to these lines. If you check out the projects page on my web site you will find a reference schematic showing a +5V PIC being interfaces to a 3.3volt SD card using this mechanism.

Actual problem: In SPI mode the SDI input to the PIC is a Schmidt trigger input. In this mode a 3.3 volt output high from the ATMEL flash is in the undefined region (not guarenteed to be high by the PIC). However if this was your problem you would still expect to see SDO activity form the flash on a cro but the PIC would not understand it.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
karlfstborst



Joined: 11 Oct 2006
Posts: 4
Location: Darmstadt, Germany

View user's profile Send private message

PostPosted: Wed Oct 11, 2006 10:17 am     Reply with quote

Thanks for your fast reply! I didn't have a pull-up resistor there, but I tried it now (connecting a 4.7kOhm resistor between ATMEL-SO and 5V and measured the voltage between GND and SO), the pin really seems to be floating - the voltage was never pulled down to 0 but stayed at 4-5V. So the Flash doesn't output zero 8 times, it just didn't recognize the command (or its broken) - the so-pin is defined to be high-resistant when not sending.

The inputs to the flash are according to the datasheet all +5V tolerant, so that should be no problem.

I didn't know about the ST-Input of the PIC, but a pull-up resistor should solve that problem, right? So when the pic is outputting 0, the pic gets 0, when its outputting 3.3V, then the PIC gets 5V-voltage drop. But as you said, I should nonetheless see something on the oscilloscope, which I don't.
asmallri



Joined: 12 Aug 2004
Posts: 1634
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Oct 11, 2006 10:30 am     Reply with quote

Quote:
I didn't know about the ST-Input of the PIC, but a pull-up resistor should solve that problem, right?


No. You need to use a level shifter such as a TTL buffer. Check out the SDI line to the PIC on my sample schematics. Without this you will most likely find it works most of the time and just stops.

Now that you know the Atmel never pulls the line low (which was more likely than always low) the next thing to determine is are you using the correct SPI mode for the Atmel device.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
karlfstborst



Joined: 11 Oct 2006
Posts: 4
Location: Darmstadt, Germany

View user's profile Send private message

PostPosted: Wed Oct 11, 2006 10:56 am     Reply with quote

I'll look into the level-shifter - the 5v are just for the prototype, later the whole circuit will run on a 3V battery anyway, so there it won't be a problem.

So for the SPI-Mode - the Atmel can use SPI-Mode 1 or 3 according to the datasheet, I've tried both - in the non-hardwareSPI-version, Mode 1 is used - so SCK=0 in idle-mode and transmit on low-high transitions, and Read-Command 0xD7. For the SPI-Code I've used Mode 3 (apparently the most used mode), the setup_spi-parameters are therefore SPI_H_TO_L as in SCK=1 on idle and SPU_XMIT_L_TO_H for transmitting on rising edges, the SPI_SAMPLE_AT_END I got from this forum, I don't know why this is better than sampling at the beginning. Then the command 0x57 for reading the status register in Mode 3. The outputting of high voltage on SCK before pulling Chip Select down, I got from this forum again. The spi_write/spi_read(0) should then take care of the clock signal for the transmit. Did I get this right, or are there some mistakes in there? Do I have to have some other code to prepare for SPI-Mode other than setup_spi? (I've seen btw. that the newest compiler has a comfortable #use SPI pragma, thats probably easier to set up).
karlfstborst



Joined: 11 Oct 2006
Posts: 4
Location: Darmstadt, Germany

View user's profile Send private message

PostPosted: Wed Oct 11, 2006 11:41 am     Reply with quote

I've just spent some time in front of the oscilloscope again, and tested with the SPI-function and found something interesting; the clocksignal (PIC-SCK) seem to be constant at 5V (apart from some noise). I don't know if the clock is going so fast, that my scope doesn't get the oscillation, but I doubt it. So if there is no clocksignal, then it won't work of course. What could cause this problem? Either the hardware-unit or the compiler-code (or my initialization) is not working properly.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group