Подключаем внешнюю флеш-память SD-Card к МиниБоту

Материал из roboforum.ru Wiki
Перейти к: навигация, поиск
1.GIF

Здесь я постараюсь оформить свои давние мысли о применении памяти в элементах ИИ.

Если подходить к памяти с точки зрения организации элементов ИИ, то для начала для начала несколько фактов:
1. Флеш-память нынче дешева как никогда и при этом постоянно цена еще падает чутли не ежемесячно. По состоянию на 5 июля 2008г. 2Гб micro-SD в розницу стоила 268р. при этом она умещается на ногте и имеет толщину меньше 1мм.
2. Операция поиска у живых организмов происходит параллельно, а не последовательно как принято у нас в программировании. А именно, из милллиона записей БД мы в программировании чтоб найти что либо должны перебрать почти весь список т.е. нам потребуется почти миллион тактов на поиск, у живых же организмов на это уходит несколько тактов при этом размер базы для них не имеет никакого значения. Мы конечно применяем разного рода ухищрения в виде предварительной сортировки и индексации, но это всё от безисходности. Факт остается фактом, чем больше БД тем больше времени уходит на поиск. При этом как такого тактования применяемого сейчас сплош и рядом в микропроцессорах у живых организмов нет. А оно собственно и не надо. Посмотрите как работает паралельная озушка, у нее никакого тактового нет. Но об этом чуть позже...
3. флеш-память можно расматривать как скучкованную в одном месте гору микросхем отдельных памятей по 512 байт. В случае с вышеупомянутой 2ГБ карточкой это 3.967.488 микросхемок по 512Кб

Ошибка создания миниатюры: convert: unable to open image `/var/www/vhosts/roboforum.ru/wiki.roboforum.ru/images/6/6e/_.GIF': No such file or directory @ error/blob.c/OpenBlob/2589. convert: missing an image filename `/var/www/vhosts/roboforum.ru/wiki.roboforum.ru/images/tmp/transform_2bc8310b4220.gif' @ error/convert.c/ConvertImageCommand/3015. Error code: 1

Итак для примера рассмотрим самый простой пример, необходимо подсчитать общее количество единичек поступивших на вход, у нас есть три пути:
--- С помощью микроконтроллера или микропроцессора написать соответсвующий последовательный код. Вывод чем больше у нас входов тем дольше мы будем подсчитывать.
--- С помощью логики собрать схему приведенную на рисунке 11.12 Тут всё хорошо никакого тактования, подсчет происходит мгновенно. Одно плохо, если необходимо увеличить количество входов, то прийдется перепаивать схему.
--- Собрать схему на флешевой памяти. Входа в нашем случае это адресные линии, выход это шина данных. Ложка дегтя которая сразу бросается в глаза, такой вариант прийдется обучать. Но позвольте господа, именно так у живых существ и просиходит! И помоему мы как раз этого и добивались! :-) И обучать-то прийдется всего только один раз, при современных скоростях это займет доли секунд

И вот тут мы плавно и незаметно подошли к понятию ассоциативной памяти.
Схеме на базе памяти по большому счету всё равно что там у нее на входах, она четко запомнила, когда на входе то-то, то на выходе должно быть то-то. Я считаю что такому принципу работает любой нейрон, хоть сложения хоть вычитания с умножением, хоть распознования образов. Т.е. в процессе обучения устанавливается ассоциация входного сигнала с номером образа.


И сдается мне, что весь наш интеоект базируется на трех китах:
-- ПИД регулирования поставленной цели согласно приоритетов -- Ассоциативной памяти -- И системы голосования распознаных образов


<source lang="vb">

$prog &HFF , &HE4 , &HD9 , &HFF ' generated. Take care that the chip supports all fuse bytes. $regfile = "m128DEF.dat" $crystal = 8000000 $baud = 4800

'Нога отвечает за Вкл/Откл SD карты в SPI режиме Config Porte.2 = Output : Chip_select Alias Porte.2

Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = Low , Phase = 0 , Clockrate = 4

Dim Флаг As Bit Dim ФлагПроверкиЗаписи As Bit Dim ФлагДанныеЗаписаныВерно As Bit

Dim ПринятыйБайт As Byte Dim Sd_command(6) As Byte 'Ответ максимум состоит из 10 байт Dim Size_answer As Byte Dim Sd_answer(10) As Byte Dim Sd_data(512) As Byte

Dim Tmp_byt1 As Byte Dim Tmp_byt2 As Byte Dim Tmp_byt3 As Byte

Dim Count_wrd As Word

Dim Tmp_wrd1 As Word Dim Tmp_wrd2 As Word

Dim Sd_address As Long

Print "Старт программы"

Begin: Chip_select = 1 'Отключить SD карту 'Ответ максимум состоит из 1 байт Size_answer = 1 ФлагПроверкиЗаписи = 0 Sd_address = &H0

