智能车制作

标题: K10DMA采集图像问题 摄像头OV7620 [打印本页]

作者: lemon~cmc    时间: 2012-4-12 23:01
标题: K10DMA采集图像问题 摄像头OV7620
首先我采用的是摄像头的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
//这个程序只能采集一行数据,求解解决方法

作者: luojihao24669    时间: 2012-4-13 00:32
DMA_TCD0_NBYTES_MLNO=DMA_NBYTES_MLNO_NBYTES(1);//每次读取一字节
你用GPIOA05来当行触发DMA,每来一个行,DMA从PORTD口读回一字节!!!!!!!!!!!!!!!!一次触发CITER,BITER减一;
作者: luojihao24669    时间: 2012-4-13 00:34
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传输一个像素点用的。

作者: lemon~cmc    时间: 2012-4-13 00:44
luojihao24669 发表于 2012-4-13 00:34
void PORTA_ISR(void)
{
PORTA_PCR4|=PORT_PCR_ISF_MASK;//清除中断标志位

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

作者: luojihao24669    时间: 2012-4-13 00:46
如果你想《每一个行中断来了,在中断了判断是否是所要采的行,再开启DMA采集一行数据(没用到PCLK步)《的话,你就要把DMA的硬件触发关了,且要把DMA_TCD0_NBYTES_MLNO=DMA_NBYTES_MLNO_NBYTES(1);//每次读取一字节
设置成你每行要采集的点数。
此方法有很大局限性,要求DMA 采集速度慢,或者像素输出快于DMA最大的速度。这样才回来的图像才有用。否则,会因为DMA速度太快,将一个像素点的值采了好几遍,造成图像拉升。
此方法与以前参赛队在行中段一次采集n个点的思路一样,节省的时间是直接DMA采一行的时间。同步不可能做得很好。噪点会有点
作者: luojihao24669    时间: 2012-4-13 00:53
lemon~cmc 发表于 2012-4-13 00:44
然后现在的问题是OV7620出来的是一个三角波,而且周期才74NS,根本就触发不了DMA中断,该怎么办呢?懂你的 ...

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

作者: lemon~cmc    时间: 2012-4-13 00:56
也就是PCLK触发一次,DMA就读取一个字节。这样就不会造成因DMA的速度过快而导致图像被拉升对吧, 但是按理说PCLK出来的应该是方波才对呀,为什么7620出来的是三角波,可以改嘛?还有一点我没有很明白的就是每进一次行中断就要去使能DMADMA_ERQ|=DMA_ERQ_ERQ0_MASK;//  是不是某个时候硬件会自动关闭了呢?会是什么时候呢?如果是传输完一个字节就关闭的话,应该是不对的,如果是这样的话,每一行不是只能采一个点了。
作者: lemon~cmc    时间: 2012-4-13 01:01
luojihao24669 发表于 2012-4-13 00:53
74ns---------13多M,我K60 100M 主频采20M的信号都可以。如果你想用PCLK同步触发DMA的话,要么你7620用低 ...

打算明天超频到180M试一下,还是不行的话,只能焊个PCLK的分频电路了。加个QQ吧,兄弟,有问题也好请教你。
作者: 月下听蝉    时间: 2012-4-13 10:29
我的是超频到了180M,没有用PCLK,可以先直接用DMA采集,采集完一行,立刻用另外一路DMA进行减样传输
作者: hy890512    时间: 2012-4-13 14:57
哥们 你的主函数呢?要超频呢
作者: lemon~cmc    时间: 2012-4-13 21:35
hy890512 发表于 2012-4-13 14:57
哥们 你的主函数呢?要超频呢

超频到180的,还是不行的。今天弄了个四分频的电路。现在还是有问题,还在研究中。
作者: luojihao24669    时间: 2012-4-13 22:53
lemon~cmc 发表于 2012-4-13 00:56
也就是PCLK触发一次,DMA就读取一个字节。这样就不会造成因DMA的速度过快而导致图像被拉升对吧, 但是按理说 ...

“也就是PCLK触发一次,DMA就读取一个字节。这样就不会造成因DMA的速度过快而导致图像被拉升对吧, 但是按理说PCLK出来的应该是方波才对呀,为什么7620出来的是三角波,可以改嘛?还有一点我没有很明白的就是每进一次行中断就要去使能DMADMA_ERQ|=DMA_ERQ_ERQ0_MASK;//  是不是某个时候硬件会自动关闭了呢?会是什么时候呢?如果是传输完一个字节就关闭的话,应该是不对的,如果是这样的话,每一行不是只能采一个点了。”
1--但是按理说PCLK出来的应该是方波才对呀,为什么7620出来的是三角波,可以改嘛?------------
    PCLK出来的既不是方波也不是三角波,他是正弦波,由于频率较高,你的示波器和探头搓,在示波器上才会看到像三角波的波形。
2-----每进一次行中断就要去使能DMADMA_ERQ|=DMA_ERQ_ERQ0_MASK;//  是不是某个时候硬件会自动关闭了呢?会是什么时候呢?如果是传输完一个字节就关闭的话,应该是不对的,如果是这样的话,每一行不是只能采一个点了。”------
   你要老老实实看DS,不要用了别人的程序就不去了解。DMADMA_ERQ|=DMA_ERQ_ERQ0_MASK开启的是硬件触发,在DMA_TCD1_CSR可以设置,在一次主传输完成(CITER减完变0)时关闭相应的通道硬件传输。
如DMA_TCD1_CSR=(0
                       |DMA_CSR_DREQ_MASK ); //完成后关闭相应的ERQ

DMA_TCD1_CSR|=DMA_CSR_START_MASK;//则是软件触发一次传送NBYTES的字节 DMA_TCD1_NBYTES_MLNO=DMA_NBYTES_MLNO_NBYTES(LEN);//一次传输的字节数






作者: sleep_ball    时间: 2012-4-14 01:38
看了两位的讨论   受益匪浅
作者: lemon~cmc    时间: 2012-4-14 20:13
luojihao24669 发表于 2012-4-13 22:53
“也就是PCLK触发一次,DMA就读取一个字节。这样就不会造成因DMA的速度过快而导致图像被拉升对吧, 但是按 ...

搞明白了,这两天弄的纠结了,狠下心来,把DMA的资料从头到尾好好的看了遍。还是很感谢哈。

作者: sleep_ball    时间: 2012-4-15 16:37
lemon~cmc 发表于 2012-4-14 20:13
搞明白了,这两天弄的纠结了,狠下心来,把DMA的资料从头到尾好好的看了遍。还是很感谢哈。

有DMA的资料么,可不可以发一份给我?    这几天也被整的头疼
作者: sleep_ball    时间: 2012-4-17 14:05
你的程序里,怎么实现将PD口采集到的数据放到video[][]数组里的?
作者: hy890512    时间: 2012-4-17 14:19
lemon~cmc 发表于 2012-4-13 21:35
超频到180的,还是不行的。今天弄了个四分频的电路。现在还是有问题,还在研究中。

是不 要用sd卡 先存储图像数据 然后 在从sd卡中读取呢

作者: eve昔枫    时间: 2012-4-17 19:35
请问下  你们K60的DMA配合使用的摄像头是5V还是3.3V啊?
作者: liaogao2    时间: 2012-4-18 21:30
请问你们超频 是超bus  还是系统时钟呢?
作者: lemon~cmc    时间: 2012-4-18 22:01
sleep_ball 发表于 2012-4-17 14:05
你的程序里,怎么实现将PD口采集到的数据放到video[][]数组里的?

配置DMA的时候,将这个传送的源地址寄存器设为你的数据端口就可以了。DMA_TCD0_SADDR=(uint32)&GPIOD_PDIR;//设置源地址GPIO口,PORTD
作者: lemon~cmc    时间: 2012-4-18 22:03
eve昔枫 发表于 2012-4-17 19:35
请问下  你们K60的DMA配合使用的摄像头是5V还是3.3V啊?

我用的K10。 摄像头用的OV7620
作者: lemon~cmc    时间: 2012-4-18 22:05
sleep_ball 发表于 2012-4-15 16:37
有DMA的资料么,可不可以发一份给我?    这几天也被整的头疼

只有英文资料。给个建议就是还是静下心来看英文资料。我可以发你个例程。然后配合着看。别像我,带着猜想去调,到头来还是得静心看各个寄存器

作者: sleep_ball    时间: 2012-4-19 14:25
lemon~cmc 发表于 2012-4-18 22:01
配置DMA的时候,将这个传送的源地址寄存器设为你的数据端口就可以了。DMA_TCD0_SADDR=(uint32)&GPIOD_PDI ...

嗯,前两天已经整明白了,还是谢谢啦
作者: sleep_ball    时间: 2012-4-19 14:26
lemon~cmc 发表于 2012-4-18 22:05
只有英文资料。给个建议就是还是静下心来看英文资料。我可以发你个例程。然后配合着看。别像我,带着猜想 ...

英文的看的头晕啊,后悔以前没好好学英语

作者: eve昔枫    时间: 2012-4-19 14:48
lemon~cmc 发表于 2012-4-18 22:03
我用的K10。 摄像头用的OV7620

你们的行中断5V触发有问题吗?我们的怎么行中断触发有问题~~
作者: lemon~cmc    时间: 2012-4-19 18:06
eve昔枫 发表于 2012-4-19 14:48
你们的行中断5V触发有问题吗?我们的怎么行中断触发有问题~~

行中断是没有问题。你也用的K10?那就看你引脚配对了没有
作者: lemon~cmc    时间: 2012-4-19 18:08
sleep_ball 发表于 2012-4-19 14:26
英文的看的头晕啊,后悔以前没好好学英语

习惯就好。
作者: sleep_ball    时间: 2012-4-24 15:46
lemon~cmc 发表于 2012-4-14 20:13
搞明白了,这两天弄的纠结了,狠下心来,把DMA的资料从头到尾好好的看了遍。还是很感谢哈。

你后来怎么弄好的啊?我超频了   也焊了四分频电路,还是不行,愁

作者: lemon~cmc    时间: 2012-4-28 15:58
sleep_ball 发表于 2012-4-24 15:46
你后来怎么弄好的啊?我超频了   也焊了四分频电路,还是不行,愁

后来一学长,点醒了,感觉DMA优势不大。就改成双数据直接采了。

作者: sleep_ball    时间: 2012-4-29 08:42
lemon~cmc 发表于 2012-4-28 15:58
后来一学长,点醒了,感觉DMA优势不大。就改成双数据直接采了。

双数据?求解释。。

作者: nc2367334102    时间: 2012-4-29 11:06
不错。
作者: lemon~cmc    时间: 2012-4-29 22:30
sleep_ball 发表于 2012-4-29 08:42
双数据?求解释。。

不好意思,打错字了,双数组。就是用双数组来存放图像。采一幅,处理这一幅,下一场就存在另一个数组。这样交替存,那么在处理的时候,就可以防止在处理的数据被新的图像覆盖,同时可以不必延时图像的采集。
作者: 筱明    时间: 2012-5-5 16:36
哥们儿,这个我也遇到了问题了 ,我们开始考虑的是用分频器分频PCLK,  后来选择了用PWM模拟PCLK  结果还是可以的
作者: leeves_chou    时间: 2012-5-13 10:47
LZ  你后来改用 双数组了吗??我们xs128的是用的双数组 我移植到k60上就不成功,,你的情况怎么样??谢谢~
作者: eve昔枫    时间: 2012-5-13 20:51
LZ,DMA采图像我们也是只采到1行,能不能说下你怎么解决的?
作者: eve昔枫    时间: 2012-5-13 20:51
希望加Q讨论下 123238334~ 谢谢
作者: 小顺子    时间: 2012-6-3 20:26
luojihao24669 发表于 2012-4-13 00:53
74ns---------13多M,我K60 100M 主频采20M的信号都可以。如果你想用PCLK同步触发DMA的话,要么你7620用低 ...

怎样降低分辨率,难不成调焦距?
作者: 小顺子    时间: 2012-6-3 20:28
筱明 发表于 2012-5-5 16:36
哥们儿,这个我也遇到了问题了 ,我们开始考虑的是用分频器分频PCLK,  后来选择了用PWM模拟PCLK  结果还是 ...

那程序应该怎样改 呢?说的是中断

作者: luojihao24669    时间: 2012-6-3 23:31
小顺子 发表于 2012-6-3 20:26
怎样降低分辨率,难不成调焦距?

一个是选则小分辨率模式,2是分频采样

作者: xinmengwangran    时间: 2012-6-4 11:02
lemon~cmc 发表于 2012-4-18 22:05
只有英文资料。给个建议就是还是静下心来看英文资料。我可以发你个例程。然后配合着看。别像我,带着猜想 ...


麻烦给我发一份例程呗 谢谢啦 刚刚开始弄K10的DMA 需向你请教一些问题
邮箱:xinmengwangran@sina.com


作者: 筱明    时间: 2012-6-6 12:21
小顺子 发表于 2012-6-3 20:28
那程序应该怎样改 呢?说的是中断

如果你开始用PCLK触发DMA中断,那么现在只需要将PWM模拟的PCLK接到你触发DMA中断的管脚上,而摄像头的PCLK上不用接出来了瑟

作者: tujunjie    时间: 2012-7-6 08:52
您好!我的DMA采集程序和你差不多,但我现在还是没有采集出来,能不能请教一下呢?谢谢

补充内容 (2012-7-6 11:00):
·兄弟,qq交流一下,可以吗
作者: lemon~cmc    时间: 2012-7-8 18:26
tujunjie 发表于 2012-7-6 08:52
您好!我的DMA采集程序和你差不多,但我现在还是没有采集出来,能不能请教一下呢?谢谢

补充内容 (2012-7- ...

279788046
作者: Y晓调...    时间: 2012-7-8 20:18
luojihao24669 发表于 2012-4-13 00:32
DMA_TCD0_NBYTES_MLNO=DMA_NBYTES_MLNO_NBYTES(1);//每次读取一字节
你用GPIOA05来当行触发DMA,每来一个行 ...

不好意思,麻烦您帮我解决个问题吧:
void GPIO_Init()
{
        PORTD_PCR0=PORT_PCR_MUX(1);
        PORTD_PCR1=PORT_PCR_MUX(1);
        PORTD_PCR2=PORT_PCR_MUX(1);
        PORTD_PCR3=PORT_PCR_MUX(1);
        PORTD_PCR4=PORT_PCR_MUX(1);//如果需要修改灰度,这里加上DMA的地址
        PORTD_PCR5=PORT_PCR_MUX(1);
        PORTD_PCR6=PORT_PCR_MUX(1);
        PORTD_PCR7=PORT_PCR_MUX(1);           
        GPIOD_PDDR&=0XFFFFFF00;//D0~D7设置为输入,数字摄像头8位灰度输入
        PORTB_PCR22=PORT_PCR_MUX(1)|PORT_PCR_IRQC(1);   //rise edge to triger the DMA transfer
        GPIOB_PDDR&=~(1<<22);                           //use as input
        PORTB_PCR23=PORT_PCR_MUX(1)|PORT_PCR_IRQC(9);   //rise edge to triger the HREF interrput
        GPIOB_PDDR&=~(1<<23);                           //use as input
        PORTA_PCR27=PORT_PCR_MUX(1)|PORT_PCR_IRQC(10);  //faling edge to triger the VSYNC interrput
        GPIOA_PDDR&=~(1<<27);                           //use as input         
不理解:最后的B22 B23 A27口的定义  比如PORTA_PCR27=PORT_PCR_MUX(1)|PORT_PCR_IRQC(10);  这里面的10是什么意思?怎么定义?要是我把A27改成A18脚,那括号里面的10 变不变???
求解决


作者: 重在学习    时间: 2012-7-22 10:30
太牛了




欢迎光临 智能车制作 (http://111.231.132.190/) Powered by Discuz! X3.2