реклама на сайте
подробности

 
 
4 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> STM32F4, DCMI и USB
zheka
сообщение Mar 20 2015, 06:46
Сообщение #1


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Коллеги, хочу передавать изображения с камеры OV7670 (640x480) на комп.
В распоряжении есть плата STM32F4Discovery, камера с ебея уже пересекает китайскую границу, проект использующий аппаратный DCMI и DMА я нашел.
Пока суровые китайские таможенники оформляют пересечение камерой границы, хочу хотя бы проэмулировать передачу данных, то есть искусственно заполнять буфер, куда DMA кидает данные тестовой картинкой и принимать ее на компе.

Оговорюсь сразу - задача специфическая, и большого FPS не потребует, 3 кадра в секунду меня устроят.Получается скорость должна составлять около 2 мбайт сек.

И что-то я в растерянности. Единственный мой опыт - USB HID на STM32F103, пакетами по 64 байта.
Отсюда первый вопрос - в орежиме USB HID какая максимально возможная скорость? 2 мбайт / сек потянет?

Далее -я пытался ковырятьс в примерах - есть там пример, который из платы дисковери делает мышку на акселерометре. Вроде бы это USB HID, но почему-то в тексте программы я встречал упоминание USB OTG. Насколько я знаю, USB HID является ведомым по отношению к компу, а комп - это всегда хост. Вроде бы, если я правильно понял - USB OTG - это разновидность USB Host, плата при этом сама становится "компом" и к ней можно подключать флешку например. Зачем для мышки USB OTG?

В общем, подскажите, что мне нужно для решения задачи?
Go to the top of the page
 
+Quote Post
Dr.Alex
сообщение Mar 20 2015, 08:20
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 386
Регистрация: 5-04-05
Из: моська, RF
Пользователь №: 3 863



Цитата(zheka @ Mar 20 2015, 09:46) *
В общем, подскажите, что мне нужно для решения задачи?

Проще всего переделать CDC на BULK.
Go to the top of the page
 
+Quote Post
adnega
сообщение Mar 20 2015, 09:29
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(Dr.Alex @ Mar 20 2015, 11:20) *
Проще всего переделать CDC на BULK.

Максимум 980кБайт/сек на USB-FS.
Go to the top of the page
 
+Quote Post
Dr.Alex
сообщение Mar 20 2015, 09:37
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 386
Регистрация: 5-04-05
Из: моська, RF
Пользователь №: 3 863



Цитата(adnega @ Mar 20 2015, 12:29) *
Максимум 980кБайт/сек на USB-FS.

Зачем ФС? ХС надо. О скорости я недавно отчитывался.
Go to the top of the page
 
+Quote Post
zheka
сообщение Mar 20 2015, 10:40
Сообщение #5


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Цитата(Dr.Alex @ Mar 20 2015, 12:37) *
Зачем ФС? ХС надо. О скорости я недавно отчитывался.


можно ссылку на отчет?
Go to the top of the page
 
+Quote Post
Dr.Alex
сообщение Mar 20 2015, 10:41
Сообщение #6


Профессионал
*****

Группа: Свой
Сообщений: 1 386
Регистрация: 5-04-05
Из: моська, RF
Пользователь №: 3 863



Цитата(zheka @ Mar 20 2015, 13:40) *
можно ссылку на отчет?

http://electronix.ru/forum/index.php?showtopic=126651
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Mar 20 2015, 10:48
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Цитата
USB OTG - это разновидность USB Host

OTG - это и Host и Device. В зависимости от того зажат специальный контакт или нет. То есть это USB которое само определяет куда оно подключилось, если к девайсу, становиться хостом, если к хосту становиться девайсом.

То есть OTG не означает что оно использовалось как хост, просто факт возможности

Цитата
В общем, подскажите, что мне нужно для решения задачи?


А для решения задачи вам надо еще драйвер на стороне Windows, есть встроенный HID и практически встроенный CDC. Остальные драйверы надо писать самому, и потому обмен через другие интерфейсы вам создаст дополнительных проблем.

Наверное идеологически правильно использовать все же CDC, но в целом можно конечно картинку представить как HID input report, и через interrupt точку гнать данные. Частота пакетов в HID если не ошибаюсь 1 КГц, размер пакета 64 байта максимальный по спецификации для HS, FS и 8 для LS.
так что через HID вы продавите 64 Кбайтай/сек - край...

Потому смотрите в сторону CDC там скорости повыше
Go to the top of the page
 
+Quote Post
mantech
сообщение Mar 20 2015, 15:29
Сообщение #8


Гуру
******

Группа: Участник
Сообщений: 2 219
Регистрация: 16-08-12
Из: Киров
Пользователь №: 73 143



Цитата(Golikov A. @ Mar 20 2015, 13:48) *
А для решения задачи вам надо еще драйвер на стороне Windows, есть встроенный HID и практически встроенный CDC. Остальные драйверы надо писать самому, и потому обмен через другие интерфейсы вам создаст дополнительных проблем.


Так-то есть еще usb video class, по которому работают камеры в винде, он стандартный, но на стороне мк реализовать сложнее.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Mar 20 2015, 16:57
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Цитата
Так-то есть еще usb video class,

это видать что-то новое появилось... правда я так давно этим USB последний раз занимался, что оно может быть вполне и староеsm.gif
Go to the top of the page
 
+Quote Post
zheka
сообщение Mar 20 2015, 17:58
Сообщение #10


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Установил я virtual comport driver версия 1.4, скачал с самого сайта ST.
Все установилось без проблем.
Но появляющийся com-порт со значком ошибки - для устройства не установлены драйверы. Хотя номер порту присваивается.
При попытке вручную что-то сделать выдается сообщение "Неправильная секция установки службы в этом ini файле"

Прошивку качал отсюда http://ctrl-v.biz/blog/7

Что я делаю не так? Ini файл прикладываю

Сообщение отредактировал zheka - Mar 20 2015, 18:03
Go to the top of the page
 
