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、测试结果

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

相关推荐
ivy159868377155 小时前
芯锦科技 HP9116 QC3+多协议USB快充接口芯片
网络·单片机·嵌入式硬件·5g·p2p
FreakStudio9 小时前
ESP32居然能当 DNS 服务器用?内含NCSI欺骗和DNS劫持实现
python·单片机·嵌入式·面向对象·并行计算·电子diy
2501_926978339 小时前
“LLM的智能本质--AGI的可能路径--人类的意识本质”三者的统一基底(5.0理论解读)
人工智能·经验分享·笔记·深度学习·机器学习·ai写作·agi
LXY_BUAA9 小时前
《嵌入式操作系统》_使用GPIOLIB编写驱动_添加驱动到内核中_20260328
驱动开发·嵌入式硬件
啊哈的哲学路途11 小时前
家里签了100M网络、1000M网络的下载速度应该是多少。
stm32
liwulin050613 小时前
【ESP32-S3】通过ROS2使用YDLIDAR X2进行SLAM、自主导航方案选择
单片机·嵌入式硬件
Truffle7电子14 小时前
STM32理论 —— FreeRTOS:任务
stm32·嵌入式·rtos
廷华电子14 小时前
SSI接口板设计
stm32·电机控制
是翔仔呐14 小时前
第11章 显示外设驱动:I2C协议OLED屏、SPI协议LCD屏字符/图片/中文显示
c语言·开发语言·stm32·单片机·嵌入式硬件·学习·gitee
m0_7167652315 小时前
C++提高编程--STL常用容器(set/multiset、map/multimap容器)详解
java·开发语言·c++·经验分享·学习·青少年编程·visual studio