Files
player/Project/Src/Drive/Source/dac.c
2025-07-05 19:47:28 +08:00

360 lines
9.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "dac.h"
#include "buff.h"
#include "irq_vector.h"
#define DHR12RD_OFFSET ((uint32_t)0x00000020)
static DAC_UserStruct *g_dac=0;
static int g_vol=5;
/*
----初始化DAC转换使用外设资源包括定时器4DACDMA
----使用硬件触发的方式定时器4中断自动触发DAC转换DMA自动传送下一个数据
*/
int DAC_NormalInit (DAC_UserStruct *dac)
{
if (g_dac) return -1;
DAC_NormalDeInit (dac);
g_dac=dac;
//初始化定时器
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
RCC_APB1PeriphClockCmd(DAC_TIMER_RCC,ENABLE);
TIM_TimeBaseInitStructure.TIM_Period = dac->rate; //自动重装载值
TIM_TimeBaseInitStructure.TIM_Prescaler=0; //定时器分频
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(DAC_TIMER,&TIM_TimeBaseInitStructure);//初始化TIM
TIM_SelectOutputTrigger (DAC_TIMER,TIM_TRGOSource_Update);
TIM_Cmd(DAC_TIMER,ENABLE);
//初始化DAC
DAC_InitTypeDef DAC_InitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,ENABLE);
DAC_InitStruct.DAC_Trigger=DAC_Trigger_T4_TRGO; //定时器触发
DAC_InitStruct.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生
DAC_InitStruct.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置
DAC_InitStruct.DAC_OutputBuffer=DAC_OutputBuffer_Disable ; //DAC1输出缓存关闭 BOFF1=1
//DAC_InitStruct.DAC_OutputBuffer=DAC_OutputBuffer_Enable ; //DAC1输出缓存打开 用于直接驱动负载
DAC_Init (DAC_Channel_1,&DAC_InitStruct);
DAC_Init (DAC_Channel_2,&DAC_InitStruct);
DAC_SetChannel1Data(DAC_Align_12b_R, 0); //12位右对齐数据格式设置DAC值
DAC_SetChannel2Data(DAC_Align_12b_R, 0); //12位右对齐数据格式设置DAC值
DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC通道1
DAC_Cmd(DAC_Channel_2, ENABLE);
DAC_DMACmd (DAC_Channel_1,ENABLE);
//DAC_DMACmd (DAC_Channel_2,ENABLE);
//初始化GPIO
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//模拟输入
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;//下拉
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
//DMA初始化
DMA_InitTypeDef DMA_InitStructure;
RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_DMA1,ENABLE);
while (DMA_GetCmdStatus(DMA1_Stream5) != DISABLE){}//等待DMA可配置
u32 tmp = (uint32_t)DAC_BASE;
tmp += DHR12RD_OFFSET + DAC_Align_12b_R;
DMA_InitStructure.DMA_Channel = DMA_Channel_7;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&DAC->DHR12RD;
//DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&DAC->DHR12LD;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)dac->buff1;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_BufferSize = dac->buff_size/4;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream5, &DMA_InitStructure);
DMA_ITConfig(DMA1_Stream5, DMA_IT_TC, ENABLE);
//DMA_FlowControllerConfig(DMA1_Stream5, DMA_FlowCtrl_Peripheral);
//DMA_FlowControllerConfig(DMA1_Stream5, DMA_FlowCtrl_Memory);
DMA_DoubleBufferModeConfig(DMA1_Stream5,(u32)dac->buff2,DMA_Memory_0);//双缓冲模式配置
DMA_DoubleBufferModeCmd(DMA1_Stream5,ENABLE);//双缓冲模式开启
//DMA中断
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init (&NVIC_InitStructure);
DMA_Cmd(DMA1_Stream5, ENABLE);
return 0;
}
void DAC_NormalDeInit (DAC_UserStruct *dac)
{
if (dac!=g_dac) return;
DMA_Cmd(DMA1_Stream5, DISABLE);
DMA_DeInit(DMA1_Stream5);
RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_DMA1,DISABLE);
DAC_Cmd(DAC_Channel_1, DISABLE); //使能DAC通道1
DAC_Cmd(DAC_Channel_2, DISABLE);
DAC_DeInit ();
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,DISABLE);
TIM_Cmd(DAC_TIMER,DISABLE);
TIM_DeInit (DAC_TIMER);
RCC_APB1PeriphClockCmd(DAC_TIMER_RCC,DISABLE);
g_dac=0;
}
//获取DAC句柄
DAC_UserStruct *DAC_GetDacHander (void)
{
return g_dac;
}
// 填充缓冲区,返回0成功-1失败
int DAC_FillBuff(int16_t *buf,int size,int nch)
{
if(g_dac->buff_Invalid==0) return -1;
int16_t *p;
if(g_dac->buff_useing==0)
{
p=(s16*)g_dac->buff2;
}else
{
p=(s16*)g_dac->buff2;
}
if(nch==2)
{
for(int i=0;i<size;i++)
{
int temp=(int16_t)buf[i];
temp=temp*g_vol/DAC_VOL_MAX;
p[i]=((temp+0x8000)>>4);
}
}
else //单声道
{
for(int i=0;i<size;i++)
{
int temp=(int16_t)buf[i];
temp=temp*g_vol/DAC_VOL_MAX;
p[2*i]=((temp+0x8000)>>4);
p[2*i+1]=p[2*i];
}
}
//填充了数据之后设置为有效
g_dac->buff_Invalid=0;
return 0;
}
//DMA中断服务函数
void DMA1_Stream5_IRQHandler (void)
{
if (DMA1->HISR&DMA_FLAG_TCIF5)
{
DMA_ClearFlag(DMA1_Stream5, DMA_FLAG_TCIF5);
if (DMA1_Stream5->CR&(1<<19))//目前正在使用buff2
{
g_dac->buff_useing=1;
}
else
{
g_dac->buff_useing=0;
}
g_dac->buff_Invalid=1;
if (g_dac->call_back) g_dac->call_back(g_dac);
}
}
//根据采样率求得定时器频率
u16 DAC_GetRate (u16 rate)
{
return 90000000/rate;
}
static void tim_irq(void);
static data_buff g_buff={0};
static void *g_irq_fun=0;
// 获取数据的函数返回0成功
static int (*g_get_value_fun)(uint16_t *value);
// 以fifo方式初始化
int DAC_FifolInit (void)
{
if (g_dac) return -1;
DAC_FifoDeInit();
buff_init(&g_buff,2048,0,0,0);
//初始化定时器
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
RCC_APB1PeriphClockCmd(DAC_TIMER_RCC,ENABLE);
TIM_TimeBaseInitStructure.TIM_Period = 90000000/11025; //自动重装载值
TIM_TimeBaseInitStructure.TIM_Prescaler=0; //定时器分频
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(DAC_TIMER,&TIM_TimeBaseInitStructure);//初始化TIM
// TIM_SelectOutputTrigger (DAC_TIMER,TIM_TRGOSource_Update);
TIM_Cmd(DAC_TIMER,ENABLE);
TIM_ITConfig(DAC_TIMER,TIM_IT_Update,ENABLE);
//初始化DAC
DAC_InitTypeDef DAC_InitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,ENABLE);
DAC_InitStruct.DAC_Trigger=DAC_Trigger_None; //定时器触发
DAC_InitStruct.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生
DAC_InitStruct.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置
DAC_InitStruct.DAC_OutputBuffer=DAC_OutputBuffer_Disable ; //DAC1输出缓存关闭 BOFF1=1
//DAC_InitStruct.DAC_OutputBuffer=DAC_OutputBuffer_Enable ; //DAC1输出缓存打开 用于直接驱动负载
DAC_Init (DAC_Channel_1,&DAC_InitStruct);
DAC_Init (DAC_Channel_2,&DAC_InitStruct);
DAC_SetChannel1Data(DAC_Align_12b_R, 0); //12位右对齐数据格式设置DAC值
DAC_SetChannel2Data(DAC_Align_12b_R, 0); //12位右对齐数据格式设置DAC值
DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC通道1
DAC_Cmd(DAC_Channel_2, ENABLE);
//初始化GPIO
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//模拟输入
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;//下拉
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
//定时器中断
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init (&NVIC_InitStructure);
g_irq_fun=irq_vector_set_irq(TIM4_IRQn,tim_irq);
return 0;
}
void DAC_FifoDeInit (void)
{
DAC_Cmd(DAC_Channel_1, DISABLE); //使能DAC通道1
DAC_Cmd(DAC_Channel_2, DISABLE);
DAC_DeInit ();
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,DISABLE);
TIM_ITConfig(DAC_TIMER,TIM_IT_Update,DISABLE);
TIM_Cmd(DAC_TIMER,DISABLE);
TIM_DeInit (DAC_TIMER);
RCC_APB1PeriphClockCmd(DAC_TIMER_RCC,DISABLE);
buff_deinit(&g_buff);
irq_vector_set_irq(TIM4_IRQn,g_irq_fun);
g_get_value_fun=0;
}
// 设置获取数据函数
int DAC_SetSetValuwFun(int (*fun)(uint16_t *))
{
g_get_value_fun=fun;
return 0;
}
// 保存数据,返回0成功
int DAC_SaveValue(uint16_t value)
{
return buff_save_bytes(&g_buff,(uint8_t *)&value,2);
}
static void tim_irq(void)
{
uint8_t vs[2];
uint32_t v=0;
if(TIM_GetITStatus(DAC_TIMER,TIM_IT_Update)==SET) //溢出中断
{
TIM_ClearITPendingBit(DAC_TIMER,TIM_IT_Update); //清除中断标志位
if(g_get_value_fun==0)
{
if(buff_read_bytes(&g_buff,vs,2)==0)
{
v=((uint16_t)vs[1]<<8)|vs[0];
v|=v<<16;
DAC->DHR12RD=v;
}
}
else
{
uint16_t v16=0;
if(g_get_value_fun(&v16)==0)
{
v=(v16<<16)|v16;
DAC->DHR12RD=v;
}
}
}
}