+Quote Post
zheka
сообщение Mar 21 2015, 12:15
Сообщение #11


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Много бубнов разбил, но установил все-таки этот драйвер.
Объясните мне феномен - как ни переключаю скорость COM-порта в Terminal - данные идут правильные и на высокой скорости. Это как?
Go to the top of the page
 
+Quote Post
Andy Mozzhevilov
сообщение Mar 21 2015, 14:28
Сообщение #12


Знающий
****

Группа: Свой
Сообщений: 877
Регистрация: 26-01-05
Из: Екатеринбург
Пользователь №: 2 206



Цитата(zheka @ Mar 21 2015, 15:15) *
Объясните мне феномен - как ни переключаю скорость COM-порта в Terminal - данные идут правильные и на высокой скорости. Это как?

Так и есть. В USB данные будут ходить с той скоростью, сколько USB позволит.
То, что вы устанавливаете, это фактически настройки для реального COM порта, который может торчать с другой стороны USB. Они уходят отдельными командами и могут быть использованы, если нужно. Например можно сделать конвертер USB-COM и по переданным параметрам устанавливать нужную скорость UART.


--------------------
Пасу котов...
Go to the top of the page
 
+Quote Post
zheka
сообщение Mar 21 2015, 14:36
Сообщение #13


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



А из DMA тогда как в USB писать?
Что записывать в DMA_InitStructure.DMA_Memory0BaseAddr ???
Go to the top of the page
 
+Quote Post
zheka
сообщение Mar 21 2015, 17:36
Сообщение #14


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



ох... у меня голова уже опухла..
Вот здесь в конце есть ссылка на якобы рабочий проект для Eclipse. http://ctrl-v.biz/blog/7
Пытаюсь переделать под Keil. Все добавил, все прописал, все пути к include тоже вбил. Не компилится и все тут.
Если кому не трудно, гляньте в аттаче...

Сообщение отредактировал zheka - Mar 22 2015, 06:25
Go to the top of the page
 
+Quote Post
zheka
сообщение Mar 22 2015, 05:37
Сообщение #15


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Нашел что надо прописать.
Компилится, линкуется. Но вываливается в Hard Fault..
Ставлю брейкпоинт на самую первую строку - брейкпоинт не срабатывает.
В чем моежт быть дело?
Файл, выложенный выше, обновил.
/////////////////

Прошелся отладчиком пошагово :
Код
        IMPORT  __main

                 LDR     R0, =SystemInit
                 BLX     R0
                 LDR     R0, =__main
                 BX      R0
                 ENDP


доходит до BX R0 и вылетает в hard_fault
Стартап я правда взял от примеров от ST для дискавери4, потому как в примере для Eclipse он как будто на другом языке написан.

Сообщение отредактировал zheka - Mar 22 2015, 07:30
Go to the top of the page
 
+Quote Post
zheka
сообщение Mar 22 2015, 16:26
Сообщение #16


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Пробовал запустить пример кейловский Virtual ComPort, который правда под 407IG, запускается, но устройство обнаруживается компом, но не опознается.
А в аттаче то, что я собрал с нуля новым модным визардом в Keil 5 версии. Не видит при линковке одну переменную, хотя все везде прописано.

Коллеги, ну помогите мне запустить хоть один из 3 указанных проектов.
Go to the top of the page
 
+Quote Post
zheka
сообщение Mar 25 2015, 17:14
Сообщение #17


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Господа, эта задача (настройка CDC на Discovery) нерешаема? Или моя просьба слишком нагла и я прошу о слишком трудоемокой помощи?
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Mar 25 2015, 17:37
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Просто сказать нечего...

А что если через куб сгенерить все и запустить? для вашей дискавери? Почему у вас все время все откуда то со стороны?

Ваш же вопрос общий, то есть надо взять дискавери и самому запустить чтобы понять что не срастается...
Go to the top of the page
 
+Quote Post
zheka
сообщение Mar 25 2015, 18:12
Сообщение #19


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Хорошо, вот вопрос для тех, у кого нет дискавери, но есть хотя бы keil.
Нашел интересны пример - шаг за шагом - для тупых http://e.pavlin.si/2014/07/10/stm32f4-disc...t-step-by-step/
Я дошел до шага 7. Во вкладке драйверы у меня нет USB. Хотя MDK Middleware и ARM CMSIS я обновлял средствами самого keil и версию указывал ту же самую, что в статье. Пишет что не хватает компонентов. А кака их скачать, если pack скачивается целиком и в каком-то урезанном объеме....
Может кто-нибудь попробовать дойти до шага 7? Не с последними версиями библиотек, а с теми, что указаны...
У меня уже 6 примеров на рабочем столе валяется и ни один по тем или иным причинам не работает.

И гугл не особо помогает. Мне нужно немного - KEIL+CDC+Discovery - готовый простой пример. Нигде нет... Есть под Eclipse полно примеров, но переделка результатов не дала - Hard fault на этапе перехода из SystemInit в main()

Далее - шаг 10, где предлагается настроить клок в RTE-Device.h. У меня все есть во вкладке, кровме клока. Это какое-то издевательство...

Сообщение отредактировал zheka - Mar 25 2015, 18:05
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Mar 25 2015, 18:52
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Cube же делает проект с USB CDC и вроде даже выкидывает исходники драйверов для кейла, так что не выходит?

а по кейлу, тут же вопросы лицензии, у меня в том кейле что есть вообще не активна Run-time Env, почему не знаю, может чего то не стоит, паков каких или еще что....
Go to the top of the page
 
+Quote Post
zheka
сообщение Mar 25 2015, 19:58
Сообщение #21


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Слазил я в CUbeMX. Он генерирует только настройки. Кода общения (прием, передача) я не увидел.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Mar 25 2015, 20:14
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



ну функции то он дает.
и прерывание настраивает.
вы галочку поставили чтобы он вам CDC USB сделал?
отмечаете что хотите USB device, а вверху в системах ставите USB CDC
Go to the top of the page
 
+Quote Post
zheka
сообщение Mar 25 2015, 20:18
Сообщение #23


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



ставил я все галочки. там main пустой. И файла проекта нет - пишет что проблемы. МОжет быть потому, что он заточен под 4.7, а у меня пятая версия.
Не хочу я сносить и ставить 4 версию ради Cube, неправильно это.

