STM32F103DAC输出直流、锯齿波、三角波,正弦波
一、DAC基本原则原理
二、 各波形输出及cubeMx设置
1、直流信号
cubeMx配置:
伪代码:
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DAC_Init();
HAL_DAC_SetValue(&hdac,DAC_CHANNEL_1,DAC_ALIGN_12_R,248);//248/4096*3.3=0.2V
//开启DAC通道1
if(HAL_DAC_Start(&hdac,DAC_CHANNEL_1)!=HAL_OK)
{
Error_Handler();
}
}
while(1)
{
}
实测结果:(手持示波器)
2、锯齿波
cubeMx配置与上一题一致。
伪代码:
int main()
{
int dacValue;
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DAC_Init();
while(1)
{
for(dacValue=o;dacValue<20;dacValue++)//循环次数和波的阶梯化相关,循环次数越多波越光滑
{
HAL_DAC_SetValue(&hdac,DAC_CHANNEL_1,DAC_ALIGN_12_R,124*dacValue);//最高2480/4096*3.3=1V
//开启DAC通道1
if(HAL_DAC_Start(&hdac,DAC_CHANNEL_1)!=HAL_OK)
{
Error_Handler();
}
HAL_Delay(1);//频率和延时时间以及阶梯数有关
]
}
实测结果:(Vpp有些误差)
3、定时器2触发DAC产生三角波
型号:
Timer2在 APB1总线上
cubeMx配置:
伪代码:
int main()
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM2_Init();
HAL_TIM_Base_Start(&htim2);//在定时器厨师话函数中添加也可以
MX_DAC_Init();
//配置DHR12RD寄存器,对应波形的最低电压
if(HAL_DAC_SetValue(&hdac,DAC_CHANNEL_1,DAC_ALIGN_12B_R,0x0)!=HAL_OK)
{Error_Handler();}
//开启DAC通道一
if(HAL_DAC_Start(&hdac,DAC_CHANNEL_1)!=HAL_OK)
{Error_Handler();}
实测结果:
因为APB1总线的频率为16Mhz,16000_000/(15+1)/(1+1)/(1023+1)=488hz,15,1,1023分别是在cubeMx中配置的预分频系数,自动装载值,三角波最大幅值,所以实测频率为488hz。
4、定时器6触发DAC转换,使用DMA方式触发产生正弦波 (APB1总线改为72Mhz)
cubeMx配置:
DAC DMA转换方式
Timer6
伪代码:
实测结果:
频率等于:72000_000/16/255/32=549hz,采了32个点,采点越多越光滑。
波表的形式要提前算好波表不太方便,第二种方法
#define PI 3.1415926
#define DAC_Num 32
void SineWave_Data(uint16_t cycle,uint16_t *D)
{
uint16_t i;
//+130是一个输出偏置,将输出波形都往上拉0.01v,621是限制输出波形幅度
for(i=0;i<cycle;i++)
{
D[i]=621*(sin((2.0*PI*i)/(cycle-1))+1)+130;
}
}
int main()
{
Uint16_t dac_data[DAC_Num ];
MX_GPIO_Init();
MX_DMA_Init();
MX_DAC_Init();
MX_TIM6_Init();
HAL_TIM_Base_Start(&htim6);//记得初始化时钟
memset(dac_data,0,sizeof(dac_data));
SineWave_Data(DAC_Num ,dac_data);
if(HAL_DAC_Start_DMA(&hdac,DAC_CHANNEL_1,(uint32_t *)dac_data,dac_num[i],DAC_ALIGN_12B_R)!=HAL_OK)
{
Error_Handler();
}
}
实测结果:
(具体参数不记得了,预分频系数为0,自动装载系数为1)
这个方法可以扩展扫频,下面是我做的一个1K到40K的扫频,代码就不展出献丑了。