智能车制作

 找回密码
 注册

扫一扫,访问微社区

查看: 12765|回复: 44
打印 上一主题 下一主题

K10DMA采集图像问题 摄像头OV7620

  [复制链接]

7

主题

149

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1404
QQ
威望
656
贡献
612
兑换币
12
注册时间
2011-3-1
在线时间
68 小时
跳转到指定楼层
1#
发表于 2012-4-12 23:01:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
首先我采用的是摄像头的PCLK信号作为DMA的触发信号。
然后发现这个信号触发不了,用示波器一看,发现PCLK出来的是个三角波,而且周期是74ns.
所以触发不了,也是很正常的。

然后我就直接将HREF行中断信号作为触发DMA的请求信号。因为来一个行中断,这个时候就应该用DMA传送一行数据了。
结果我发现还是不行。因为还要使能通道:DMA_ERQ|=DMA_ERQ_ERQ0_MASK;//使能通道0硬件DMA请求

这就有问题了,因为一个是DMA的中断触发,和这个使能是个什么样的关系呢。
为了采到数据,我直接在主函数中先执行DMA_ERQ|=DMA_ERQ_ERQ0_MASK;
然后我始终只能采回来一行数据。
求解,该怎么做?

附上代码吧
/*
* ImageAcquisition.h
*
*  Created on: 2012-3-27
*      Author: damon
*/
#ifndef IMAGE_ACQUISITION_H
#define IMAGE_ACQUISITION_H
#include "derivative.h" /* include peripheral declarations */
#define ENDROW 240        //OV7620,每场240行
#define  H 27
#define  V 160
typedef unsigned char  uint8;  /*  8 bits */
typedef unsigned short int uint16; /* 16 bits */
typedef unsigned long int uint32; /* 32 bits */
typedef char       int8;   /*  8 bits */
typedef short int         int16;  /* 16 bits */
typedef long int      int32;  /* 32 bits */

unsigned int row=0;//摄像头行计数,最大240
uint8 video[H][V];//存放数据数组
unsigned int imagerow=0;//采集行计数,最大H
unsigned int const data_table[H]={46,53,68,83,97,109,120,130,139,147,
                                  155,163,170,178,186,192,197,202,206,210,
                                  214,218,222,225,228,231,234};//需采集数据的行,2cm一行实际测得
