Перейти к содержанию
    

DCMI c DMA - плучаю пустой буфер

Уже куда только не писал, пытаюсь запустить камеру OV7670 на STM32F429

Работаю с халом, ибо приходится.

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

 

Для теста записал в первую ячейку белый пиксель - выводиться, но остальны ячейки по нулям, DMA даже не прикосается к массиву

 

Прерывания работают, DMA2_Stream1_IRQHandler срабатывает один раз сразу после вызова HAL_DCMI_Start_DMA(). DCMI_IRQHandler срабатывает просто очень часто, если вынуть камеру - все перестает работаеть (значит, данные то идут?)

 

Думаю, не стоит говорить о том, что инициализация по I2C тоже проходит успешно

 

 

Код инициализации для ленивых:

// Настрока DCMI и DMA
uint8_t DCMI_DMA_init(void){
GPIO_InitTypeDef GPIO_InitStruct;

DCMI_HandleTypeDef *hdcmi = &OV7670_hdcmi_eval;

// Тактирование
__GPIOE_CLK_ENABLE();
__GPIOA_CLK_ENABLE();
__GPIOC_CLK_ENABLE();
__GPIOB_CLK_ENABLE();
__DCMI_CLK_ENABLE();
__DMA2_CLK_ENABLE();

// .... DCMI порты (обрезано, чтоб не грузить читателя) ....

// DMA ( - изначально)
OV7670_hdma.Init.Direction = DMA_PERIPH_TO_MEMORY;
OV7670_hdma.Init.PeriphInc = DMA_PINC_DISABLE;
OV7670_hdma.Init.MemInc = DMA_MINC_ENABLE;
OV7670_hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
OV7670_hdma.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; // DMA_MDATAALIGN_WORD - DMA_MDATAALIGN_HALFWORD
OV7670_hdma.Init.Mode = DMA_NORMAL; // DMA_CIRCULAR - DMA_NORMAL
OV7670_hdma.Init.Priority = DMA_PRIORITY_HIGH;
OV7670_hdma.Init.FIFOMode = DMA_FIFOMODE_ENABLE; // DMA_FIFOMODE_DISABLE - DMA_FIFOMODE_ENABLE
OV7670_hdma.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
OV7670_hdma.Init.MemBurst = DMA_MBURST_SINGLE;
OV7670_hdma.Init.PeriphBurst = DMA_PBURST_SINGLE;
OV7670_hdma.Instance = DMA2_Stream1;


// DCMI
hdcmi->Init.SynchroMode = DCMI_SYNCHRO_HARDWARE;
hdcmi->Init.CaptureRate = DCMI_CR_ALL_FRAME;
hdcmi->Init.HSPolarity = DCMI_HSPOLARITY_LOW;
hdcmi->Init.VSPolarity = DCMI_VSPOLARITY_HIGH;
hdcmi->Init.ExtendedDataMode = DCMI_EXTEND_DATA_8B;
hdcmi->Init.PCKPolarity = DCMI_PCKPOLARITY_RISING;
hdcmi->Init.JPEGMode = DCMI_JPEG_DISABLE;
hdcmi->Instance = DCMI;

// Прерывание по завершении передачи
HAL_NVIC_SetPriority(DCMI_IRQn, 5, 1);
HAL_NVIC_EnableIRQ(DCMI_IRQn);

// Прерывание при полном приеме
HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);


// Связываем DMA с DCMI
__HAL_LINKDMA(hdcmi, DMA_Handle, OV7670_hdma);

// Инициализация DCMI
if(HAL_DCMI_Init(hdcmi) != HAL_OK){
	return 0;
}

// Инициализация DMA
if(HAL_DMA_Init(hdcmi->DMA_Handle) != HAL_OK){
	return 0;
}

return 1;
}

 

Пытаюсь получить картинку так:

    if(HAL_DCMI_Start_DMA(&OV7670_hdcmi_eval, DCMI_MODE_SNAPSHOT, &OV7670_buffer, (uint32_t)((IMG_ROWS * IMG_COLUMNS * 2) / 4)) != HAL_OK){
        LCD_ILI9341_Puts(100, 165, "Error DMA", &LCD_Font_16x26, ILI9341_COLOR_WHITE, ILI9341_COLOR_BLACK);
    }
    HAL_Delay(100);

    LCD_ILI9341_DisplayImage((uint16_t*)OV7670_buffer);

 

А вот файлы для того, кому не лень:

main.c: http://code.re/8fG

OV7670.c: http://code.re/8fF

OV7670.h: http://code.re/8fE

 

 

Меня волнуют слейдущие моменты:

- Подтяжка портов к плюсу

- DMA_FIFOMODE_ENABLE

- DMA_MDATAALIGN_HALFWORD

- мод DMA - DMA_NORMAL

- клок камеры настроеный на 16МГц

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Парсить ваш код времени нет, сорри.

