#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转换,使用外设资源包括定时器4,DAC,DMA ----使用硬件触发的方式,定时器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>4); } } else //单声道 { for(int i=0;i>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; } } } }