2026-06-01 2:28 PM
Hi all,
I'm having a go at programming on the STM32N6570-DK. My goal final goal for this little project is to show the difference in pixel values between the first frame and current frame. This is usually done in vision systems to "filter" out the static objects. I've simplified this project to merely taking 2 snapshots, saving them on 2 RAM locations, calculating the difference between the two snapshots and saving it on a 3rd RAM location. My code is based on the following example codes to start the project:
So far I've successfully taken 2 snapshots and saved them on 2 locations. I'm trying to take a copy on of a snapshot on the 3rd location, but it fails, because when I try to show it on the LCD screen the screen is black. I'd appreciate any pointers to relevant documentation, explanation or code snippets to make this work.
Here is the code, it basically runs the "DCMIPP_SnapshotDecimationMode" example, except I've added hdma2d and a button to control the image shown on the screen.
DMA2D_HandleTypeDef hdma2d;
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
ISP_AppliHelpersTypeDef appliHelpers = {0};
DCMIPP_DecimationConfTypeDef pDecConfig = {0};
uint32_t pitch_value ; /* Number of bytes per line */
/* USER CODE END 1 */
/* Enable the CPU Cache */
/* Enable I-Cache---------------------------------------------------------*/
SCB_EnableICache();
/* Enable D-Cache---------------------------------------------------------*/
SCB_EnableDCache();
/* MCU Configuration--------------------------------------------------------*/
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
BSP_LED_Init(LED_GREEN);
BSP_LED_Init(LED_RED);
/* UART log */
#if USE_COM_LOG
COM_InitTypeDef COM_Init;
/* Initialize COM init structure */
COM_Init.BaudRate = 115200;
COM_Init.WordLength = COM_WORDLENGTH_8B;
COM_Init.StopBits = COM_STOPBITS_1;
COM_Init.Parity = COM_PARITY_NONE;
COM_Init.HwFlowCtl = COM_HWCONTROL_NONE;
BSP_COM_Init(COM1, &COM_Init);
if (BSP_COM_SelectLogPort(COM1) != BSP_ERROR_NONE)
{
Error_Handler();
}
#endif
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_DCMIPP_Init();
/* Initialize the IMX335 Sensor ----------------------------- */
IMX335_Probe(IMX335_R2592_1944, IMX335_RAW_RGGB10);
/* USER CODE BEGIN 2 */
/* Fill init struct with Camera driver helpers */
appliHelpers.GetSensorInfo = GetSensorInfoHelper;
appliHelpers.SetSensorGain = SetSensorGainHelper;
appliHelpers.GetSensorGain = GetSensorGainHelper;
appliHelpers.SetSensorExposure = SetSensorExposureHelper;
appliHelpers.GetSensorExposure = GetSensorExposureHelper;
/* Initialize the Image Signal Processing middleware */
if(ISP_Init(&hcamera_isp, &hdcmipp, 0, &appliHelpers, ISP_IQParamCacheInit[0]) != ISP_OK)
{
Error_Handler();
}
if (HAL_DCMIPP_CSI_PIPE_Start(&hdcmipp, DCMIPP_PIPE1, DCMIPP_VIRTUAL_CHANNEL0 , BUFFER_ADDRESS_FIRST, DCMIPP_MODE_CONTINUOUS) != HAL_OK)
{
Error_Handler();
}
/* Start the Image Signal Processing */
if (ISP_Start(&hcamera_isp) != ISP_OK)
{
Error_Handler();
}
/* give the ISP 60 frames to set color balance */
while(NbMainFrames < 60)
{
BSP_LED_Toggle(LED_GREEN);
if (ISP_BackgroundProcess(&hcamera_isp) != ISP_OK)
{
BSP_LED_Toggle(LED_RED);
}
}
NbMainFrames = 0;
/* stop the acquisition */
HAL_DCMIPP_CSI_PIPE_Stop(&hdcmipp, DCMIPP_PIPE1, DCMIPP_VIRTUAL_CHANNEL0);
LCD_Init(FRAME_WIDTH, FRAME_HEIGHT);
/* --- ADD THIS: Initialize PC13 for the Button --- */
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL; // Change to GPIO_PULLUP if your button grounds the pin
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* Set an initial state tracker for the buffers */
uint8_t current_buffer_is_perma = 1; // Since LCD_Init sets it to BUFFER_ADDRESS_SECOND initially
/* USER CODE END 2 */
if (HAL_DCMIPP_CSI_PIPE_Start(&hdcmipp, DCMIPP_PIPE1, DCMIPP_VIRTUAL_CHANNEL0 , BUFFER_ADDRESS_FIRST, DCMIPP_MODE_SNAPSHOT) != HAL_OK)
{
Error_Handler();
}
while(NbMainFrames != 1);
NbMainFrames = 0;
HAL_Delay(1000);
pitch_value = (800 * 2) / 2;
pDecConfig.HRatio = DCMIPP_HDEC_1_OUT_2;
pDecConfig.VRatio = DCMIPP_VDEC_1_OUT_2;
HAL_DCMIPP_PIPE_SetDecimationConfig(&hdcmipp, DCMIPP_PIPE1, &pDecConfig);
HAL_DCMIPP_PIPE_EnableDecimation(&hdcmipp, DCMIPP_PIPE1);
HAL_DCMIPP_PIPE_SetPitch(&hdcmipp, DCMIPP_PIPE1, pitch_value);
/* Update LTDC Display window */
HAL_LTDC_SetWindowSize(&hltdc, FRAME_WIDTH/2 , FRAME_HEIGHT/2, LTDC_LAYER_1);
if (HAL_DCMIPP_CSI_PIPE_Start(&hdcmipp, DCMIPP_PIPE1, DCMIPP_VIRTUAL_CHANNEL0 , BUFFER_ADDRESS_FIRST, DCMIPP_MODE_SNAPSHOT) != HAL_OK)
{
Error_Handler();
}
while(NbMainFrames != 1);
NbMainFrames = 0;
HAL_Delay(1000);
pitch_value = (800 * 2) / 4;
pDecConfig.HRatio = DCMIPP_HDEC_1_OUT_4;
pDecConfig.VRatio = DCMIPP_VDEC_1_OUT_4;
HAL_DCMIPP_PIPE_SetDecimationConfig(&hdcmipp, DCMIPP_PIPE1, &pDecConfig);
HAL_DCMIPP_PIPE_EnableDecimation(&hdcmipp, DCMIPP_PIPE1);
HAL_DCMIPP_PIPE_SetPitch(&hdcmipp, DCMIPP_PIPE1, pitch_value);
/* Update LTDC Display window */
HAL_LTDC_SetWindowSize(&hltdc, FRAME_WIDTH/4 , FRAME_HEIGHT/4, LTDC_LAYER_1);
if (HAL_DCMIPP_CSI_PIPE_Start(&hdcmipp, DCMIPP_PIPE1, DCMIPP_VIRTUAL_CHANNEL0 , BUFFER_ADDRESS_FIRST, DCMIPP_MODE_SNAPSHOT) != HAL_OK)
{
Error_Handler();
}
HAL_Delay(1000);
if (HAL_DCMIPP_CSI_PIPE_Start(&hdcmipp, DCMIPP_PIPE1, DCMIPP_VIRTUAL_CHANNEL0 , BUFFER_ADDRESS_SECOND, DCMIPP_MODE_SNAPSHOT) != HAL_OK)
{
Error_Handler();
}
while(NbMainFrames != 1);
NbMainFrames = 0;
/* USER CODE END 2 */
BSP_PB_Init(BUTTON_USER1,BUTTON_MODE_GPIO);
//DMA2D INIT
/* USER CODE BEGIN DMA2D_Init 0 */
/* USER CODE END DMA2D_Init 0 */
/* USER CODE BEGIN DMA2D_Init 1 */
/* USER CODE END DMA2D_Init 1 */
__HAL_RCC_DMA2D_CLK_ENABLE();
hdma2d.Instance = DMA2D;
hdma2d.Init.Mode = DMA2D_M2M;
hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB565;
hdma2d.Init.OutputOffset = 0;
hdma2d.LayerCfg[1].InputOffset = 0;
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565;
hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
hdma2d.LayerCfg[1].InputAlpha = 0xFF;
if (HAL_DMA2D_Init(&hdma2d) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMA2D_ConfigLayer(&hdma2d, 1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN DMA2D_Init 2 */
/* USER CODE END DMA2D_Init 2 */
//DMA2D INIT END
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if (BSP_PB_GetState(BUTTON_USER1))
{
HAL_Delay(50);
if (BSP_PB_GetState(BUTTON_USER1))
{
BSP_LED_Toggle(LED_GREEN);
/* Swap the buffers tracker */
if (current_buffer_is_perma == 1)
{
HAL_LTDC_SetAddress(&hltdc, BUFFER_ADDRESS_FIRST, LTDC_LAYER_1);
current_buffer_is_perma = 2;
}
else if(current_buffer_is_perma == 2)
{
HAL_LTDC_SetAddress(&hltdc, BUFFER_ADDRESS_SECOND, LTDC_LAYER_1);
current_buffer_is_perma = 3;
}
else if(current_buffer_is_perma == 3)
{
HAL_DMA2D_Start(&hdma2d,
BUFFER_ADDRESS_FIRST,
BUFFER_ADDRESS_THIRD,
800,
480);
HAL_DMA2D_PollForTransfer(&hdma2d, 10);
HAL_LTDC_SetAddress(&hltdc, BUFFER_ADDRESS_THIRD, LTDC_LAYER_1);
current_buffer_is_perma = 1;
}
/* 3. Wait for the user to release the button.
Release means the pin goes back HIGH to GPIO_PIN_SET */
while (BSP_PB_GetState(BUTTON_USER1))
{
HAL_Delay(10);
}
}
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}The code below shows how my buffers are defined:
#define FRAME_WIDTH 800
#define FRAME_HEIGHT 480
#define FRAME_BUFFER_SIZE (FRAME_WIDTH * FRAME_HEIGHT*2)
#define BUFFER_ADDRESS_FIRST 0x34200000
#define BUFFER_ADDRESS_SECOND (BUFFER_ADDRESS + FRAME_BUFFER_SIZE)
#define BUFFER_ADDRESS_THIRD BUFFER_ADDRESS - FRAME_BUFFER_SIZEI'm looking forward to your suggestions!
We’re moving the ST Community to a new platform to give you a better and more reliable community experience.