系列文章目录
嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记01:赛事介绍与硬件平台
嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记02:开发环境安装
嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记03:G4时钟结构
嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记04:从零开始创建工程模板并开始点灯
嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记05:Systick滴答定时器
嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记06:按键输入
嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记07:ADC模数转换
嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记08:LCD液晶屏
嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记09:EEPROM
嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记10:USART串口通讯
嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记11:数字电位器MCP4017
嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记12:DAC数模转换
嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记13:RTC实时时钟
嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记14:PWM捕获
嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记15:PWM输出
嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记16:第十四届省赛真题
目录
系列文章目录
前言
一、基础知识
二、程序设计
总结
前言
DAC是将数字量转化成模拟量的器件,我们可以通过编程来实现输出某个特定的电压值,也就是模拟量。STM32G4内部集成了一个DAC模块,我们通过对STM32的编程就可以实现在它的特定的管脚上输出一个特定的电压,当然这个电压是可以通过我们的程序进行变化的,比如我们可以让他输出一个三角波或者正弦波都是可以的,只要在0-3.3V的范围之内就可以。当然,DAC输出也会受限于内部DAC器件的位数和精度。
一、基础知识
首先我们要了解一下STM32的哪个管脚可以作为DAC输出来使用,我们可以打开数据手册,在第四章管脚描述的部分找到管脚定义,搜索DAC就可以找到。
PA4可以作为DAC1的输出1通道,PA5可以作为DAC1的输出2通道,所以PA4、PA5就是我们这个芯片的DAC输出管脚。
对应的开发板上有一个J3的排针,也就是我们的拓展接口。我们通过对PA4、PA5的排针进行电压测量就可以知道我们编程的正不正确(通过万用表或者示波器)。
我们再看一下参考手册中关于DAC的基本描述,可以看到它是一个12位的DAC,也就是可以输出的数字量的范围是0-4095,即0-FFF。它也可以配置成8位。在12位模式下,数据可以配置成左对齐或者右对齐,也就是要用两个字节来对它进行输出控制(因为8<12<16),如果是左对齐的话就是FFF0,如果是右对齐就是0FFF,我们一般是用右对齐,这样它的范围就是0-0FFF,也就是0到4095。(如果是左对齐,就是0000,0010-FFF0,就不是很方便,所以我们推荐用右对齐)。然后,DAC有两个输出通道,每个通道有自己独立的转换器,在双DAC通道模式下,转换可以独立发生也可以同时发生,这个看我们的编程,可以让他同时输出也可以单独输出。
然后我们主要看一下DAC的特性:
- 有四个DAC接口,每个最多两个输出通道(我们这个芯片版本是阉割版本,因为管脚太少)
- 可以设置左对齐或者右对齐的12位模式(只选右对齐就可以了)
- 可以同步更新(我们也不需要用到)
- 内置噪声波形和三角波形的发生
- 内置锯齿波的发生
- 双通道可以同时输出也可以独立输出
- 可以用到DMA(用不到)
- 可以由外部触发输出,也可以由软件控制输出
- DAC输出模式由buffered模式和unbuffered模式(缓存机制:来一连串指令可以逐个输出,unbuffered模式则只输出最后一个,我们一般工作在buffered模式)
- ……
这部分最关键的就是要知道我们的DAC的接口PA4、PA5,以及它是12位的右对齐。
二、程序设计
这部分主要就是讲如何在STM32上编程控制DAC的两个管脚输出电压,并且这个电压我们的程序是可以控制的。
首先我们看一下程序设计步骤:
1.将“模板”用CubeMX生成代码
2.配置DAC输出的IO口:PA4->DAC1_OUT1,PA5->DAC1_OUT2
3.DAC输出模式:输出到外部引脚(connected to external pin)
4.将dac.c和dac.h移植到“编程工程”
- main.c包含dac.h
- 添加DAC相关的HAL库驱动文件
- 在conf.h文件中启动DAC模块
- DAC1初始化(MX_DAC1_Init)
- 调用HAL_DAC_SetValue和HAL_DAC_Start函数编写程序
如图配置引脚:
设置外部引脚输出(不用勾选外部触发,用软件输出就可以了):
其他的不需要配置,保持默认就可以了。然后我们生成代码。有的人可能会问DAC要不要配置时钟,我们这里是不需要的,用系统时钟就可以了,因为DAC的触发主要是通过外部触发或者内部软件触发,所以时钟是不需要进行配置的。
生成代码后我们就可以把DAC进行移植,这个步骤我们之前已经进行过很多次了,程序设计步骤中写的也很详细,就不细说了。
然后我们就可以用HAL_DAC_SetValue()和HAL_DAC_Start()来编写程序生成电压。HAL_DAC_SetValue()有四个参数,第一个是DAC的处理结构体,直接写&hadc1就行了。第二个参数是它的通道,DAC_CHANNEL_1或者DAC_CHANNEL_2。第三个参数是对齐方式,我们前面说到是用12位右对齐,所以是DAC_ALIGN_12B_R。第四个是输入的数据(0-4095)。4095对应的就是3.3V,如1365对应的就是1.1V 。
这些参数的定义都是可以在函数定义里面找到的,如果考场上记不住就直接到定义里找。
例如:
HAL_DAC_SetValue(&hdac1,DAC_CHANNEL_1,DAC_ALIGN_12B_R,1365)
就是在PA4上输出1365的模拟电压1.1V(因为4095/3=1365)
设置完DAC的值后要启动一下HAL_DAC_Start(&hdac1,DAC_CHANNEL_1),这个参数只需要写一个是哪个结构体和哪个通道就可以了。
void DAC_Process(void)
{
HAL_DAC_SetValue(&hdac1,DAC_CHANNEL_1,DAC_ALIGN_12B_L,1365);
HAL_DAC_Start(&hdac1,DAC_CHANNEL_1);//PA4输出1.1V
HAL_DAC_SetValue(&hdac1,DAC_CHANNEL_2,DAC_ALIGN_12B_L,2730);
HAL_DAC_Start(&hdac1,DAC_CHANNEL_2);//PA5输出2.2V
}
while (1)
{
DAC_Process();
}
需要注意的是我们DAC是先设值再启动,不同于ADC是先启动再设值。
当然,上面这个程序我们也可以这样写:
u8 dac_val1,dac_val2;
void DAC_Process(float dac_volt1,dac_volt2)
{
dac_val1=dac_volt1/3.3f*4095;
dac_val2=dac_volt2/3.3f*4095;
HAL_DAC_SetValue(&hdac1,DAC_CHANNEL_1,DAC_ALIGN_12B_L,dac_val1);
HAL_DAC_Start(&hdac1,DAC_CHANNEL_1);//PA4输出1.1V
HAL_DAC_SetValue(&hdac1,DAC_CHANNEL_2,DAC_ALIGN_12B_L,dac_val2);
HAL_DAC_Start(&hdac1,DAC_CHANNEL_2);//PA5输出2.2V
}
while (1)
{
DAC_Process(1.1f,2.2f);
}
这样调用的时候直接输入需要的电压就行了。
总结
这一节的重点在于要知道DAC的接口PA4、PA5,以及它是12位的右对齐,知道要配置外部引脚输出,还要会写HAL_DAC_SetValue()和HAL_DAC_Start()的程序。