OpenEdv-开源电子网

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

最近在做无FIFO的OV7670的DMA方式 ,如何实现在定时器开启的一瞬间就使DMA传输

[复制链接]

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
发表于 2015-5-10 15:54:49 | 显示全部楼层 |阅读模式
5金钱
因为用的是f103zet6,没有dcmi功能,用io口直接抓取OV7670输出数据不太理想,因此想尝试DMA方式

对定时器和DMA不是很熟练,想实现在HREF上升沿来到的瞬间,开启定时器使DMA传输320*2个数据

但是不知道如何设置让定时器一开启就使DMA传输数据,求帮助   采用的是TIM3的通道1

void TIM3_Init(u16 arr,u16 psc)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

    TIM_TimeBaseStructure.TIM_Period = arr;  
    TIM_TimeBaseStructure.TIM_Prescaler =psc;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
 
    //TIM_Cmd(TIM3, ENABLE); 
                            
}

void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cmar)
{
     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  
    
  DMA_DeInit(DMA_CHx); 
    
    DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)&GPIOC->IDR&0xff;  //DMA外设数据寄存器的基地址   PC0~7
    DMA_InitStructure.DMA_MemoryBaseAddr = cmar; 
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize = 640 ; 
 
    
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; 
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; 
    DMA_Init(DMA_CHx, &DMA_InitStructure); 
          
}

void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
{
    DMA_Cmd(DMA_CHx, DISABLE ); 
     DMA_SetCurrDataCounter(DMA_CHx,640);
     DMA_Cmd(DMA_CHx, ENABLE);
}      

u8 row[320][2];
TIM3_Init(20-1,7200-1);         //重载数和分频系数不知如何设置,因为并不需要,需要的只是定时器一开启就使DMA传输  是否只需要定时器频率小于HREF频率?
MYDMA_Config(DMA1_Channel6,(u32)row);
TIM_DMACmd(TIM3,TIM_DMA_CC1,ENABLE);
外部输入中断函数
{    
    TIM_Cmd(TIM3, ENABLE); 
    TIM3->CNT=0x13;
     MYDMA_Enable(DMA_Channel6);
     while(DMA_GetFlagStatus(DMA1_FLAG_TC6)==RESET);    //等待DMA传输完成
  
          DMA_ClearFlag(DMA1_FLAG_TC6);
      
       TIM_Cmd(TIM3, DISABLE);
}

while(1){};

不知道这样设置是否可行?另外好像定时器关闭后再开启不会重载初值


最佳答案

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

