DMA方式传输数据到TIM3,更新PWM

定义:DMA,全称为: Direct Memory Access,即直接存储器访问, DMA 传输将数据从一个地址空间复制到另外一个地址空间。 当 CPU 初始化这个传输动作,传输动作本身是由DMA 控制器 来实行和完成。典型的例子就是移动一个外部内存的区块到芯片内部更快的内存区。

作用对象:存储器和存储器间的传输,外设和存储器,存储器和外设的传输;闪存、 SRAM、外设的 SRAM、 APB1 APB2 和 AHB 外设均可作为访问的源和目标。

优点:DMA 传输方式无需 CPU 直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路, 能使 CPU 的效率大为提高。
 

注意:

1.子程序中定义了数组,若主函数中出现未定义或重复定义警告,则加extern u16 buf[4]表明变量已在其他地方定义 ;

不可再次赋值external u16 buf[4] = {200,400,600,800};则会报错。

2.TIM_DMACmd(TIM3, TIM_DMA_Update, ENABLE);TIM_DMA_Update对应通道3,刚开始设置TIM_DMA_CC1对应通道6无法实现本现象,原因未知。

1.DMA配置

void DMA_Configuration(void)
{
  DMA_InitTypeDef D;

  //详见函数库手册第90页解释
  DMA_DeInit(DMA1_Channel3); //DMA1_3通道初始化
  D.DMA_PeripheralBaseAddr =(u32)&TIM3->CCR1;      //DMA外设基址 TIM3_CCR1_Address 
  D.DMA_MemoryBaseAddr = (u32)buf;                 //DMA内存基址
  D.DMA_DIR = DMA_DIR_PeripheralDST;               //DST外设作为数据传送目的地址,SRC则作为源地址
  D.DMA_BufferSize = 4;                                   //DMA缓存大小
  D.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不增加
  D.DMA_MemoryInc = DMA_MemoryInc_Enable;          //内存地址寄存器不增加
  D.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外存字宽16bit
  D.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;              //内存字宽16bit
  D.DMA_Mode = DMA_Mode_Normal; 	//工作在循环模式
	//D.DMA_Mode =DMA_Mode_Circular;
  D.DMA_Priority = DMA_Priority_High; //DMA置为高优先级
  D.DMA_M2M = DMA_M2M_Disable;                  //不置为内存到内存传输
  DMA_Init(DMA1_Channel3, &D);                  //初始化DMA1
  DMA_Cmd(DMA1_Channel3, ENABLE);     //DMA1_3使能

}

2.定时器PWM输出配置

u16 buf[4] = {200,400,600,800};
static void GPIO_Config(void) 
{                                                          
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);         //TIM3钟源
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);  //PA、PB钟源

  //GPIOA 配置: TIM3 channel 1 和 2 推挽复用
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  // 复用推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void TIM3_Init()
{
 TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_OCInitTypeDef  TIM_OCInitStructure;

  //定时器设置
  TIM_TimeBaseStructure.TIM_Period = 999;       //当定时器从0计数到999,即为1000次,为一个定时周期
  TIM_TimeBaseStructure.TIM_Prescaler = 0;            //设置预分频:不预分频,即为36MHz
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;        //设置时钟分频系数:不分频
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //向上计数模式
  //TIM_TimeBaseStructure.TIM_RepetitionCounter = 2;

  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

  //PWM通道1模式设置
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;            //配置为PWM模式1
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;        
  TIM_OCInitStructure.TIM_Pulse = buf[0];           //设置跳变值,当计数器计数到这个值时,电平发生跳变
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  //当定时器计数值小于CCR1_Val时为高电平
  TIM_OC1Init(TIM3, &TIM_OCInitStructure); //使能通道1

 

TIM_Cmd(TIM3, ENABLE); //TIM3使能

			 
TIM_DMACmd(TIM3, TIM_DMA_Update, ENABLE); //TIM3 DMA请求使能,注:TIM3_Update请求对应DMA通道为DMA1_chanel3
}

3.主函数

extern u16 buf[4];
int main()
{
GPIO_Config(); //配置端口
TIM3_Init();  
DMA_Configuration(); //配置DMA
}

4.结果:

DMA方式传输数据到TIM3,更新PWM_第1张图片

可以看到PA6输出低电平占200,400,600,800的脉冲,若D.DMA_Mode =DMA_Mode_Circularl; 则200,400,600,800的脉冲循环出现。

你可能感兴趣的:(单片机开发)