Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: DCMI c DMA - плучаю пустой буфер
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Fataris
Уже куда только не писал, пытаюсь запустить камеру OV7670 на STM32F429
Работаю с халом, ибо приходится.
При попытки забрать данных с буфера он оказывается пустым, на дисплее черный экран

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

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

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


Код инициализации для ленивых:
CODE
// Настрока 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МГц
KSN
Парсить ваш код времени нет, сорри.
Вот рабочий пример:
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Мгц
Fataris
Я мого видел примеров, но все они на SPL, а мне необходим HAL
Я использую RGB565, 320 на 240 - этого вроде хватает

Но буфер пустует, не пойму из-за чего
LightElf
QUOTE (Fataris @ Aug 28 2015, 16:07) *
Я мого видел примеров, но все они на SPL, а мне необходим HAL
Я использую RGB565, 320 на 240 - этого вроде хватает
Но буфер пустует, не пойму из-за чего

Данные с камеры идут (осциллографом)? Полярность HSYNC/VSYNC/PCLK правильно настроена?
Fataris
Да, данные шли, камеры OV шлют данные сразу, как к ним подключается тактирование и даже можно различить образы среди помех (может кому полезно будет)

Дело было в версии хала, не пользуйтесь халом от кокса, возможно, к прочтению этого сообшения кем-то эту проблему устронят, но лучше скачайте свежую версию с ST и проверьте свой код на ней
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.