ДА и, если честно - я хочу попроще. МНе USB нужен а этот wizard, что в статье делает с использованием RTOS. Ну куда пушка по воробьям? Но попытки переделать кучу простых примеров под другие среды успеха не приносят.
Я выложил выше пару проектов, с которыми какая-то мелкая проблема. Они, работающие меня бы устроили.

Сообщение отредактировал zheka - Mar 25 2015, 20:23
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Mar 25 2015, 20:23
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



увы с 5 кейлом не помогу...

Цитата
Не видит при линковке одну переменную, хотя все везде прописано.

а переменная то не в библиотеке случаем? а не подключить ли ее в проект надо?
Go to the top of the page
 
+Quote Post
zheka
сообщение Mar 25 2015, 20:31
Сообщение #25


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Ну вот к примеру
http://www.wolinlabs.com/blog/stm32f4.virtual.com.port.html
Скажите, это вообще в keil будет работать?

Цитата
а переменная то не в библиотеке случаем? а не подключить ли ее в проект надо?

Ну этот проект как раз собран с ошибкой - там последние версии библиотек, а они несовместимы с каким-то драйвером. Так что даже если и скомпилится, работать не будет.

С правильными версиями библиотек, сделанное как в статье http://e.pavlin.si/2014/07/10/stm32f4-disc...t-step-by-step/ у меня скомпилилось, но поскольку я не нашел вкладку clock configuration, поэтому устройство не обнаруживается.

Еще раз говорю, я не прошу за меня писать проекты.
Просто ищу человека, который работал с CDC на Discovery с KEIL. Мне нужен пример, который без бубнов скомпилится, запустится, передаст байт туда и обратно. С остальным я разберусь сам.

Пост 14. Если это перестанет вылетать на этапе перехода от SystemInit к main(), я буду несказанно рад.
Go to the top of the page
 
+Quote Post
zheka
сообщение Mar 26 2015, 04:28
Сообщение #26


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Заработало....
Go to the top of the page
 
+Quote Post
zheka
сообщение Mar 26 2015, 19:08
Сообщение #27


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



А как настраивается скорость CDC?
У меня в проекте где-то настройки USART, я с ними сначала колдовал. Потом, терзаемый смутными сомнениями, вообще закомментировал инициализацию USART - работать не перестало... Значит настройка USART ни при чем.
В функции USB_OTG_BSP_Init ничего такого про скорость нет..
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Mar 26 2015, 21:10
Сообщение #28


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



скорость никак не настраивается.... Она не имеет смысла, будет работать на любой до максимальной
CDC же передает данные по USB, а оно имеет свою скорость, и ограничивает вас только максимумом и все...

настройки скорости в винде в виртуальном порте - это так, атавизм. Иногда их можно использовать на стороне приемника, чтобы если данные дальше по UART пойдут, задать скорость по выставленной, но если просто данные гонять надо, то скорость не имеет смысла
Go to the top of the page
 
+Quote Post
zheka
сообщение Mar 27 2015, 04:30
Сообщение #29


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



ОК.
Тогда проблема следующая. ЗАпустил на компе программу Terminal и ловлю посылки.
А посылки такие (имитирую передачу кадра 640х480)
Код
for (i=0;i<480;i++)
{
    for (j=0;j<10;j++)  usb_cdc_printf("....... ....... ....... ....... ....... ....... ....... ...\r\n");        
    usb_cdc_printf("END_LINE\r\n");
  }  
usb_cdc_printf("END_FRAME END_FRAME END_FRAME END_FRAME END_FRAME \r\n");
Delay(50);


Получаю явные пропуски данных.
Как для начала понять - контроллер отправляет не все или комп захлебывается?
Т
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Mar 27 2015, 05:39
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



комп вряд ли.
Надо смотреть что за коды ошибки возвращают функции отправки... Только предварительно надо по ним пройтись и посмотреть, там часто бывает ошибочные ситуации просто заглушены кодом что все хорошо. Так что раскрутите все функции до самого копирования в буфер отправки, проверьте возвраты ошибок, и поглядите где флаг USB сбрасываются. По идее ситуация что хочется, а не можется должна быть обозначена.

А со стороны компа буферы гиганские, его трудно перегрузить ИМХО...
Go to the top of the page
 
+Quote Post
zheka
сообщение Mar 27 2015, 06:12
Сообщение #31


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Да как же это проверить, если функция всегда будет возвращать USB_OK?
Код
static uint16_t cdc_DataTx (uint8_t* Buf, uint32_t Len)
{

    uint32_t i;
    //loop through buffer
    for( i = 0; i < Len; i++ )
    {
        //push data into transfer buffer
        APP_Rx_Buffer[APP_Rx_ptr_in] = Buf[i];
        //increase pointer value
        APP_Rx_ptr_in++;
        /* To avoid buffer overflow */
        if(APP_Rx_ptr_in == APP_RX_DATA_SIZE)
        {
            APP_Rx_ptr_in = 0;
        }
    }

    return USBD_OK;
}

Смотрел разные библиотеки, "говор" в них немного разный, но суть этой функции везде одна и та же
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Mar 27 2015, 08:40
Сообщение #32


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



эта хрень не уменьшается по мере отправки?
APP_Rx_ptr_in ?

Если нет, то значит должен быть еще указатель который показывает где сейчас указатель последних отправленных данных

Go to the top of the page
 
+Quote Post
zheka
сообщение Apr 14 2015, 09:38
Сообщение #33


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Возвращаюсь к проекту.
Мне удалось-таки настроить CDC на последней 5 версии KEIL и ее библиотеках. ПО упомянутой мной ранее СТАТЬЕ
Как выяснилось, отправка байтов все-таки не поспевала за командами контроллера. Ибо когда я поставил буфер 1024 байта, а отправляю единовременно по 640 байт, проблемы не возникает.
Но, сами понимаете, решение это временное. Хотелось бы знать, как мне организовать проверку, окончено ли задание по отправке пакета, можно ли направлять следующий? Как понять, свободен ли буфер? Перековырял всю библиотеку - то ли лыжи не едут... то ли я не пойму как это сделать...
Go to the top of the page
 
+Quote Post
zheka
сообщение Apr 14 2015, 11:55
Сообщение #34


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Действительно, проблема оказалась временно решенной.
Как только я попытался передать большой поток данных, начались тормоза. Первые ошибки отправки посыпались примерно на 16 500 байте.
Вот как я отправляю
Код
while(1)
{

  
        
    if (USBD_Configured (0)) {
                                        /* USB -> MCU                      */
      if (usb_rx_ch == -1) {
        usb_rx_ch = USBD_CDC_ACM_GetChar (0);
      }
      if (usb_rx_ch != -1) {

            
                
                for (j=0;j<480;j++)
                    {
                    for (i=0;i<640;i++)
                    {
                        sprintf(ss,"%d ",i);
                      RESULT=USBD_CDC_ACM_PutChar (0, ss[0]); // на эту хрень не обращайте внимания, это временно урезаный кусок.
                        if (RESULT==-1)
                        {    
                          if (ERRORS==0) {ierr=i;jerr=j;}
                            ERRORS++;
                        }    
                    }
                }
            }
            if (usb_rx_ch != LF) usb_rx_ch = -1;
                        
        }  
    
    }

ierr и jerr - для контроля, когда возникает первая ошибка.

Так как все-таки правильно передавать данные?

Сообщение отредактировал zheka - Apr 14 2015, 12:06
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Apr 15 2015, 05:46
Сообщение #35


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



Вроде б очевидно, что если функция не может отправить данные, надо чуть-чуть подождать, и это не ошибка, а вполне стандартная ситуация.

PS всегда считал, что документацию кейл содержит в порядке. Ан нет - в код повсюду добавили параметр instance, а в описании на сайте его нет.


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
zheka
сообщение Apr 15 2015, 05:56
Сообщение #36


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Спасибо, я уже в принципе и сам дошел до этого, ставлю небольшую задержку между отправками каждого байта. Подобрал ее опытным путем, пытаясь получить максимальную скорость. В итоге - 307200 байт передаются примерно за секунду.
Кто-то писал, что CDC позволяет выжать 900 кбайт/сек.
Как этого добиться?
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Apr 15 2015, 06:04
Сообщение #37


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



Чёрт, ну вот как, как до этого можно догадаться?!
Есть обратная связь, получилось положить в буфер CDC или не получилось. Почему бы ей не пользоваться?

Как ускорять кейловскую библиотеку, я не знаю. Подозреваю, что только выкидыванием и переписыванием.


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
zheka
сообщение Apr 15 2015, 06:15
Сообщение #38


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Цитата
Вроде б очевидно, что если функция не может отправить данные, надо чуть-чуть подождать

Цитата
Чёрт, ну вот как, как до этого можно догадаться?!

Не надо иронизировать, а?
Я прекрасно понимаю, что нужно чуть-чуть подождать, я спрашивал, как не ждать определенное время, а четко ловить момент, когда можно еще что-то пихать. Что-то типа while(cdc_is_busy) {}

Цитата
Как ускорять кейловскую библиотеку, я не знаю. Подозреваю, что только выкидыванием и переписыванием.

Очень странное предложение. А я думал настройками, коих великое множество.
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Apr 15 2015, 10:30
Сообщение #39


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



Если USBD_CDC_ACM_PutChar () не смог сделать этот самый putchar, он вернёт -1.
Соответственно, ничего страшного не случится, если попросить его сделать это ещё раз. И ещё.

А настроек там немного совсем. Во всяком случае, таких, которые может крутить пользователь. Размер пакета там уже установлен в 64 байта, что ещё можно поменять, не знаю.
Как оно устроено внутри, кейл не говорит.


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
zheka
сообщение Apr 15 2015, 10:54
Сообщение #40


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Про ошибки - проехали.
ПРо быстродействие - я уже где-то вычитал, что для того чтобы достичь максимума в 1.2 мбайт/с, нужно оперировать нужно массивами.
Для массивов есть спецфункция
Код
extern int32_t USBD_CDC_ACM_WriteData (int8_t instance, const uint8_t *buf, int32_t len);

Как видите len - 32битный.
Но в настройках больше 64 байт в endpoint не ставится.
Даже если сам buf объявить больше чем на 64 байта - устройство USB не определяется.

Где собака порылась?




Сообщение отредактировал zheka - Apr 15 2015, 10:56
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Apr 15 2015, 10:59
Сообщение #41


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



может где то в районе спецификации USB, по которой контрольная точка больше 64 байт для HS, FS устройств не допускает?
Go to the top of the page
 
+Quote Post
zheka
сообщение Apr 15 2015, 11:09
Сообщение #42


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Цитата(Golikov A. @ Apr 15 2015, 13:59) *
может где то в районе спецификации USB, по которой контрольная точка больше 64 байт для HS, FS устройств не допускает?

Возможно, но для HS размера пакета в настройках ставится 512 байт. И тем не менее - это тоже не 32 бит, как допускает параметр len
Это и наталкивало меня на мысль, что размер буфера - вещь аппаратная, в функцию можно пихать столько, сколько позволяет разерность len и ресурсы конкретного контроллера, а она уже сама позаботится о разбивке.

Кроме того, в настройках есть такой параметр: Maximum Communication Device Send Buffer Size, который выставляется до 1024 байт. СОбственно у меня он и выставлен в 1024 байт и я уже раскатал на них губу.

Сообщение отредактировал zheka - Apr 15 2015, 11:27
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Apr 15 2015, 11:42
Сообщение #43


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



цитаты из исходников кейла:

* - 'Maximum Communication Device Send Buffer Size' specifies the maximum
* value for \em len in \ref USBD_CDC_ACM_WriteData

// <o>Maximum Communication Device Send Buffer Size
// <i>Specifies size of buffer used for sending of data to USB Host.
// <8=> 8 Bytes <16=> 16 Bytes <32=> 32 Bytes <64=> 64 Bytes
// <128=>128 Bytes <256=>256 Bytes <512=>512 Bytes <1024=>1024 Bytes
#define USBD_CDC%Instance%_SEND_BUF_SIZE 1024