Spiinit 'Инициализация SPI у меги

Gosub Init_sd 'Инициализация SPI у SD карты

 Do
 Gosub Clear_sd_buffer   'Очистить буфер для чтения/записи SD карты
 Sd_data(1) = 10
 Sd_data(2) = 20
 Sd_data(3) = 30
 Sd_data(4) = 40
 Sd_data(5) = 50
 Sd_data(6) = 60
 Sd_data(7) = 70
 Sd_data(8) = 80
 Sd_data(9) = 90
 Sd_data(10) = 100
 Gosub Write_sd_data  'Записать данные в SD карту
 Gosub Read_sd_data  'Прочитать данные из SD карты
 Sd_address = Sd_address + 512
 Loop Until Sd_address = 2048

End

'-------------------------------------------------------------------------------

Init_sd: 'Подпограмма инициализирует SPI у SD карты

Print "Инициализация SPI у SD карты"

'Переводим SD карту в SPI режим ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(&Hff)

Chip_select = 0 'Включить SD карту

Print "Ресет" 'Послать команду ресет SD карты Sd_command(1) = &H40 Sd_command(2) = &H00 Sd_command(3) = &H00 Sd_command(4) = &H00 Sd_command(5) = &H00 Sd_command(6) = &H95 Gosub Send_sd_command

Print "Инициализация"

 Do 'Послать команду инициализации SD карты  
 Sd_command(1) = &H41
 Sd_command(2) = &H00
 Sd_command(3) = &H00
 Sd_command(4) = &H00
 Sd_command(5) = &H00
 Sd_command(6) = &H55
 Gosub Send_sd_command
 Waitms 100
 Loop Until Sd_answer(1) = 0

Chip_select = 1 'Отключить SD карту

Print "Инициализация SPI у SD карты окончена" Return

Send_sd_command: 'Подпограмма посылает команду SD карте

ПринятыйБайт = Spimove(&Hff) ПринятыйБайт = Spimove(sd_command(1)) ПринятыйБайт = Spimove(sd_command(2)) ПринятыйБайт = Spimove(sd_command(3)) ПринятыйБайт = Spimove(sd_command(4)) ПринятыйБайт = Spimove(sd_command(5)) ПринятыйБайт = Spimove(sd_command(6))

Gosub Receive_sd_command 'Получить ответ от SD карты

ПринятыйБайт = Spimove(ПринятыйБайт) Return

Receive_sd_command: 'Подпограмма получает ответ от SD карты

 Do
 ПринятыйБайт = Spimove(&Hff)
 Loop Until ПринятыйБайт <> &HFF

Tmp_byt1 = 0

 Do
 Incr Tmp_byt1
 Sd_answer(tmp_byt1) = ПринятыйБайт
 ПринятыйБайт = Spimove(&Hff)
 Loop Until ПринятыйБайт = &HFF Or Size_answer = Tmp_byt1

Print "Ответ SD карты" For Tmp_byt2 = 1 To Tmp_byt1

 Print "Байт №" ; Tmp_byt2 ; " = " ; Sd_answer(tmp_byt2)

Next Return

Clear_sd_buffer: 'Подпограмма очищяет буфер для чтения/записи SD карты

For Count_wrd = 1 To 512

 Sd_data(count_wrd) = 0

Next Return

