本人想用stm32的DAC输出固定电压值,,有人之前调试过这个项目吗?我急需例程。求解救。 20
1个回答
展开全部
玩了几天模拟电路,因做程控放大电路,需要输出可调电压,于是转战STM32上来了,采用DMA通道输出DAC,输出为一正弦波。
DAC配置略显简单,由于悟性不够,部分原因还是不懂。DMA通道传送DAC时,选取DAC_Channnel2程序很好使,而改为DAC_Channnel1时,相应地址等均作改变,但是就是没有波形输出,无果。
选用TIM2作定时器触发,TIM2在APB1上,最高频率36MHz,预分频系数为1时测出正弦波形频率经换算频率为72MHz,而预分频系数为2时,换算频率为36MHz,正常情况应该相等的,不明所以。查询资料,有博客上说,采用默认库配置,TIM2最高频率可以为72MHz,不理解。于是更改程序,自己配置时钟,预分频系数为1时依然为72MHz,而预分频系数为2时,频率为36MHz,无果
//purpose: DA转换,DAC1->PA4管脚输出转换后的模拟值 ,DAC2->PA5
// 产生正弦波频率= 主频/(TIM_Prescaler+1)/TIM_Period/产生一个正弦波的点数
#include "stm32f10x.h"
#define DAC_DHR12R2_Address 0x40007414 //相应地址通过数据手册和参考手册去查询
/* Init Structure definition */
DAC_InitTypeDef DAC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
const uint16_t Sine12bit[32] = { //数据源用来产生波形
2047, 2447, 2831, 3185, 3498, 3750, 3939, 4056, 4095, 4056,
3939, 3750, 3495, 3185, 2831, 2447, 2047, 1647, 1263, 909,
599, 344, 155, 38, 0, 38, 155, 344, 599, 909, 1263, 1647};
uint32_t DualSine12bit[32];
uint32_t Idx = 0;
/* Private function prototypes -----------------------------------------------*/
void RCC_Configuration(void);
void TIM_Configuration(void);
void DAC_Configuration(void);
void DMA_Configuration(void);
void GPIO_Configuration(void);
int main(void)
{
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f10x_xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f10x.c file
*/
// System Clocks Configuration
RCC_Configuration();
/* Once the DAC channel is enabled, the corresponding GPIO pin is automatically
connected to the DAC converter. In order to avoid parasitic consumption,
the GPIO pin should be configured in analog */
GPIO_Configuration();
TIM_Configuration();
DAC_Configuration();
for (Idx = 0; Idx < 32; Idx++)
{
DualSine12bit[Idx] = (Sine12bit[Idx] << 16) + (Sine12bit[Idx]); //双通道输出正弦波
}
DMA_Configuration();
/* Enable DMA for DAC Channel1 */
DAC_DMACmd(DAC_Channel_2, ENABLE);
/* TIM6 enable counter */
TIM_Cmd(TIM6, ENABLE);
while (1)
{
}
}
/**
* @brief Configures the different system clocks.
* @param None
* @retval None
*/
void RCC_Configuration(void)
{
//时钟配置,不使用库默认时钟配置
ErrorStatus HSEStartUpStatus; //定义外部高速晶体启动状态枚举变量
RCC_DeInit(); //复位RCC外部设备寄存器到默认值
RCC_HSEConfig(RCC_HSE_ON); //打开外部高速晶振
HSEStartUpStatus = RCC_WaitForHSEStartUp(); //等待外部高速时钟准备好
if(HSEStartUpStatus == SUCCESS) //外部高速时钟已经准别好
{
RCC_HCLKConfig(RCC_SYSCLK_Div1); //配置AHB(HCLK)时钟=SYSCLK
RCC_PCLK2Config(RCC_HCLK_Div1); //配置APB2(PCLK2)钟=AHB时钟
RCC_PCLK1Config(RCC_HCLK_Div2); //配置APB1(PCLK1)钟=AHB 1/2时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div4); //配置ADC时钟=PCLK2 1/4
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //配置PLL时钟 == 外部高速晶体时钟*9
RCC_ADCCLKConfig(RCC_PCLK2_Div4); //配置ADC时钟= PCLK2/4
RCC_PLLCmd(ENABLE); //使能PLL时钟
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) //等待PLL时钟就绪
{
}
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//配置系统时钟 = PLL时钟
while(RCC_GetSYSCLKSource() != 0x08) //检查PLL时钟是否作为系统时钟
{
}
}
// DMA2 clock enable
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
/* GPIOA Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* DAC Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
/* TIM2 Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
}
void TIM_Configuration(void)
{
// Time base configuration
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 25-1; //计数周期25
TIM_TimeBaseStructure.TIM_Prescaler = 1-1; //预分频系数1
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
// TIM6 TRGO selection */
TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update); //触发源更新
}
void DAC_Configuration(void)
{
// DAC channel1 Configuration
DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO; //DAC触发 TIM6触发
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; //不使用内部波形发生器
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable; //关闭外部输出缓存
DAC_Init(DAC_Channel_1, &DAC_InitStructure); //用DAC输出波形,传输的数据比较多,所以采用DMA传输可以节省CPU的开支
DAC_Init(DAC_Channel_2, &DAC_InitStructure);
// Enable DAC Channel1: Once the DAC channel1 is enabled, PA.04 is automatically connected to the DAC converter
DAC_Cmd(DAC_Channel_1, ENABLE);
DAC_Cmd(DAC_Channel_2, ENABLE);
}
void DMA_Configuration(void)
{
DMA_DeInit(DMA2_Channel4); //将dma的通道寄存器设为默认值
DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR12R2_Address; //定义dma外设基地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&Sine12bit;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //外设作为数据传输的目的地
DMA_InitStructure.DMA_BufferSize = 32; //dma缓存大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器 递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设数据宽度
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //工作在循环缓存模式,数据传输数目为0时,自动恢复配置初值
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //通道未被设置成内存到内存模式,与循环模式相对
DMA_Init(DMA2_Channel4, &DMA_InitStructure); //将DMA_InitStructure中指定的参数初始化dma的通道寄存器
// Enable DMA2 Channel4
DMA_Cmd(DMA2_Channel4, ENABLE); //使能通道
}
/**
* @brief Configures the different GPIO ports.
* @param None
* @retval None
*/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Once the DAC channel is enabled, the corresponding GPIO pin is automatically
connected to the DAC converter. In order to avoid parasitic consumption,
the GPIO pin should be configured in analog */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5; //一旦DAC通道使能,相应的GPIO PA4,PA5自动与DAC的模拟输出相连,
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //为了避免避免寄生的干扰和额外的功耗,PA4 置成模拟输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
想输出固定电压,将数组里的数都变成一个数就可以了
转自http://haoxi.spaces.eepw.com.cn/articles/article/item/97855
望采纳。
DAC配置略显简单,由于悟性不够,部分原因还是不懂。DMA通道传送DAC时,选取DAC_Channnel2程序很好使,而改为DAC_Channnel1时,相应地址等均作改变,但是就是没有波形输出,无果。
选用TIM2作定时器触发,TIM2在APB1上,最高频率36MHz,预分频系数为1时测出正弦波形频率经换算频率为72MHz,而预分频系数为2时,换算频率为36MHz,正常情况应该相等的,不明所以。查询资料,有博客上说,采用默认库配置,TIM2最高频率可以为72MHz,不理解。于是更改程序,自己配置时钟,预分频系数为1时依然为72MHz,而预分频系数为2时,频率为36MHz,无果
//purpose: DA转换,DAC1->PA4管脚输出转换后的模拟值 ,DAC2->PA5
// 产生正弦波频率= 主频/(TIM_Prescaler+1)/TIM_Period/产生一个正弦波的点数
#include "stm32f10x.h"
#define DAC_DHR12R2_Address 0x40007414 //相应地址通过数据手册和参考手册去查询
/* Init Structure definition */
DAC_InitTypeDef DAC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
const uint16_t Sine12bit[32] = { //数据源用来产生波形
2047, 2447, 2831, 3185, 3498, 3750, 3939, 4056, 4095, 4056,
3939, 3750, 3495, 3185, 2831, 2447, 2047, 1647, 1263, 909,
599, 344, 155, 38, 0, 38, 155, 344, 599, 909, 1263, 1647};
uint32_t DualSine12bit[32];
uint32_t Idx = 0;
/* Private function prototypes -----------------------------------------------*/
void RCC_Configuration(void);
void TIM_Configuration(void);
void DAC_Configuration(void);
void DMA_Configuration(void);
void GPIO_Configuration(void);
int main(void)
{
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f10x_xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f10x.c file
*/
// System Clocks Configuration
RCC_Configuration();
/* Once the DAC channel is enabled, the corresponding GPIO pin is automatically
connected to the DAC converter. In order to avoid parasitic consumption,
the GPIO pin should be configured in analog */
GPIO_Configuration();
TIM_Configuration();
DAC_Configuration();
for (Idx = 0; Idx < 32; Idx++)
{
DualSine12bit[Idx] = (Sine12bit[Idx] << 16) + (Sine12bit[Idx]); //双通道输出正弦波
}
DMA_Configuration();
/* Enable DMA for DAC Channel1 */
DAC_DMACmd(DAC_Channel_2, ENABLE);
/* TIM6 enable counter */
TIM_Cmd(TIM6, ENABLE);
while (1)
{
}
}
/**
* @brief Configures the different system clocks.
* @param None
* @retval None
*/
void RCC_Configuration(void)
{
//时钟配置,不使用库默认时钟配置
ErrorStatus HSEStartUpStatus; //定义外部高速晶体启动状态枚举变量
RCC_DeInit(); //复位RCC外部设备寄存器到默认值
RCC_HSEConfig(RCC_HSE_ON); //打开外部高速晶振
HSEStartUpStatus = RCC_WaitForHSEStartUp(); //等待外部高速时钟准备好
if(HSEStartUpStatus == SUCCESS) //外部高速时钟已经准别好
{
RCC_HCLKConfig(RCC_SYSCLK_Div1); //配置AHB(HCLK)时钟=SYSCLK
RCC_PCLK2Config(RCC_HCLK_Div1); //配置APB2(PCLK2)钟=AHB时钟
RCC_PCLK1Config(RCC_HCLK_Div2); //配置APB1(PCLK1)钟=AHB 1/2时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div4); //配置ADC时钟=PCLK2 1/4
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //配置PLL时钟 == 外部高速晶体时钟*9
RCC_ADCCLKConfig(RCC_PCLK2_Div4); //配置ADC时钟= PCLK2/4
RCC_PLLCmd(ENABLE); //使能PLL时钟
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) //等待PLL时钟就绪
{
}
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//配置系统时钟 = PLL时钟
while(RCC_GetSYSCLKSource() != 0x08) //检查PLL时钟是否作为系统时钟
{
}
}
// DMA2 clock enable
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
/* GPIOA Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* DAC Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
/* TIM2 Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
}
void TIM_Configuration(void)
{
// Time base configuration
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 25-1; //计数周期25
TIM_TimeBaseStructure.TIM_Prescaler = 1-1; //预分频系数1
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
// TIM6 TRGO selection */
TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update); //触发源更新
}
void DAC_Configuration(void)
{
// DAC channel1 Configuration
DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO; //DAC触发 TIM6触发
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; //不使用内部波形发生器
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable; //关闭外部输出缓存
DAC_Init(DAC_Channel_1, &DAC_InitStructure); //用DAC输出波形,传输的数据比较多,所以采用DMA传输可以节省CPU的开支
DAC_Init(DAC_Channel_2, &DAC_InitStructure);
// Enable DAC Channel1: Once the DAC channel1 is enabled, PA.04 is automatically connected to the DAC converter
DAC_Cmd(DAC_Channel_1, ENABLE);
DAC_Cmd(DAC_Channel_2, ENABLE);
}
void DMA_Configuration(void)
{
DMA_DeInit(DMA2_Channel4); //将dma的通道寄存器设为默认值
DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR12R2_Address; //定义dma外设基地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&Sine12bit;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //外设作为数据传输的目的地
DMA_InitStructure.DMA_BufferSize = 32; //dma缓存大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器 递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设数据宽度
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //工作在循环缓存模式,数据传输数目为0时,自动恢复配置初值
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //通道未被设置成内存到内存模式,与循环模式相对
DMA_Init(DMA2_Channel4, &DMA_InitStructure); //将DMA_InitStructure中指定的参数初始化dma的通道寄存器
// Enable DMA2 Channel4
DMA_Cmd(DMA2_Channel4, ENABLE); //使能通道
}
/**
* @brief Configures the different GPIO ports.
* @param None
* @retval None
*/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Once the DAC channel is enabled, the corresponding GPIO pin is automatically
connected to the DAC converter. In order to avoid parasitic consumption,
the GPIO pin should be configured in analog */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5; //一旦DAC通道使能,相应的GPIO PA4,PA5自动与DAC的模拟输出相连,
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //为了避免避免寄生的干扰和额外的功耗,PA4 置成模拟输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
想输出固定电压,将数组里的数都变成一个数就可以了
转自http://haoxi.spaces.eepw.com.cn/articles/article/item/97855
望采纳。
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询