Буфер, в который пишет USBD_CDC_ACM_WriteData() (ну и ваши тысячи USBD_CDC_ACM_PutChar()) организован в основной памяти контроллера, и оттуда библиотека перекладывает в контроллер USB кусочками по 64 байта.


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
zheka
сообщение Apr 15 2015, 12:32
Сообщение #44


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Цитата
Буфер, в который пишет USBD_CDC_ACM_WriteData() (ну и ваши тысячи USBD_CDC_ACM_PutChar()) организован в основной памяти контроллера,


вооооот....
Тогда почему же, если я делаю вот так
Код
uint8_t DataOut[64];
uint8_t *pDataOut;
.....
USBD_CDC_ACM_WriteData(0,pDataOut,64);

и ставлю в первой строке DataOut[640], то при запуске USB вообще не определяется?

Работая кусками по 64 байта и склеивая их по 10 уже на компьютере, я все-таки получил вывод картинки со скоростью 1 кадр за 0.3 секунды (как раз примерно 900 кб/сек).
Но гложет меня этот короткий буфер.
Я пока-что искусственно генерю содержимое памяти. Сейчас вот прикручу DCMI и DMA - подозреваю что будут проблемы. Хотелось целую строку запихивать в буфер и тут же по сигналу окончания считывания строки отправлять ее по USB...

Максимум чего удалось добиться - uint8_t DataOut[256];

Сообщение отредактировал zheka - Apr 15 2015, 11:53
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Apr 15 2015, 12:41
Сообщение #45


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(zheka @ Apr 15 2015, 15:32) *
Максимум чего удалось добиться - uint8_t DataOut[256];

Вы бы пояснили, в ситуации, когда USB не определяется, 640 и 256 фигурируют только в размерности DataOut[], или при вызове USBD_CDC_ACM_WriteData() тоже?

А то сейчас можно подумать, что DataOut[] локальная переменная, для которой просто не хватает стека.
Go to the top of the page
 
+Quote Post
zheka
сообщение Apr 15 2015, 12:58
Сообщение #46


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Цитата
А то сейчас можно подумать, что DataOut[] локальная переменная, для которой просто не хватает стека.


Ах тыж ёшкин кот... точно!!!
Она у меня и правда локальная. Сделал глобальной, выставил 640 байт - все пашет.
Спасибо!

P.S. Ушел к знакомому шаману за специальным бубном, который потребуется чтобы прикрутить DCMI.....

Сообщение отредактировал zheka - Apr 15 2015, 12:59
Go to the top of the page
 
+Quote Post
zheka
сообщение Apr 18 2015, 18:59
Сообщение #47


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Продолжаю пляски с бубном
Прикрутил камеру. НА текущий момент читатся и пишутся регистры, камера, судя по осциллограммам работает.
О том, что нормально работает камера и са DCMI свидетельствует то, что помещенный в окно отладчика Watch регистр DCMI->DR мпостоянно изеняется, приченм, если камеру закрыть, там нули, а если посветить - то чем ярче, тем больше выпозают числа.

А вот с DMA какие-то проблемы - выделенный по дкадр буфер все время пуст. ДЛя проверки даже предварително заполнял его заданным значениями - они отображаются, но не меняются.
Вот инициализация:
CODE

static void Camera_HW_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
DCMI_InitTypeDef DCMI_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

__IO uint32_t Timeout = TIMEOUT_MAX;

RCC_AHB1PeriphClockCmd(SCCB_Clock, ENABLE);

// Configure SIO_C and SIO_D as OUT (for SCCB/I2C)
GPIO_InitStructure.GPIO_Pin = SIO_C_Pin | SIO_D_Pin;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // PullUp is include on module
GPIO_Init(SCCB_Port, &GPIO_InitStructure);

// Configure MCO0(PA8) as clock out for Camera Module (XCLK pin)
OV7670_XCLK_Conf();

// Configures the DCMI GPIOs to interface with the OV7670 camera module
// Enable DCMI GPIOs clocks
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB |
RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOE,
ENABLE);

// Connect DCMI pins to AF13
// PORTA
GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_DCMI); // HSYNC
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_DCMI); // PCLK
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_DCMI); // D0
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_DCMI); // D1

// PORTB
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_DCMI); // D5
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_DCMI); // VSYNC
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_DCMI); // D6
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_DCMI); // D7 -

// PORTC
GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_DCMI); // D4

// PORTE
GPIO_PinAFConfig(GPIOE, GPIO_PinSource0, GPIO_AF_DCMI); // D2
GPIO_PinAFConfig(GPIOE, GPIO_PinSource1, GPIO_AF_DCMI); // D3

// DCMI GPIO configuration
// D0..D1(PA9/10), HSYNC(PA4), PCLK(PA6)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_6 | GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOA, &GPIO_InitStructure);

// D5..D7(PB6/8/9), VSYNC(PB7)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOB, &GPIO_InitStructure);

// D4(PC11)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOC, &GPIO_InitStructure);

// D2..D3(PE0/1)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOE, &GPIO_InitStructure);
//---------------------------------------------------------------------------------------
// GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_DCMI); //d0
// GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_DCMI); //d1
// GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_DCMI); //d2

//---------------------------------------------------------------------------------------
// Configures the DCMI to interface with the OV7670 camera module
// Enable DCMI clock
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE);

// Reinitialize
DCMI_DeInit();

// DCMI configuration
DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_Continuous;
DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;
DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Rising;
DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High;
DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_Low;
DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;
DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;

DCMI_Init(&DCMI_InitStructure);


// Configures the DMA2 to transfer Data from DCMI
// Enable DMA2 clock
RCC_AHB1PeriphClockCmd(DMA_Camera_STREAM_CLOCK, ENABLE);

