1 DMA通道
STM32F407有两个DAM,每个DMA有8个数据流,每个数据流有8个通道。
数据流之间可以配置优先级。
2 DMA输出配置
使用DMA输出波形,基本思路为,使用定时器循环间隔触发DMA请求,由DMA将波表数据输出到外设上(IO口,DA的输入等)。定时器的中断周期决定了波表的读取频率,进而决定了最后波形的频率,而波表决定了波形的形状。
大体配置步骤:
1)DMA方向:存储器对外设的传输;
2)模式:循环模式;
3)数据项数寄存器NDTR设置为波表的长度。
4)内存地址设置为波表头,地址设置为增量模式;
5)外设地址设置为对应的外设(IO的ODR寄存器,DA的DHRx寄存器),地址为非增量模式;
5)触发改为定时中断触发,定时中断的周期要根据输出波形的频率和波表来确定,ftime = fsin * 波表size;
3 示例代码
3.1DMA 配置
以定时器1更新事件触发DMA发送,根据DMA通道可知TIM1_UP为DMA2 Steam5 Channel6。
/**********配置DMA**********/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能
DMA_DeInit(DMA2_Stream5);
while (DMA_GetCmdStatus(DMA2_Stream5) != DISABLE){}//等待DMA可配置
/* 配置 DMA Stream */
DMA_InitStructure.DMA_Channel = DMA_Channel_6; //通道选择
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(GPIOE->ODR));//DMA外设地址
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)tab;//DMA 存储器0地址
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;//存储器到外设模式
DMA_InitStructure.DMA_BufferSize = TAB_SIZE;//数据传输量
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度:8位
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;// 使用循环模式
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;//非常高优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发单次传输
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发单次传输
DMA_Init(DMA2_Stream5, &DMA_InitStructure);//初始化DMA Stream
3.2触发源配置-定时器更新事件TIM1_UP触发
TIM_TimeBaseStructure.TIM_Prescaler=psc; //预分频
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period=arr; //重装载值
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_RepetitionCounter=0; //重复计数值 会影响更新频率
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);
TIM_ARRPreloadConfig(TIM1,ENABLE);
TIM_DMACmd(TIM1,TIM_DMA_Update,ENABLE);//使能DMA请求源
3.3开启传输
开启传输有两点,一是通道本身要使能,二是触发请求源要能工作。
另外,实验发现每次传输前要把传输完成标志清掉,不然DMA不会工作。
DMA_ClearFlag(DMA2_Stream5,DMA_FLAG_TCIF5|DMA_FLAG_HTIF5|DMA_FLAG_TEIF5|DMA_FLAG_DMEIF5|DMA_FLAG_FEIF5);//清除传输完成标志
DMA_Cmd(DMA2_Stream5, ENABLE); //开通DMA数据流,此时触发源产生就会传输一次数据
TIM_Cmd(TIM1, ENABLE); //使能定时器,更新事件会不断触发DMA
1 DMA通道
STM32F407有两个DAM,每个DMA有8个数据流,每个数据流有8个通道。
数据流之间可以配置优先级。
2 DMA输出配置
使用DMA输出波形,基本思路为,使用定时器循环间隔触发DMA请求,由DMA将波表数据输出到外设上(IO口,DA的输入等)。定时器的中断周期决定了波表的读取频率,进而决定了最后波形的频率,而波表决定了波形的形状。
大体配置步骤:
1)DMA方向:存储器对外设的传输;
2)模式:循环模式;
3)数据项数寄存器NDTR设置为波表的长度。
4)内存地址设置为波表头,地址设置为增量模式;
5)外设地址设置为对应的外设(IO的ODR寄存器,DA的DHRx寄存器),地址为非增量模式;
5)触发改为定时中断触发,定时中断的周期要根据输出波形的频率和波表来确定,ftime = fsin * 波表size;
3 示例代码
3.1DMA 配置
以定时器1更新事件触发DMA发送,根据DMA通道可知TIM1_UP为DMA2 Steam5 Channel6。
/**********配置DMA**********/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能
DMA_DeInit(DMA2_Stream5);
while (DMA_GetCmdStatus(DMA2_Stream5) != DISABLE){}//等待DMA可配置
/* 配置 DMA Stream */
DMA_InitStructure.DMA_Channel = DMA_Channel_6; //通道选择
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(GPIOE->ODR));//DMA外设地址
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)tab;//DMA 存储器0地址
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;//存储器到外设模式
DMA_InitStructure.DMA_BufferSize = TAB_SIZE;//数据传输量
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度:8位
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;// 使用循环模式
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;//非常高优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发单次传输
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发单次传输
DMA_Init(DMA2_Stream5, &DMA_InitStructure);//初始化DMA Stream
3.2触发源配置-定时器更新事件TIM1_UP触发
TIM_TimeBaseStructure.TIM_Prescaler=psc; //预分频
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period=arr; //重装载值
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_RepetitionCounter=0; //重复计数值 会影响更新频率
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);
TIM_ARRPreloadConfig(TIM1,ENABLE);
TIM_DMACmd(TIM1,TIM_DMA_Update,ENABLE);//使能DMA请求源
3.3开启传输
开启传输有两点,一是通道本身要使能,二是触发请求源要能工作。
另外,实验发现每次传输前要把传输完成标志清掉,不然DMA不会工作。
DMA_ClearFlag(DMA2_Stream5,DMA_FLAG_TCIF5|DMA_FLAG_HTIF5|DMA_FLAG_TEIF5|DMA_FLAG_DMEIF5|DMA_FLAG_FEIF5);//清除传输完成标志
DMA_Cmd(DMA2_Stream5, ENABLE); //开通DMA数据流,此时触发源产生就会传输一次数据
TIM_Cmd(TIM1, ENABLE); //使能定时器,更新事件会不断触发DMA
举报