|
|
View previous topic :: View next topic |
Author |
Message |
hansimg
Joined: 24 May 2010 Posts: 8
|
interfacing pic16f877a with eeprom 25lc640 |
Posted: Mon May 31, 2010 10:49 am |
|
|
I'm trying write a memory 25lc640 and use this code to the pic:
Code: | #include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#define SPI_MODE_0_0 0x4000
#define SPI_MODE_0_1 0x0000
#define SPI_MODE_1_0 0x0010
#define SPI_MODE_1_1 0x4010
/*
// If your hardware SPI pins are different than the
// ones used on the 16F877, then define them here
// and un-comment this section.
#define EEPROM_SELECT PIN_C2
#define EEPROM_CLK PIN_C3
#define EEPROM_DI PIN_C5
#define EEPROM_DO PIN_C4
*/
#include <25LC640_Hardware_SPI.c>
#include <STDLIB.H>
//========================
void main()
{
int8 data;
int8 wrote;
int16 addr;
int16 errors = 0;
init_ext_eeprom();
// Fill eeprom with random data.
printf("\n\r");
printf("writing");
srand(0x55);
for(addr = 0; addr < EEPROM_SIZE; addr++)
{
write_ext_eeprom(addr, (int8)rand());
if((int8)addr == 0)
putc('.');
}
// Read the eeprom and check for errors.
printf("\n\r");
printf("reading");
srand(0x55);
for(addr = 0; addr < EEPROM_SIZE; addr++)
{
data = read_ext_eeprom(addr);
wrote = (int8)rand();
if(data != wrote)
{
printf("%lx: read %x, should be %x\n\r", addr, data, wrote);
errors++;
if(errors >= 10)
break;
}
if((int8)addr == 0)
putc('.');
}
printf("\n\r");
printf("done\n\r");
while(1);
} |
And this code for driver memory:
Code: |
#ifndef EEPROM_SELECT
#define EEPROM_SELECT PIN_C2
#define EEPROM_CLK PIN_C3
#define EEPROM_DI PIN_C5
#define EEPROM_DO PIN_C4
#endif
#define EEPROM_ADDRESS long int
#define EEPROM_SIZE 8192
void init_ext_eeprom()
{
output_high(EEPROM_SELECT);
setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_16 );
}
//--------------------------------
int1 ext_eeprom_ready(void)
{
int8 data;
output_low(EEPROM_SELECT);
spi_write(0x05);
data = spi_read(0);
output_high(EEPROM_SELECT);
return(!bit_test(data, 0));
}
//--------------------------------
void write_ext_eeprom(EEPROM_ADDRESS address, BYTE data)
{
while(!ext_eeprom_ready());
output_low(EEPROM_SELECT);
spi_write(0x06);
output_high(EEPROM_SELECT);
output_low(EEPROM_SELECT);
spi_write(0x02);
spi_write(address >> 8);
spi_write(address);
spi_write(data);
output_high(EEPROM_SELECT);
}
//--------------------------------
BYTE read_ext_eeprom(EEPROM_ADDRESS address)
{
int8 data;
while(!ext_eeprom_ready());
output_low(EEPROM_SELECT);
spi_write(0x03);
spi_write(address >> 8);
spi_write(address);
data = spi_read(0);
output_high(EEPROM_SELECT);
return(data);
} |
I take this code from PCM_PROGRAMER, but when i try to simulate it in proteus i receive the follows message:
[PIC16 MSSP] PC=0X0148. Data written SSPBUF whilst MSSP (in master mode) is active - data has been ignored.
[SPIMEM] Transfer did not end on a byte boundary, data will not be writen.
I think that is something wrong with my schematic, here is it.
If anyone knows what i did wrong, please help me. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon May 31, 2010 11:21 am |
|
|
What is your compiler version number? |
|
|
hansimg
Joined: 24 May 2010 Posts: 8
|
|
Posted: Mon May 31, 2010 11:29 am |
|
|
CCS 4.057 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon May 31, 2010 2:49 pm |
|
|
It works for me. I compiled your code with vs. 4.057, and ran it on
a PicDem2-Plus board with a 25LC640 on it. I get this result displayed
in the terminal window:
Quote: |
writing................................
reading................................
done
|
It's not getting any errors. I looked at the signals with a scope and
they're all active. It's putting out bursts of 8 clocks on the SCLK pin.
I think it's working and the problem is in Proteus. |
|
|
semmoor
Joined: 09 May 2012 Posts: 46 Location: KSA
|
|
Posted: Fri Jul 27, 2012 5:20 am |
|
|
did it work on proteus? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9241 Location: Greensville,Ontario
|
|
Posted: Fri Jul 27, 2012 5:26 am |
|
|
Since PCM Programmer proved your code works on real hardware the problem( again) is Proteus !
Sigh, I know I sound like a broken record , but Proteus is FULL of bugs, errors, faulty DRCs and is NOT a reliable simulation.You cannot fix Proteus so I suggest you toss it into the 'trash bin' asap. |
|
|
semmoor
Joined: 09 May 2012 Posts: 46 Location: KSA
|
|
Posted: Fri Jul 27, 2012 5:42 am |
|
|
temtronic wrote: | Since PCM Programmer proved your code works on real hardware the problem( again) is Proteus !
Sigh, I know I sound like a broken record , but Proteus is FULL of bugs, errors, faulty DRCs and is NOT a reliable simulation.You cannot fix Proteus so I suggest you toss it into the 'trash bin' asap. |
you're 100% right, it's full of bugs , and can never be like real hardware, but people use it because it's really easy to find any device and just use it, but i'm thinking to stop using it, everyday errors, bugs etc... |
|
|
ettore
Joined: 30 Sep 2012 Posts: 1
|
|
Posted: Sun Sep 30, 2012 4:54 pm |
|
|
Don't be too fast to blame Proteus.
In such the case I can demonstrate how the bug comes from CCS compiler optimizer, not Proteus.
Just to begin I have made a simple program like this:
Code: | #include <16F877a.H> //<18F458.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#define SPI_MODE_0_0 0x4000
#define SPI_MODE_0_1 0x0000
#define SPI_MODE_1_0 0x0010
#define SPI_MODE_1_1 0x4010
#define CHIP_SELECT PIN_C2
void main()
{ volatile int8 data = 0xAA;
volatile int16 addr = 0x100;
//#OPT 0
output_high(CHIP_SELECT);
setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_16 );
output_low(CHIP_SELECT);
spi_write(0x06);
output_high(CHIP_SELECT);
output_low(CHIP_SELECT);
spi_write(0x02);
spi_write(addr >> 8);
spi_write(addr);
spi_write( data);
output_high(CHIP_SELECT);
while(1);
} |
and used it on my HW board and Proteus simulator as well, and for either PIC16 or PIC18 popular devices. While the version for PIC18 ever works either for Proteus or real device the one for PIC16 did not; neither for Proteus nor for the real PIC. What I've got in the HW is the chip select pin which goes high before the entire 4 bytes writes procedure is completed. In Proteus I get the same as well and in addition I get a couple of warning messages that tell me I'm writing into the SSPBUF while the Master SSP module is still transmitting.
Given that with other compilers the program reported above works fine, then in order to understand where the problem resides I had to investigate about the assembler code generated with the compiler. The spi_Write(value) internal function is translated with asm codes like these (comment are mine):
Code: | .................... spi_write(0x02);
004D: MOVF 13,W ; -> dummy read of the SSPBUF buffer. This clears the BF flag bit in status register, otherwise software polling won't work.
004E: MOVLW 02
004F: MOVWF 13 ; Value is written in SSPBUF. The BF flag bit is still cleared at this point.
0050: BSF 03.5 ; Switch to bank 1.
0051: RRF 14,W ; Rotate right the BF flag into the C flag STATUS bit.
0052: BTFSC 03.0 ; Polling test of the BF bit of the status register (bit BF is rotated into the C STATUS flag).
0053: GOTO 051 ; When 8 bits are transmitted then BF is set and the software can go on, otherwise do polling again. |
For PIC16 and when optimizer is configured for all the levels but 0 the SSPBUF dummy read MOVF is removed! Perhaps the optimizer presumes it's an obsolete code or something like that but interestingly enough this happens when the data is a variable not a literal. Anyway, as a result of this code removal the BF flag bit is not cleared and polling test exits before than the whole byte is transmitted.
However if you put somewhere the directive #OPT 0 then the above code works well even for PIC16 family, although the translated code is not optimized anymore.
If you check the translated code with optimizer disabled then you'll see again the dummy read - MOVF 13,W - in the code, as it should be!
I have made these tests with the CCS compiler version 4.107.
Proteus is a great piece of a software, but certainly not bug free in any case ... exactly as the CCS compiler though! This thread is a demonstration.
At any rate, please feel free to send the results of my fault finding to the CCS company for further investigation and bug fixing.
Regards,
Ettore Arena |
|
|
matheuslps
Joined: 29 Sep 2010 Posts: 73 Location: Brazil
|
|
Posted: Sun Aug 25, 2013 4:09 pm |
|
|
Thanks ettore!!!
Your tip did work for me.
Just added #OPT 0 on the code and now it is working with Proteus! Finally!
I am able to work with the max7219.
bye |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Mon Aug 26, 2013 2:08 am |
|
|
Classic read the manual.....
If you perform spi_write, by default it will return as soon as the byte is transferred to the output buffer. A _subsequent_ spi_write, will wait till the previous transaction is completed.
However if you perform spi_read, this will always wait for the transfer to complete.
So the _last_ spi_write in the transaction, needs to be replaced with:
Code: |
int8 dummy; //in the declarations
dummy=spi_read(data);
output_high(CHIP_SELECT);
//Or
spi_write( data);
while (!spi_data_is_in()) ;
output_high(CHIP_SELECT);
|
|
|
|
|
|
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
|