Вот рабочий пример:


void OV7670_Snapshot2RAMBuffer(void)
{
 DMA_InitTypeDef  DMA_InitStructure;
 NVIC_InitTypeDef NVIC_InitStructure;

   // Включение тактирования
 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

 // DMA деинициализация
 DMA_Cmd(DMA2_Stream1, DISABLE);
 DMA_DeInit(DMA2_Stream1);
 DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TCIF1);  

   /* Enable the DMA Stream IRQ Channel */
 NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream1_IRQn;
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 NVIC_Init(&NVIC_InitStructure);     
   /* Enable the DMA Stream IRQ Channel */
 NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 NVIC_Init(&NVIC_InitStructure);     
 dma2Stream0 = 0;
 dma2Stream1 = 0;

 DMA_DoubleBufferModeConfig(DMA2_Stream1,(uint32_t)&ov7670_ram1[0],DMA_Memory_0);
 DMA_DoubleBufferModeCmd(DMA2_Stream1, ENABLE);

 // DMA инициализация
 DMA_InitStructure.DMA_Channel = DMA_Channel_1;
 DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS;
 DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)ov7670_ram0;
 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
 DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE_WORD;
 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
 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_Disable;
 DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
 DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
 DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
 DMA_Init(DMA2_Stream1, &DMA_InitStructure);

 DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TCIF1);  

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

 // DMA деинициализация
 DMA_Cmd(DMA2_Stream0, DISABLE);
 DMA_DeInit(DMA2_Stream0);
 DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);  

   // DMA инициализация
     DMA_InitStructure.DMA_Channel = DMA_Channel_0;
     DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ov7670_ram0[0];
     DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)(SDRAM_BANK_ADDR);
     DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToMemory;
     DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE_WORD;
     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
     DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
     DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
     DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
     DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
     DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_INC4;
     DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_INC4;
     DMA_Init(DMA2_Stream0, &DMA_InitStructure);

     DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);  
     /* Enable DMA Stream Transfer Complete interrupt */
     DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);

 // DMA включен
 DMA_Cmd(DMA2_Stream1, ENABLE);
 // DCMI инициализация
 OV7670_InitDCMI(1);
 // DCMI включен
 DCMI_Cmd(ENABLE);
 // Capture включен
 DCMI_CaptureCmd(ENABLE);
}

void DMA2_Stream1_IRQHandler(void)
{
 /* Test on DMA Stream Transfer Complete interrupt */
 if(DMA_GetITStatus(DMA2_Stream1, DMA_IT_TCIF1))
 {
   /* Clear DMA Stream Transfer Complete interrupt pending bit */
   DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TCIF1);
   if (DMA2_Stream1->CR&0x00080000) { /* ram1*/
     DMA2_Stream0->PAR = (uint32_t)&ov7670_ram0[0];
     DMA2_Stream0->M0AR = (uint32_t)(SDRAM_BANK_ADDR + dma2Stream1*76800);
   } else {  /* ram0 */
     DMA2_Stream0->PAR = (uint32_t)&ov7670_ram1[0];
     DMA2_Stream0->M0AR = (uint32_t)(SDRAM_BANK_ADDR + dma2Stream1*76800);
   }
   DMA2_Stream0->CR |= (uint32_t)DMA_SxCR_EN;
   dma2Stream1++;
 }
}

//#warning "Uncomment function for DCMI used"
void DMA2_Stream0_IRQHandler(void)
{
 /* Test on DMA Stream Transfer Complete interrupt */
 if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0))
 {
   /* Clear DMA Stream Transfer Complete interrupt pending bit */
   DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
   dma2Stream0++;
 }
}

Принцип следующий:

есть 2 буфера в RAM по 19200 32-х разрядных слов. Один канал DMA берет данные с камеры и кидает в активный буфер (по кольцу). Второй канал DMA из RAM перекидывает в SRAM(внешняя), т.к. для разрешения 640x480 необходимо 307200*2=614400 байт(формат YUV). Clock камеры 24Мгц

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я мого видел примеров, но все они на SPL, а мне необходим HAL

Я использую RGB565, 320 на 240 - этого вроде хватает

 

Но буфер пустует, не пойму из-за чего

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я мого видел примеров, но все они на SPL, а мне необходим HAL

Я использую RGB565, 320 на 240 - этого вроде хватает

Но буфер пустует, не пойму из-за чего

Данные с камеры идут (осциллографом)? Полярность HSYNC/VSYNC/PCLK правильно настроена?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, данные шли, камеры OV шлют данные сразу, как к ним подключается тактирование и даже можно различить образы среди помех (может кому полезно будет)

 

Дело было в версии хала, не пользуйтесь халом от кокса, возможно, к прочтению этого сообшения кем-то эту проблему устронят, но лучше скачайте свежую версию с ST и проверьте свой код на ней

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...