OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 17311|回复: 12

STM32F407+OV2640 DCMI+DMA双缓冲方式采集图像帧数据时数据丢失

[复制链接]

7

主题

75

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
401
金钱
401
注册时间
2012-12-30
在线时间
41 小时
发表于 2015-2-6 15:39:21 | 显示全部楼层 |阅读模式
5金钱
如题开启DCMI+DMA双缓冲方式采集图像(JPG格式),在DMA传输完成中断里将已存储数据的缓冲区的数据复制到CCM RAM(整张JPG数据的缓冲区)里,然后DCMI帧中断时再将最后一个缓冲区里的数据复制到CCM RAM。部分程序如下:
[mw_shl_code=c,true]#define DMA_DBM_BUF_SIZE 1024 // DMA单通道数据缓冲区大小,以字为单位, 双缓冲时使用 #define JPEG_BUF_WORD_SIZE (1024*16) // JPEG数据缓冲通道大小,以字为单位, __align(32) uint32_t jpegbuf[JPEG_BUF_WORD_SIZE] __attribute__((at(0x10000000))); // CCM RAM全部用来存放JPG数据 typedef struct { uint32_t* JpegBuf; //JPEG数据缓存 uint32_t JpegDataLength; JPEG_COLLECT_STATE JpegState; }JpegInfoStruct; JpegInfoStruct JpegInfo; JpegInfo.JpegBuf = jpegbuf; static uint32_t buf0[DMA_DBM_BUF_SIZE]; static uint32_t buf1[DMA_DBM_BUF_SIZE];[/mw_shl_code] [mw_shl_code=c,true]u8 dma_buf_sw[2] = {0}; void ov2640_dcmi_callback(void) { u32 i,j; u32 *p = &JpegInfo.JpegBuf[JpegInfo.JpegDataLength]; if(JpegInfo.JpegState == JPEG_COLLECT_STOPED) { j = DMA_DBM_BUF_SIZE - DMA_GetCurrDataCounter(DMA2_Stream1); if (DMA2_Stream1->CR & DMA_Memory_1) { for(i=0; i<j; i++) p = buf1; } else { for(i=0; i<j; i++) p = buf0; } JpegInfo.JpegDataLength += j; JpegInfo.JpegState = JPEG_COLLECT_FINISH; } } void ov2640_dma_callback(void) { u32 i; u32 *p = &JpegInfo.JpegBuf[JpegInfo.JpegDataLength]; if(JpegInfo.JpegDataLength < JPEG_BUF_WORD_SIZE) { if (DMA2_Stream1->CR & DMA_Memory_1) // buf0传输完成 {[/mw_shl_code] [mw_shl_code=c,true]            dma_buf_sw[0]++; for(i=0; i<DMA_DBM_BUF_SIZE; i++) { p = buf0; buf0 = 0; } } else // buffer1传输完成 {[/mw_shl_code] [mw_shl_code=c,true]            dma_buf_sw[1]++; for(i=0; i<DMA_DBM_BUF_SIZE; i++) { p = buf1; buf1 = 0; } } JpegInfo.JpegDataLength += DMA_DBM_BUF_SIZE; } else { JpegInfo.JpegState = JEPG_COLLECT_ERROR; printf("jpg buffer overflow!!!\n\r"); } } void OV2640_PHOTO_START() { JpegInfoReset();[/mw_shl_code] [mw_shl_code=c,true]    dma_buf_sw[0] = 0;     dma_buf_sw[1] = 0; //DCMI_Cmd(ENABLE); DMA2_Stream1->NDTR = (uint16_t)DMA_DBM_BUF_SIZE; DMA_Cmd(DMA2_Stream1, ENABLE); DCMI_CaptureCmd(ENABLE); JpegInfo.JpegState = JPEG_IS_COLLECTING; } void OV2640_PHOTO_END() { //DCMI_Cmd(DISABLE); DMA_Cmd(DMA2_Stream1, DISABLE); while(DMA_GetCmdStatus(DMA2_Stream1) != DISABLE); DCMI_CaptureCmd(DISABLE); JpegInfo.JpegState = JPEG_COLLECT_STOPED; } void DMA2_Stream1_IRQHandler(void) { if(DMA_GetFlagStatus(DMA2_Stream1,DMA_FLAG_TCIF1)!=RESET) // DMA2_Steam1,传输完成标志 { DMA_ClearFlag(DMA2_Stream1,DMA_FLAG_TCIF1); // 清除传输完成中断 ov2640_dma_callback(); // 读DMA通道数据 } } void DCMI_IRQHandler(void) { if (DCMI_GetITStatus(DCMI_IT_OVF) != RESET) // 置位 { DCMI_ClearITPendingBit(DCMI_IT_OVF); OV2640_PHOTO_END(); printf("there is a DCMI overflow interrupt.\r\n"); } else if (DCMI_GetITStatus(DCMI_IT_FRAME) != RESET) { DCMI_ClearITPendingBit(DCMI_IT_FRAME); OV2640_PHOTO_END(); ov2640_dcmi_callback(); } } // 返回0:OK,返回1:超时,返回2:文件头错误,返回3:文件尾错误 u8 wait_frame_data_ready(u32 timeout_ms) { u8 *pbuf; vu32 i,j,size; while(JpegInfo.JpegState != JPEG_COLLECT_FINISH); // 等待图像接收完成     printf("dma_buf_sw[0] = %d, dma_buf_sw[1] = %d\n\r", dma_buf_sw[0], dma_buf_sw[1]); { pbuf=(u8*)JpegInfo.JpegBuf; size = JpegInfo.JpegDataLength*4; for(i=0;i<size;i++)//查找 0XFF,0XD8 { if((pbuf==0XFF)&&(pbuf[i+1]==0XD8)) { j=i; break; } } if(i==size) { return 2;//没找到 0XFF,0XD8 } else { for(;i<size;i++) //查找FFD9 { if((pbuf==0XFF)&&(pbuf[i+1]==0XD9)) break; } if(i==size) { return 3; } else { JpegInfo.JpegDataLength = i + 2 - j; // 将图片数据长度转换成实际的字节长度 JpegInfo.JpegState = JPEG_DATA_VALID; return 0; } } } } void OV2640_DCMI_INIT(void) { DCMI_InitTypeDef DCMI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; camera_dcmi_io_init(); camera_power_control(DISABLE); delay_ms(5); camera_power_control(ENABLE); delay_ms(10); /* Enable DCMI clock */ RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE); /* DCMI configuration *******************************************************/ DCMI_DeInit(); DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_Continuous;//连续模式 ===================== DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;//全帧捕获 DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;//8位数据格式 DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_Low;// HSYNC 低电平有效 DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Rising;//PCLK 上升沿有效 DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;//硬件同步HSYNC,VSYNC DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_Low;//VSYNC 低电平有效 DCMI_Init(&DCMI_InitStructure); DCMI_JPEGCmd(ENABLE); NVIC_InitStructure.NVIC_IRQChannel = DCMI_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0xF; //抢占优先级1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化NVIC寄存器 /* DCMI Interrupts config ***************************************************/ DCMI_ITConfig(DCMI_IT_FRAME, ENABLE); DCMI_ITConfig(DCMI_IT_OVF, ENABLE); DCMI_ITConfig(DCMI_IT_ERR, ENABLE); DCMI_Cmd(ENABLE); // 可以始终保持使能状态 } void OV2640_DMA_INIT(uint32_t DmaMemBaseAddr0, uint32_t DmaMemBaseAddr1, uint32_t DmaMemSize) { DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; /* Enable DMA2 clock */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); /* DMA2 Stream1 Configuration */ DMA_DeInit(DMA2_Stream1); while (DMA_GetCmdStatus(DMA2_Stream1) != DISABLE) {} DMA_InitStructure.DMA_Channel = DMA_Channel_1; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&DCMI->DR); DMA_InitStructure.DMA_Memory0BaseAddr = DmaMemBaseAddr0; // 目标地址0 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_BufferSize = DmaMemSize; 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_VeryHigh; 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(DMA2_Stream1, &DMA_InitStructure); if (DmaMemBaseAddr1) // 是否开启双缓冲 { // 通道2基地址 第一个被使用的缓冲通道 DMA_DoubleBufferModeConfig(DMA2_Stream1, DmaMemBaseAddr1, DMA_Memory_0); // 下一个缓冲通道基地址 下一个要使用的缓冲通道号 DMA_MemoryTargetConfig(DMA2_Stream1, DmaMemBaseAddr1, DMA_Memory_1); DMA_DoubleBufferModeCmd(DMA2_Stream1, ENABLE); // 双缓冲模式 DMA_ITConfig(DMA2_Stream1, DMA_IT_TC, ENABLE); // 开启传输完成中断 NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0xD; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } } OV2640_DMA_INIT((uint32_t)buf0, (uint32_t)buf1, DMA_DBM_BUF_SIZE); [/mw_shl_code]