Write_sd_data: 'Подпограмма записывает данные в SD карту по адресу Sd_address размером 512 байт 'данные берёт из Sd_data(512)

 Do
 Tmp_byt3 = 0
   Do
   Флаг = 0
   Chip_select = 0     'Включить SD карту
   Print "Запись"
   Print "Записать блок данных (512 байт) по адресу " ; Hex(sd_address)
     Do
     Incr Tmp_byt3
     Print "Попытка записать данные №" ; Tmp_byt3
     Sd_command(1) = &H58  'Послать команду записать блок данных по адресу (sd_address) в SD карту
     Tmp_wrd1 = Highw(sd_address)
     Tmp_wrd2 = Sd_address
     Sd_command(2) = High(tmp_wrd1)
     Sd_command(3) = Low(tmp_wrd1)
     Sd_command(4) = High(tmp_wrd2)
     Sd_command(5) = Low(tmp_wrd2)
     Sd_command(6) = &H55
     Gosub Send_sd_command
     Loop Until Sd_answer(1) = 0 Or Tmp_byt3 = 5
   If Sd_answer(1) <> 0 Then
     Флаг = 1       'Команда на запись не прошла
     Print "Пришёл неверный ответ от команды записи"
   Else
     Print "Послать данные"
     ПринятыйБайт = Spimove(&Hff)      'Послать данные
     ПринятыйБайт = Spimove(&Hfe)      'Послать стартовые байты
     'Послать данные
     For Count_wrd = 1 To 512
       ПринятыйБайт = Spimove(sd_data(count_wrd))
     Next
     'Послать CRC16
     ПринятыйБайт = &H55
     ПринятыйБайт = Spimove(ПринятыйБайт)
     ПринятыйБайт = &H55
     ПринятыйБайт = Spimove(ПринятыйБайт)
     Gosub Receive_sd_command      'Получить ответ от SD карты
     If Sd_answer(1) <> 229 Then
       Sd_answer(1) = 1         'Данные не записались
       If Tmp_byt3 = 5 Then
         Флаг = 1
         Print "Пришёл неверный ответ после записи данных"
       End If
     Else
       ПринятыйБайт = Spimove(&Hff)
       Chip_select = 1        'Отключить Sd карту
       ПринятыйБайт = Spimove(&Hff)
       Chip_select = 0        'Включить SD карту
       ПринятыйБайт = Spimove(&Hff)
       Print "Данные успешно записаны"
       Sd_answer(1) = 0
     End If
   End If
   Chip_select = 1     'Отключить Sd карту
   Waitms 10     'Время, которое неоюходимо, для записи данных в SD карту
   If Флаг = 1 Then
     Tmp_byt3 = 0      'Произошла ошибка при записи команды или данных
     Gosub Init_sd      'Инициализация SPI у SD карты
   End If
   Loop Until Флаг = 0 And Sd_answer(1) = 0
 ФлагПроверкиЗаписи = 1  'Проверить правильно ли записали
 Gosub Read_sd_data  'Прочитать данные из SD карты
 If ФлагДанныеЗаписаныВерно = 1 Then
   Print "Верификация прошла успешно"
 Else
   Print "Верификация не прошла"
 End If
 Loop Until ФлагДанныеЗаписаныВерно = 1

Return

Read_sd_data: 'Подпограмма читает данные из SD карты по адресу Sd_address размером 512 байт 'данные записывает в Sd_data(512) ФлагДанныеЗаписаныВерно = 1

 Do
 Флаг = 0
 Chip_select = 0  'Включить SD карту
 If ФлагПроверкиЗаписи = 1 Then
   Print "Верификация"
 Else
   Print "Чтение"
 End If
 Print "Установить размер блока чтения данных - 512"
 'Послать команду установить размер блока 512 в SD карту
 Sd_command(1) = &H50
 Sd_command(2) = &H00
 Sd_command(3) = &H00
 Sd_command(4) = &H02
 Sd_command(5) = &H00
 Sd_command(6) = &H55
 Gosub Send_sd_command
 Print "Прочитать блок данных по адресу " ; Hex(sd_address)
 'Послать команду прочитать блок данных по адресу (sd_address) в SD карту
 Tmp_byt3 = 0
   Do
   Incr Tmp_byt3
   Print "Попытка прочитать данные №" ; Tmp_byt3
   Sd_command(1) = &H51
   Tmp_wrd1 = Highw(sd_address)
   Tmp_wrd2 = Sd_address
   Sd_command(2) = High(tmp_wrd1)
   Sd_command(3) = Low(tmp_wrd1)
   Sd_command(4) = High(tmp_wrd2)
   Sd_command(5) = Low(tmp_wrd2)
   Sd_command(6) = &H55
   Gosub Send_sd_command
   Loop Until Sd_answer(1) = 0 Or Tmp_byt3 = 5
 If Sd_answer(1) <> 0 Then
   Флаг = 1     'Команда на чтение не прошла
   Print "Пришёл неверный ответ от команды чтения"
 Else
   'Получение данных
   'Поймать стартовый байт
     Do
     ПринятыйБайт = Spimove(&Hff)
     Loop Until ПринятыйБайт = &HFE
   For Count_wrd = 1 To 512     'Получить 512 байт данных
     If ФлагПроверкиЗаписи = 1 Then
       ПринятыйБайт = Spimove(&Hff)        'Читаем и сравниваем с Sd_data(512)
       If ПринятыйБайт <> Sd_data(count_wrd) Then
         ФлагДанныеЗаписаныВерно = 0
       End If
     Else
       Sd_data(count_wrd) = Spimove(&Hff)        'Читаем и записываем в Sd_data(512)
     End If
   Next
   'Получить КС
   ПринятыйБайт = Spimove(&Hff)
   ПринятыйБайт = Spimove(&Hff)
   Print "Данные успешно считаны"
 End If
 Chip_select = 1   'Отключить Sd карту'
 If Флаг = 1 Then
   'Произошла ошибка при записи команды или данных
   Gosub Init_sd    'Инициализация SPI у SD карты
 End If
 Loop Until Флаг = 0

ФлагПроверкиЗаписи = 0 Return

</source>