//====================================================================== //函数名称:DMA_Disable() //函数功能:关闭1个DMA模块 //输 入:DMA_Struct_TypeDef *DMA_Struct DMA结构体地址 //输 出:无 //返 回: 0 : 成功 // -1 : 失败 //====================================================================== int DMA_Disable(DMA_Struct_TypeDef *DMA_Struct) { const DMAMUX_x_TypeDef DMAMUX_x = DMAMUX_x_GET((*DMA_Struct).DMAMUX_Source); switch ((*DMA_Struct).DMA_CHn) { case DMA_CH0: disable_irq(DMA_CH0_IRQn); break; case DMA_CH1: disable_irq(DMA_CH1_IRQn); break; case DMA_CH2: disable_irq(DMA_CH2_IRQn); break; case DMA_CH3: disable_irq(DMA_CH3_IRQn); break; default: return (-1); } DMAMUX_CHCFG_REG(DMAMUXx[DMAMUX_x], (*DMA_Struct).DMA_CHn) = 0; DMA_DCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) = 0; DMA_DSR_BCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) &= ~DMA_DSR_BCR_BCR_MASK; return (0); }
/*! * @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通道传输 }
//====================================================================== //函数名称:DMA_Init() //函数功能:初始化1个DMA模块 //输 入:DMA_Struct_TypeDef *DMA_Struct 需要初始化的DMA结构体地址 //输 出:无 //返 回: 0 : 成功 // -1 : 失败 // -2 : 传输字节数超出范围(<0x0FFFFF) //====================================================================== int DMA_Init(DMA_Struct_TypeDef *DMA_Struct) { if ((*DMA_Struct).DMA_BytesCount > 0x0FFFFF) return (-2); const DMAMUX_x_TypeDef DMAMUX_x = DMAMUX_x_GET((*DMA_Struct).DMAMUX_Source); switch (DMAMUX_x) { case DMAMUX0: SIM_SCGC6 |= SIM_SCGC6_DMAMUX_MASK; break; default: return (-1); } SIM_SCGC7 |= SIM_SCGC7_DMA_MASK; DMAMUX_CHCFG_REG(DMAMUXx[DMAMUX_x], (*DMA_Struct).DMA_CHn) = 0; DMA_DCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) = 0; DMA_DCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) &= ~DMA_DCR_DMOD_MASK; const DMAMUX_SRC_TypeDef DMAMUX_SRC = DMAMUX_SRC_GET((*DMA_Struct).DMAMUX_Source); if (DMAMUX_SRC == DMA_SoftTrig) { DMA_DCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) &= ~DMA_DCR_ERQ_MASK; } else { DMAMUX_CHCFG_REG(DMAMUXx[DMAMUX_x], (*DMA_Struct).DMA_CHn) |= DMAMUX_CHCFG_SOURCE(DMAMUX_SRC); if ((*DMA_Struct).DMAMUX_Trig == DMA_Periodic) DMAMUX_CHCFG_REG(DMAMUXx[DMAMUX_x], (*DMA_Struct).DMA_CHn) |= DMAMUX_CHCFG_TRIG_MASK; else DMAMUX_CHCFG_REG(DMAMUXx[DMAMUX_x], (*DMA_Struct).DMA_CHn) &= ~DMAMUX_CHCFG_TRIG_MASK; } //Source DMA_SAR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) = DMA_SAR_SAR((*DMA_Struct).DMA_Source.DMA_Addr); DMA_DCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) &= ~DMA_DCR_SSIZE_MASK; DMA_DCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) |= DMA_DCR_SSIZE((*DMA_Struct).DMA_Source.Data_Size); if ((*DMA_Struct).DMA_Source.Addr_INC == DMA_ADDR_INC) DMA_DCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) |= DMA_DCR_SINC_MASK; else DMA_DCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) &= ~DMA_DCR_SINC_MASK; DMA_DCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) &= ~DMA_DCR_SMOD_MASK; DMA_DCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) |= DMA_DCR_SMOD((*DMA_Struct).DMA_Source.Addr_MOD); //Destination DMA_DAR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) = DMA_SAR_SAR((*DMA_Struct).DMA_Destination.DMA_Addr); DMA_DCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) &= ~DMA_DCR_DSIZE_MASK; DMA_DCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) |= DMA_DCR_DSIZE((*DMA_Struct).DMA_Destination.Data_Size); if ((*DMA_Struct).DMA_Destination.Addr_INC == DMA_ADDR_INC) DMA_DCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) |= DMA_DCR_DINC_MASK; else DMA_DCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) &= ~DMA_DCR_DINC_MASK; DMA_DCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) |= DMA_DCR_DMOD((*DMA_Struct).DMA_Destination.Addr_MOD); DMA_DSR_BCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) &= ~DMA_DSR_BCR_BCR_MASK; DMA_DSR_BCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) |= DMA_DSR_BCR_BCR((*DMA_Struct).DMA_BytesCount); if ((*DMA_Struct).DMA_CycleSteal == DMA_CycleSteal) DMA_DCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) &= ~DMA_DCR_CS_MASK; else DMA_DCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) |= DMA_DCR_CS_MASK; if (DMAMUX_SRC == DMA_SoftTrig) DMA_DCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) |= DMA_DCR_START_MASK; else DMA_DCR_REG(DMAx[0], (*DMA_Struct).DMA_CHn) |= DMA_DCR_ERQ_MASK; //DMAMUX_CHCFG_REG(DMAMUXx[DMAMUX_x], (*DMA_Struct).DMA_CHx) |= DMAMUX_CHCFG_ENBL_MASK; return (0); }
//====================================================================== //函数名称:DMA_Strat() //函数功能:开始DMA模块传输 //输 入:DMA_Struct_TypeDef *DMA_Struct DMA结构体地址 //输 出:无 //返 回:无 //====================================================================== void DMA_Start(DMA_Struct_TypeDef *DMA_Struct) { DMAMUX_CHCFG_REG(DMAMUXx[DMAMUX_x_GET((*DMA_Struct).DMAMUX_Source)], (*DMA_Struct).DMA_CHn) |= DMAMUX_CHCFG_ENBL_MASK; }