asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
AT93C46 64 x 16bit external EEPROM EZ bitbang |
Posted: Fri Mar 11, 2016 4:43 pm |
|
|
driver for ATMEL 93C46 16 bit x 64 words storage and retrieval
Code: |
// ATMEL AT 93C46 , EEPROM operating in 64 byte - 16 bit mode for R/W
// //
#define EE_CS PIN_A2
#define EE_CK PIN_C0
#define EE_DI PIN_C4
#define EE_DO PIN_A3
// INIT dependencies
// setup_timer_0( T0_INTERNAL|RTCC_DIV_64); // 15 msec per tick
// with 4.1943 mhz cystal
// 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_low(EE_DI); 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++){ // only 9 clocks required here
output_high(EE_CK); delay_cycles(2); output_low(EE_CK); delay_cycles(2);
}
output_low(EE_DI); delay_cycles(2); output_low(EE_CS);
}
//send the following to initialize EEPROM after reset or cold start
void init_46_eeprom(void) { ee_sendcmd(0); }
// write a 16bit data item to address 0-63
void WEX_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'
output_low(EE_CS);
}
// read back int16 frfom eeprom
//
unsigned int16 REX_eeprom(byte address) {
byte cmdout=0b11000000; // ^^^^^
unsigned int16 Rdata=0;
int8 i;
#bit sbit=cmdout.7
#bit abit=address.5
// NOTE we are using address bit6 not 7 for shifts
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
output_low(EE_DI);
for (i=0; i!=16; i++){
output_high(EE_CK);
rdata |= input_state(EE_DO); // adcdata OR input pin with 16bit int
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);
}
|
|
|