说明:文档记录基于RT-Thread的STM32F103外设DAC操作。
1.DAC的GPIO配置
函数位于 drivers\stm32f1xx_hal_msp.c
//DAC底层驱动,时钟配置,引脚 配置
//此函数会被HAL_DAC_Init()调用
//hdac:DAC句柄
void HAL_DAC_MspInit(DAC_HandleTypeDef* hdac)
{GPIO_InitTypeDef GPIO_Initure;__HAL_RCC_DAC_CLK_ENABLE(); //使能DAC时钟__HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟GPIO_Initure.Pin=GPIO_PIN_4; //PA4GPIO_Initure.Mode=GPIO_MODE_ANALOG; //模拟GPIO_Initure.Pull=GPIO_NOPULL; //不带上下拉HAL_GPIO_Init(GPIOA,&GPIO_Initure);//新增DAC2GPIO_Initure.Pin=GPIO_PIN_5; //PA4GPIO_Initure.Mode=GPIO_MODE_ANALOG; //模拟GPIO_Initure.Pull=GPIO_NOPULL; //不带上下拉HAL_GPIO_Init(GPIOA,&GPIO_Initure);
}
void HAL_DAC_MspInit(DAC_HandleTypeDef* hdac)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(hdac->Instance==DAC){/* USER CODE BEGIN DAC_MspInit 0 *//* USER CODE END DAC_MspInit 0 *//* Peripheral clock enable */__HAL_RCC_DAC_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/**DAC GPIO ConfigurationPA4 ------> DAC_OUT1PA5 ------> DAC_OUT2*/GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/* USER CODE BEGIN DAC_MspInit 1 *//* USER CODE END DAC_MspInit 1 */}}
2.调试代码
以下是成功调试的代码,开发板是野火的 霸道STM32,这个开发板只有DAC2 ;PA5能用,所以代码是在 原子的 DAC1,PAC4的基础上增加了DAC2, 关于RT Thread 线程部分也只做了 DAC2部分的。
备注:关于DAC1,DAC2 的引脚配置的函数位于 drivers \ stm32f1xx_hal_msp.c 的
void HAL_DAC_MspInit(DAC_HandleTypeDef* hdac) 函数,里面对DAC1,DAC2的IO进行了配置,如果只用到其中一个,需要到这个函数里面把其一关闭。
GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;//这段代码同时配置了DAC1,DAC2即 PA4,PA5,如果只需其一,删掉其一即可。
2.1 DAC_DRIVERS.h
#include <rtthread.h>
#include <rtdevice.h>
#include "board.h"extern DAC_HandleTypeDef DAC1_Handler;//DAC句柄
extern DAC_HandleTypeDef DAC2_Handler;//DAC句柄void DAC2_test(void);
2.2 DAC_DRIVERS.c
#include "DAC_DRIVERS.h"DAC_HandleTypeDef DAC1_Handler; //DAC句柄
DAC_HandleTypeDef DAC2_Handler; //DAC句柄
//初始化DAC1
void DAC1_Init(void)
{DAC_ChannelConfTypeDef DACCH1_Config;DAC1_Handler.Instance = DAC;HAL_DAC_Init(&DAC1_Handler); //初始化DACDACCH1_Config.DAC_Trigger = DAC_TRIGGER_NONE; //不使用触发功能DACCH1_Config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE; //DAC1输出缓冲关闭HAL_DAC_ConfigChannel(&DAC1_Handler, &DACCH1_Config, DAC_CHANNEL_1); //DAC通道1配置HAL_DAC_Start(&DAC1_Handler, DAC_CHANNEL_1); //开启DAC通道1
}//初始化DAC2
void DAC2_Init(void)
{DAC_ChannelConfTypeDef DACCH2_Config;DAC2_Handler.Instance = DAC;HAL_DAC_Init(&DAC2_Handler); //初始化DACDACCH2_Config.DAC_Trigger = DAC_TRIGGER_NONE; //不使用触发功能DACCH2_Config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE; //DAC1输出缓冲关闭HAL_DAC_ConfigChannel(&DAC2_Handler, &DACCH2_Config, DAC_CHANNEL_2); //DAC通道1配置HAL_DAC_Start(&DAC2_Handler, DAC_CHANNEL_2); //开启DAC通道1
}//设置通道1输出电压
//vol:0~3300,代表0~3.3V
void DAC1_Set_Vol(rt_uint16_t vol)
{double temp = vol;temp /= 1000;temp = temp * 4096 / 3.3;HAL_DAC_SetValue(&DAC1_Handler, DAC_CHANNEL_1, DAC_ALIGN_12B_R, temp); //12位右对齐数据格式设置DAC值
}//设置通道2输出电压
//vol:0~3300,代表0~3.3V
void DAC2_Set_Vol(rt_uint16_t vol)
{double temp=vol;temp /= 1000;temp = temp * 4096 / 3.3;HAL_DAC_SetValue(&DAC2_Handler, DAC_CHANNEL_2, DAC_ALIGN_12B_R, temp); //12位右对齐数据格式设置DAC值
}/* 线程 DAC2_entry 的入口函数 */
static void DAC2_entry(void *param)
{DAC2_Init();rt_uint16_t vout = 1300;while (1){DAC2_Set_Vol(vout);rt_kprintf("DAC2, PA5= %d mV \n", 1300);rt_thread_mdelay(2000); //以ms为单位延时,函数自动去算出设置的时间需要多少时钟节拍。}}
//线程创建函数
void DAC2_test(void)
{rt_thread_t tid1; //创建线程控制块指针来接收线程创建函数的返回值,目的是通过返回值判断线程是否创建ok/* 创建线程 1,名称是 DAC2,入口是 DAC2_entry*/tid1 = rt_thread_create("DAC2", DAC2_entry, RT_NULL, 5000, //设置内存堆栈大小10, 10); //设置优先级,时间片参数,时间片是在有多个相同优先级线程时,这个线程每次被执行多少个时间片/* 如果获得线程控制块,启动这个线程 */if (tid1 != RT_NULL)rt_thread_startup(tid1);
}
//INIT_APP_EXPORT(DAC2_test);