Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Схемы » Программатор Dataflash AT45DBxx


Программатор Dataflash AT45DBxx

Сообщений 1 страница 6 из 6

1

Давайте общими усилиями придумаем программатор для этой памяти! ))

ВНИМАНИЕ!!! Схемы с LPT и прочие "пять проводков" сюда не писать - задача сделать девайс под новые ноутбуки или под те компьютеры, где нет COM, LPT

Основные требования:
1) Работа по USB через переходник FT232BM
2) Программирование микроконтроллером, т.е. схема такая: FT232BM -> Atmega8(например) - > Dataflash
3) Загрузка прошивки с помощью простой терминальной утилиты

Схема устройства простая:
1) Микросхема FT232BM ведет обмен данными с микроконтроллером через UART
2) Микроконтроллер подрублен к флехе через встроенный в MCU интерфейс SPI
3) Питается все по схеме USB -> LM1117 (преобразователь напряжения в 3.3 В)

Отредактировано yakuzaa (2008-04-01 17:22:32)

0

2

Программатор полностью функционирует!!! (14 апреля 2008 г.)

Вот собственно код для mega32 (эта микросхема выбрана в отладочных целях)

(С) - за основу взят проект программатора I2C микросхем памяти, который описан на:

http://www.mcselec.com/index.php?option … ;Itemid=57

я только заменил процедуры I2C на процедуры работы с dataflash

программное обеспечение остается тем же :)

программатор наконец-таки заработал - данные в микруху пишет!!! :D :D :D

Ошибка скрывалась в обработчике прерывания UART

Но для воспроизведения звукового фрагмента из флешки все равно пользуюсь процедурами Ведущего Специалиста - за что ему огррромное спасибо! :-)

Исходный код PROGRAMMATOR.BAS:

Код:
$regfile = "m32def.DAT"
$crystal = 16000000
$baud = 19200
$hwstack = 256
$swstack = 256
$framesize = 256

Dim Startbyte As Byte , Instring As String * 45 , Complete As Bit
Dim Temp As Byte , Temps As String * 3
Dim Bytecount As Byte , Addresshigh As Byte , Addresslow As Byte , Recordtype As Byte , Databyte(16) As Byte , Checksm As Byte
Dim Lus As Byte , Pos As Byte , Checksum_calc As Byte , Checksum_error As Bit
Dim Pagge As Word , Addresse As Word
Pagge = 0
Addresse = 0

Enable Urxc
Enable Interrupts
On Urxc Bytereceived_isr

$include "at45.bas"
Waitms 300
'=== Main  ===

Do
If Complete = 1 Then                                        'Wait until the buffer is filled with one line
  Gosub Process_buffer                                      'Process the buffer
  Gosub Calculate_checksum                                  'Calculate the cheksum
     If Recordtype = &H01 Then                              'EOF finished, send a ACK and return
      Print "Y";
     Else
       If Checksum_error = 0 Then                           'If there's no error continue
         Select Case Recordtype                             'do something with the recordtype
            Case &H00                                       'Data byte
                Gosub Prog_eeprom                           'Recordtype &H00 = databyte, so lets programm the Eeprom
            Case &H02                                       'Extended Linear Address Records, not (yet) supported
               nop
         End Select
       Print "Y";                                           'Checksum ok, send a ACK
      Else
       Print "Z";                                           'Checksum error send a Nack
     End If
    End If
  Complete = 0 : Instring = ""                              'Reset the variable
End If
Loop
End


'=== Subroutines ===
Prog_eeprom:
 
 ' здесь-то и был косяк
 '  получееный байт записывался дважды, да и буфер неправильно заливался ))

   If Addresse < 264 Then
   Call Writetobuffer(1 , Addresse , Databyte(lus))
   Else
   Call Buffertopage(1 , Pagge)
   Incr Pagge
   Addresse = 0
   Call Writetobuffer(1 , Addresse , Databyte(lus))
   End If

   Incr Addresse

   Next Lus

   If Pagge > 2047 Then Print "Z"
Return


