stm32 DA 数模转换
stm32并不是所有的型号都有DAC功能,只有stm32f103xC/D/E系列 才有DAC转换功能。由于库函数手册中没有相关说明,所以只能通过在MDK提供的相关库文件 stm32f10x_dac.c 中找到相应的DAC函数,做了一番尝试。
折腾了一天,实现了DAC的转换和三角波的输出。我使用的是 stm32rct6的芯片,有两个DAC通道,在PA4和PA5两个引脚上。
DAC的库函数配置相关参数说明:
void DAC_Configuration(void)
{
DAC_InitTypeDef DAC_InitStructure;
DAC_InitStructure.DAC_Trigger = DAC_Trigger_Software; //软件触发,不使用定时器 或者外部中断等触发
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; //不产生三角波(DAC_Wave_Triangle) 或者 噪声波(DAC_Wave_Noise)
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable; //提高驱动能力可以打开缓冲
DAC_Init(DAC_Channel_1, &DAC_InitStructure);
DAC_DMACmd(DAC_Channel_1, DISABLE); //不使用DMA
DAC_Cmd(DAC_Channel_1, ENABLE);
}
DAC_InitStructure.DAC_Trigger :触发方式。可选的外部触发源一共有八个。
六个是定时器触发:TIM2,TIM4,TIM5,TIM6,TIM7和TIM8。
剩下两个分别是:EXTI线路9和软件触发。
DAC_InitStructure.DAC_WaveGeneration:波形发生器。STM32内部集成了两个幅度可调的波形发生器,可以产生三角波(DAC_Wave_Triangle)和噪声波(DAC_Wave_Noise)。如果我们使用自定义的缓冲区输出波形,就不需要配置这个参数或者使其为DAC_WaveGeneration_None.
DAC_InitStructure.DAC_OutputBuffer:即是否使用输出缓存。输出缓存的功能主要用来减小输出阻抗,是STM32的DAC无需外部运放就可以直接驱动负载。
相关参数在stm32f10x_dac.h中可以找到。
这里实现:
- 设置DAC输出固定电压
- 设置DAC输出三角波形
stm32 DA 数模转换代码:
#include “stm32f10x.h”
#include “stdio.h”
#define DAC_TEST_1 1 //设置DAC输出固定电压
#define DAC_TEST_2 0 //设置DAC输出三角波形
void RCC_Configuration(void);
void GPIO_Configuration(void);
void USART_Configuration(void);
void DAC_Configuration(void);
void TIM_Configuration(void);
void Delay(u32 us);
int main(void)
{
RCC_Configuration();
USART_Configuration();
GPIO_Configuration();
DAC_Configuration();
#if DAC_TEST_1
DAC_SetChannel1Data(DAC_Align_12b_R, 4095); //刷新DA值,数据右对齐 取值范围 0~ 4095
//板子上接的参考电压时3.3v 所以4095时为3.3v
DAC_SoftwareTriggerCmd(DAC_Channel_1,ENABLE); //软件触发,DA值更新
printf(“\r\n The Value is : %d \r\n”,DAC_GetDataOutputValue(DAC_Channel_1)); //读取DAC引脚输出的值
#elif DAC_TEST_2
TIM_Configuration();
#endif
while(1);
}
void DAC_Configuration(void)
{
DAC_InitTypeDef DAC_InitStructure;
#if DAC_TEST_1
DAC_InitStructure.DAC_Trigger = DAC_Trigger_Software; //软件触发,不使用定时器 或者外部中断等触发
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; //不产生三角波(DAC_Wave_Triangle) 或者 噪声波(DAC_Wave_Noise)
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable; //提高驱动能力可以打开缓冲
DAC_Init(DAC_Channel_1, &DAC_InitStructure);
#elif DAC_TEST_2
DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO; //选择定时器2作外部触发源
DAC_InitStructure.DAC_WaveGeneration =DAC_Wave_Triangle; //产生三角波
DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_2047; //三角波的高为2047 最高可以为4095
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable; //无输出缓冲 提高驱动能力可以打开缓冲
DAC_Init(DAC_Channel_1, &DAC_InitStructure);
#endif
DAC_DMACmd(DAC_Channel_1, DISABLE); //不使用DMA
DAC_Cmd(DAC_Channel_1, ENABLE);
}
void TIM_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 72; //初装值 72 每秒产生1 000 000次更新
TIM_TimeBaseStructure.TIM_Prescaler = 0x0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); //使用更新事件作为触发输出
TIM_Cmd(TIM2, ENABLE);
}
void Delay(u32 us) //vu32 1us一次
{
u32 time=100us/7;
while(–time);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA , &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA , &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA , &GPIO_InitStructure);
}
void RCC_Configuration(void)
{
/ 定义枚举类型变量 HSEStartUpStatus /
ErrorStatus HSEStartUpStatus;
/ 复位系统时钟设置/
RCC_DeInit();
/ 开启HSE/
RCC_HSEConfig(RCC_HSE_ON);
/ 等待HSE起振并稳定/
HSEStartUpStatus = RCC_WaitForHSEStartUp();
/ 判断HSE起是否振成功,是则进入if()内部 /
if(HSEStartUpStatus == SUCCESS)
{
/ 选择HCLK(AHB)时钟源为SYSCLK 1分频 /
RCC_HCLKConfig(RCC_SYSCLK_Div1);
/ 选择PCLK2时钟源为 HCLK(AHB) 1分频 /
RCC_PCLK2Config(RCC_HCLK_Div1);
/ 选择PCLK1时钟源为 HCLK(AHB) 2分频 /
RCC_PCLK1Config(RCC_HCLK_Div2);
/ 设置FLASH延时周期数为2 /
FLASH_SetLatency(FLASH_Latency_2);
/ 使能FLASH预取缓存 /
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
/ 选择锁相环(PLL)时钟源为HSE 1分频,倍频数为9,则PLL输出频率为 8MHz 9 = 72MHz /
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
/ 使能PLL /
RCC_PLLCmd(ENABLE);
/ 等待PLL输出稳定 /
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
/ 选择SYSCLK时钟源为PLL /
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/ 等待PLL成为SYSCLK时钟源 /
while(RCC_GetSYSCLKSource() != 0x08);
}
/ 打开APB2总线上的GPIOA时钟/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO|RCC_APB2Periph_USART1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC|RCC_APB1Periph_TIM2 , ENABLE);
}
void USART_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
USART_ClockInitTypeDef USART_ClockInitStructure;
USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
USART_ClockInit(USART1 , &USART_ClockInitStructure);
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
USART_Init(USART1,&USART_InitStructure);
USART_Cmd(USART1,ENABLE);
}
int fputc(int ch,FILE *f)
{
USART_SendData(USART1,(u8) ch);
while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);
return ch;
}
我的板子上stm32输出三角波的效果不是很好,可能是板子的原因。这里使用詹小七同学的程序调试图片
感谢詹小七同学的调试 符合标准的三角波形 效果如下: