📄 lpld_gpio_dma.c
字号:
/*
* 测试硬件平台: LPLD_K60 Card
* 版权所有: 北京拉普兰德电子技术有限公司
* 网络销售: http://laplenden.taobao.com
* 公司门户: http://www.lpld.cn
*
* 说明: 本工程基于Kintis K60开源底层开发包开发,
* 所有开源驱动代码均在"LPLD"文件夹下,调用说明见文档[#LPLD-003-N]
*
* 文件名: LPLD_GPIO_DMA.c
* 用途: 增强型DMA与GPIO模块综合例程,用于数字摄像头采集
* OV系列数字摄像头均可使用
*
* LPLD_K60 Card 硬件配置说明:
* 摄像头位数据位 - PortD0~7
* PCLK - PortC0
* 行中断 - PortB0
* 场中断 - PortB3
* 图像数据输出 - K60串口5,波特率115200,每幅图帧头发0x01
*
*/
#include "common.h"
#include "HAL_eDMA.h"
#include "HAL_GPIO.h"
#include "uart.h"
#define H 200
#define V 150
#define PHOTO_SIZE H*V
void portb_isr(void);
void GPIO_Init(void);
void dma1_isr(void);
/********************************************************************/
LPLD_eDMA_Cfg_t User_Def_DMA_Init; //声明DMA初始化结构体
uint8_t Pix_Data[PHOTO_SIZE]; //采集50行 200列的图像数据
uint8_t V_Cnt; //行采集计数
uint8_t Field_Over; //场采集完成标志
uint8_t Is_SendPhoto; //图像发送标志
void main (void)
{
int i;
DisableInterrupts;
//变量初始化
for(i=0;i<PHOTO_SIZE;i++)
{
Pix_Data[i]=0;
}
V_Cnt=0; //行计数
Field_Over=1; //场开始标志位
Is_SendPhoto=1; //从串口发送图像
//IO口初始化
GPIO_Init();
//DMA初始化结构体赋值
User_Def_DMA_Init.Channelx =DMA_CH1; //设置为通道1
User_Def_DMA_Init.Peri_DmaReq =PORTC_DMAREQ; //IO C 产生DMA请求
User_Def_DMA_Init.Minor_loop_Length =H; //主循环次数
User_Def_DMA_Init.Source_Addr =(uint32_t)&GPIOD_PDIR; //设置源地址
User_Def_DMA_Init.Dest_Addr =(uint32_t)Pix_Data; //目的地址为Pix_Data的首地址
User_Def_DMA_Init.Dma_irqc =1; //采集结束触发中断
User_Def_DMA_Init.isr_func =dma1_isr; //自定义通道1中断服务子程序
//初始化DMA模块
LPLD_DMA_Init(&User_Def_DMA_Init);
EnableInterrupts;
enable_irq (88); //PORTB 中断 PB3产生场中断和PB0产生行中断
while(1)
{
if(Is_SendPhoto)
{
//先发送一场图像的帧头0x01
uart_putchar(UART5_BASE_PTR,0x01);
for(i=0;i<PHOTO_SIZE;i++)
{
if(Pix_Data[i]==0x01)Pix_Data[i]++;
uart_putchar(UART5_BASE_PTR,Pix_Data[i]);
}
}
}
}
/********************************************************************/
void GPIO_Init(void)
{
LPLD_GPIO_Init(PORTD_BASE_PTR,0,0,2,0); //选择IO D作为数据口
LPLD_GPIO_Init(PORTD_BASE_PTR,1,0,2,0);
LPLD_GPIO_Init(PORTD_BASE_PTR,2,0,2,0);
LPLD_GPIO_Init(PORTD_BASE_PTR,3,0,2,0);
LPLD_GPIO_Init(PORTD_BASE_PTR,4,0,2,0);
LPLD_GPIO_Init(PORTD_BASE_PTR,5,0,2,0);
LPLD_GPIO_Init(PORTD_BASE_PTR,6,0,2,0);
LPLD_GPIO_Init(PORTD_BASE_PTR,7,0,2,0);
LPLD_GPIO_Init(PORTC_BASE_PTR,0,0,2,1); // 选择PTC0作为触发端
// 配置成输入下拉电阻的模式
// DMA上升沿触发
LPLD_GPIO_Init(PORTB_BASE_PTR,0,0,2,9); // 选择PTB0作为行中断
// 配置成输入下拉电阻的模式
// IO上升沿中断
LPLD_GPIO_Init(PORTB_BASE_PTR,3,0,2,9); // 选择PTB1作为场中断
// 配置成输入下拉电阻的模式
// IO上升沿中断
LPLD_GPIO_SetIsr(PORTB_BASE_PTR, portb_isr); //设置PortB口的自定义中断服务子程序
}
/********************************************************************
函数名称:portb_isr
函数描述:IOB双边沿触发产生的中断请求
产中断产生采集信号开始信号
___
___| |_________________________________________________________
用于采集摄像头的行中断,HREF 信号如下
________________________
________| |_______________________________
|->有效数据,启动DMA, |->一行数据采集完毕,
函数输入量:无
函数输入量:无
********************************************************************/
void portb_isr(void)
{
if((PORTB_ISFR & 0x00000001) && !Field_Over)
{
LPLD_DMA_Start(1,1); //使能通道1 DMA 请求
V_Cnt++;
}
else if(PORTB_ISFR & 0x00000008)
{
LPLD_DMA_Init(&User_Def_DMA_Init); //初始化DMA模块
V_Cnt=0; //行采集计数清零
Field_Over=0; //场采集完成清零
}
}
void dma1_isr(void)
{
if(V_Cnt==V)
{
Field_Over=1; //场采集完成置位
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -