Tutorial-Datei
- Dies ist die ausgelagerte Tutorial-Datei zum Artikel BASCOM, SD/MMC und andere (SPI)-Flash-Karten.
- Sie erscheint hier getrennt, weil der Artikel sonst zu groß würde (meint ein freundlicher Lektor im Hintergrund) !
Eigentlich wollte ich diese Tutorial-Datei als Download einstellen, - habe aber nicht gefunden, wie das geht.
Falls das jemand weis, wäre ich für eine Info dankbar --> NLB@Manager-OnWeb.de .
QuellCode Get Flash FileSector.bas
Hier - etwas umständlicher - im Copy und Paste Verfahren die Programm-Datei:
'CopyRight 'Dipl.-Ing. Norbert L. Brodtmann , Gütersloh Germany 'This program is wrote to become familiar with SD-Card technologies 'in order to integrate it in my 8-acis Robotic-Controller (www.RoBo-mac.de). 'It is based on J.F. Vögel's AVR-DOS and uses parts of its code issued in his product documentation. 'It may be used in accordance of BASCOM's and AVR-DOS's license policy and agreement. '* This program returns the Start-Sector Number of any file - short filenames (8.3) - stored in a Flash-Card ' in order to use it with direct access of the commands DriveWriteSektor() / DriveReadSektor() etc. '* It also gives output to measure Transfer-Time; to benefit this, you need an oscilloscope. '* In addition you will find a trick to read a file's (Long)-Name using DriveReadSektor(), only. '* You can use this program just to become familiar with SD-Cards too ' or include parts in your application. Therefore it is divvied in 5 parts. 'Part 1 'Declaration based on the used Hardware (Mega 128 / LCD 4 x 20 / SD-Card board of Display 3000). 'Part 2 'Additional declaration of including AVR-DOS and the type of Flash-Card used (FC, SD/MCC etc. ). 'Please note: You have to adapt the "config_CARD.bas" (for example Config_MMC.bas) to your system too. 'There is a (Compiler-) Function-switch to select of the following possibilities. 'Function_1 Test DOS-Commands using COM/TERMINAL in dialog 'Function_2 Running Part 3 to 5 'Function_3 Direct Sector Access and measurement of transfer-time by using an oscilloscope (Bort B.7) ' In addition you will find a trick to read a file's ' - (Long)-Name (up to 40 Characters + Extension = 44 in total incl. "dot") and its ' - Date/Time-Stamp. 'Function_1/2 needs a SRAM Size > 3k, Function_3 less than 1k 'Part 3 'A "GOSUB" Routine_fileinfo 'Asking for the files name (8.3) and searching information concerning this file (also including the Sector#) 'Part 4 'A "GOSUB" Routine_sector_select 'using the Sector# with the command DriveReadSektor() as a "how to do" example 'Part 5 'A "GOSUB" Routine_transfer_time_1 'to measure transfer time. Bort B.7 toggles with every DriveReadSektor() command. 'Using an oscilloscope you will get an frequency. Each period consists the time to read two sectors! 'This Routine is based on something similar I found in the Internet several times '- however I do not know the Copyright owner, I suppose it is shareware. 'Please note: 'There is a tutorial (in German language) concerning these items at 'http://www.rn-wissen.de/index.php/Hauptseite '--- Part1 --------------------------------------------------- $regfile = "m128def.dat" 'ATmega128 $crystal = 16000000 '--- Config Lcdbus = 4 '4-bit Step_Step_Mode Config Lcd = 20 * 4 '20x4 LCD display Config Lcdpin = Pin , Db4 = Porte.4 , Db5 = Porte.5 , Db6 = Porte.6 , Db7 = Porte.7 , E = Porte.3 , Rs = Porte.2 Const Lcd_line1 = "Get_Flash_FileSector" Const Lcd_line2 = "CopyRight:" Const Lcd_line3 = " www.RoBo-mac.de" Cls : Cursor Off Noblink Locate 1 , 1 : Lcd Lcd_line1 Locate 2 , 1 : Lcd Lcd_line2 Locate 3 , 1 : Lcd Lcd_line3 'Special Function (Display 3000) Config Pinb.4 = Input 'Cardsensor Config Pinb.5 = Output 'SD-Card active (High) / inaktiv (Low) Config Pinb.6 = Input 'Writeprotect active (Low) / inaktiv (High) Config Pinb.7 = Output 'Toggel Portb = &B01110000 If Pinb.4 = 1 Then Locate 4 , 1 : Lcd "Card NO" End Else Locate 4 , 1 : Lcd "Card YES " If Pinb.6 = 1 Then Locate 4 , 11 : Lcd "read only" Else Locate 4 , 11 : Lcd "read/write" End If End If '--- Part2 --------------------------------------------------- ' Adjust HW Stack, Soft-Stack and Frame size to 128 minimum each!!! $hwstack = 128 $swstack = 128 $framesize = 128 Enable Interrupts $baud1 = 9600 Open "Com1:" As Binary As #1 ' use #1 for fs_interpreter 'Include here your driver for Compactflash/HardDisk or other '$include "Config_CompactFlash_M128.bas" '$Include "Config_HardDisk_M128.bas" $include "Config_MMC.bas" 'Select a function 'Const Function_switch = 1 'SRAM ca. 3340 / FS_Interpreter.bas active 'Const Function_switch = 2 'SRAM ca. 3030 / will use Part 3 to 5 Const Function_switch = 3 'SRAM ca. 780 / Just direct Sector Access #if Function_switch = 3 'Direct Sector Access and measurement of transfer-time 'Does not neet: Config_AVR-DOS.bas !!! Dim Ptr As Word 'Address-Pointer SRAM Dim Buffer As String * 512 Dim Mmc_error As Byte Dim Sector_now As Word Ptr = Varptr(buffer) For Sector_now = 512 To 10511 '512 is normaly the first Data-Sector 'Sector_now = 512 'endles 'Toggle Portb.7 Set Portb.7 Mmc_error = Drivereadsector(ptr , Sector_now) 'Ca. 1,37 msec HW / 6,05 msec SW per Sector 'Mmc_error = Drivewritesector(ptr , Sector_now) 'Ca. 1,83 msec HW / 7,5 msec SW per Sector Reset Portb.7 ''( 'The following code will only work fine, if these information '- are specially placed by the PC-Program writing the file '- to a very fresh formatted SD-Card!!! Dim Datei_name As String * 45 At Buffer + 00 Overlay 'File Name max: (40.3) Dim Datei_date_time As String * 19 At Buffer + 45 Overlay Dim Interim As Byte Dim Interim_2 As Byte At Mmc_error + 00 Overlay If Sector_now = 512 Then Waitms 1500 Locate 4 , 1 : Lcd Spc(20) Locate 4 , 1 : Lcd Mid(datei_name , 1 , 20) Wait 1 Interim_2 = Len(datei_name) 'Shiftlcd Left moves whole display, therefore If 20 < Interim_2 Then Interim_2 = Interim_2 - 19 For Interim = 2 To Interim_2 Locate 4 , 1 : Lcd Mid(datei_name , Interim , 20) Waitms 200 Next Wait 1 End If Locate 4 , 1 : Lcd Mid(datei_date_time , 1 , 19) + " " Wait 1 End If '') Next End '------------------------------------------------------------- #else $include "Config_AVR-DOS.bas" 'Include AVR-DOS Configuration and library Dim Btemp1 As Byte Print #1 , "Wait for Drive" If Gbdriveerror = 0 Then Print #1 , "Init File System ... "; Btemp1 = Initfilesystem(1) ' Partition 1 ' use 0 for drive without Master boot record If Btemp1 <> 0 Then Print #1 , Print #1 , "Error: " ; Btemp1 ; " at Init file system" Print #1 , End Else Print #1 , " OK" Print #1 , "Filesystem: " ; Gbfilesystem Print #1 , "FAT Start Sector: " ; Glfatfirstsector Print #1 , "Root Start Sector: " ; Glrootfirstsector Print #1 , "Data First Sector: " ; Gldatafirstsector Print #1 , "Max. Cluster Nummber: " ; Glmaxclusternumber Print #1 , "Sectors per Cluster: " ; Gbsectorspercluster Print #1 , "Root Entries: " ; Gwrootentries Print #1 , "Sectors per FAT: " ; Glsectorsperfat Print #1 , "Number of FATs: " ; Gbnumberoffats Print #1 , Print #1 , End If Else Print #1 , "Error during Drive Init: " ; Gbdriveerror End End If #endif #if Function_switch = 1 Config Clock = Soft Config Date = Mdy , Separator = . $include "FS_Interpreter.bas" 'No GOSUBs allowed, (DIM conflicts) #endif #if Function_switch = 2 Gosub Routine_fileinfo Gosub Routine_sector_select Gosub Routine_transfer_time_1 #endif End #if Function_switch = 2 '--- Part3 --------------------------------------------------- Routine_fileinfo: Dim File_name As String * 12 Dim Pbfilenr As Byte Dim Lltemp1 As Long Dim Lbfilenumber As Byte Dim Lbfilemode As Byte Dim Lwfiledirentry As Word Dim Llfiledirsectornumber As Long Dim Llfilefirstcluster As Long Dim Llfilesize As Long Dim Llfileposition As Long Dim Llfilesectornumber As Long Dim Lbfilebufferstatus As Byte Dim Lwfilebufferaddress As Word Dim Sector_start As Long Pbfilenr = 127 'use 127, to avoid conflicts with auto generatet numbers from FreeFile (128 to 255) File_select: Input "Select FileName (8.3) / Type END to finish program " , File_name Locate 2 , 1 : Lcd "File: " Locate 2 , 7 : Lcd File_name Locate 3 , 1 : Lcd " " If Ucase(file_name) = "END" Then Print #1 , "Program finished" Locate 3 , 1 : Lcd "Program finished" End End If Open File_name For Input As #pbfilenr Loadadr Pbfilenr , X ld r24, X !Call _GetFileHandle brcc PrintFileInfo1 rjmp PrintFileInfoError Printfileinfo1: Loadadr Lbfilenumber , X ldi r24, 25 !Call _Mem_Copy Loadadr Lwfilebufferaddress , X st X+, zl st X+, zh Print #1 , Print #1 , "File " ; File_name Print #1 , "Handle#: " ; Lbfilenumber Print #1 , "Open mode: " ; Bin(lbfilemode) Print #1 , "Dir Entry#: " ; Lwfiledirentry Print #1 , "Dir Sector#: " ; Llfiledirsectornumber Print #1 , "First Cluster#: " ; Llfilefirstcluster Print #1 , "Size: " ; Llfilesize Print #1 , "Position: " ; Llfileposition Print #1 , "Sector#: " ; Llfilesectornumber Print #1 , "Buffer Status: " ; Bin(lbfilebufferstatus) Lltemp1 = 0 Sector_start = Llfilesectornumber Close #pbfilenr Locate 3 , 1 : Lcd "Sector#:" Locate 3 , 10 : Lcd Sector_start Return Printfileinfoerror: 'Print #1 , "No Filehandle for " ; Pbfilenr ; " found" Print #1 , "FileName < " ; File_name ; " > Not Found " Print #1 , Locate 3 , 1 : Lcd " Not Found " Goto File_select '--- Part4 --------------------------------------------------- Routine_sector_select: Dim Ptr As Word 'Address-Pointer SRAM Dim Buffer As String * 512 Dim Mmc_error As Byte Dim Sector_now As Long Dim Sector_size As Long Dim Sector_max As Long Sector_size = Llfilesize Shift Sector_size , Right , 9 'Division 512 Byte/Sector 'Btemp1 = Llfilesize \ 512 'does not work correct, therefore: Shift Sector_size , Left , 9 If Sector_size < Llfilesize Then Shift Sector_size , Right , 9 Sector_size = Sector_size + 1 Else Shift Sector_size , Right , 9 End If Ptr = Varptr(buffer) 'SRAM Adr von Buffer Mmc_error = Drivereadsector(ptr , Sector_start) Print Print Print "SectorSize: " ; Sector_size Print "Read Start-Sector(" ; Sector_start ; ") ok." Print Print Buffer Print Return '--- Part5 --------------------------------------------------- Routine_transfer_time_1: Print "For 'Transfer-Time' measurement with an oscilloscope use toggling PortB.7" Print "- 1 Period represents 2 Sectors" Print Print "Test the 'Transfer-Time' " Print " - for Read and Write (to be choosen by changing block-marker)" Print " - with and without the Print-Commands" Print " - with Soft/Hard SPI. To do so, select used SPI in File Config_CARD.bas" Print Input "To start the test, strike ENTER/RETURN now ! / Type END to finish program" , File_name Print Print If Ucase(file_name) = "END" Then Print #1 , "Program finished" Locate 3 , 1 : Lcd "Program finished" End End If Ptr = Varptr(buffer) Sector_max = Sector_start + Sector_size Sector_max = Sector_max - 1 If Gbdriveerror = 0 Then Mmc_error = Driveinit() If Mmc_error = 0 Then Print "Driveinit Ok. " For Sector_now = Sector_start To Sector_max Toggle Portb.7 'Read ''( Mmc_error = Drivereadsector(ptr , Sector_now) If Mmc_error = 0 Then Print "ReadSector(" ; Sector_now ; ") ok." Print Buffer Else Print "Error during ReadSector(" ; Sector_now ; ") : " ; Mmc_error End If '') '---------------- 'Write '( ' ' Mmc_error = Drivewritesector(ptr , Sector_now) If Mmc_error = 0 Then Print "WriteSector(" ; Sector_now ; ") ok." Print Buffer Else Print "Error during WriteSector(" ; Sector_now ; ") : " ; Mmc_error End If ') Next Sector_now Else Print "Error during Driveinit(): " ; Mmc_error End If Print "End of Test" End If Return #endif