void caiji_IO_init()
{
SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK | SIM_SCGC5_PORTB_MASK ;
PORTA_PCR4= PORT_PCR_MUX(1)|PORT_PCR_IRQC(9);  //A4引脚设置为GPIO模式,上升沿中断,行中断
PORTB_PCR10= PORT_PCR_MUX(1)|PORT_PCR_IRQC(10); //B10引脚设置为GPIO模式,下降沿中断,场中断
PORTA_PCR5=PORT_PCR_MUX(1)|PORT_PCR_IRQC(1); //A5引脚设置为GPIO模式,上升沿触发DMA请求

/*PTD0-PTD7 as GPIO input*/
PORTD_PCR0 = PORT_PCR_MUX(1); //PTD0 as open drain input
PORTD_PCR1 = PORT_PCR_MUX(1); //PTD1 as open drain input
PORTD_PCR2 = PORT_PCR_MUX(1); //PTD2 as open drain input
PORTD_PCR3 = PORT_PCR_MUX(1); //PTD3 as open drain input
PORTD_PCR4 = PORT_PCR_MUX(1); //PTD4 as open drain input
PORTD_PCR5 = PORT_PCR_MUX(1); //PTD5 as open drain input
PORTD_PCR6 = PORT_PCR_MUX(1); //PTD6 as open drain input
PORTD_PCR7 = PORT_PCR_MUX(1); //PTD7 as open drain input
GPIOD_PDDR = 0x0;    //PTD0-PED7 as GPIO input;
}
void DMA0_Init(void)
{
SIM_SCGC6|=SIM_SCGC6_DMAMUX_MASK;//打开DMA多路复用器时钟
SIM_SCGC7|=SIM_SCGC7_DMA_MASK;//打开DMA模块时钟
DMAMUX_CHCFG0=DMAMUX_CHCFG_SOURCE(49);//DMA通道0对应49号DMA请求,即PORTA


DMA_TCD0_CITER_ELINKNO=DMA_CITER_ELINKNO_CITER(V);//当前主循环次数,采集点数
DMA_TCD0_BITER_ELINKNO=DMA_BITER_ELINKNO_BITER(V);//起始主循环次数,采集点数
DMA_TCD0_SADDR=(uint32)&GPIOD_PDIR;//设置源地址GPIO口,PORTD


DMA_TCD0_SOFF=0;//每次传送源地址不变
//DMA_TCD1_NBYTES_MLOFFYES=DMA_NBYTES_MLOFFYES_NBYTES(1)+DMA_NBYTES_MLOFFNO_SMLOE_MASK+DMA_NBYTES_MLOFFYES_MLOFF(-4);//传送4字节
DMA_TCD0_NBYTES_MLNO=DMA_NBYTES_MLNO_NBYTES(1);//每次读取一字节
DMA_TCD0_SLAST=0;//主循环结束后源地址0回写tcd
DMA_TCD0_DLASTSGA=0;//主循环结束后目的地址0回写tcd
DMA_TCD0_DADDR=(uint32)video;//设置目的地址,video数组第一个元素
DMA_TCD0_DOFF=1;//每次写目的地址加1
DMA_TCD0_ATTR=DMA_ATTR_SSIZE(0)+DMA_ATTR_DSIZE(0);//源数据宽度8bit,目的数据宽度8bit
DMA_TCD0_CSR=DMA_CSR_DREQ_MASK;//DMA通道0主循环结束后停止硬件请求
DMA_TCD0_CSR|=DMA_CSR_INTMAJOR_MASK;//使能DMA0中断
DMAMUX_CHCFG0|=DMAMUX_CHCFG_ENBL_MASK;//DMA通道0使能

DMA_ERQ|=DMA_ERQ_ERQ0_MASK;//使能通道0硬件DMA请求  (我在初如化的时候来开启,这样才进了中断,不然不能进中断。因为我用HREF来触发DMA,而又要在DMA中才来开启使能,所以进不了中断。我想这应该是原因

}
void DMA_CHO_ISR(void)
{
DMA_INT|=DMA_INT_INT0_MASK;//清除通道0中断
row_F[imagerow]=1;//采集完成标志
imagerow++;
}
void enable_irq (int irq)
{
    int div;
    if (irq > 91) irq=91;//确定irq号为有效的irq号
    div = irq/32;//确定对应的寄存器号
    switch (div)
    {
     case 0x0:
              NVICICPR0 = 1 << (irq%32);
              NVICISER0 = 1 << (irq%32);
              break;
     case 0x1:
              NVICICPR1 = 1 << (irq%32);
              NVICISER1 = 1 << (irq%32);
              break;
     case 0x2:
              NVICICPR2 = 1 << (irq%32);
              NVICISER2 = 1 << (irq%32);
              break;
    }              
}
//-------------------------------------------------------------------------*
//函数名: disable_irq                                                      *
//功  能: 禁止irq中断                                                      *
//参  数: irq:irq号                *
//返  回: 无                                                               *
//说  明: irq号不是中断向量号                                              *
//-------------------------------------------------------------------------*
void disable_irq (int irq)
{
    int div;
   
    //确定irq号为有效的irq号
    if (irq > 91) irq=91;
   
    //确定对应的NVICISER
    div = irq/32;
   
    switch (div)
    {
     case 0x0:
               NVICICER0 = 1 << (irq%32);
              break;
     case 0x1:
              NVICICER1 = 1 << (irq%32);
              break;
     case 0x2:
              NVICICER2 = 1 << (irq%32);
              break;
    }              
}
void PORTB_ISR(void)//场中断,B10,下降沿中断
{
PORTA_PCR5|=PORT_PCR_ISF_MASK;//清除中断标志
DMA0_Init();
enable_irq(0);//使能DMA通道0完成中断
row=0;//初始化行
imagerow=0;//初始化采集行
enable_irq (87);//使能A口中断 ,A4行中断
}
void PORTA_ISR(void)
{
PORTA_PCR4|=PORT_PCR_ISF_MASK;//清除中断标志位
row++; //行计数
if(row==data_table[imagerow])//如果当前行数据应该采集
{
  DMA_ERQ|=DMA_ERQ_ERQ0_MASK;//使能通道0硬件DMA请求  
}
else if(row>=ENDROW) //一场完成,关闭行中断
{
  disable_irq (87);
    }
}
void Delay(unsigned int count)
{
unsigned int i;
for(;count > 0;count--)
  for(i = 0;i < 50000;i++);
}
#endif
//这个程序只能采集一行数据,求解解决方法

5

主题

315

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2729
QQ
威望
1332
贡献
539
兑换币
76
注册时间
2011-2-27
在线时间
429 小时
2#
发表于 2012-4-13 00:32:08 | 只看该作者
DMA_TCD0_NBYTES_MLNO=DMA_NBYTES_MLNO_NBYTES(1);//每次读取一字节
你用GPIOA05来当行触发DMA,每来一个行,DMA从PORTD口读回一字节!!!!!!!!!!!!!!!!一次触发CITER,BITER减一;
回复 支持 反对

使用道具 举报

5

主题

315

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2729
QQ
威望
1332
贡献
539
兑换币
76
注册时间
2011-2-27
在线时间
429 小时
3#
发表于 2012-4-13 00:34:35 | 只看该作者
void PORTA_ISR(void)
{
PORTA_PCR4|=PORT_PCR_ISF_MASK;//清除中断标志位
row++; //行计数
if(row==data_table[imagerow])//如果当前行数据应该采集
{
  DMA_ERQ|=DMA_ERQ_ERQ0_MASK;//使能通道0硬件DMA请求  
}
else if(row>=ENDROW) //一场完成,关闭行中断
{
  disable_irq (87);
    }
}
这个使用在PCLK触发DMA传输一个像素点用的。
回复 支持 反对

