STM32 使用DMA产生正弦波,三角波,方波

一:思想
使用stm32产生波形当然肯定要用到DAC了,这是必不可少的,虽然stm32自带三角波生成器,但这里我们主要用dma,这样不论想生成什么波形都可以,只要构造出相应函数列表;

二:函数列表实现

主要就是采样法,在一个波形图上选取多个点,然后把相应数值存起来,等待调用(DMA循环调用),然后通过DAC把数值转换,最后近似得到波形,这种方法其实也就是数学中的描点法;
正弦波:

u16 D_sin[256];
void SineWave_Data()
{
     
	u16 i;
	for( i=0;i<=255;i++)
	{
     
		D_sin[i]=(u16)(4095*(sin(i*2*3.1415926/255)+1)/2);
	}
}

方波:

u16 D_fang[N];
void Fang_Data()
{
     
	u16 i;
	for(i=0;i<N/2;i++)
	{
     
		D_fang[i]= (u16)(0);
	}
	for( i=N/2;i<N;i++)
	{
     
		D_fang[i]=(u16)(4095);
	}
}

三角波:

u16 D_saw[N];
void Saw_Data()
{
     
	u16 i;
	for( i=0;i<N/2;i++)
	{
     
		D_saw[i]= (u16)(4095*2*i/N);
	}
	for( i=N/2;i<N;i++)
	{
     
		D_saw[i]= (u16)(2*4095*(N-i)/N);
	}
}

把生成的数存到相应的数组里就行,等待DMA调用;

三:按键控制频率增减:
//按键初始化

void KEY_init()
{
     
	RCC->APB2ENR|=1<<2;     //使能PORTA时钟
	RCC->APB2ENR|=1<<4;     //使能PORTC时钟
	//JTAG_Set(SWD_ENABLE);	//关闭JTAG,开启SWD
	GPIOA->CRL&=0XFFFFFFF0;	//PA0设置成输入	  
	GPIOA->CRL|=0X00000008;   
	GPIOA->CRH&=0X0FFFFFFF;	//PA15设置成输入	  
	GPIOA->CRH|=0X80000000; 			 
	GPIOA->ODR|=1<<15;	   	//PA15上拉,PA0默认下拉
	GPIOC->CRL&=0XFF0FFFFF;	//PC5设置成输入	  
	GPIOC->CRL|=0X00800000;   
	GPIOC->ODR|=1<<5;	   	//PC5上拉 
}

//主函数按键控制部分

//方波和正弦波按键控制
if(KEY_0 == 0 && mode==0 )
	{
     
		delay_ms(10);
		fang_Hz +=1;
		saw_Hz +=1;
		mode=1;
	}
else if(KEY_1==0 && mode==0)
	{
     
		delay_ms(10);
		fang_Hz -=1;
		saw_Hz -=1;
		mode=1;
	}
if(KEY_0 == 1 && KEY_1==1)
		mode=0;
Init_config(fang_Hz,saw_Hz);//将按键控制加入

四:DAC,DMA,TIME初始化;
//这里只列举正弦波

//DAC初始化
void Dac1_Init()//用于正弦波产生
{
     
	RCC->APB1ENR|=1<<29; //使能 DAC 时钟 
	RCC->APB2ENR|=1<<2; //使能 PORTA 时钟 
	GPIOA->CRL&=0XFFF0FFFF; 
	GPIOA->CRL|=0X00000000; //PA4 模拟输入
	DAC->CR|=1<<0; //使能 DAC1
	DAC->CR|=1<<2; //使用触发功能 TEN1=1
	DAC->CR|=0<<1; //DAC1 输出缓存不使能 BOFF1=1
	DAC->CR|=4<<3; //DAC TIM2 TRGO,不过要 TEN1=1 才行
	DAC->CR|=0<<6; //不使用波形发生
	DAC->CR|=0<<8;//幅值设置
	DAC->CR|=1<<12;//DAC1 DMA 使能
	DAC->DHR12R1=0;
}
//DMA初始化
void DMA2_init1()
{
     
	    RCC->AHBENR|=1<<1; //开启 DMA2 时钟
			delay_ms(5); //等待 DMA 时钟稳定
			DMA2_Channel3->CPAR=(u32)&(DAC->DHR12R1); 	 	//DMA2 外设地址 
			DMA2_Channel3->CMAR=(u32)D_sin; 	//DMA2,存储器地址
			DMA2_Channel3->CNDTR=256;    	//DMA2,传输数据量
			DMA2_Channel3->CCR=0X00000000;	//复位
			DMA2_Channel3->CCR|=1<<4;  		//从存储器读
			DMA2_Channel3->CCR|=0<<6; 		//外设地址非增量模式
			DMA2_Channel3->CCR|=1<<7; 	 	//存储器增量模式
			DMA2_Channel3->CCR|=1<<8; 	 	//外设数据宽度为16位
			DMA2_Channel3->CCR|=1<<10; 		//存储器数据宽度16位
			DMA2_Channel3->CCR|=1<<12; 		//最高优先级
			DMA2_Channel3->CCR|=1<<13; 		//最高优先级
			DMA2_Channel3->CCR|=0<<14; 		//非存储器到存储器模式	
			DMA2_Channel3->CCR|=1<<5;  		//循环发送模式
			DMA2_Channel3->CCR|=1<<0;     //开启DMA传输
}
//定时器初始化
void TIM2_Int_Init(u16 arr)//初始化TIM2--正弦
{
     
	RCC->APB1ENR|=1<<0; //TIM2 时钟使能 
	TIM2->CR1|=0<<4;//向上计数模式
	TIM2->ARR=arr; //设定计数器自动重装值
	TIM2->PSC=0; //预分频器 7200,得到 10Khz 的计数时钟 频率=72000/(899+1)=80Khz
	TIM2->CR2|=2<<4; //选择更新事件作为触发中断(TRGO)
	TIM2->CR1|=0x01; //使能定时器2
}

五:总结
以上就可以生成正弦波了,但是还缺少一点点东西把他们组织起来,大家自行添加就行;由于本人才学疏浅,不能将思路很好的梳理,只能提供代码供大家参考;
如果有需要源码的,加我qq就行;

你可能感兴趣的:(嵌入式,stm32波形发生,嵌入式,单片机,stm32)