#include "dac.h" #include "buff.h" #include "irq_vector.h" #include "stm32f4xx.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可配置 uint32_t 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, (uint32_t)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); } } // 根据采样率求得定时器频率 uint16_t DAC_GetRate(uint16_t 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; } } } }