使用道具 举报

7

主题

149

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1404
QQ
威望
656
贡献
612
兑换币
12
注册时间
2011-3-1
在线时间
68 小时
4#
 楼主| 发表于 2012-4-13 00:44:44 | 只看该作者
luojihao24669 发表于 2012-4-13 00:34
void PORTA_ISR(void)
{
PORTA_PCR4|=PORT_PCR_ISF_MASK;//清除中断标志位

然后现在的问题是OV7620出来的是一个三角波,而且周期才74NS,根本就触发不了DMA中断,该怎么办呢?懂你的意思了,太感谢 了。
回复 支持 反对

使用道具 举报

5

主题

315

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2729
QQ
威望
1332
贡献
539
兑换币
76
注册时间
2011-2-27
在线时间
429 小时
5#
发表于 2012-4-13 00:46:58 | 只看该作者
如果你想《每一个行中断来了,在中断了判断是否是所要采的行,再开启DMA采集一行数据(没用到PCLK步)《的话,你就要把DMA的硬件触发关了,且要把DMA_TCD0_NBYTES_MLNO=DMA_NBYTES_MLNO_NBYTES(1);//每次读取一字节
设置成你每行要采集的点数。
此方法有很大局限性,要求DMA 采集速度慢,或者像素输出快于DMA最大的速度。这样才回来的图像才有用。否则,会因为DMA速度太快,将一个像素点的值采了好几遍,造成图像拉升。
此方法与以前参赛队在行中段一次采集n个点的思路一样,节省的时间是直接DMA采一行的时间。同步不可能做得很好。噪点会有点
回复 支持 反对

使用道具 举报

5

主题

315

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2729
QQ
威望
1332
贡献
539
兑换币
76
注册时间
2011-2-27
在线时间
429 小时
6#
发表于 2012-4-13 00:53:59 | 只看该作者
lemon~cmc 发表于 2012-4-13 00:44
然后现在的问题是OV7620出来的是一个三角波,而且周期才74NS,根本就触发不了DMA中断,该怎么办呢?懂你的 ...

74ns---------13多M,我K60 100M 主频采20M的信号都可以。如果你想用PCLK同步触发DMA的话,要么你7620用低分辨模式,这时PCLK有8M多吧,够DMA的了。或者你超频,DMA的速度提高。你没必要用那么高的分辨率,你还是用低分辨率模式采集好一些。
回复 支持 反对

使用道具 举报

7

主题

149

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1404
QQ
威望
656
贡献
612
兑换币
12
注册时间
2011-3-1
在线时间
68 小时
7#
 楼主| 发表于 2012-4-13 00:56:53 | 只看该作者
也就是PCLK触发一次,DMA就读取一个字节。这样就不会造成因DMA的速度过快而导致图像被拉升对吧, 但是按理说PCLK出来的应该是方波才对呀,为什么7620出来的是三角波,可以改嘛?还有一点我没有很明白的就是每进一次行中断就要去使能DMADMA_ERQ|=DMA_ERQ_ERQ0_MASK;//  是不是某个时候硬件会自动关闭了呢?会是什么时候呢?如果是传输完一个字节就关闭的话,应该是不对的,如果是这样的话,每一行不是只能采一个点了。
回复 支持 反对

使用道具 举报

7

主题

149

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1404
QQ
威望
656
贡献
612
兑换币
12
注册时间
2011-3-1
在线时间
68 小时
8#
 楼主| 发表于 2012-4-13 01:01:17 | 只看该作者
luojihao24669 发表于 2012-4-13 00:53
74ns---------13多M,我K60 100M 主频采20M的信号都可以。如果你想用PCLK同步触发DMA的话,要么你7620用低 ...

打算明天超频到180M试一下,还是不行的话,只能焊个PCLK的分频电路了。加个QQ吧,兄弟,有问题也好请教你。
回复 支持 反对

使用道具 举报

7

主题

293

帖子

0

精华

常驻嘉宾

Rank: 8Rank: 8

积分
3350
威望
1454
贡献
676
兑换币
140
注册时间
2011-8-12
在线时间
610 小时
9#
发表于 2012-4-13 10:29:46 | 只看该作者
我的是超频到了180M,没有用PCLK,可以先直接用DMA采集,采集完一行,立刻用另外一路DMA进行减样传输
回复 支持 反对

使用道具 举报

0

主题

43

帖子

0

精华

高级会员

Rank: 4

积分
501
威望
309
贡献
82
兑换币
2
注册时间
2011-9-25
在线时间
55 小时
10#
发表于 2012-4-13 14:57:31 | 只看该作者
哥们 你的主函数呢?要超频呢
回复 支持 反对

使用道具 举报

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

本版积分规则

关于我们|联系我们|小黑屋|智能车制作 ( 黑ICP备2022002344号

GMT+8, 2024-12-27 14:36 , Processed in 0.164175 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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