' Program: AT45Term.BAS written using PicBasicPro ver 2.43 ' PicBasic Pro program to interface with an Atmel ATDB041B DataFlash, ' 4mbit 8pin IC using the SPI protocol. ' ' ALPHA CODE ' N O T F O R R E L E A S E ' ************* NOT FOR COMMERCIAL USE ************************* ' Ver. 0.5 Jul, 2003 ' 'Last modified: Aug 18 ' ' ' Proprietory Owner: COMPsys, Copyright 2003 ' ' Project Reference: AT45DB ' MCU: Microchip PIC16F877 ' Software: Compiler PBP V.2.43, MicroCodePlus IDE ' PIC Programmer: EPIC used to load the bootloader, ' Custom PCB with a serial interface ' for ISP and terminal output ' ' Initial Date: Jul 26, 2003 ' Projected Completion Date: Unknown ' ' Author: Ranjit Diol ' rsdiol@compsys1.com ' http://www.compsys1.com/workbench ' ' '*************************************************************** ' (c) COMPSys, 2003 ' All Rights Reserved '*************************************************************** '' DISCLAIMER: This file is being released as non-commericial ' software. It is being provided "AS IS", neither the author, ' nor COMPSys shall be held liable for any damages caused ' by its use. ' ' Contact: rsdiol@compsys1.com for more information ' '******************************************************************* ' Windows and DOS are registered trademarks of Microsoft Corporation '******************************************************************* ' 'Brief: The AT45DB041B is a 2.7-3.6 volt part however the data lines, ' CS,SCK,WP are 5v tolerant ' One possible method of using the device in a 5v circuit would be ' to suplly Vcc through a voltage divider. ' Example: ' ' A couple of 5v to 3v conversion methods '======================================== 'Method 1: A 20 cent solution, but only if you have a hefty power source ' that can afford a drain strain! 'Parts: R1 100 ohm R2 200 ohm 1/4w resistors ' Vin(5v)----- 100 ohm R1 ' | ' -----------Vout 3.3v (no load) ' | this will fall within the ' 200 ohm R2 2.7-3.6v range of the AT45DB041 ' | The AT45DB041 requires 35ma max ' | during write/erase operations. Reading ' GND requires 10ma max. The typical currents ' are much less. ' 'Method 2: A 50 cent solution - much more elegant! ' Parts: ' IC1 LM317 ' R1 280 ohm R2 392 ohm (even a 390 will do) 1/8w resistors ' ' LM317 Top view 1=Adj 2=Out 3=In ' __ ' IC1 (___) ' 1 2 3----------- Vin (5v-20v) ' | | ' R1 between 1 & 2 280------------- 3v out ' | ' R2 between Gnd & 1 |____ 392_______ GND ' ' ' AT45Dbxxx Data sheets available at http://www.atmel.com ' '============== Pin Connections ================ ' AT45DB041B ' PIC RB0 --> MOSI 1 8 MISO --> PIC RB1 ' PIC RB2 <-> SCK 2 7 Gnd --- Gnd ' Vcc --- /RST 3 6 Vcc --- Vcc ' PIC RB3 --> /CS 4 5 /WP --- Vcc ' '=============================================== ' AT45DB041 8pin SOIC pins: ' Pin1:MOSI ,Pin2:SCK,Pin3:/RESET,Pin4:/CS ' Pin5:/WP, Pin6:Vcc, Pin7:Gnd,Pin8:MISO ' PIC pins: ' Portb.0 MOSI,Portb.1 SDO,Portb.2 SCK, Portb.3 CS ' ' AT45DB041 /WP (Pin5) and /RESET (pin3) are pulled high ' with a 4.7k resistor. ' ' Voltage: ' An LM3LM2937-3.3 is used to provide 3.3 volts ' the PIC16F876 is run at 3.3v @ 10Mhz by disabling the PowerUpTimer ' ' ============ Memory Addressing ============== ' ' ' I M P O R T A N T ' PLEASE NOTES ' ************** Uncomment for a PIC16F876 operating on 3.3volts ************** '@ device pic16F876, xt_osc, wdt_on, pwrt_off, bod_off, lvp_off, cpd_off, wrt_off, protect_off ' ***************************************************************************** DEFINE LOADER_USED 1 'If using ISP DEFINE OSC 20 'Adjust to suit your design 'DEFINE OSC 10 'For an 16F876 running at 3.3v ADCON1 = 7 'Adjust ADC for your needs OPTION_REG.7=1 'Disable PORTB pull ups include "modedefs.bas" DEFINE DEBUG_REG PORTC 'Debug pin port DEFINE DEBUG_BIT 6 'Debug pin bit DEFINE DEBUG_BAUD 9600 'Debug baud rate DEFINE DEBUG_MODE 0 'Debug mode: 0 = True, 1 = Inverted DEFINE DEBUGIN_REG PORTC 'Debugin pin port DEFINE DEBUGIN_BIT 7 'Debugin pin bit DEFINE DEBUGIN_MODE 0 'Debugin mode: 0 = True, 1 = Inverted DEFINE HSER_BAUD 9600 'Hser baud rate DEFINE HSER_CLROERR 1 'Hser clear overflow automatically DEFINE HSER_SPBRG 129 'Hser spbrg init DEFINE HSER_RCSTA 90h 'Hser receive status init DEFINE HSER_TXSTA 24h 'Hser transmit status init high speed Symbol TXEN = TXSTA.5 'High= Enable transmit Symbol BRGH = TXSTA.2 'High=Select high baud rate Symbol SPEN = RCSTA.7 'High=Enable Serial Port Symbol CREN = RCSTA.4 'High=Enable continuous reception BRGH = 1 'High speed 'Constants,variables and aliases 'AT45DB041 instructions ATBuf1Wr con $84 'Buffer 1 write ATBuf2Wr con $87 'Buffer 2 write ATBuf1Rd con $54 'Buffer 1 read ATBuf2Rd con $56 'Buffer 2 read ATContRd con $68 'Continous array read ATPageRd con $52 'Main memory page read ATStatRd con $57 'Status Read ATB1PgEr con $83 'Buffer 1 to page with erase ATB2PgEr con $86 'Buffer 2 to page with erase ATB1PgNe con $88 'Buffer 1 to page with no erase ATB2PgNe con $89 'Buffer 2 to page with no erase ATPgEras con $81 'Page erase ATBkEras con $50 'Block erase ATPgBuf1 con $82 'Page program through buffer 1 ATPgBuf2 con $85 'Page program through buffer 2 ATPg2Bf1 con $53 'Page to buffer 1 transfer ATPg2Bf2 con $53 'Page to buffer 2 transfer ATPgB1cp con $60 'Page to buffer 1 compare ATPgB2cp con $60 'Page to buffer 2 compare ATPgRew1 con $58 'Auto page rewrite via buffer 1 ATPgRew2 con $58 'Auto page rewrite via buffer 2 'Other constants PageSz con 264 BuffSz con 264 PageCnt con 263 'AT45DB041 Connections MOSI var PORTB.0 ' AT45DB041 PIN 1 MISO var PORTB.1 ' AT45DB041 PIN 8 SCK var PORTB.2 ' AT45DB041 PIN 2 CS var PORTB.3 ' AT45DB041 PIN 4 TRISB.0 = 0 : TRISB.1 = 1 : TRISB.2=0 : TRISB.3=0 'Diagnostic LEDs wr_led var PORTB.7 err_led var PORTB.6 ok_led var PORTB.5 TRISB.7=0 : TRISB.6=0 : TRISB.5=0 'I2C Variables ctl con $A0 'EEPROM control code edata var BYTE 'Data byte to be written 'I2C Eeprom Pins scl var PORTC.3 'I2C SCL for ext eeprom sda var PORTC.4 'I2C SDA for ext eeprom 'Serial Pins out_pin var PORTC.6 'Serial OUT pin in_pin var PORTC.7 'Serial IN pin ser_baud con 84 '84=9600 32= 19200 Baud '***************** General Variables used ************************** 'Variables used (may be some that are no longer in use -- haven't cleaned up as yet!) page var word PageNum var word AT45sz var word addr var word adrs var word addr_H var word 'MMC Address is a 32 bit address, addr_h is bits 31-16 addr_L var word 'and addr_l is is bits 0-15 cmd var byte 'command var crc var byte 'crc var dat var byte 'data var i var byte 'counter var x var word 'counter var ix var byte chr var byte len var word y var byte 'counter var res var byte 'response var stat var byte 'Dataflash status w_lo var word w_hi var word w_rem var word w_res var word w_div var word arg1 var byte arg2 var byte arg3 var byte ErrFlag var byte TOcnt var byte buff var byte ATcmd var byte Opt var byte Wr_opt var byte Wr_opt = 0 'Status alias symbol ATstatus = stat.bit7 'Turn off diagnostic LEDs low wr_led : low ok_led : low err_led 'For debugging hserout ["AT45 Starting....",13,10] 'Initialize adrs=0 : cmd=0 : page=0 high cs 'Disassert AT45 cs line pause 200 'Let things settle gosub DummyRd 'May not be necessary in all cases ' ***** Jump over the subroutines ************** goto Main '********************* ' SUB-ROUTINES ' ******************** 'Subroutine that sends a command w/parameters 'Some commands require 1 or 4 no-care bytes after the command SendCmd: gosub CalcBits 'Calculate the 24 bits low cs SHIFTOUT MOSI,SCK,MSBFIRST,[cmd\8,page\16,addr\8] Select Case cmd Case ATPageRd,ATContRd '$52,$68 shiftout MOSI,SCK,MSBFIRST,[0\16,0\16] '4 byte no-care Case ATBuf1Rd,ATBuf2Rd '$54,$56 shiftout MOSI,SCK,MSBFIRST,[0\8] '1 byte no-care end select return 'Calculate Page & Addr address based on a linear address CalcAddr: disable R0 = addr_H R2 = addr_L PageNum = DIV32 PageSz Adrs = R2 enable return 'Calculate the 24 bits to be sent to the AT45DB041 given Page & Addr CalcBits: page=page << 1 page.bit0 = addr.bit8 addr = addr.byte0 return 'Subroutine for busy signal 'It will "time-out" after 256 attempts CheckReady: TOcnt=0 : ErrFlag=0 low cs Shiftout MOSI,SCK,MSBFIRST,[ATStatRd] '$57 ATbusy: Shiftin MISO,SCK,MSBPOST,[stat] TOcnt=TOcnt-1: if TOCnt=0 then ATErr1 if ATstatus=0 then ATbusy goto NotBusy ATErr1: hserout ["AT45DB041 Busy Error!",13,10] high Err_Led ErrFlag=1 'Set the ErrFlag NotBusy: high cs return 'Routine to simple cycle the AT45 IC DummyRd: low cs cmd=ATPageRd ' $52 read page direct command page=0 : addr=0 gosub SendCmd for ix=0 to 31 ' read some bytes shiftin MISO,SCK,MSBPOST,[chr\8] next ix high cs return 'Routine to calculate the size of the dataflash (512kb to 64mb) GetSize: gosub CheckReady 'Get AT45DB status, bits 3-5 contain size info AT45sz=stat & %00111000 'Mask bits 3-5 AT45sz=AT45sz>>3 'Dispose of the beginning 3 zeroes if AT45sz=0 then hserout ["DataFlash Size=512kbit",13,10] : goto SzDone i=1: At45Sz=At45Sz-1 i=i< 127 then chr="." if chr < 32 then chr="." hserout [chr] next ix high CS hserout [13,10] hserout ["More? 1=yes 2=no",13,10] hserin [dec1 chr] if chr<>1 then InData PageNum=PageNum+1 goto DataRead goto InData DataWrite: hserout ["Enter text ~ (tilde) to end",13,10] 'Write data to one of the two buffers cmd=ATBuf1Wr '$84 write to buffer 1 command addr=adrs 'Start address in the buffer gosub SendCmd Get_Key: hserin 1000,Get_Key,[chr] if chr <32 OR chr > 127 then Get_key if chr = "~" then Wr_Done shiftout MOSI,SCK,MSBFIRST,[chr\8] ' put it in the AT45D0xx 'addr= addr+1 'if addr>263 then goto Get_Key Wr_Done: high cs 'Write the buffer if Opt = 2 then cmd=ATB1PgEr 'Erase page and then write the buffer to the page if Opt = 3 then cmd=ATB1PgNe 'No erase and write page=PageNum gosub SendCmd high cs gosub CheckReady 'Check if AT45 is busy high cs goto InData AT_Test: 'PageNum=512 'Page number 'adrs=0 'Address on that page 0-264 for the AT45DB041B 'Given: Address = 270336 = $00042000 the result should be PageNum= 1024 Adrs=0 'addr_H = 0 '$0004 'addr_L = 0 '$2000 hserout ["Writing sample text to Buffer 1:",dec PageNum, " at Address:",dec adrs,13,10] 'goto ATRead 'Just read, no writing is done 'Write data to one of the two buffers cmd=ATBuf1Wr '$84 write to buffer 1 command addr=adrs 'Start address in the buffer gosub SendCmd len = 62 for ix=0 to len 'Message length in bytes lookup ix,["Welcome! This is an Atmel AT45DB041B 4mbit dataflash 8 pin chip!"],chr shiftout MOSI,SCK,MSBFIRST,[chr\8] ' put it in the AT45D0xx hserout [chr] next ix high cs hserout [13,10] 'Read back the data from the buffer hserout ["Reading back buffer...",13,10] cmd=ATBuf1Rd '$54 read from buffer 1 command addr=adrs 'Start address in the buffer gosub SendCmd for ix=0 to len 'message length in bytes shiftin MISO,SCK,MSBPOST,[chr] ' get it from the AT45D0xx hserout [chr] next high cs hserout [13,10] hserout ["Erase & write to DataFlash sector...",13,10] '------------------------------------------------ 'Erase page and then write the buffer to the page cmd=ATB1PgEr ' $83 erase page and write command page=PageNum gosub SendCmd high cs gosub CheckReady 'Check if AT45 is busy high cs ATRead: hserout ["Reading back DataFlash sector...",13,10] 'Read data directly from a page cmd=ATPageRd '$52 read page direct command page=PageNum addr=adrs gosub SendCmd for ix=0 to len 'message length in bytes shiftin MISO,SCK,MSBPOST,[chr\8] hserout [chr] next ix high CS hserout [13,10] hserout ["Finished",13,10] goto InData LoopEnd: goto LoopEnd end '=================== END OF CODE =============================