STM32G474之DAC

STM32G474分别使用CORDIC硬件和"math.h"的正弦值,从DAC1和DAC2输出。

1、DAC特点

PA4的附加功能为DAC1_OUT1,无需映射,直接将它配置为模拟功能,就可以使用了。

PA6的附加功能为DAC2_OUT1,无需映射,直接将它配置为模拟功能,就可以使用了。

2、测试程序

DAC_HandleTypeDef DAC_1_Handler; //DAC1句柄

DAC_HandleTypeDef DAC_2_Handler; //DAC2句柄

void DAC1_Init(void)

{

DAC_ChannelConfTypeDef DAC1_CH1; //DAC通道参数相关结构体

GPIO_InitTypeDef GPIO_InitStruct; //IO口参数结构体

__HAL_RCC_DAC1_CLK_ENABLE(); //使能DAC1时钟

__HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟

GPIO_InitStruct.Pin = GPIO_PIN_4; //选择引脚编号为4

GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; //模拟模式

GPIO_InitStruct.Pull = GPIO_NOPULL; //引脚上拉和下拉都没有被激活

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; //输出速度设置为25MHz至50MHz

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

//根据GPIO_InitStruct结构变量指定的参数初始化GPIOC的外设寄存器

DAC_1_Handler.Instance = DAC1; //DAC1

HAL_DAC_Init(&DAC_1_Handler); //初始化DAC1

DAC1_CH1.DAC_HighFrequency = DAC_HIGH_FREQUENCY_INTERFACE_MODE_ABOVE_160MHZ;

//DAC时钟选择

DAC1_CH1.DAC_DMADoubleDataMode = DISABLE; //双重数据模式(高带宽模式)关闭

DAC1_CH1.DAC_SignedFormat = DISABLE; //有符号模式关闭

DAC1_CH1.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE; //关闭采样保持

DAC1_CH1.DAC_Trigger = DAC_TRIGGER_NONE; //不需要外部触发

DAC1_CH1.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; //DAC输出缓冲器打开

DAC1_CH1.DAC_UserTrimming = DAC_TRIMMING_FACTORY; //工厂矫正模式

DAC1_CH1.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_DISABLE; //不允许内部连接DAC1_CH1

HAL_DAC_ConfigChannel(&DAC_1_Handler, &DAC1_CH1, DAC_CHANNEL_1); //初始化

HAL_DACEx_SelfCalibrate(&DAC_1_Handler, &DAC1_CH1, DAC_CHANNEL_1); //矫正

HAL_DAC_Start(&DAC_1_Handler,DAC_CHANNEL_1); //开启DAC1通道1

HAL_DAC_SetValue(&DAC_1_Handler,DAC_CHANNEL_1,DAC_ALIGN_12B_R,2048);

//设置DAC输出电压: 2048*3.3/(0xFFF+1)=1.65V

Sin_CORDIC_INT();//用CORDIC算法实现正弦计算

}

void DAC2_Init(void)

{

DAC_ChannelConfTypeDef DAC2_CH1; //DAC通道参数相关结构体

GPIO_InitTypeDef GPIO_InitStruct; //IO口参数结构体

__HAL_RCC_DAC2_CLK_ENABLE(); //使能DAC2时钟

__HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟

GPIO_InitStruct.Pin = GPIO_PIN_6; //选择引脚编号为6

GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; //模拟模式

GPIO_InitStruct.Pull = GPIO_NOPULL; //引脚上拉和下拉都没有被激活

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; //输出速度设置为25MHz至50MHz

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

//根据GPIO_InitStruct结构变量指定的参数初始化GPIOC的外设寄存器

DAC_2_Handler.Instance = DAC2; //DAC2

HAL_DAC_Init(&DAC_2_Handler); //初始化DAC2

DAC2_CH1.DAC_HighFrequency = DAC_HIGH_FREQUENCY_INTERFACE_MODE_ABOVE_160MHZ;

//DAC时钟选择

DAC2_CH1.DAC_DMADoubleDataMode = DISABLE; //双重数据模式(高带宽模式)关闭

DAC2_CH1.DAC_SignedFormat = DISABLE; //有符号模式关闭

DAC2_CH1.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE; //关闭采样保持

DAC2_CH1.DAC_Trigger = DAC_TRIGGER_NONE; //不需要外部触发

DAC2_CH1.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; //DAC输出缓冲器打开

DAC2_CH1.DAC_UserTrimming = DAC_TRIMMING_FACTORY; //工厂矫正模式

DAC2_CH1.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_DISABLE; //不允许内部连接DAC2_CH1

HAL_DAC_ConfigChannel(&DAC_2_Handler, &DAC2_CH1, DAC_CHANNEL_1); //初始化

HAL_DACEx_SelfCalibrate(&DAC_2_Handler, &DAC2_CH1, DAC_CHANNEL_1); //矫正

HAL_DAC_Start(&DAC_2_Handler,DAC_CHANNEL_1); //开启DAC2通道1

HAL_DAC_SetValue(&DAC_2_Handler,DAC_CHANNEL_1,DAC_ALIGN_12B_R,2048);

//设置DAC2输出电压: 2048*3.3/(0xFFF+1)=1.65V

}

//函数功能: 用CORDIC算法实现正弦计算
void Sin_CORDIC_INT (void)

