asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
AT93C46A 16bit EEPROM driver arbitrary PINS |
Posted: Wed May 07, 2014 3:34 pm |
|
|
i had to use a clients "old stock" in a project update-
the ATMEL brand --AT93C46A
which has very SLOW timing constraints and is ONLY
able to run in a fixed 16 bit mode, with 64 addresses...
there is no CCS standard driver-
this could easily be re-purposed to other 16 bit eeproms,
and needed to be "bit-bang" as only arbitrary pins were free
in the design to host the part. ( ended up using MCLR pin as Data receiver!)
Code: |
// ATMEL AT 93C46A , contrary EEPROM with ONLY 16 bit mode for R/W
// DEP 5/2014 supports addresses 0-63 for a smoking 64 16 bit WORDS
//
#define EE_CS PIN_A2
#define EE_CK PIN_C0
#define EE_DI PIN_C4
#define EE_DO PIN_A3
// CMD=0 EWEN enable erase/write
// CMD=1 EWDS disable " "
// CMD=2 ERAL ALL bytes erase
// NOTE1: CMD 2 MUST be preceded by a CMD 0
// NOTE2: ERASE single(address) byte not supported since
// chip will overwrite an address w/o a previous unitary erase
void EE_SENDCMD( int8 cmd){
byte cmdout; // ^^^^^
int8 i;
#bit sbit=cmdout.7
output_low(EE_DI); output_low(EE_CS); output_low(EE_CK);
if(2==cmd) cmdout=0b10010000; // ERAL =EraseAll addresses
else if (1==cmd) cmdout=0b10000000;
else cmdout=0b10011000;
output_high(EE_cs);
for (i=0; i!=5; i++ ){
if (sbit) output_high(EE_DI);
else output_low(EE_DI);
delay_cycles(2); output_high(EE_CK); cmdout <<= 1;
delay_cycles(1); output_low(EE_CK); delay_cycles(2);
}
output_low(EE_CK); output_low(EE_DI);
for (i=0; i!=4; i++){ output_high(EE_CK); delay_cycles(2); output_low(EE_CK); delay_cycles(2);
}
delay_cycles(2); output_low(EE_CS);
}
void init_46_eeprom(void) { ee_sendcmd(0); }
// setup_timer_0( T0_INTERNAL|RTCC_DIV_64); // 15 msec per tick
// with 4.1943 mhz cystal
void W_eeprom( unsigned int8 address, unsigned int16 data) {
byte cmdout=0b10100000; // ^^^^^
int8 i;
#bit sbit=cmdout.7
#bit dbit=data.15
#bit abit=address.5
output_low(EE_DI); output_low(EE_CS); output_low(EE_CK);
output_high(EE_CS); delay_cycles(1);
// send cmd header
for (i=0; i!=3; i++){ // send command prefix
if(sbit) output_high(EE_DI);
else output_low(EE_DI);
delay_cycles(1); output_high(EE_CK); cmdout <<=1; output_low(EE_CK);
}
output_low(EE_DI); // header is out - now for address
for (i=0; i!=6; i++){
if(abit) output_high(EE_DI);
else output_low(EE_DI);
delay_cycles(2); output_high(EE_CK); address <<=1; output_low(EE_CK);
delay_cycles(2);
}
// now send data
for (i=0; i!=16; i++){
if(dbit) output_high(EE_DI);
else output_low(EE_DI);
delay_cycles(1); output_high(EE_CK); data <<=1;
output_low(EE_CK); delay_cycles(1);
}
output_low(EE_DI); delay_cycles(2);
// now instead of fixed delay wait for chip or timer to exit
set_timer0(0); // you can use delay_ms(15) instead here
T0IF=0;
do{ delay_cycles(2); } while ( !T0IF );
// up to 15 msecs for the write to 'take' using system timer0
output_low(EE_CS); // lower chip select and go
}
// read a 16 bit value back from EEPROM
unsigned int16 R_eeprom(byte address) {
byte cmdout=0b11000000; // ^^^^^
unsigned int16 Rdata=0;
int8 i;
#bit sbit=cmdout.7
#bit abit=address.5
output_low(EE_DI); output_low(EE_CS); output_low(EE_CK); output_high(EE_CS);
// send cmd header
for (i=0; i!=3; i++){
if(sbit) output_high(EE_DI);
else output_low(EE_DI);
delay_cycles(1); output_high(EE_CK); cmdout <<=1; output_low(EE_CK);
}
output_low(EE_DI);
// header is out - now for address
for (i=0; i!=6; i++){
if(abit) output_high(EE_DI);
else output_low(EE_DI);
delay_cycles(1); output_high(EE_CK); address <<=1; output_low(EE_CK);
}
output_low(EE_DI); // now to read data
for (i=0; i!=16; i++){
output_high(EE_CK);
rdata |= input_state(EE_DO); // EEPROM data OR input pin with 16bit integer
output_low(EE_CK);
if (i !=15) rdata <<=1; // and shift that bit along toward MSB
}
output_low(EE_CK); output_low(EE_DI); output_low(EE_CS);
return(rdata);
}
// DEMO of sending two bytes instead of one int16 word to W_EEPROM()
void save2bytes( unsigned int8 addr, byte hibyte, byte lobyte){
W_eeprom( addr, MAKE16(hibyte,lobyte);
} |
any suggestions to make it neater and sweeter always accepted.
|
|