折腾了半天,总算OK了,记录一下,方便以后查看~
硬件部分:
跳线帽将AIN和DAC连起来即可,如下图所示:
具体看原理图:
下图中,PWM AUDIO就是上图开发板上的AIN引脚。
下图中,PWM AUDIO通过TDA1308T芯片对应到PHONE(3.5mm音频输出口)。
其他信息:
1)图1 DAC对应STM32芯片的PA4引脚;
2)本次使用TIM3定时器,其他定时器也可用。
软件部分:
通过硬件连接方式,不难理解开发思路:
1)DAC输出信号至音频输出端;
2)利用TIM定时器产生中断给DAC喂数据;
具体代码如下:
1)dac.h头文件
/**
******************************** STM32F10x *********************************
* @文件名称: dac.h
* @作者名称: Aaron
* @库版本号: V3.5.0
* @工程版本: V1.0.0
* @开发日期: 2020年11月23日
* @摘要简述: dac头文件
******************************************************************************/
/*----------------------------------------------------------------------------
* @更新日志:
* @无
* ---------------------------------------------------------------------------*/
#ifndef __DAC_H
#define __DAC_H
/* 包含头文件 -----------------------------------------------------------------*/
#include "stm32f10x.h"
/* 函数申明 -------------------------------------------------------------------*/
void Dac1_Init(void); // DAC1 初始化
void Dac1_Set_Vol(u16 vol); // 设置DAC1 电压值
#endif /* __DAC_H */
/****** Copyright (C)2020 Aaron. All Rights Reserved ****** END OF FILE *******/
2)dac.c源文件
/**
******************************** STM32F10x *********************************
* @文件名称: dac.c
* @作者名称: Aaron
* @库版本号: V3.5.0
* @工程版本: V1.0.0
* @开发日期: 2020年11月23日
* @摘要简述: dac源文件
******************************************************************************/
/*----------------------------------------------------------------------------
* @更新日志:
* @无
* ---------------------------------------------------------------------------*/
/* 包含头文件 -----------------------------------------------------------------*/
#include "dac.h"
/************************************************
函数名称:void Dac1_Init()
函数功能:Dac1初始化函数
入口参数:无
返回参数:无
开发作者:Aaron
*************************************************/
void Dac1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
DAC_InitTypeDef DAC_InitType;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE ); // 使能GPIOA通道时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE ); // 使能DAC通道时钟
// 设置PA4,模拟输入,因为一旦使能DACx通道后,相应的GPIO引脚会自动与DAC模拟输出相连,设置为输入,可避免额外的干扰
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // 选择引脚4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模拟输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_4) ; // 令PA4输出高
DAC_InitType.DAC_Trigger=DAC_Trigger_None; // 不使用触发功能
DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None; // 不使用波形发生
DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0; // 屏蔽、幅值设置
DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable ; // DAC1输出缓存关闭 BOFF1=1
DAC_Init(DAC_Channel_1,&DAC_InitType);
DAC_Cmd(DAC_Channel_1, ENABLE); // 使能DAC1转换通道
DAC_SetChannel1Data(DAC_Align_12b_R, 0); // 12位右对齐数据格式设置DAC值
}
/************************************************
函数名称:Dac1_Set_Vol(u16 vol)
函数功能:设置通道1输出电压函数
入口参数:u16 vol:输入值范围0~3300,表示0~3.3V
返回参数:无
开发作者:Aaron
*************************************************/
void Dac1_Set_Vol(u16 vol)
{
float temp=vol;
temp/=1000; // 即temp=temp/1000
temp=temp*4096/3.3; // 因为DAC是12位,所以2^12=4096
DAC_SetChannel1Data(DAC_Align_12b_R,temp); // 12位右对齐数据格式设置DAC值
}
3)timer.h头文件
/**
******************************** STM32F10x *********************************
* @文件名称: timer.h
* @作者名称: Aaron
* @库版本号: V3.5.0
* @工程版本: V1.0.0
* @开发日期: 2020年11月23日
* @摘要简述: timer源文件
******************************************************************************/
/*----------------------------------------------------------------------------
* @更新日志:
* @无
* ---------------------------------------------------------------------------*/
#ifndef __TIMER_H
#define __TIMER_H
/* 包含头文件 -----------------------------------------------------------------*/
#include "stm32f10x.h"
/* 函数申明 -------------------------------------------------------------------*/
void TIMER3_Interrput_Init(u16 arr, u16 psc); // 定时器3中断初始化函数
#endif /* __TIMER_H */
/****** Copyright (C)2020 Aaron. All Rights Reserved ****** END OF FILE *******/
4)timer.c源文件
/**
******************************** STM32F10x *********************************
* @文件名称: timer.c
* @作者名称: Aaron
* @库版本号: V3.5.0
* @工程版本: V1.0.0
* @开发日期: 2020年11月23日
* @摘要简述: timer源文件
******************************************************************************/
/*----------------------------------------------------------------------------
* @更新日志:
* @无
* ---------------------------------------------------------------------------*/
/* 包含头文件 -----------------------------------------------------------------*/
#include "timer.h"
/************************************************
函数名称:TIMER3_Interrput_Init(u16 arr, u16 psc)
函数功能:定时器3 中断初始化函数
入口参数:u16 arr:自动重装载值, u16 psc:时钟预分频数
举例:令arr=4999,psc=7199,
则计数周期为(7199+1)/72000000=0.00001s,对应频率10KHz;
计数(4999+1)=5000值,需0.5s
返回参数:无
开发作者:Aaron
*************************************************/
void TIMER3_Interrput_Init(u16 arr, u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitTypeStruct;
NVIC_InitTypeDef NVIC_InitTypeDef_TIM3Struct;
TIM_DeInit(TIM3);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); // 使能TIM3时钟
// 定时器7 参数初始化配置
TIM_TimeBaseInitTypeStruct.TIM_Period=arr;
TIM_TimeBaseInitTypeStruct.TIM_Prescaler=psc;
TIM_TimeBaseInitTypeStruct.TIM_CounterMode=TIM_CounterMode_Down; // 向上计数模式
TIM_TimeBaseInitTypeStruct.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitTypeStruct);
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); // 使能定时器3更新中断
// 定时器3 中断优先级配置
NVIC_InitTypeDef_TIM3Struct.NVIC_IRQChannel=TIM3_IRQn;
NVIC_InitTypeDef_TIM3Struct.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitTypeDef_TIM3Struct.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitTypeDef_TIM3Struct.NVIC_IRQChannelSubPriority=3;
NVIC_Init(&NVIC_InitTypeDef_TIM3Struct);
// 使能定时器3
TIM_Cmd(TIM3,ENABLE);
}
/************************************************
函数名称:TIM3_IRQHandler()
函数功能:定时器3 中断服务函数
入口参数:无
返回参数:无
开发作者:Aaron
*************************************************/
extern u16 Data;
void TIM3_IRQHandler(void)
{
// 获取定时器3 状态
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) // 判断定时器3 状态是否为更新中断
{
GetData();
Dac1_Set_Vol(Data);
TIM_ClearITPendingBit(TIM3,TIM_IT_Update); // 清除更新中断标识
}
}
5)main.c主函数
/**
******************************** STM32F10x *********************************
* @文件名称: main.c
* @作者名称: Aaron
* @库版本号: V3.5.0
* @工程版本: V1.0.0
* @开发日期: 2020年11月23日
* @摘要简述: 主函数
******************************************************************************/
/*----------------------------------------------------------------------------
* @更新日志:
* @无
* ---------------------------------------------------------------------------*/
/* 包含头文件 -----------------------------------------------------------------*/
#include "led.h"
#include "dac.h"
#include "timer.h"
#include "delay.h"
int main(void)
{
LED_Init(); // LED端口初始化//
LED0=1;
delay_init(); // 延时函数初始化//
TIMER3_Interrput_Init(3599, 1);
Dac1_Init(); // DAC初始化//
while(1)
{
delay_ms(200);
LED0=!LED0;
}
}
备注:getdata相关代码主要用来计算要喂给dac的值,我建了一个3000个数值的正弦波信号来调试程序,后期更具需要改声音数据吧。
实验结果:
将耳机插在Phone口上(即3.5mm音频接口),耳机左声道可听到所设的声音。
关于DAC和TIM定时器相关知识可参考之前我写的学习心得~