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

AT93C46A 16bit EEPROM driver arbitrary PINS

Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message

Joined: 20 Nov 2007
Posts: 2116
Location: albany ny

View user's profile Send private message AIM Address

AT93C46A 16bit EEPROM driver arbitrary PINS
PostPosted: Wed May 07, 2014 3:34 pm     Reply with quote

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!)

// 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;


  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);
// 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
 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);
 // 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++){
     rdata |= input_state(EE_DO); // EEPROM data   OR input pin with 16bit integer
     if (i !=15) rdata <<=1;         // and shift that bit along toward MSB
   output_low(EE_CK);    output_low(EE_DI);    output_low(EE_CS);
// 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.
Very Happy Very Happy
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library 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