×
单片机 > 单片机程序设计 > 详情

STM32 三角波输出

发布时间:2020-08-26 发布时间:
|
STM32还可以生成三角波,跟之前的生成正弦波和阶梯波不同,它不需要DMA帮助描点来画出波形,而是自己就可以生成三角波,因为三角波非常简单,只是线性的波形,所以对于DAC来说完全不是事。
下面就来讲讲怎么输出三角波,还是基于我自己的标准工程。
1、工程的修改
1)代码中需要用到定时器,所以添加stm32f10x_tim.c到STM32F10x_StdPeriod_Driver工作组中。
2)除了定时器,还需要用到DAC,故添加stm32f10x_dac.c到STM32F10x_StdPeriod_Driver工作组中。
3)打开stm32f10x_conf.h文件,把stm32f10x_tim.h、stm32f10x_dac.h、包含进来,也就是将原先屏蔽的包含这些文件的语句去掉屏蔽。
4)新建TriangleWave.c与TriangleWave.h这两个文件分别保存在BSP文件夹中的src与inc中,并将TriangleWave.c添加进工程的BSP中。
 
2、TriangleWave.c与TriangleWave.h程序的编写
显示初始化下引脚。两路三角波的都在DAC的CH1与CH2对应的两个引脚PA4与PA5输出,所以要配置下这两个引脚,代码如下:

/*************************************************************
Function : TriangleWave_GPIO_Init
Description: 三角波对应的引脚初始化
Input : none
return : none
*************************************************************/
static void TriangleWave_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//初始化引脚时钟

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;//初始化DAC的CH1与CH2对应的引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模拟输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
}

接下去的是定时器的配置,代码如下:

/*************************************************************
Function : TriangleWave_TIM_Init
Description: 三脚波需要的定时器初始化
Input : none
return : none
*************************************************************/
static void TriangleWave_TIM_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//初始化TIM2的时钟

TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);//初始化时基结构体
TIM_TimeBaseStructure.TIM_Period = 100;//周期值为100
TIM_TimeBaseStructure.TIM_Prescaler = 0;//不预分频
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;//时钟不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//增计数
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);//初始化TIM2

TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);//设置触发源为更新触发,更新周期一次,则触发一次DAC转换
TIM_Cmd(TIM2, ENABLE);//打开定时器
}

这里设置定时器不分频,周期为100,增计数,在设置触发源为更新触发,这样的话,每次定时器更新,就触发一次DAC转换。
接下去是DAC的配置,先看看代码:

/*************************************************************
Function : TriangleWave_DAC_Init
Description: 三角波需要的DAC初始化
Input : none
return : none
*************************************************************/
static void TriangleWave_DAC_Init(void)
{
DAC_InitTypeDef DAC_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);//初始化DAC时钟

DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;//DAC的触发源为TIM2
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_Triangle;//输出三角波
DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_2047;//三角波的幅值对应的数字量为2047,即1.65V,频率为72M/100/2048/2=175Hz左右(与实际输出频率有一点出入)
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;//不适用DAC输出缓冲
DAC_Init(DAC_Channel_1, &DAC_InitStructure);//初始化DAC的CH1

DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_1023;//三角波的幅值对应的数字量为1023,即0.825V,频率为72M/100/1024/2=252Hz左右(与实价输出频率有一点出入)
DAC_Init(DAC_Channel_2, &DAC_InitStructure);//初始化DAC的CH2

DAC_Cmd(DAC_Channel_1, ENABLE);//打开DAC的CH1
DAC_Cmd(DAC_Channel_2, ENABLE);//打开DAC的CH2

DAC_SetDualChannelData(DAC_Align_12b_R, 0x00, 0x00);//设置DAC两个通道的数据右对齐,波谷对应的数字量风别为0,0
}

生成三角波的关键就在这个代码里了。首先是要设置DAC的触发源为TIM2,并设置DAC生成的波形为三角波。DAC完全可以自己生成三角波,而不用借助DMA。接下去设置DAC的CH1的幅值为2047,CH2的幅值为1023。要知道DAC是12位的,它的最高数字量为4095,所以通道1输出的三角波型对应的数字量会随着定时器更新从0~2747增加,在从2047~0减少;通道2输出的三脚波对应的数字量会随着定时器更新从0~1023增加,再从1023~0减少。最后在设置DAC的谷值为0。如果参考电压为3.3v,那么通道1的波形就会从0v~1.65v增加,再从1.65v~0v减少;通道1的波形就会从0~0.825v增加,在从0.825~0减少,这样的话就形成了三角波了。还要有一点要说的,上面代码中,DAC_SetDualChannelData(DAC_Align_12b_R, 0x00, 0x00);这句话很重要,它的意思是设置DAC的两个通道的数据右对齐,并且设置两路通道的波形的波谷为0。如果我们这样设置:DAC_SetDualChannelData(DAC_Align_12b_R, 0xFF, 0xFF),设置波谷的数字量为0xff,那么波形就会抬高0xff对应的电压0.2v左右。还要讲讲输出三角波的频率是怎么计算的,定时器的时钟为72M,它设置的周期为100,DAC的CH1的幅值设置成2047,DAC的CH2的幅值设置成1023,那么就可以计算出输出两路三角波的频率了:
CH1输出频率 = 72M / 100 / 2048 / 2 = 175.8Hz
CH2输出频率 = 72M /100 / 1024 / 2 = 351.6Hz
 
还要写一个总函数:TriangleWave_Init()来初始化下上面的代码:

/*************************************************************
Function : TriangleWave_Init
Description: 三角波初始化
Input : none
return : none
*************************************************************/

void TriangleWave_Init(void)
{
TriangleWave_GPIO_Init();
TriangleWave_TIM_Init();
TriangleWave_DAC_Init();
}

下面在贴出TriangleWave.h文件的代码:

#ifndef __TRIANGLEWAVE_H__
#define __TRIABGLEWAVE_H__
#include "stm32f10x.h"

void TriangleWave_Init(void);

#endif

3、main函数的编写
main函数非常简单,只是调用一些初始化函数,代码如下:

/*************************************************************
Function : main
Description: main入口
Input : none
return : none
*************************************************************/
int main(void)
{
BSP_Init();
TriangleWave_Init();
PRINTF("\nmain() is running!\r\n");
while(1)
{
LED1_Toggle();
Delay_ms(1000);
}
}

4、测试
用示波器的探头分别取测试PA4与PA5的引脚,然后查看它们的波形。
PA4,也就是DAC的CH1输出的波形的频率理论上应该为175.8Hz左右,实际波形如下:
PA5,也就是DAC的CH2输出的波形的频率理论上应该为351.6Hz左右,实际波形如下:
 图形中可以看出来,实际输出的三角波频率与理论上计算得到的频率还是有点偏差的,我上面的代码设置频率只有几百Hz,如果增加频率到1KHz以上,就会发现实际输出的三角波频率与理论上计算出的频率偏差比较大的!


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
51单片机入门led闪烁程序