小白最近要参加电赛弄OV7670好几天了,因为用的是mini板帧率非常低,所以不能直接用串口发送数据,想用DMA发送,但是发送的时候什么都发送不出来,但是用串口的printf函数能发送
#include "DMA.h"
#include "delay.h"
u16 DMA_Length=0;
void MYDMA_Init(DMA_Channel_TypeDef* DMA_CHx,u32 CPAR,u32 CMAR,u16 LEN)
{
RCC->AHBENR|=1<<0;
delay_ms(10);
DMA_CHx->CPAR=(u32)CPAR;
DMA_CHx->CMAR=(u32)CMAR;
DMA_Length=LEN;
DMA_CHx->CNDTR=DMA_Length;
DMA_CHx->CCR=0x00000000;
DMA_CHx->CCR|=1<<12; //优先级中
DMA_CHx->CCR|=1<<7; //指针增量递增
DMA_CHx->CCR|=1<<4; //初始化
// DMA_CHx->CCR&=0<<0;
}
void MYDMA_EN(DMA_Channel_TypeDef* DMA_CHx)
{
DMA_CHx->CCR&=0<<0;
DMA_CHx->CNDTR=DMA_Length;
DMA_CHx->CCR|=1<<0;
}
这是配置函数
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "lcd.h"
#include "ov7670.h"
#include "exti.h"
#include "cal_per_t.h"
#include "DMA.h"
extern u8 Pic_buf[H][V]; //V=80 H=60
u16 BUF_LEN=sizeof(Pic_buf);
u8 YUV_Y,YUV_UV;
extern u8 postion;
extern u8 ov_sta; //在exit.c里面定义
void camera_refresh(void)
{
u8 x,y;
if(ov_sta==2)
{
LCD_Scan_Dir(U2D_L2R); //从上到下,从左到右
LCD_SetCursor(0x00,0x0000); //设置光标位置
LCD_WriteRAM_Prepare(); //开始写入GRAM
OV7670_CS=0;
OV7670_RRST=0; //开始复位读指针
OV7670_RCK=0;
OV7670_RCK=1;
OV7670_RCK=0;
OV7670_RRST=1; //复位读指针结束
OV7670_RCK=1;
for(x=0;x<120;x++)
{
for(y=0;y<160;y++)
{
GPIOB->CRL=0X88888888;
OV7670_RCK=0;
YUV_Y=OV7670_DATA; //读数据
OV7670_RCK=1;
OV7670_RCK=0;
YUV_UV=OV7670_DATA; //读数据
OV7670_RCK=1;
GPIOB->CRL=0X33333333;
if((x%2)&&(y%2))
{
if(((y/2)>14)&&((y/2)<65))
{
if(YUV_Y>L_THRESHOLD)
{
LCD_WR_DATA(0xffff);
Pic_buf[x/2][y/2]=0xff; //白
}
else
{
LCD_WR_DATA(0x0000);
Pic_buf[x/2][y/2]=0x00; //黑
}
}
else
{
LCD_WR_DATA(0xffff);
Pic_buf[x/2][y/2]=0xff;
}
}
else
LCD_WR_DATA(0x8430);
}
}
OV7670_CS=1;
OV7670_RCK=0;
OV7670_RCK=1;
EXTI->PR=1<<15; //清除LINE8上的中断标志位
ov_sta=0; //开始下一次采集
LCD_Scan_Dir(DFT_SCAN_DIR); //恢复默认扫描方向
}
}
int main(void)
{
u8 i,j;
u16 pro=0;
Stm32_Clock_Init(9); //系统时钟设置
uart_init(72,9600); //串口初始化为9600
delay_init(72); //延时初始化
LCD_Init(); //初始化LCD
lcddev.width=120;
lcddev.height=160;
while(OV7670_Init())//初始化OV7670
{
LCD_Fill(60,150,239,166,WHITE);
delay_ms(200);
}
delay_ms(2000);
EXTI15_Init(); //使能定时器捕获
OV7670_CS=0;
MYDMA_Init(DMA1_Channel4,(u32)&USART1->DR,(u32)Pic_buf,BUF_LEN);
while(1)
{
camera_refresh(); //更新显示
median_filter(); //中值滤波
Get_black_line(); //寻黑线
USART1->CR3|=1<<7;
MYDMA_EN(DMA1_Channel4);
switch (aut_choose_mod())
{
case 0:{u8 i=go_stra();if(i)start_end_point2(i);}break;
case 1:start_end_point1(postion);break;
case 2:change_dir();break;
}
postion=0;
}
}
这是主函数,所有的配置都是按例程来的不知道为什么不行;
还有就是我接了摄像头以后烧进DMA例程以后,把PC5(KEY0的IO)的线拔 了以后摁KEY0的时候,DMA也不会发数据到串口,拔所有的线(除了摄像头的数据线D0-D7)以后,烧进去才可以,把例程改成在循环里不断执行也可以,但是复制到我的程序里就不行了。
用debug调试我写的程序的时候,发现DMA1_Channel4->CPAR,DMA1_Channel4->CMAR地址都是正确的,DMA1_Channel4->CNTDR寄存器初始化的时候赋值是正确的,但是在读取DMA1_Channel4->CNTDR的时候数值不太对,要么是4799,要么是4797,要么是0,(总量为4800)。另外USART1->DR寄存器的值一直为0,但是用printf函数能正常发送。查了半天数据手册也没发现什么不太对劲的地方,也不知道是有占用(我也把通道优先级调到最高过,也是没用,定时中断也没用,只有摄影头有个帧中断是外部中断PA15)还是怎么回事。
求大神指点一下。
@正点原子
对比两者的区别。可以看DMA,USART3的各个寄存器变化。
一周热门 更多>