DAC+DMA(1k-25k)任意正弦波输出

2019-07-21 00:41发布

  经过一天不懈的努力,终于搞出来了,本人用TIME4触发DAC实现DMA传输产生正弦波(100点),经测试误差1HZ,主要代码如下:
void DMA_Config(DMA_Channel_TypeDef*DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
 u32 DR_Base;  //做缓冲用,不知道为什么.非要不可
 RCC->AHBENR|=1<<1;//开启DMA2时钟
 __nop();                    //等待 DMA1 时钟稳定
    __nop();                    //经测试最少 2 个 nop
    __nop(); 
 DR_Base=cpar;
 DMA_CHx->CPAR=DR_Base;   //DMA1 外设地址
 DMA_CHx->CMAR=(u32)cmar; //DMA1,存储器地址
 DMA1_MEM_LEN=cndtr;      //保存DMA传输数据量
 DMA_CHx->CNDTR=cndtr;    //DMA1,传输数据量
 DMA_CHx->CCR=0X00000000;//复位
 DMA_CHx->CCR|=1<<4;  //从存储器读
 DMA_CHx->CCR|=1<<5;  //循环模式
 DMA_CHx->CCR|=0<<6;  //外设地址非增量模式
 DMA_CHx->CCR|=1<<7;  //存储器增量模式
 DMA_CHx->CCR|=1<<8;  //外设数据宽度为16位
 DMA_CHx->CCR|=1<<10; //存储器数据宽度16位
 DMA_CHx->CCR|=1<<12; //中等优先级
 DMA_CHx->CCR|=0<<14; //非存储器到存储器模式 
 
 DMA_CHx->CCR|=1<<1;  //允许完成中断
// DMA_CHx->CCR|=1<<2;  //允许半完成中断
 DMA_CHx->CCR|=1<<0;  //开启DMA传输
 
 MY_NVIC_Init(1,3,DMA2_Channel3_IRQChannel,2);
// MYDMA2_Enable(DMA2_Channel3);    
}
//开启一次DMA传输
void DMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
{
 DMA_CHx->CCR&=~(1<<0);       //关闭DMA传输
 DMA_CHx->CNDTR=DMA1_MEM_LEN; //DMA1,传输数据量
 DMA_CHx->CCR|=1<<0;          //开启DMA传输


void Dac1_Init(void)
{
 RCC->APB2ENR|=1<<2;    //使能PORTA时钟    
 RCC->APB1ENR|=1<<29;   //使能DAC时钟    
     
 GPIOA->CRL&=0XFF00FFFF;
 GPIOA->CRL|=0X00000000;//PA4 PA5模拟输入      DAC->CR|=1<<0; //使能DAC1
 DAC->CR|=1<<1; //DAC1输出缓存不使能 BOFF1=1
 DAC->CR|=1<<2; //使用触发功能 TEN1=0
 DAC->CR|=5<<3; //(0101)DAC TIM6 TRGO,不过要TEN1=1才行
 DAC->CR|=0<<6; //不使用波形发生
 DAC->CR|=0<<8; //屏蔽、幅值设置
 DAC->CR|=1<<12; //DAC1 DMA使能  DAC->DHR12R1=0;
 DAC->DHR12R2=0;
}
void Timerx_Init(u16 arr,u16 psc)
{
 RCC->APB1ENR|=1<<2;//TIM4时钟使能  
 __nop();
 __nop();
  TIM4->ARR=arr;  //设定计数器自动重装值//刚好1ms   
 TIM4->SC=psc;  //预分频器7200,得到10Khz的计数时钟
 //TIM2->CR1=0x8000; //ARPE使能 
 TIM4->CR2|=3<<4;    //比较脉冲 (必须要)
 //TIM2->CR1|=1<<2;         
 TIM4->CR1|=0x01;    //使能定时器2    
}
while(1)
{         DMA_Config(DMA2_Channel3,(u32)&DAC->DHR12R1,(u32)Sine12bit,100); 
       DMA_Enable(DMA2_Channel3);
     Dac1_Init();
     f = 800; 
     Timerx_Init(720000/f,0);

}
f表示频率,PA4输出  
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
34条回答
verymao
2019-07-22 12:29
回复【6楼】浮夸:
---------------------------------
回复【6楼】浮夸:

回复【5楼】正点原子:
---------------------------------
溢出一次就触发一次dac,改变TIM4->ARR的值改变频率,经测试很好用,主要是误差很小很小。

---------------------------------
假如每传一个数据就要重新触发的话,那还用什么DMA呀,直接在定时器中断中更新DAC的值不是更简便....

一周热门 更多>