STM32兴趣篇一:基于正点原子开发板(战舰)的DAC音频输出软硬件配置记录

折腾了半天,总算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定时器相关知识可参考之前我写的学习心得~

猜你喜欢

转载自blog.csdn.net/Leisure_ksj/article/details/110099151