// DMA2 Stream1 Configuration
DMA_DeInit(DMA_CameraToRAM_Stream);
// Check if the DMA Stream is disabled before enabling it.
// Note that this step is useful when the same Stream is used multiple times:
// enabled, then disabled then re-enabled... In this case, the DMA Stream disable
// will be effective only at the end of the ongoing data transfer and it will
// not be possible to re-configure it before making sure that the Enable bit
// has been cleared by hardware. If the Stream is used only once, this step might
// be bypassed.
while (DMA_GetCmdStatus(DMA_CameraToRAM_Stream) != DISABLE)
{
}
DMA_InitStructure.DMA_Channel = DMA_Camera_Channel;
DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&RAM_Buffer;
//DMA_InitStructure.DMA_Memory0BaseAddr = 0x60020000;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = BuffSize;
// DMA_InitStructure.DMA_BufferSize = 1;

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
// DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

DMA_Init(DMA_CameraToRAM_Stream, &DMA_InitStructure);

// Enable DMA Stream Transfer Complete interrupt
DMA_ITConfig(DMA_CameraToRAM_Stream, DMA_IT_TC , ENABLE);

// Check if the DMA Stream has been effectively enabled.
// The DMA Stream Enable bit is cleared immediately by hardware if there is an
// error in the configuration parameters and the transfer is no started (ie. when
// wrong FIFO threshold is configured ...)
Timeout = TIMEOUT_MAX;
while ((DMA_GetCmdStatus(DMA_CameraToRAM_Stream) != ENABLE) && (Timeout-- > 0))
{
}

// Check if a timeout condition occurred
if (Timeout == 0)
{
// Manage the error: to simplify the code enter an infinite loop
while (1)
{
// Dopísa program
}
}

// // Enable the DMA Stream IRQ Channel
NVIC_InitStructure.NVIC_IRQChannel = DMA_Camera_STREAM_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

}


Буфер объявлен так
Код
__IO uint16_t RAM_Buffer[BuffSize];


Ну и вот что у меня в прерываниях
Код
void  DMA_Camera_STREAM_IRQHANDLER(void)
{
    uint16_t i;
    // Test on DMA Stream Transfer Complete interrupt
    if(DMA_GetITStatus(DMA_CameraToRAM_Stream, DMA_Camera_IT_TCIF))
    {
//        LCD_REG = 0x0022;
        //for(i = 0; i < BuffSize; i++)
//            LCD_RAM = RAM_Buffer[i];

        // Clear DMA Stream Transfer Complete interrupt pending bit
        DMA_ClearITPendingBit(DMA_CameraToRAM_Stream, DMA_Camera_IT_TCIF);
    }
}

void DCMI_IRQHandler(void)
{
    uint16_t i;

    if(DCMI_GetITStatus(DCMI_IT_FRAME))
    {
//        LCD_REG = 0x0022;
        //for(i = 0; i < BuffSize; i++)
//            LCD_RAM = RAM_Buffer[i];
        //for(i = 0; i < 28800; i++)
//            LCD_RAM = 0x0000;

         DCMI_ClearITPendingBit(DCMI_IT_FRAME);
    }
}


Оба прерывания вызываются, все ОК,
Но буфер пуст...

У меня вопрос - а нужен ли мне собственно DMA?
МОжно ли как-то без него заполнять буфер длиной 640 байт а по прерыванию новой строки отправлять этот буфер по USB?

ДОБАВЛЮ:
Если это
Код
//    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;


заменить на это
Код
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
//    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;

ну то есть включить DMA_MemoryInc, то в буфере оказываются данные, но в дальнейшем не изменяются.
И прерывание DMA_Stream не вызывается...

Сообщение отредактировал zheka - Apr 18 2015, 18:57
Go to the top of the page
 
+Quote Post
zheka
сообщение Apr 19 2015, 11:08
Сообщение #48


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Таак... У меня каша в голове пока что....
Вот смотрите, мне нужно следующее - чтобы DMA заполнял данными из DCMI буфер длиной в одну строку (1280 байт при RGB565), чтобы первый байт строки был первым байтом буфера. Далее - по окончанию передачи строки (не знаю, как лучше ее ловить, по прерываниям из DCMI или в DMA есть какое прерывание, означающее что вся строка передана, в этот момент я собираюсь забирать из буфера данные и отправлять их по USB (это уже настроено).


Вот мои последние настройки DMA и DCMI
CODE

DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_Continuous;
DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;
DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Rising;
DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High;
DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_Low;
DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;
DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;

DCMI_Init(&DCMI_InitStructure);


// Configures the DMA2 to transfer Data from DCMI
// Enable DMA2 clock
RCC_AHB1PeriphClockCmd(DMA_Camera_STREAM_CLOCK, ENABLE);

// DMA2 Stream1 Configuration
DMA_DeInit(DMA_CameraToRAM_Stream);
// Check if the DMA Stream is disabled before enabling it.
// Note that this step is useful when the same Stream is used multiple times:
// enabled, then disabled then re-enabled... In this case, the DMA Stream disable
// will be effective only at the end of the ongoing data transfer and it will
// not be possible to re-configure it before making sure that the Enable bit
// has been cleared by hardware. If the Stream is used only once, this step might
// be bypassed.
while (DMA_GetCmdStatus(DMA_CameraToRAM_Stream) != DISABLE)
{
}
DMA_InitStructure.DMA_Channel = DMA_Camera_Channel;
DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&RAM_Buffer;
//DMA_InitStructure.DMA_Memory0BaseAddr = 0x60020000;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = BuffSize;
// DMA_InitStructure.DMA_BufferSize = 1;

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
// DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

DMA_Init(DMA_CameraToRAM_Stream, &DMA_InitStructure);

// Enable DMA Stream Transfer Complete interrupt
DMA_ITConfig(DMA_CameraToRAM_Stream, DMA_IT_TC , ENABLE);




// Check if the DMA Stream has been effectively enabled.
// The DMA Stream Enable bit is cleared immediately by hardware if there is an
// error in the configuration parameters and the transfer is no started (ie. when
// wrong FIFO threshold is configured ...)
Timeout = TIMEOUT_MAX;
while ((DMA_GetCmdStatus(DMA_CameraToRAM_Stream) != ENABLE) && (Timeout-- > 0))
{
}

// Check if a timeout condition occurred
if (Timeout == 0)
{
// Manage the error: to simplify the code enter an infinite loop
while (1)
{
// Dopísa program
}
}

// // Enable the DMA Stream IRQ Channel
NVIC_InitStructure.NVIC_IRQChannel = DMA_Camera_STREAM_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);