以下是OV2640 STM32直驱的关键代码。 dma.c: [mw_shl_code=c,true]//SRAM --> LCD_RAM dma配置 //caddr:数据源地址 //16位,从SRAM传输到LCD_RAM. void MYDMA_SRAMLCD_Init(u32 caddr) { RCC->AHBENR|=1<<1; //开启DMA2时钟 DMA2_Channel5->CPAR=caddr; //DMA2,源存储器地址 DMA2_Channel5->CMAR=(u32)&LCD->LCD_RAM; //目标地址为LCD_RAM DMA2_Channel5->CNDTR=0; //DMA2, ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-5-10 15:54:50 | 显示全部楼层
以下是OV2640 STM32直驱的关键代码。
dma.c:
[mw_shl_code=c,true]//SRAM --> LCD_RAM dma配置 //caddr:数据源地址 //16位,从SRAM传输到LCD_RAM. void MYDMA_SRAMLCD_Init(u32 caddr) { RCC->AHBENR|=1<<1; //开启DMA2时钟 DMA2_Channel5->CPAR=caddr; //DMA2,源存储器地址 DMA2_Channel5->CMAR=(u32)&LCD->LCD_RAM; //目标地址为LCD_RAM DMA2_Channel5->CNDTR=0; //DMA2,传输数据量,暂定为0 DMA2_Channel5->CCR=0X00000000; //复位 DMA2_Channel5->CCR|=0<<4; //从外设读 DMA2_Channel5->CCR|=0<<5; //普通模式 DMA2_Channel5->CCR|=1<<6; //外设地址增量模式 DMA2_Channel5->CCR|=0<<7; //存储器非增量模式 DMA2_Channel5->CCR|=1<<8; //外设数据宽度为16位 DMA2_Channel5->CCR|=1<<10; //存储器数据宽度16位 DMA2_Channel5->CCR|=1<<12; //中等优先级 DMA2_Channel5->CCR|=1<<14; //存储器到存储器模式(不需要外部请求) } //开启一次SRAM到LCD的DMA的传输 void MYDMA_SRAMLCD_Enable(void) { DMA2_Channel5->CCR&=~(1<<0); //关闭DMA传输 DMA2_Channel5->CNDTR=lcddev.width; //设置传输长度 DMA2_Channel5->CCR|=1<<0; //开启DMA传输 } [/mw_shl_code]
main函数:
[mw_shl_code=c,true]int main(void) { u8 res; u8 *pname; //带路径的文件名 u8 key; //键值 u8 sd_ok=1; //0,sd卡不正常;1,SD卡正常. u16 pixcnt=0; //像素统计 u16 linecnt=0; //行数统计 Stm32_Clock_Init(9); //系统时钟设置 uart_init(72,115200); //串口初始化为115200 delay_init(72); //延时初始化 usmart_dev.init(72); //初始化USMART LED_Init(); //初始化与LED连接的硬件接口 KEY_Init(); //初始化按键 LCD_Init(); //初始化LCD BEEP_Init(); //蜂鸣器初始化 W25QXX_Init(); //初始化W25Q128 my_mem_init(SRAMIN); //初始化内部内存池 exfuns_init(); //为fatfs相关变量申请内存 f_mount(fs[0],"0:",1); //挂载SD卡 f_mount(fs[1],"1:",1); //挂载FLASH. POINT_COLOR=RED; while(font_init()) //检查字库 { LCD_ShowString(30,50,200,16,16,"Font Error!"); delay_ms(200); LCD_Fill(30,50,240,66,WHITE);//清除显示 } Show_Str(30,50,200,16,"STM32F103 开发板",16,0); Show_Str(30,70,200,16,"OV2640照相机实验",16,0); Show_Str(30,90,200,16,"KEY0:拍照(bmp格式)",16,0); Show_Str(30,110,200,16,"KEY1:拍照(jpg格式)",16,0); Show_Str(30,130,200,16,"2015年4月16日",16,0); res=f_mkdir("0:/PHOTO"); //创建PHOTO文件夹 if(res!=FR_EXIST&&res!=FR_OK) //发生了错误 { Show_Str(30,150,240,16,"SD卡错误,无法拍照!",16,0); sd_ok=0; } ov2640_framebuf=mymalloc(SRAMIN,52*1024);//申请帧缓存 pname=mymalloc(SRAMIN,30); //为带路径的文件名分配30个字节的内存 while(!pname||!ov2640_framebuf) //内存分配出错 { Show_Str(30,150,240,16,"内存分配失败!",16,0); delay_ms(200); LCD_Fill(30,150,240,146,WHITE);//清除显示 delay_ms(200); } while(OV2640_Init()) //初始化OV2640 { Show_Str(30,150,240,16,"OV2640 错误!",16,0); delay_ms(200); LCD_Fill(30,150,239,206,WHITE); delay_ms(200); } Show_Str(30,170,200,16,"OV2640 正常",16,0); delay_ms(1500); //TIM6_Int_Init(10000,7199); //10Khz计数频率,1秒钟中断,屏蔽则不打印帧率 OV2640_RGB565_Mode(); //RGB565模式 OV2640_OutSize_Set(lcddev.width,lcddev.height); ov2640_speed_ctrl(); MYDMA_SRAMLCD_Init((u32)ov2640_framebuf); while(1) { while(OV2640_VSYNC) //等待帧信号 { key=KEY_Scan(0); //不支持连按 if(key==KEY0_PRES||key==KEY1_PRES) { LED1=0; //DS1亮 if(sd_ok) //SD卡正常才可以拍照 { if(key==KEY0_PRES) //BMP拍照 { camera_new_pathname(pname,0); //得到文件名 res=bmp_encode(pname,0,0,lcddev.width,lcddev.height,0); }else if(key==KEY1_PRES) //JPG拍照 { camera_new_pathname(pname,1); //得到文件名 res=ov2640_jpg_photo(pname); OV2640_OutSize_Set(lcddev.width,lcddev.height); ov2640_speed_ctrl(); } if(res)//拍照有误 { Show_Str(30,130,240,16,"写入文件错误!",16,0); }else { Show_Str(30,130,240,16,"拍照成功!",16,0); Show_Str(30,150,240,16,"保存为:",16,0); Show_Str(30+42,150,240,16,pname,16,0); BEEP=1; //蜂鸣器短叫,提示拍照完成 delay_ms(100); } }else //提示SD卡错误 { Show_Str(40,130,240,12,"SD卡错误!",12,0); Show_Str(40,150,240,12,"拍照功能不可用!",12,0); } LED1=1; //DS1灭 BEEP=0; //关闭蜂鸣器 delay_ms(1800); } } LCD_SetCursor(0,0); //设置坐标 LCD_WriteRAM_Prepare(); //开始写入GRAM linecnt=0; //行统计清零 pixcnt=0; //像素计数器清零 while(linecnt<lcddev.height) { while(OV2640_HREF) { while(OV2640_PCLK==0); ov2640_framebuf[pixcnt++]=OV2640_DATA; while(OV2640_PCLK==1); while(OV2640_PCLK==0); ov2640_framebuf[pixcnt++]=OV2640_DATA; while(OV2640_PCLK==1); } if(pixcnt) { MYDMA_SRAMLCD_Enable(); //启动DMA数据传输 pixcnt=0; linecnt++; } } ov_frame++; LED0=!LED0; } }[/mw_shl_code]



我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
 楼主| 发表于 2015-5-10 18:12:56 | 显示全部楼层
没人么。。。。。。
在线等、
回复

使用道具 举报

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
 楼主| 发表于 2015-5-10 18:56:25 | 显示全部楼层
快来人啊~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
回复

使用道具 举报

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
 楼主| 发表于 2015-5-10 20:11:36 | 显示全部楼层
自挽、、、0 00 0 0 00
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-5-10 22:25:14 | 显示全部楼层
定时器开启的时候,调用:MYDMA_Enable
可以吧
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
 楼主| 发表于 2015-5-11 20:20:55 | 显示全部楼层
回复【5楼】正点原子:
---------------------------------
DMA传输出来的数据不对,一直都在重复0111.....不知道为什么?。。。麻烦帮忙看看DMA设置是不是不错了?
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-5-12 00:14:23 | 显示全部楼层
回复【6楼】q1092840790:
---------------------------------
月底我发布一个STM32F103驱动OV2640的代码,到时候你参考下。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
 楼主| 发表于 2015-5-12 10:01:47 | 显示全部楼层
回复【7楼】正点原子:
---------------------------------
等月底,黄花菜都凉了。。。。我还是自己多尝试下吧。
麻烦原子哥了。。。
回复

使用道具 举报

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
 楼主| 发表于 2015-5-12 17:07:36 | 显示全部楼层
求人帮解决问题。。。。
while(DMA_GetFlagStatus(DMA1_FLAG_TC6)==RESET);    //等待DMA传输完成   这句的完成几乎是以秒为单位的
不是说DMA传输速率很快么。。。怎么这么慢?
回复

使用道具 举报

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
 楼主| 发表于 2015-5-12 22:08:33 | 显示全部楼层
回复【8楼】q1092840790:
---------------------------------
原子哥。。。你帮忙看下程序吧。。。实在是弄不出来。TFT显示的图像不对,看了下串口传出的数据完全不对

实验36 摄像头实验.rar

3.29 MB, 下载次数: 453

回复

使用道具 举报

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
 楼主| 发表于 2015-5-12 22:10:04 | 显示全部楼层
求广大朋友帮忙
回复

使用道具 举报

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
 楼主| 发表于 2015-5-12 23:32:25 | 显示全部楼层
回复【12楼】正点原子:
---------------------------------
原子哥。我的核心问题是触发DMA从外设(OV7670 .C0~7)传输数据到数组Row[640],得到图像信息不对.....而不是图像显示的问题。显示图像的功能已经实现了
经过修改DMA传输完成640个数据的频率已经跟行同步信号(HREF)一样了。但是传出来的信息不对


您这个是直接IO口抓取数据了吧?您实现的方式大概是IO口直抓数据传到SRAM,然后DMA传输SRAM到LCD->RAM

我现在在尝试的是DMA传输OV7670的数据到数组里,然后再在主程序里面将这个信息传到LCD->RAM

IO口直抓数据,然后直接传到LCD->RAM显示的方式我已经做到了...但就1帧每秒,处理图像 激光测距的精度不够
[mw_shl_code=c,true]//更新LCD显示 void camera_refresh(void) { u32 i,j; u16 color; LCD_Scan_Dir(U2D_L2R); //从上到下,从左到右 LCD_SetCursor(0x00,0x0000); //设置光标位置 LCD_WriteRAM_Prepare(); //开始写入GRAM while(OV7670_VSYNC==0);//0-1 while(OV7670_VSYNC==1);//1-0 只有在VSYNC为低时,才写入数据 //240*320=76800 每个像素用RGB565表示,即每个像素占两个字节,一个像素需传递两次 for(i=0;i<240;i++) { while(OV7670_HREF==0);//0-1 只有在HERE为高时,才传递数据 for(j=0;j<320;j++) { //读取高8位 while(OV7670_PCLK==0); //0-1 数据在PCLK上升沿保持稳定,在此时读取数据 color=GPIOC->IDR&0XFF; //读数据 while(OV7670_PCLK==1); //1-0 //左移高八位 color<<=8; //读取低8位 while(OV7670_PCLK==0); //0-1 color|=GPIOC->IDR&0XFF; //读数据 while(OV7670_PCLK==1); //1-0 //显示LCD LCD->LCD_RAM=color; } while(OV7670_HREF==1); //1-0 } //ov_frame++; LCD_Scan_Dir(DFT_SCAN_DIR); //恢复默认扫描方向 } [/mw_shl_code]
上面这个是我实现IO直抓和直接显示的函数


回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-5-12 23:44:28 | 显示全部楼层
回复【13楼】q1092840790:
---------------------------------
DMA从IO读取数据到内存,不好做哦。
论坛貌似有个高手搞出来过,不过我没做过。
你搜索下看看能不能找到吧
DMA读取IO,你必须在PCLK的控制下读取,核心问题就是,如何一个PCLK,触发一次DMA,我想到的的办法是利用定时器的外部触发模式,联和DMA,通过IO触发定时器,定时器触发dma,从而间接实现IO控制DMA,想法是这样,不过我没实际测试,得你自己研究了。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
 楼主| 发表于 2015-5-12 23:53:49 | 显示全部楼层
回复【14楼】正点原子:
---------------------------------
我实现的思路是HREF的上升沿中断开启定时器触发DMA一次传输320*2个数据。。当然我失败了,传出来的数据不对
在IO直抓实现后,一个礼拜都在尝试DMA读IO的方式....只发现当定时器的频率高到一定程度时,DMA完成320*2个数据的传输频率是跟HREF一样的,当定时器的频率低时,相应的DMA完成320.*2个数据传输的频率就特别低

定时器触发DMA传输,DMA传输每个数据的频率与定时器频率相关?
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-5-13 23:32:55 | 显示全部楼层
这样不行的
必须在PCLK的控制下采集,你直接靠HREF,铁定失败。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
 楼主| 发表于 2015-5-14 09:57:22 | 显示全部楼层
回复【16楼】正点原子:
---------------------------------
对于您贴出来的如上程序,有几点疑惑。。。
1: LCD_Scan_Dir(U2D_L2R);    为什么在一帧图像开始传输之前,没设置LCD扫描模式?  相应的在传输完之后 LCD_Scan_Dir(DFT_SCAN_DIR);恢复默认扫描模式
2:while(linecnt<lcddev.height)   //240    
        {
            while(OV2640_HREF)
            {  
                while(OV2640_PCLK==0);
                ov2640_framebuf[pixcnt++]=OV2640_DATA;   //这部分我修改成Row[pixcnt++]=GPIOC->IDR&0XFF;  
                while(OV2640_PCLK==1);
                                                                                    //    Row[pixcnt]<<=8;
                while(OV2640_PCLK==0);
                ov2640_framebuf[pixcnt++]=OV2640_DATA;    //     Row[pixcnt]|=GPIOC->IDR&0XFF;

                while(OV2640_PCLK==1);        
            }  
            if(pixcnt)          既然pixcnt为像素点统计,那么假设在QVGA情况下  此处应该设为if(pixcnt==320)吧?一行应为320个像素点
            {
                MYDMA_SRAMLCD_Enable();    //开启DMA
                pixcnt=0;
                linecnt++;
            }
        }
3:您的思路是把SRAM的图像信息用DMA传到LCD    源存储地址为ov2640_framebuf
     DMA2_Channel5->CCR|=0<<4;      //从外设读    不应该是从存储器外设的LCD_RAM么?
     DMA2_Channel5->CCR|=1<<6;      //外设地址增量   //在LCD_Scan_Dir(U2D_L2R); 模式下,貌似LCD->LCD_RAM会自动增量
     DMA2_Channel5->CCR|=0<<7;         //存储器地址不增量   存储器地址应该是增量才对? ov2640_framebuf[pixcnt] 
     DMA2_Channel5->CCR|=1<<14;                 //存储器到存储器模式(不需要外部请求)     源存储地址到LCD_RAM,两个都是存储器,是这样理解吗?
4.CPAR是外设地址寄存器,CMAR为存储器地址寄存器。。。CPAR对应ov2640_framebuf[pixcnt]  数组,CMAR对应LCD_RAM?
回复

使用道具 举报

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
 楼主| 发表于 2015-5-14 16:30:06 | 显示全部楼层
回复【16楼】正点原子:
---------------------------------
谢谢原子哥提供的sram到LCD_RAM的思路。但我感觉的您的程序部分地方问题很大,我根据自己的理解进行修改,已经弄出来了   但比较遗憾的是感觉帧数4帧一秒仍然上不去

我对XCLK执行 RCC_MCOConfig(RCC_MCO_HSE  ); 应该是给了它8M的频率,示波器实测也是8M
{0x11, 0x04},   //内部时钟分频       不能再往下调了,再调的话,图像色彩失真
{0x6b, 0x40},//PLL*4   这个是输入时钟*4么?  是不是意味着我输入时钟为8M,实际用的为32M,在经过上面0x11寄存器配置   实际用的时钟为6.4M?
其余寄存器配置均按照您的f103的摄像头试验配置
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-5-14 22:11:39 | 显示全部楼层
回复【17楼】q1092840790:
---------------------------------
1,不需要设置,因为我用的是OV2640,输出图像就是从左到右,从上到下的方式。
2,height=320,我没说是240.一行是240个像素。
3,存储器到存储器也可以。
4,我这是存储器到存储器模式,CPAR对应源地址,CMAP对应目标地址。

回复【18楼】q1092840790:
---------------------------------
实测无问题。
我用的2640自带晶振,所以不存在你说的XCLK问题了。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
 楼主| 发表于 2015-5-15 17:17:36 | 显示全部楼层
回复【19楼】正点原子:
---------------------------------
16楼提出的问题是由于2640跟7670的差别导致的,我已经按照7670的标准重新改过,并且成功输出图像了。

现在就是比较纠结帧数问题(现在的设置大概一秒4、5帧的样子)。。。

首先比较疑惑的是,为什么带fifo的摄像头帧数可以高到10帧左右,采用IO直抓直显却只有1帧不到,前者跟后者均是读出数据之后,直接写给LCD_RAM,只不过一个是从fifo里半个像素的读,一个是直接从IO口半个像素的读,帧数却有这么大的差距?

现在采用的IO直抓,然后DMA传到显存的方式,因为CPU不用再进行写操作,可以让帧数达到4、5帧左右,这说明IO直抓数据还是有那么快响应的,一个写到LCD_RAM的命令可以让帧数一下拉下这么大?

正点原子OV7670的内置晶振是12M的,{0x11, 0x00}不分频,{0x6b, 0x40},内置时钟4倍频,那么pclk应该是48M了,因为缓存fifo的存在,可以使用这么高的工作频率,同时因为fifo的存在会导致帧数从理论直接降到一半。   

您现在的2640大概同样带的12M晶振,如果上面提到的两个寄存器仍然这样设置的话,那么您2640的帧数又可以达到多少?
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-5-15 22:52:50 | 显示全部楼层
回复【20楼】q1092840790:
---------------------------------
我的OV2640,240*320输出分辨率的时候,7帧左右。
320*480的时候,3帧左右
480*800的时候,1帧不到。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-5-15 22:53:29 | 显示全部楼层
受限条件:STM32的IO读取速度不够快。
具体表现:提速就花屏...
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
 楼主| 发表于 2015-5-15 23:44:37 | 显示全部楼层
回复【22楼】正点原子:
---------------------------------
= = 我已经不指望提速了。。。。但我要对图像数据做处理的,但是一把处理的函数加进去,出来的图像就有问题了


while(1)
    {    
        LED1=!LED1;
        //camera_refresh();
        LCD_Scan_Dir(U2D_L2R);      
        LCD_SetCursor(0x00,0x0000);   
        LCD_WriteRAM_Prepare(); 
        while(OV7670_VSYNC==0);//0-1
        while(OV7670_VSYNC==1);//1-0    
        

        for(linecnt=0;linecnt<240;linecnt++)        
        {
            while(OV7670_HREF==0);
            for(pixcnt=0;pixcnt<320;pixcnt++)
            {
                while(OV7670_PCLK==0);
                Row[pixcnt]=GPIOC->IDR&0XFF;   
                while(OV7670_PCLK==1);
                Row[pixcnt]<<=8;
                while(OV7670_PCLK==0);  
                Row[pixcnt]|=GPIOC->IDR&0XFF;
                Row1[pixcnt]=Row[pixcnt];
                while(OV7670_PCLK==1);        
            }
            MYDMA_SRAMLCD_Enable();   
            PicHandle(linecnt,(unsigned int *)Row1);   //图像处理部分
            while(DMA_GetFlagStatus(DMA2_FLAG_TC5)==RESET);  
            DMA_ClearFlag(DMA2_FLAG_TC5);
            
        }
        LCD_Scan_Dir(DFT_SCAN_DIR);  
        TP_Drow_Touch_Point(120,160,RED);
        
    }      

心累到不行。。。
回复

使用道具 举报

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
 楼主| 发表于 2015-5-16 00:03:18 | 显示全部楼层
刚验证出来。。。PicHandle(linecnt,(unsigned int *)Row1);   这个函数处理时间大概4ms,将这个函数用delay_ms(4);代替。。。现象一模一样 。。
看来是不能在那个地方处理函数了,因为一处理,就会占用4ms时间,导致这段时间内的数据丢失。。。。。
但是定义Row[240][320]存储一帧数据的话、、、肯定因为内存不足。。。那我应该在显示完一帧数据之后处理图像信息,然而尝试将图像信存储到flash里面,会因为执行这个操作占用时间,导致IO数据丢失,所以这个思路也不行。。。。


最终途径只能在一帧传到LCD完之后,采取立即去LCD显存读取数据的方式,
for(linecnt=0;linecnt<240;linecnt++)
{
    for(pixcnt=0;pixcnt<320;pixcnt++)
    {
          LCD_SetCursor(0x00+linecnt,0x0000+pixcnt);
           color=LCD_RD_DATA();     
     }
}
不知道采用如上方式读取数据是否正确?
而且这样读取数据出来之后,由于空间有限,是不可能对整幅图像进行处理的,只有采用点扫描或者行扫描。。。。感觉真是悲剧
回复

使用道具 举报

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
 楼主| 发表于 2015-5-16 23:08:46 | 显示全部楼层
已解决,谢谢原子哥一直以来的耐心的答复
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-5-16 23:11:05 | 显示全部楼层
回复【25楼】q1092840790:
---------------------------------
呵呵,恭喜啊。
我们的OV7670摄像头模块,带FIFO版本,现在我调试,速度可以到30帧。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
 楼主| 发表于 2015-5-17 22:31:00 | 显示全部楼层
回复【26楼】正点原子:
---------------------------------
用到DMA传输到显存吧、、
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-5-17 23:04:25 | 显示全部楼层
回复【27楼】q1092840790:
---------------------------------
没,就IO抓。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

1

主题

10

帖子

0

精华

新手上路

积分
48
金钱
48
注册时间
2014-11-1
在线时间
3 小时
发表于 2015-7-30 10:43:37 | 显示全部楼层
请问有没有程序  可以给我参考一下吗  我也有个不带fifo的ov7670的摄像头,想学习一下     我用的是mini的
回复

使用道具 举报

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
 楼主| 发表于 2015-8-1 21:49:17 | 显示全部楼层
回复【29楼】中奥ol:
---------------------------------
关键的代码其实就一点点。。。。
void camera_refresh(void)
{
    u32 i,j;
     u16 color;    
        
        LCD_Scan_Dir(U2D_L2R);      
        LCD_SetCursor(0x00,0x0000);  
        LCD_WriteRAM_Prepare();   
    
        while(OV7670_VSYNC==0);//0-1
    while(OV7670_VSYNC==1);//1-0   

        //240*320=76800   
     
    for(i=0;i<240;i++)
    {
        while(OV7670_HREF==0);//0-1
        for(j=0;j<320;j++)        
        {
            
         
            while(OV7670_PCLK==0);            //0-1         
            color=GPIOC->IDR&0XFF;    //??????
            while(OV7670_PCLK==1);        //1-0
       
            color<<=8;  
         
            while(OV7670_PCLK==0);            //0-1
            color|=GPIOC->IDR&0XFF;  
            while(OV7670_PCLK==1);        //1-0
         
            LCD->LCD_RAM=color;    
        }   
        while(OV7670_HREF==1); //1-0
    }        
    LCD_Scan_Dir(DFT_SCAN_DIR); 
}   


XCLK给的是8MHz
回复

使用道具 举报

1

主题

12

帖子

0

精华

新手上路

积分
43
金钱
43
注册时间
2015-8-5
在线时间
2 小时
发表于 2015-8-6 10:41:22 | 显示全部楼层
回复【30楼】q1092840790:
---------------------------------
能不能把你们对ov7670的寄存器配置那一部分弄出来一下啊,我现在只能初始化成功,仿真可以到while(1)循环里面,可是可能不满足许多if循环,所以一直没有图像出来,这个摄像头的寄存器真的配置相当麻烦,
回复

使用道具 举报

1

主题

19

帖子

0

精华

新手上路

积分
43
金钱
43
注册时间
2014-10-29
在线时间
0 小时
发表于 2015-8-24 16:06:57 | 显示全部楼层
楼主 既然做出来了 能分享一下源码吗 我这里做不出来
回复

使用道具 举报

1

主题

19

帖子

0

精华

新手上路

积分
43
金钱
43
注册时间
2014-10-29
在线时间
0 小时
发表于 2015-8-24 20:05:48 | 显示全部楼层
做了好久终于做出来了  这是IO口直接抓取的程序 再战舰开发板上调成功!!!
感谢本帖帖主的支持!!!!!

无FIFO摄像头 IO抓取.zip

4.3 MB, 下载次数: 2163

回复

使用道具 举报

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
 楼主| 发表于 2015-8-29 11:09:50 | 显示全部楼层
回复【33楼】piaoran111999:
---------------------------------
你这个是我最开始弄的那种思路....IO口直接抓取,边抓边写到LCD里面。。。帧数特别慢。。。
我把我最后用的程序传上来。。。思路是IO口直接抓,然后用DMA传到LCD里,帧数要稍微高一点....里面LCD相关的代码要替换,因为我用的显示屏不是战舰的。。
在HARDWARE文件夹下的LCD全部替换成战舰的就好了

时间有点久了。。。IO口也不是直接对应的战舰的,要稍微修改下

摄像头实验.rar

3.58 MB, 下载次数: 5986

回复

使用道具 举报

1

主题

19

帖子

0

精华

新手上路

积分
43
金钱
43
注册时间
2014-10-29
在线时间
0 小时
发表于 2015-8-31 20:35:27 | 显示全部楼层
谢谢贴主  谢谢你的例子  现在我的程序全是改自你的  谢谢 谢谢  我打算用定时器的输入捕获作为DMA触发 这样可能做到真正的外部触发   能加个QQ吗 我的QQ:384710930  希望与你更深的交流
回复

使用道具 举报

9

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2015-4-29
在线时间
17 小时
 楼主| 发表于 2015-9-1 16:38:26 | 显示全部楼层
回复【35楼】piaoran111999:
---------------------------------
我是学生.....现在没在弄这个了,很多东西都忘了,没必要。     输入捕获你可以自己尝试一下
回复

使用道具 举报

1

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
163
金钱
163
注册时间
2016-3-2
在线时间
30 小时
发表于 2016-3-4 15:00:46 | 显示全部楼层
piaoran111999 发表于 2015-8-24 20:05
做了好久终于做出来了&nbsp; 这是IO口直接抓取的程序 再战舰开发板上调成功!!!
感谢本帖帖主的支持!! ...

为什么用keil打不开,用记事本可以打开,请问为什么,不懂
回复

使用道具 举报

11

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
68
金钱
68
注册时间
2016-7-17
在线时间
25 小时
发表于 2016-9-1 21:45:31 | 显示全部楼层
piaoran111999 发表于 2015-8-31 20:35
谢谢贴主&nbsp;&nbsp;谢谢你的例子&nbsp;&nbsp;现在我的程序全是改自你的&nbsp;&nbsp;谢谢&nbsp;谢谢&nbsp; ...

请问你做出来了吗?我一直做不成,理论是可以的,我看到有人做出来,只是没代码
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-30 03:03

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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