Process_buffer:
Temps = Mid(instring , 1 , 2) : Bytecount = Hexval(temps)   'Read the numbers of bytes
Temps = Mid(instring , 3 , 2) : Addresshigh = Hexval(temps) 'Read the high adress
Temps = Mid(instring , 5 , 2) : Addresslow = Hexval(temps)  'Read the low adress
Temps = Mid(instring , 7 , 2) : Recordtype = Hexval(temps)  'Read the recordtype
For Lus = 1 To Bytecount                                    'Process the number of data bytes
      Pos = Lus * 2
      Pos = Pos + 7
      Temps = Mid(instring , Pos , 2) : Databyte(lus) = Hexval(temps)       'Read the databytes
Next Lus
Pos = Pos + 2                                               'read the last byte
Temps = Mid(instring , Pos , 2) : Checksm = Hexval(temps)   'Read checksum
Return


Calculate_checksum:
Temp = 0                                                    'Add up all the databytes
Temp = Temp + Bytecount
Temp = Temp + Addresshigh
Temp = Temp + Addresslow
Temp = Temp + Recordtype
   For Lus = 1 To Bytecount
    Temp = Temp + Databyte(lus)
   Next Lus
Checksum_calc = 256 - Temp                                  'taking its two's complement
   If Checksum_calc <> Checksm Then                         'Compare it with the readed value
    Checksum_error = 1
   Else
    Checksum_error = 0
   End If
Return

Bytereceived_isr:
Temp = Udr                                                  'get the binary value that came across
If Temp = &H0D Then                                         'Received CR = end of line, line complete
 If Len(instring) < 8 Then                                  'To short, startover again
   Complete = 0
   Instring = ""
 Else
   Complete = 1                                             'String is complete set the flag
 End If
End If

If Startbyte = &H3A Then                                    'we have previously received the start byte and this is now data
  If Temp > &H0F Then                                       'Add incoming data to buffer
     Instring = Instring + Chr(temp)
    If Len(instring) > 45 Then Instring = ""                'String is to long, reset and startover again
 End If
End If

If Temp = &H3A Then                                         'if we received an : then its the beginning of an new line.
   Startbyte = Temp
   Complete = 0
   Instring = ""
End If
Return

Исходный код AT45.BAS:

Код:
Declare Sub Initspi
Declare Function Writebyte(byval Bb As Byte) As Byte
Declare Function Getdevicedensity(byval Register As Byte) As Byte
Declare Sub At45ready
Declare Sub Sendaddress(byval Page_address As Word , Byval Buffer_address As Word)
Declare Sub Sendcmd(byval Opcode As Byte , Page_address As Word)
Declare Sub Autopagerewrite(byval Buffer As Byte , Byval Page_address As Word)
Declare Sub Pageerase(byval Page_address As Word)
Declare Sub Pagetobuffer(byval Buffer As Byte , Byval Page_address As Word)
Declare Sub Buffertopage(byval Buffer As Byte , Byval Page_address As Word)
Declare Sub Writetobuffer(byval Buffer As Byte , Byval Addr As Word , Byval Dat As Byte)
Declare Function Readfrombuffer(byval Buffer As Byte , Byval Addr As Word) As Byte

Config Timer1 = Pwm , Prescale = 1 , Compare A Pwm = Clear Down , Pwm = 8

Dim Den As Byte
Dim Page_size As Word
Dim Pages As Word
Dim Pag As Word
Dim Adr As Word

Config Pind.6 = Output
Greenled Alias Portd.6
Greenled = 0

Cs Alias Portb.4

Ddrb = &B10111001
Waitms 1000
Call Initspi
Waitms 100

Den = Getdevicedensity(&H57)
If Den = 1 Then
   Print "128K"
   Page_size = 264
   Pages = 512
Elseif Den = 2 Then
   Print "256K"
   Page_size = 264
   Pages = 1024
Elseif Den = 3 Then
   Print "Memory size=512K"
   Page_size = 264
   Pages = 2048
   Greenled = 1
Elseif Den = 4 Then
   Print "1M"
   Page_size = 264
   Pages = 4096
Elseif Den = 5 Then
   Print "2M"
   Page_size = 528
   Pages = 4096
Elseif Den = 6 Then
   Print "4M"
   Page_size = 528
   Pages = 8192
End If
Waitms 1000

Greenled = 0

Goto Dfend



'******************************************
'Sub: InitSPI
'Purpose: Initailizes the hardware SPI
'Parameters: none
'Returns: nothing
'******************************************