观察接收到的图片发现在图片底部有一条不正常的色带,调试发现在帧中断之前的最后一次DMA传输完成中断里应该复制进图片缓冲区的数据全为0,而且大小刚好是一个缓冲区的大小数据如下图





从图中可以看到最后一次DMA传输完成中断里面复制的数据全是0,图像尾数据正常。通过上面程序里面printf("dma_buf_sw[0] = %d, dma_buf_sw[1] = %d\n\r", dma_buf_sw[0], dma_buf_sw[1]);这句打印出来dma_buf_sw[1]比dma_buf_sw[0]大2(理论上dma_buf_sw[1]应该小于等于dma_buf_sw[0])。调试了好几天找不出原因,因此前来求助各位大神,先谢谢了。
附一张拍出来的图片

最佳答案

查看完整内容[请看2#楼]

 勉强算是把问题解决了,自己结贴了。 之前试过F429discovery的板子,用上面的程序依旧有问题。之前采用单缓冲+移动DMA指针方式采集图像是没有问题的(在DMA传输数据量小于64K次并且内存剩余空间足够的话不需要用双缓冲方式),大概方法如下: buffer; //图片缓冲区 dma_next_addr = 0; #define DMA_TRANSFER_LEN   xxx //单次DMA传输数据量 init() {     ......;     DMA_M0A ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

7

主题

75

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
401
金钱
401
注册时间
2012-12-30
在线时间
41 小时
 楼主| 发表于 2015-2-6 15:39:22 | 显示全部楼层
 勉强算是把问题解决了,自己结贴了。
之前试过F429discovery的板子,用上面的程序依旧有问题。之前采用单缓冲+移动DMA指针方式采集图像是没有问题的(在DMA传输数据量小于64K次并且内存剩余空间足够的话不需要用双缓冲方式),大概方法如下:
buffer[PICTURE_MAX_SIZE]; //图片缓冲区
dma_next_addr = 0;
#define DMA_TRANSFER_LEN   xxx //单次DMA传输数据量
init()
{
    ......;
    DMA_M0AR = (u32)buffer;
    DMA_M1AR = (u32)&buffer[DMA_TRANSFER_LEN];
    dma_next_addr = (u32)&buffer[DMA_TRANSFER_LEN*2];
    ......;
}

// DMA传输完成中断
dma_isr()
{
    if (DMA2_Stream1->CR & DMA_Memory_1) // buf0已满
    {
        DMA2_Stream1->M0AR = (u32)&buffer[dma_next_addr]; //修改DMA M0AR指针
    }
    else // buffer1传输完成
    {
        DMA2_Stream1->M1AR = (u32)&buffer[dma_next_addr]; //修改DMA M1AR指针
    }
    dma_next_addr += DMA_TRANSFER_LEN; // 移动指针
}
这种方法适合在DMA传输数据量大于64K的情况。之前用这种方法采集图像没有任何问题。但是现在的情况由于系统资源紧缺,不可能直接开辟一整块DMA缓冲区用来存放图片,同时也没有外部存储设备,即使有,传输速度也是个问题,考虑到CCM有64KB没有用到,于是打算将图片暂存到这里。但是CCM内存不支持DMA数据传输,因此还是需要到主内存中开辟缓冲区,通过DMA将数据先存到这个小缓冲区,然后复制到CCM中。由于用1楼的双缓冲方式,存在数据丢失问题,检查了n遍程序没有发现问题,也移植了原子哥的程序还是没解决问题,通过调试结果来看只能怀疑是DMA控制器在倒数第二次传输完成时没有切换指针。实在没有办法,既然DMA硬件不自动切换指针,那我就尝试手动软件切换指针吧,于是就用到了上面移动指针的方法。要让DMA_MxAR前后两轮传输(一轮指的是DMA_M0AR和DMA_M1AR指向的两个缓冲区传输完成)指向不同的地址至少需要3*DMA_TRANSFER_LEN的缓冲大小,最开始尝试用3倍的大小,发现奇数处理起来略麻烦,于是改成4倍大小,程序最开始分配一个DMA缓冲区,大小为4*DMA_TRANSFER_LEN,初始化时让DMA_M0AR和DMA_M1AR分别指向缓冲区的起始地址和1/4大小的地址,第一次传输完成中断时让DMA_M0AR指向2/4缓冲区的地址,第二次传输完成让DMA_M1AR指向3/4缓冲区的地址,第三次传输完成让DMA_M0AR指向缓冲区起始地址,第四次传输完成让DMA_M1AR指向1/4缓冲区的地址,如此循环。具体程序如下:

[mw_shl_code=c,true]static uint32_t *dma_buf; static uint32_t *pdmabuf[4] = {0}; static u8 dma_buf_sw[2] = {0}; static u16 dma_cnt = 0; #define DMA_TRANSFER_LEN 1280 #define DMA_BUF_SIZE (4*DMA_TRANSFER_LEN) /** * @brief DCMI帧中断回调函数 * @param None * @retval None */ void ov2640_dcmi_callback(void) { portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; u16 i,j; u32 *p = &JpegInfo.JpegBuf[JpegInfo.JpegDataLength]; u32 *q; if(JpegInfo.JpegState == JPEG_COLLECT_STOPED) { if(dma_cnt%4>=2) { q = pdmabuf[0]; } else { q = pdmabuf[2]; } if(!(dma_cnt&1)) { j = DMA_TRANSFER_LEN*2 - DMA_GetCurrDataCounter(DMA2_Stream1); } else { j = DMA_TRANSFER_LEN - DMA_GetCurrDataCounter(DMA2_Stream1); } for(i=0; i<j; i++) p = q; JpegInfo.JpegDataLength += j; JpegInfo.JpegState = JPEG_COLLECT_FINISH; if(camera_data_ready_mutex != NULL) { xSemaphoreGiveFromISR(camera_data_ready_mutex, &xHigherPriorityTaskWoken); if(xHigherPriorityTaskWoken != pdFALSE) { portEND_SWITCHING_ISR( xHigherPriorityTaskWoken ); } } } } /** * @brief DMA中断回调函数。 * @param None * @retval None */ void ov2640_dma_callback(void) { u32 *p = &JpegInfo.JpegBuf[JpegInfo.JpegDataLength]; u16 i,j = DMA_TRANSFER_LEN*2; u32 *q; dma_cnt++; if(JpegInfo.JpegDataLength < JPEG_BUF_WORD_SIZE) { if (DMA2_Stream1->CR & DMA_Memory_1) // buf0已满 { dma_buf_sw[0]++; if(dma_buf_sw[0] & 1) { DMA2_Stream1->M0AR = (u32)pdmabuf[2]; } else { DMA2_Stream1->M0AR = (u32)pdmabuf[0]; } } else // buffer1传输完成 { dma_buf_sw[1]++; if(dma_buf_sw[1] & 1) { DMA2_Stream1->M1AR = (u32)pdmabuf[3]; q = pdmabuf[0]; } else { DMA2_Stream1->M1AR = (u32)pdmabuf[1]; q = pdmabuf[2]; } for(i=0; i<j; i++) { p = q; q = 0; } JpegInfo.JpegDataLength += j; } } else { JpegInfo.JpegState = JEPG_COLLECT_ERROR; printf("jpg buffer overflow!!!\n\r"); } } void init(void) { ....; dma_buf = (u32 *)pvPortMalloc(DMA_BUF_SIZE*4);     if(dma_buf == NULL)     {         printf("jpeg dma buffer alloc failed!\n\r");         return;     }     JpegInfo.JpegBuf = jpegbuf;     pdmabuf[0] = dma_buf;     pdmabuf[1] = &dma_buf[DMA_BUF_SIZE/4];     pdmabuf[2] = &dma_buf[DMA_BUF_SIZE/2];     pdmabuf[3] = &dma_buf[DMA_BUF_SIZE/4*3]; ....; } 。。。不知道怎么退出代码框了,就在这里面编辑吧。 每次的数据复制都在一轮传输结束后,其实也可以在每次DMA传输完成中断里都进行数据复制的操作, 主要是为了化零为整和缩减代码量(其实也多不了多少),这样做也可能会有危险,担心被其它中断 程序打断造成数据还没复制完就被新的数据覆盖了?不过目前测试还没出现这种情况。 差不多就是这样,简直是曲线救国啊,虽然弄得比较复杂,但是在没有占用过多的系统开销的情况下 确实把问题解决了,程序也比较稳定。 如果有人遇到一样的问题,此贴可以作为一个参考,不过还是希望有人能帮忙找出问题根源所在。 [/mw_shl_code]
回复

使用道具 举报

7

主题

146

帖子

1

精华

高级会员

Rank: 4

积分
895
金钱
895
注册时间
2014-1-2
在线时间
156 小时
发表于 2015-2-6 19:43:08 | 显示全部楼层
我调试也也是这个结果,只有一小部分图像,其他的都是灰色。
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165377
金钱
165377
注册时间
2010-12-1
在线时间
2111 小时
发表于 2015-2-6 22:45:20 | 显示全部楼层
说明你中间处理的时候,右一次数据处理慢了,丢失了一次数据。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

7

主题

75

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
401
金钱
401
注册时间
2012-12-30
在线时间
41 小时
 楼主| 发表于 2015-2-7 16:28:49 | 显示全部楼层
回复【3楼】正点原子:
---------------------------------
可是我调低了摄像头的输出时钟速率和帧速率都没效果呢,每次的DMA传输完成中断里执行的都是一样的操作为什么就是最后一次有问题?即使是处理慢了那也不至于丢失一整个缓冲的数据吧,还是会有一部分数据存到CCM里,如果说是因为最后一次DMA传输完成之后数据还没来得及复制立刻又产生了DCMI帧中断,但是我设置的DMA传输完成中断的优先级要高于DCMI帧中断,也不至于被抢占吧。另外在
void ov2640_dma_callback(void)
{
    u32 i;
    u32 *p = &JpegInfo.JpegBuf[JpegInfo.JpegDataLength];
    
    if(JpegInfo.JpegDataLength < JPEG_BUF_WORD_SIZE)
    {
        if (DMA2_Stream1->CR & DMA_Memory_1) 
        {
            dma_buf_sw[0]++;
            for(i=0; i<DMA_DBM_BUF_SIZE; i++) 
            {
                p = buf0;
                buf0 = 0;
            }
        }
        else 
        {
            dma_buf_sw[1]++;
            for(i=0; i><DMA_DBM_BUF_SIZE; i++) 
            {
                p = buf1;
                buf1 = 0;
            }
        }
        JpegInfo.JpegDataLength += DMA_DBM_BUF_SIZE;
    } else {
        JpegInfo.JpegState = JEPG_COLLECT_ERROR;
        printf("jpg buffer overflow!!!\n\r");
    }
}
这里面最后一次DMA传输完成中断里确实执行了JpegInfo.JpegDataLength += DMA_DBM_BUF_SIZE;这一句(否则前面的那一段0的区域是不会保存的),说明前面的复制操作也应该是执行了的。这样想的话唯一能想到的原因就是在最后一次DMA传输完成中断时CT标志位没有自动切换到另一缓冲区?>
回复

使用道具 举报

7

主题

75

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
401
金钱
401
注册时间
2012-12-30
在线时间
41 小时
 楼主| 发表于 2015-2-7 19:43:39 | 显示全部楼层
测试将DMA缓冲区大小改为1KB,即 "#define DMA_DBM_BUF_SIZE    256" 后采集图像正常,再没有看到一大片0。而除此之外其他的大小一律会有前面的问题。虽然能这样能将就用,不过一是没找到问题的根源,二是缓冲区太小DMA频繁中断影响系统性能,因此还是希望有人能帮忙找出问题所在。
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165377
金钱
165377
注册时间
2010-12-1
在线时间
2111 小时
发表于 2015-2-7 21:58:57 | 显示全部楼层
回复【4楼】xijiele:
---------------------------------
请参考下我们综合实验的处理方式。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

7

主题

75

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
401
金钱
401
注册时间
2012-12-30
在线时间
41 小时
 楼主| 发表于 2015-2-8 17:41:44 | 显示全部楼层
回复【6楼】正点原子:
---------------------------------
移植了你们实验42的“照相机实验”的程序(其实之前的程序也基本是参照你们的程序写的),只修改了引脚定义,注释了与摄像头无关的代码,加了一小段测试程序,结果依然存在上述问题,看来我只能怀疑是硬件问题了,明天换一块板子试试
回复

使用道具 举报

0

主题

15

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2014-8-13
在线时间
0 小时
发表于 2015-3-15 10:06:27 | 显示全部楼层
回复【8楼】xijiele:
---------------------------------
你好,我用的是DMA双缓冲模式,图像传输完成后,我用DMA_IT_TCIF1中断一次,以便于我用串口打印出数据,验证SRAM缓冲区数据的正确性,是否是一幅图片的数据,可是在调试中发现,程序根本没有进入到DMA2_Stream1_IRQHandler(void)中断函数中去,整个程序执行下来串口终端上也没有我要的数据,这是为什么?求解答,谢谢!
越努力越幸运,优秀是一种习惯
回复

使用道具 举报

7

主题

75

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
401
金钱
401
注册时间
2012-12-30
在线时间
41 小时
 楼主| 发表于 2015-3-16 21:26:15 | 显示全部楼层
回复【9楼】小明去:
---------------------------------
这个可能原因就很多了,先检查你的DCMI配置、DMA配置、中断配置看有没有问题,具体可以参照原子哥的例程,如果确定软件没问题再拿示波器测下摄像头的时钟、VSYNC看是否正常
回复

使用道具 举报

0

主题

15

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2014-8-13
在线时间
0 小时
发表于 2015-3-17 09:05:19 | 显示全部楼层
回复【10楼】xijiele:
---------------------------------
谢谢提醒,是DMA的配置问题,已经改好了,谢谢!
越努力越幸运,优秀是一种习惯
回复

使用道具 举报

1

主题

5

帖子

0

精华

初级会员

Rank: 2

积分
59
金钱
59
注册时间
2015-5-1
在线时间
4 小时
发表于 2015-5-12 16:20:24 | 显示全部楼层
回复【11楼】小明去:
---------------------------------
请问你改了什么地方好像我的也是 没有进入到中断服务函数里
回复

使用道具 举报

2

主题

17

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2015-11-10
在线时间
0 小时
发表于 2015-11-14 17:18:06 | 显示全部楼层
楼主是在DCMI帧中断里又开了DMA数据中断,我如果想在一帧结束之后取每帧的像素点数值怎么办呢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-27 02:42

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表