/*! * @brief 鹰眼ov7725 DMA中断服务函数 * @since v5.0 */ void ov7725_eagle_dma() { //ov7725_eagle_img_flag = IMG_FINISH ; DMA_IRQ_CLEAN(DMA_CH4); //清除通道传输中断标志位 DMA_DIS(DMA_CH4); DMA_IRQ_DIS(DMA_CH4) ; //uart_putchar (UART0, 3); }
void DMA0_ISR(void) { DMA_DIS(CAMERA_DMA_CH); //关闭通道CHn 硬件请求 DMA_IRQ_CLEAN(CAMERA_DMA_CH); //清除通道传输中断标志位 img_flag = IMG_FINISH ; GPIOD_PTOR |= (1 << 13); }
void DMA_CH4_Handler(void) { //DMA通道4 DMA_IRQ_CLEAN(DMA_CH4) ; DMA_IRQ_DIS(DMA_CH4); DMA_DIS(DMA_CH4); DMA_Over_Flag = 1 ; }
/*! * @brief 鹰眼ov7725管脚初始化(内部调用) * @since v5.0 */ void ov7725_eagle_port_init() { //DMA通道0初始化,PTA27触发源(默认上升沿),源地址为PTB_B0_IN,目的地址为:IMG_BUFF,每次传输1Byte dma_portx2buff_init(DMA_CH4, (void *)&PTE_B0_IN, ov7725_eagle_img_buff[0], PTD12, DMA_BYTE1,DATACOUNT , DADDR_KEEPON); DMA_DIS(DMA_CH4); DMA_IRQ_DIS(DMA_CH4); DMA_IRQ_CLEAN(DMA_CH4); //清除通道传输中断标志位 disable_irq(PORTD_IRQn); //关闭PTd的中断 //set_irq_priority(90,0); }
void Ov7725_exti_Init() { //DMA通道0初始化,PTB0上升沿触发DMA传输,源地址为PTD_BYTE0_IN,目的地址为:BUFF ,每次传输1Byte,传输320次后停止传输,保存目的地址不变 DMA_PORTx2BUFF_Init(CAMERA_DMA_CH, (void *)&PTB_BYTE0_IN, (void *)IMG_BUFF, PTB8, DMA_BYTE1, 320*2-2, DMA_rising_down_keepon); DMA_DIS(DMA_CH0); //先关闭 DMA DMA_IRQ_DIS(DMA_CH0); //不需要使用DMA中断,由行中断来控制DMA传输 exti_init(PORTA,29,rising_down); //场中断,内部下拉,上升沿触发中断 exti_init(PORTA,28,rising_down); //行中断,内部下拉,上升沿触发中断 }
void DMA_CH4_Handler(void) { //DMA通道4 // u16 i ; // uart_putchar(UART0,0XAA); DMA_IRQ_CLEAN(DMA_CH4) ; DMA_IRQ_DIS(DMA_CH4); DMA_DIS(DMA_CH4); DMA_Over_Flg = 1 ; // disable_irq(PORTC+87); }
/*! * @brief 鹰眼ov7725管脚初始化(内部调用) * @since v5.0 */ void ov7725_eagle_port_init() { //DMA通道0初始化,PTC10触发源(默认上升沿),源地址为PTC_B0_IN,目的地址为:IMG_BUFF,每次传输1Byte dma_portx2buff_init(CAMERA_DMA_CH, (void *)&PTC_B0_IN, (void *)ov7725_eagle_img_buff, PTC10, DMA_BYTE1, CAMERA_DMA_NUM, DADDR_KEEPON); DMA_DIS(CAMERA_DMA_CH); disable_irq(PORTC_IRQn); //关闭PTA的中断 DMA_IRQ_CLEAN(CAMERA_DMA_CH); //清除通道传输中断标志位 DMA_IRQ_EN(CAMERA_DMA_CH); port_init(PTC10, ALT1 | DMA_FALLING | PULLUP ); //PCLK port_init(PTC9, ALT1 | IRQ_RISING | PULLUP | PF); //场中断,上拉,上降沿触发中断,带滤波 }
/*! * @brief DMA初始化,读取端口数据到内存 * @param DMA_CHn 通道号(DMA_CH0 ~ DMA_CH15) * @param SADDR 源地址( (void * )&PTx_Bn_IN 或 (void * )&PTx_Wn_IN ) * @param DADDR 目的地址 * @param PTxn 触发端口 * @param DMA_BYTEn 每次DMA传输字节数 * @param count 一个主循环传输字节数 * @param cfg DMA传输配置,从DMA_cfg里选择 * @since v5.0 * @note DMA PTXn触发源默认上升沿触发传输,若需修改,则初始化后调用 port_init 配置DMA 触发方式 初始化后,需要调用 DMA_EN 来实现 * Sample usage: uint8 buff[10]; dma_portx2buff_init(DMA_CH0, PTB_B0_IN, buff, PTA7, DMA_BYTE1, 10, DADDR_RECOVER); //DMA初始化,源地址:PTB_B0_IN,目的地址:buff,PTA7触发(默认上升沿),每次传输1字节,共传输 10次 ,传输结束后恢复地址 port_init(PTA7,ALT1 | DMA_FALLING); //默认触发源是上升沿,此处改为 下降沿触发 DMA_EN(DMA_CH0); //需要使能 DMA 后才能传输数据 */ void dma_portx2buff_init(DMA_CHn CHn, void *SADDR, void *DADDR, PTXn_e ptxn, DMA_BYTEn byten, uint32 count) { uint8 BYTEs = (byten == DMA_BYTE1 ? 1 : (byten == DMA_BYTE2 ? 2 : (byten == DMA_BYTE4 ? 4 : 0 ) ) ); //计算传输字节数 uint8 ptx0; //断言,检测传递进来参数是否正确 ASSERT( //用断言检测 源地址和每次传输字节数是否正确 ( (byten == DMA_BYTE1) //传输一个字节 && ( (SADDR >= &PTA_B0_IN) && (SADDR <= ( &PTE_B3_IN ))) ) || ( (byten == DMA_BYTE2) //传输两个字节(注意,不能跨端口) && ( (SADDR >= &PTA_B0_IN) && (SADDR <= ( &PTE_W1_IN )) && (((uint32)SADDR & 0x03) != 0x03) ) //保证不跨端口 ) || ( (byten == DMA_BYTE4) //传输四个字节 && ((SADDR >= &PTA_B0_IN) && (SADDR <= ( &PTE_B0_IN ))) && (((uint32)SADDR & 0x03) == 0x00) //保证不跨端口 ) ); ASSERT(count < 0x8000); //断言,最大只支持0x7FFF //DMA 寄存器 配置 /* 开启时钟 */ SIM_SCGC7 |= SIM_SCGC7_DMA_MASK; //打开DMA模块时钟 #if (defined(MK60DZ10)|| defined(MKL26Z4)) SIM_SCGC6 |= SIM_SCGC6_DMAMUX_MASK; //打开DMA多路复用器时钟 #elif defined(MK60F15) SIM_SCGC6 |= SIM_SCGC6_DMAMUX0_MASK; //打开DMA多路复用器时钟 #endif DMAMUX0_CHCFG(CHn)=0x00; DMA_DSR_BCR(CHn)|=DMA_DSR_BCR_DONE_MASK; /* 配置 DMA 通道 的 传输控制块 TCD ( Transfer Control Descriptor ) */ DMA_SAR(CHn) = (uint32)SADDR; // 设置 源地址 DMA_DAR(CHn) = (uint32)DADDR; // 设置目的地址 DMA_DCR(CHn) = (0 | DMA_DCR_SSIZE(byten) | DMA_DCR_DSIZE(byten) //| DMA_DCR_SINC_MASK //传输后源地址增加(根据位宽) | DMA_DCR_DINC_MASK //传输后目的地址增加(根据位宽) | DMA_DCR_CS_MASK // 0为不停得传输,直到BCR为0;1为一次请求传输一次 //| DMA_DCR_START_MASK //软件触发传输 | DMA_DCR_ERQ_MASK //硬件触发传输(与上面START二选一) | DMA_DCR_D_REQ_MASK //传输完成后硬件自动清ERQ ); DMA_DSR_BCR(CHn) = (0 | DMA_DSR_BCR_BCR(count) //传输数目 ); /* 配置 DMA 触发源 */ #if defined(MK60DZ10) DMAMUX_CHCFG_REG(DMAMUX_BASE_PTR, CHn) = (0 #elif (defined(MK60F15) || defined(MKL26Z4)) DMAMUX_CHCFG_REG(DMAMUX0_BASE_PTR, CHn) = (0 #endif | DMAMUX_CHCFG_ENBL_MASK /* Enable routing of DMA request */ //| DMAMUX_CHCFG_TRIG_MASK /* Trigger Mode: Periodic PIT周期触发传输模式 通道1对应PIT1,必须使能PIT1,且配置相应的PIT定时触发 */ | DMAMUX_CHCFG_SOURCE( PTX(ptxn) + DMA_PORTA) /* 通道触发传输源: */ ); //配置触发源(默认是 上升沿触发) port_init(ptxn, ALT1 | DMA_RISING); /* 配置输入源 */ dma_gpio_input_init(SADDR,BYTEs); DMA_DIS(CHn); //使能通道CHn 硬件请求 //DMA_IRQ_CLEAN(CHn); /* 开启中断 */ //DMA_EN(CHn); //使能通道CHn 硬件请求 //DMA_IRQ_EN(CHn); //允许DMA通道传输 }