Sub Initspi
Ddrb = Ddrb Or &H07
Portb = Portb Or &H1F
Spcr = &H5C
End Sub


'******************************************
'Function:Writebyte
'Purpose: Writes a byte to spi port
'Parameters: byte to be writen
'Returns: 1 if write sucessful 0 if timeout
'******************************************

Function Writebyte(byval Bb As Byte) As Bit
Local Retry As Byte , Tmp As Byte
Tmp = 1
Spdr = Bb                                                   'Write To Port
Retry = 40                                                  'Change this if you want
While Tmp = 1
  Tmp = Spsr And Spif
  Decr Retry
Wend
If Retry = 0 Then Writebyte = 0 Else Writebyte = 1
End Function


'******************************************
'Function:GetDeviceDensity
'Purpose: Returns the device density
'Parameters: none
'Returns: Device density
'1=128K, 2=256K, 3=512k, 4=1M, 5=2M, 6=4M
'******************************************
Function Getdevicedensity(byval Register As Byte) As Byte
Local Ok As Byte , Density As Byte , Status As Byte
Reset Cs                                                    'CS low select flash
Ok = Writebyte(register)                                    'Read Status Register
If Ok = 1 Then
  Ok = Writebyte(&Hff)                                      'Dummy byte
  Status = Spdr                                             'read the status
End If
Set Cs
Shift Status , Right , 3
Density = Status And &H07
Getdevicedensity = Density                                  'Return Density
End Function

'******************************************
'Sub:AT45Ready
'Purpose: Waits for flash ready (not busy)
'Parameters: none
'Returns: nothing
'******************************************

Sub At45ready
Local Ok As Byte
  Reset Cs
  While Ok = 1                                              'While is not ready
    Ok = Writebyte(&H57)
    Ok = Writebyte(&Hff)
    Ok = Spdr And &H80                                      'Read The Busy Bit
  Wend
End Sub



'******************************************
'Sub:SendAdress
'Purpose: Sends both buffer and page address to the Flash
'Parameters: Page address and buffer nr.
'Returns: nothing
'******************************************


Sub Sendaddress(byval Page_address As Word , Byval Buffer_address As Word)
  Local Upper_page_address As Byte , Lower_page_address As Byte , Ok As Byte , Tmp As Byte
  If Page_size = 264 Then                                   '1 , 2 , 4 Or 8m
    Shift Page_address , Left , 1
  Else                                                      '16M or 32M
    Shift Page_address , Left , 2
  End If
  Upper_page_address = High(page_address)
  Lower_page_address = Low(page_address) Or High(buffer_address)
  Ok = Writebyte(upper_page_address)
  If Ok = 1 Then
    Ok = Writebyte(lower_page_address)
  End If
  If Ok = 1 Then
     Tmp = Low(buffer_address)
     Ok = Writebyte(tmp)
  End If
End Sub


'******************************************
'Sub:SendCmd
'Purpose: Sends a command (opcode) to the Flash
'and also snds address
'Parameters: Command, Page address
'Returns: nothing
'******************************************

Sub Sendcmd(byval Opcode As Byte , Page_address As Word)
  Local Ok As Byte
  Ok = Writebyte(opcode)
  If Ok = 1 Then
    Call Sendaddress(page_address , 0)
  End If
End Sub



Sub Autopagerewrite(byval Buffer As Byte , Byval Page_address As Word)
  Call At45ready
  Reset Cs
  If Buffer = 1 Then
    Call Sendcmd(&H58 , Page_address)                       'buffer 1
  Else
    Call Sendcmd(&H59 , Page_address)                       ' buffer2
  End If
  Set Cs
End Sub


'******************************************
'Sub:PageErase
'Purpose: Erases a page
'Parameters: Page address
'Returns: nothing
'******************************************

Sub Pageerase(byval Page_address As Word)
 Call At45ready
 Reset Cs
 Call Sendcmd(&H81 , Page_address)
 Set Cs
End Sub


'******************************************
'Sub:PageTo buffer
'Purpose: Moves a given page to the buffer
'Parameters: Page address and buffer nr
'Returns: nothing
'******************************************


Sub Pagetobuffer(byval Buffer As Byte , Byval Page_address As Word)
  Call At45ready
  Reset Cs
  If Buffer = 1 Then
    Call Sendcmd(&H53 , Page_address)
  Else
    Call Sendcmd(&H55 , Page_address)
  End If
  Set Cs
  Waitus 250
End Sub

'******************************************
'Sub:Buffer to Page
'Purpose: Moves the buffer (1 or 2) to a page
'Parameters: Page address and buffer nr
'Returns: nothing
'******************************************
Sub Buffertopage(byval Buffer As Byte , Byval Page_address As Word)
 Call At45ready
 Reset Cs
 If Buffer = 1 Then
   Call Sendcmd(&H83 , Page_address)
 Else
   Call Sendcmd(&H86 , Page_address)
 End If
 Set Cs
End Sub

'******************************************
'Sub:WritetoBuffer
'Purpose: Writes a byte to buffer 1 or 2
'Parameters: Page address and buffer nr and data
'Returns: nothing
'******************************************

Sub Writetobuffer(byval Buffer As Byte , Byval Addr As Word , Byval Dat As Byte)
  Local Ok As Byte
  Call At45ready
  Reset Cs
  If Buffer = 1 Then
    Ok = Writebyte(&H84)
  Else
    Ok = Writebyte(&H87)
  End If
   Call Sendaddress(0 , Addr)
   Ok = Writebyte(dat)
   Set Cs
End Sub

'******************************************
'Function:ReadFromBuffer
'Purpose: Reads a byte to buffer 1 or 2
'Parameters: Address and buffer nr
'Returns: The byte read
'******************************************
Function Readfrombuffer(byval Buffer As Byte , Byval Addr As Word) As Byte
 Local Ok As Byte , Dat As Byte
 Call At45ready
 Reset Cs
  If Buffer = 1 Then
    Ok = Writebyte(&H54)
  Else
    Ok = Writebyte(&H56)
  End If
  If Ok = 1 Then
    Call Sendaddress(0 , Addr)
  End If
  If Ok = 1 Then
    Ok = Writebyte($ff)
  End If
    If Ok = 1 Then
      Ok = Writebyte($ff)                                   ' / / Dummy Byte To Get Result From Slave
      Dat = Spdr                                            ' / / Read After Transmit
    End If
   Set Cs
   Readfrombuffer = Dat
End Function

Dfend:

Отредактировано yakuzaa (2008-04-14 15:07:10)

0

3

бррр, а чем мой код не устроил??
Кстати, есть очень даже не плохой преобразователь ср2101 ср2102.
Есть еще очень даже неплохой апнот где таня2313 подключена к усб и выполняет роль порта уарта и еепромки.Советую этот способ также.

0

4

слегка офтоп

Для тех кто еще не видел этой ссылки и кто юзает параллельный порт и хочет поиграться с at45
--

Отредактировано pomidor (2008-03-31 10:56:07)

0

5

Ведущийспециалист написал(а):

бррр, а чем мой код не устроил??
Кстати, есть очень даже не плохой преобразователь ср2101 ср2102.
Есть еще очень даже неплохой апнот где таня2313 подключена к усб и выполняет роль порта уарта и еепромки.Советую этот способ также.

Привет! Твой код как раз и заработал у меня - т.е. чтение страницы 264-байтной страницы из микрухи и передача его в шим проходит нормально! отчасти, я думаю, потому, что большинство процедур написано на ассемблере

вот только с записью данных в микруху по событию в UART я пока еще не разобрался )) а именно в примере с записью страницы во флеш:

Код:
'A = Red
'Call Buffer1_write
'For Temp1 = 1 To 132
'Call Wordout()
'Next Temp1
'Set Select_memory
'Call Buffer1_to_flash(1)

как я понимаю, здесь идет запись переменной A 132 раза, которая состоит из двух байт (а значит это уже word), а значит записывается 264 байта

вопрос: как тогда организовать запись однобайтового числа? заменить процедуру wordout() на byteout() ? и увеличить цикл до 264?
например, вот так почему-то не заработало...:

Код:
Dim a as byte
N = 100
Call Buffer1_write
For Temp1 = 1 To 264
Call Byteout()
Next Temp1
Set Select_memory
Call Buffer1_to_flash(1)

Отредактировано yakuzaa (2008-04-07 11:02:40)

0

6

Странно, вообще то все верно, должно работать

0


Вы здесь » Программирование ATMEL в BASCOM. » Схемы » Программатор Dataflash AT45DBxx