{

CORDIC_HandleTypeDef hcordic; //三角函数描述结构体

CORDIC_ConfigTypeDef sCordicConfig; //参数配置结构体

__HAL_RCC_CORDIC_CLK_ENABLE(); //开启时钟

hcordic.Instance = CORDIC; //选择三角函数计算单元

HAL_CORDIC_Init(&hcordic); //初始化

sCordicConfig.Function = CORDIC_FUNCTION_SINE; //选择计算正弦

sCordicConfig.Precision = CORDIC_PRECISION_6CYCLES; //选择计算精度等级

sCordicConfig.Scale = CORDIC_SCALE_0; //选择计算系数

sCordicConfig.NbWrite = CORDIC_NBWRITE_1; //选择计算结果个数

sCordicConfig.NbRead = CORDIC_NBREAD_1; //选择输出正弦

sCordicConfig.InSize = CORDIC_INSIZE_32BITS;
//选择输入数据格式Q1.31,在Q1.31格式的数字范围:-1 (0x80000000) to 1 至 2^(-31) (0x7FFFFFFF).

sCordicConfig.OutSize = CORDIC_OUTSIZE_32BITS; //选择数据输出格式Q1.31

HAL_CORDIC_Configure(&hcordic, &sCordicConfig); //初始化

}

//0<=angles<360,返回值在-1和1之间
//主频170MHz时,本函数执行时间330ns
float sin_f(float angles)

{

MODIFY_REG(CORDIC->CSR,CORDIC_CSR_FUNC|CORDIC_CSR_SCALE,CORDIC_FUNCTION_SINE|CORDIC_SCALE_0);

//选择计算类型:CORDIC_FUNCTION_SINE

WRITE_REG(CORDIC->WDATA, (int32_t)((180.0f-angles)*11930464.7f));
//小于180度为正数,大于180度为负数,乘以11930464.7就转换成"q1.31格式"的数据
//写入CORDIC_WDATA寄存器后,就可以读取"CORDIC_RDATA寄存器的数据"
//由于"模为0x80000000",0x80000000/180=2147483648/180=11930464.7

return (int32_t)READ_REG(CORDIC->RDATA)/2147483648.0f;
//读取CORDIC_RDATA寄存器的数据是"q1.31格式"的数据,经过转换后,就是正弦值
//由于"模为0x80000000",也就是2147483648,除以"模"后就得到正弦值,范围为[-1,1]

}

//函数功能:测试DAC输出正弦波形
void Test_DAC_Output_CORDIC_Sin(void)

{

__IO float i=0.0f;

__IO uint16_t ADC_value1=0x00;

while(1)

{

for(i=0.0f;i<360.0f;i=i+0.1f)

{

ADC_value1=((sin_f(i)+1.65f)/3.3f)*4095.0f;
//使用硬件实现,需要3.72ms完成一个for循环
//设置偏置电压为1.65V,当sin_f(i)=0,ADC的值为1.65V

HAL_DAC_SetValue(&DAC_1_Handler,DAC_CHANNEL_1,DAC_ALIGN_12B_R,ADC_value1);

//设置DAC输出电压: ADC_value1 * 3.3 / (0xFFF+1),单位为"V"

}

}

}

//函数功能:测试DAC输出正弦波形
void Test_DAC_Output_math_Sin(void)

{

__IO float i=0.0f;

__IO uint16_t ADC_value1=0x00;

while(1)

{

for(i=0.0f;i<360.0f;i=i+0.1f)

{

ADC_value1=( ( sin(i*3.1415926/180)+1.65f )/3.3f )*4095.0f;

//使用数学函数,需要172ms完成一个for循环

HAL_DAC_SetValue(&DAC_2_Handler,DAC_CHANNEL_1,DAC_ALIGN_12B_R,ADC_value1);

//设置DAC输出电压: ADC_value1 * 3.3 / (0xFFF+1),单位为"V"

}

}

}

3、测试结果

在没有任何延时的条件下,硬件产生正弦波形周期比软件产生正弦波形要小很多。,说明硬件响应速度比软件快。

相关推荐
智商偏低30 分钟前
单片机之helloworld
单片机·嵌入式硬件
June bug1 小时前
【软考中级·软件评测师】下午题·面向对象测试之架构考点全析:分层、分布式、微内核与事件驱动
经验分享·分布式·职场和发展·架构·学习方法·测试·软考
青牛科技-Allen2 小时前
GC3910S:一款高性能双通道直流电机驱动芯片
stm32·单片机·嵌入式硬件·机器人·医疗器械·水泵、
森焱森4 小时前
无人机三轴稳定控制(2)____根据目标俯仰角,实现俯仰稳定化控制,计算出升降舵输出
c语言·单片机·算法·架构·无人机
白鱼不小白4 小时前
stm32 USART串口协议与外设(程序)——江协教程踩坑经验分享
stm32·单片机·嵌入式硬件
S,D4 小时前
MCU引脚的漏电流、灌电流、拉电流区别是什么
驱动开发·stm32·单片机·嵌入式硬件·mcu·物联网·硬件工程
芯岭技术7 小时前
PY32F002A单片机 低成本控制器解决方案,提供多种封装
单片机·嵌入式硬件
youmdt8 小时前
Arduino IDE ESP8266连接0.96寸SSD1306 IIC单色屏显示北京时间
单片机·嵌入式硬件
嘿·嘘8 小时前
第七章 STM32内部FLASH读写
stm32·单片机·嵌入式硬件
Meraki.Zhang8 小时前
【STM32实践篇】:I2C驱动编写
stm32·单片机·iic·驱动·i2c