Что нужно поменять?
Особенно волнует, как настраивать вот эти строки

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
// DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;

И почему в источнике слово, а в конечной точке - полслова?
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Apr 19 2015, 14:47
Сообщение #49


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



В ДМА настраиваю ширину входного и выходного канала
оно может 32 битные числа по 8 бит в UART перекладывать или собирать 16 битный SPI d 32 битные int.
Также в ДМА настраивают писать в один адрес или автоматически сдвигать. Если вы кладете данные в UART, например, то адрес приемника один, и ДМА делают без автоинкремента. А если вы кладете данные в память, то надо чтобы каждые новые данные клались в новый адрес, и тогда нужен автоинкремент.

Теперь смотрите ширину входных - выходных ваших данных и постоянство адресов и настраивайте ДМА.
Go to the top of the page
 
+Quote Post
zheka
сообщение Apr 20 2015, 03:13
Сообщение #50


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Вы мне объясните еще две вещи - как в DCMI настроить частоту PIX_CLK и почему D0-D7 настраиваются как выходы? Ведь в камеру если что и пишется, то по i2c, но никак не по шине данных..
Go to the top of the page
 
+Quote Post
zheka
сообщение Apr 22 2015, 15:56
Сообщение #51


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Вот черт же, где правда?
Стр.41 даташита https://www.fer.unizg.hr/_download/repository/OV7670new.pdf
Vertical Frame (Row) Start VSTRT [7:0], VREF[2:0]
То есть старшие 8 бит - в регистре VSTRT, младшие 3 бита - в регистре VREF
Дальше лезем в описание регистра VREF:
bit [3:2] - VREF end low 2 bits

Где правда?
Go to the top of the page
 
+Quote Post
zheka
сообщение Apr 22 2015, 17:17
Сообщение #52


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Оказывается есть аппаратная функция захвата ОБЛАСТИ в контроллере DCMI
Код
typedef struct
{
  uint16_t DCMI_VerticalStartLine;      /*!< Specifies the Vertical start line count from which the image capture
                                             will start. This parameter can be a value between 0x00 and 0x1FFF */

  uint16_t DCMI_HorizontalOffsetCount;  /*!< Specifies the number of pixel clocks to count before starting a capture.
                                             This parameter can be a value between 0x00 and 0x3FFF */

  uint16_t DCMI_VerticalLineCount;      /*!< Specifies the number of lines to be captured from the starting point.
                                             This parameter can be a value between 0x00 and 0x3FFF */

  uint16_t DCMI_CaptureCount;           /*!< Specifies the number of pixel clocks to be captured from the starting
                                             point on the same line.
                                             This parameter can be a value between 0x00 and 0x3FFF */
} DCMI_CROPInitTypeDef;

и позволяет вводить "человеческие" значения.

Таким образом, у меня один вопрос к специалистам - те значения, что в камере по умолчанию - они все-таки какие координаты окна и разрешение дают?
Надеюсь 0,0,640,480?



Сообщение отредактировал zheka - Apr 22 2015, 18:08
Go to the top of the page
 
+Quote Post
zheka
сообщение Apr 22 2015, 19:21
Сообщение #53


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Какой-то шайтан... Как не настраиваю, DCMI все равно выдает 480 строк:
Код
DCMI_DeInit();



    // DCMI configuration
    DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_Continuous;
    DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;
    DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Rising;
    DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High;        
    DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_Low;
    DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;
    DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;

    DCMI_Init(&DCMI_InitStructure);



DCMI_CROPInitStructure.DCMI_HorizontalOffsetCount=0;
DCMI_CROPInitStructure.DCMI_CaptureCount=320*2;
DCMI_CROPInitStructure.DCMI_VerticalStartLine=0;
DCMI_CROPInitStructure.DCMI_VerticalLineCount=240;
DCMI_CROPConfig(&DCMI_CROPInitStructure);
DCMI_CROPCmd(ENABLE);
    
       DCMI_ITConfig(DCMI_IT_VSYNC, ENABLE);
      DCMI_ITConfig(DCMI_IT_LINE, ENABLE);
      DCMI_ITConfig(DCMI_IT_FRAME, ENABLE);
      DCMI_ITConfig(DCMI_IT_OVF, ENABLE);
      DCMI_ITConfig(DCMI_IT_ERR, ENABLE);


А вот обработчик прерываний
Код
void DCMI_IRQHandler(void)
{
    uint16_t i;

    if(DCMI_GetITStatus(DCMI_IT_FRAME))
    {
    
         DCMI_ClearITPendingBit(DCMI_IT_FRAME);
        lines=current_line;
        current_line=0;

    }

    if(DCMI_GetITStatus(DCMI_IT_VSYNC))
    {
    
         DCMI_ClearITPendingBit(DCMI_IT_VSYNC);
        
    }
    
    if(DCMI_GetITStatus(DCMI_IT_ERR))
    {
    
         DCMI_ClearITPendingBit(DCMI_IT_ERR);
        
    }


    
    if(DCMI_GetITStatus(DCMI_IT_LINE))
    {
    current_line++;
         DCMI_ClearITPendingBit(DCMI_IT_LINE);
    }
}


В дебаггере у меня lines. Как только ловится кадр, в Lines помещается значение насчитанных строк.
Go to the top of the page
 
+Quote Post
zheka
сообщение Apr 26 2015, 09:02
Сообщение #54


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Камера поддается, но не сдается.
Куски картинки в искаженном цвете я уже вижу. Но как-то неправильно DCMI и DMA у меня кооперируются.

Интерфейс DCMI имеет регистр DCMI->DR, содержащий 32 бита, то есть в режиме RGB565 в него кладется 4 байта - информация о 2-х пикселях.
Я настроил камеры на выдачу фрагмента размерами 200х200 пикселей, то есть размер буфера у меня 80 000 байт, длина строки 400 байт.
Я заполняю буфер через DMA, а потом пакетами по 400 байт пересылаю картинку на компьютер.
В итоге картинка получается странная - складывается ощущение, что строка все же имеет длину 200 байт и запись в картинку получается следующего формата
1 строка 2 строка
3 строка 4 строка
5 строка 6 строка

Плюс почему-то нижняя часть картинки оказывается вверху и наоборот. А верхняя половина буфера пуста.
Собственно с передаче картинки на комп и ее расшифровкой проблем нет - заполнял буфер искусственно, получал правильную картинку. ПРоблемы с записью в DMA.
Вот код
CODE
extern __IO uint8_t RAM_Buffer[80000];
uint8_t *pRAM_Buffer;

..................................................

DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_Continuous;
DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;
DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Rising;
DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High;
DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_Low;
DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;
DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;

DCMI_Init(&DCMI_InitStructure);

DCMI_ITConfig(DCMI_IT_VSYNC, ENABLE);
DCMI_ITConfig(DCMI_IT_LINE, ENABLE);
DCMI_ITConfig(DCMI_IT_FRAME, ENABLE);

DCMI_ITConfig(DCMI_IT_ERR, ENABLE);
// Enable DCMI Capture mode



// Configures the DMA2 to transfer Data from DCMI
// Enable DMA2 clock
RCC_AHB1PeriphClockCmd(DMA_Camera_STREAM_CLOCK, ENABLE);

// DMA2 Stream1 Configuration
DMA_DeInit(DMA_CameraToRAM_Stream);

while (DMA_GetCmdStatus(DMA_CameraToRAM_Stream) != DISABLE)
{
}
DMA_InitStructure.DMA_Channel = DMA_Camera_Channel;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&DCMI->DR);
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&RAM_Buffer;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = BuffSize;


DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
//DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

DMA_Init(DMA_CameraToRAM_Stream, &DMA_InitStructure);

// Enable DMA Stream Transfer Complete interrupt
DMA_ITConfig(DMA_CameraToRAM_Stream, DMA_IT_TC, ENABLE);
..........................
// Передача двухсот строк

pRAM_Buffer=RAM_Buffer;
for (j=0;j<200;j++)
{
USBD_CDC_ACM_WriteData(0,pRAM_Buffer+400*j,400);
delay_us(1000);

}


Картинку прикладываю. Камера лежит на столе и в ее объектив попадает мое ухо))

Вот картинка

Сообщение отредактировал IgorKossak - Apr 26 2015, 10:24
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!

Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Apr 27 2015, 06:16
Сообщение #55


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



А как мы можем быть уверены что у вас не такое ухоsm.gif?

есть подозрение что вы один и тот же кусок по кругу передаете...
число точек в строке правильное?
Go to the top of the page
 
+Quote Post
zheka
сообщение Apr 27 2015, 17:19
Сообщение #56


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Как выяснилось, у меня размер буфера в DMA был равен размеру массива данных в абсолютных цифрах. Вот только массив у меня 8-битный, а в DMA надо было пересчитывать на 32 бита, то есть делить на 4.
Хреновая цветность - не настроена гамма, плюс по какой-то причине мой софт декодирует полученные данные как RGB555, хотя явно указано - 16 битный формат. Временно настроил камеру на RGB555 - вроде бы все ОК.
Навел камеру на телек, что за спиной. Смотрю в окне своей программы "Лунтика" и наслаждаюсь. Как оказывается для счастья мало надо.

Go to the top of the page
 
+Quote Post
adnega
сообщение Apr 27 2015, 18:28
Сообщение #57


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(zheka @ Apr 27 2015, 20:19) *
не настроена гамма

Я долго страдал от зеленых лиц...
CODE
sccb_wr_reg(REG_COM7, 0x80); /* reset to default values */
//sccb_wr_reg(REG_CLKRC, 0x80);
sccb_wr_reg(REG_COM11, 0x0A);
sccb_wr_reg(REG_COM7, 0x04); /* output format: rgb */
sccb_wr_reg(REG_RGB444, 0x00); /* disable RGB444 */
sccb_wr_reg(REG_COM15, 0xD0); /* set RGB565 */
//sccb_wr_reg(0x0C, 0x00);

// COLOR SETTING
sccb_wr_reg(0x4f, 0x80);
sccb_wr_reg(0x50, 0x80);
sccb_wr_reg(0x51, 0x00);
sccb_wr_reg(0x52, 0x22);
sccb_wr_reg(0x53, 0x5e);
sccb_wr_reg(0x54, 0x80);
sccb_wr_reg(0x56, 0x40);
sccb_wr_reg(0x58, 0x9e);
sccb_wr_reg(0x59, 0x88);
sccb_wr_reg(0x5a, 0x88);
sccb_wr_reg(0x5b, 0x44);
sccb_wr_reg(0x5c, 0x67);
sccb_wr_reg(0x5d, 0x49);
sccb_wr_reg(0x5e, 0x0e);
sccb_wr_reg(0x69, 0x00);
sccb_wr_reg(0x6a, 0x40);
sccb_wr_reg(0x6b, 0x0a);
sccb_wr_reg(0x6c, 0x0a);
sccb_wr_reg(0x6d, 0x55);
sccb_wr_reg(0x6e, 0x11);
sccb_wr_reg(0x6f, 0x9f);

sccb_wr_reg(0xb0, 0x84);
sccb_wr_reg(0x11, 0x81);

Надеюсь этот код добавит вам счастья.
Go to the top of the page
 
+Quote Post
zheka
сообщение Apr 27 2015, 18:33
Сообщение #58


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



adnega, а в комп чем передаете? Какова скорость?
Go to the top of the page
 
+Quote Post
adnega
сообщение Apr 27 2015, 20:21
Сообщение #59


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(zheka @ Apr 27 2015, 21:33) *
adnega, а в комп чем передаете? Какова скорость?

Я на экране, подключенном к МК, отображаю.
Go to the top of the page
 
+Quote Post

4 страниц V   1 2 3 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th June 2025 - 22:57
Рейтинг@Mail.ru


Страница сгенерированна за 0.0219 секунд с 7
ELECTRONIX ©2004-2016