上海网站建设公司介绍wordpress th7
web/
2025/9/29 20:48:27/
文章来源:
上海网站建设公司介绍,wordpress th7,网站建设技术服务的方式是什么意思,邓州市网站建设上一篇笔记中学习了ADC驱动#xff0c;STM32MP157 也有DAC外设#xff0c;DAC也使用的IIO驱动框架。本章就来学习一下如下在Linux下使用STM32MP157上的DAC。
DAC简介
ADC是模数转换器#xff0c;负责将外界的模拟信号转换为数字信号。DAC刚好相反#xff0c;是数模转换器…上一篇笔记中学习了ADC驱动STM32MP157 也有DAC外设DAC也使用的IIO驱动框架。本章就来学习一下如下在Linux下使用STM32MP157上的DAC。
DAC简介
ADC是模数转换器负责将外界的模拟信号转换为数字信号。DAC刚好相反是数模转换器负责将SOC的数字信号转换为模拟信号。
STM32MP157的DAC模块(数字/模拟转换模块)是12位数字输入电压输出型的DAC。DAC可以配置为8位或12位模式也可以与DMA控制器配合使用。DAC工作在12位模式 时数据可以设置成左对齐或右对齐。DAC模块有2个输出通道每个通道都有独立的转换器。在双DAC模式下2个通道可以独立地进行转换也可以同时进行转换并同步地更新2个通道的输出。DAC可以通过引脚输入参考电压Vref(同ADC共用)以获得更精确的转换结果。STM32MP157的DAC模块主要特点有
1个DAC 接口最大两个DAC输出通道。12位模式下数据左对齐或者右对齐。同步更新功能。噪声波、三角波形生成。外部触发。双DAC通道同时或者分别转换。每个通道都有DMA功能。输入参考电压VREF。……
STM32MP157 DAC框图如下图所示 图中VDDA和VSSA为DAC模块模拟部分的供电而VREF则是DAC模块的参考电压。DAC_OUT1/2就是DAC的两个输出通道了DAC_OUT1对应PA4引脚DAC_OUT2对应PA5引脚。正点原子STM32MP157开发板使用DAC_OUT1引脚为PA4。
DAC驱动源码分析
设备树下的DAC节点
stm32mp151.dtsi文件中的dac节点信息如下 第2行compatible属性值为“st,stm32h7-dac-core”所以在整个Linux源码里面搜索这个字符串即可找到STM32MP157的DAC驱动核心文件这个文件就是drivers/iio/dac/stm32-dac-core.c。
第11、18行compatible属性值“st,stm32-dac”搜索这个字符串可以找到ADC驱动文件这个文件就是drivers/iio/dac/stm32-dac.c。
关于STM32MP157的DAC节点更为详细的信息请参考对应的绑定文档Documentation/devicetree/bindings/iio/dac/st,stm32-dac.txt。接下来简单分析一下绑定文档后面需要根据绑定文档修改设备树使能DAC对应的通道。
DAC首先需要一个根节点DAC根节点属性如下
1、必要属性
compatible兼容性属性必须的可以设置为“st,stm32h7-dac-core”。regDAC控制器寄存器信息。clocks时钟。clock-names时钟名字必须为“pclk”。vref-supply此属性对应vref参考电压句柄。address-cells设置为1。size-cells设置为0。
2、可选属性
pinctrl 引脚配置信息。resets复位句柄。
STM32MP157有两个DAC通道每个DAC通道对应一个子节点DAC子节点相关属性 如下
compatible兼容性属性必须的可以设置为“st,stm32-dac”。reg不同ADC控制器寄存器地址偏移信息。io-channel-cells设置为1。
DAC驱动源码分析
STM32MP157 DAC驱动文件也有两个stm32-dac-core.c和stm32-dac.c。stm32-dac-core.c是DAC核心层主要用于DAC时钟、电源等初始化。需要重点关注的是stm32-dac.c这个文件。stm32-adc.c主体框架是platform配合IIO驱动框架实现DAC驱动。
stm32_dac结构体
首先来看一下stm32_dac结构体内如如下 stm32_dac结构体很简单比上一章的stm32_adc结构体要简单很多只有一个stm32_dac_common成员变量内容如下 可以看出DAC驱动也采用了regmap API。
stm32_dac_probe函数
接下来看一下stm32_dac_probe函数内容如下(有省略) 第12行调用devm_iio_device_alloc函数申请iio_dev这里也连stm32_dac内存一起申请 了。
第17行调用iio_priv函数从iio_dev里面得到stm32_dac首地址。
第19-23行初始化iio_dev重点是第22行的stm32_dac_iio_info因为用户空间读取或设置DAC数据最终就是由stm32_dac_iio_info来完成的。
第25行调用stm32_dac_chan_of_init函数设置DAC通道。
第36行调用iio_device_register函数向内核注册iio_dev。
同样的stm32_dac_probe函数核心就是初始化DAC然后建立DAC的IIO驱动框架。
stm32_dac_iio_info结构体
stm32_dac_iio_info结构体内容如下所示 第2行stm32_dac_read_raw函数用于读取DAC信息读取DAC原始数据值、分辨率等。
第3行stm32_dac_write_raw函数用于设置DAC值。
stm32_dac_read_raw和stm32_dac_write_raw函数内容如下 第1-17行stm32_dac_read_raw函数读取DAC的原始值以及分辨率非常简单。
第19-31行stm32_dac_write_raw函数向DAC写入原始值也就是设置DAC。
硬件原理图分析
DAC原理图如下 上一章讲ADC的时候说了JP2是一个3P的排针用来设置ADC连接可调电位器还DAC。本章学习使用DAC因此可以使用跳线帽将JP2的1,2引脚连接起来。也就是将DAC和ADC连接在一起如下图所示 可以编写应用程序设置DAC然后再使用ADC采集回去。正点原子STM32MP157开发板使用了DAC通道 1引脚为PA4。
DAC驱动编写
修改设备树
DAC驱动ST已经编写好了只需要修改设备树即可。首先在stm32mp15-pinctrl.dtsi文件中添加DAC使用的PA4引脚配置信息
示例代码 58.4.1.1 PA4 引脚配置信息
1 dac_ch1_pins_a: dac-ch1 {
2 pins {
3 pinmux STM32_PINMUX(A, 4, ANALOG);
4 };
5 };接下来在stm32mp157d-atk.dts文件中向根节点添加vdd子节点信息内容如下
示例代码 58.4.1.2 vdd 子节点
1 v3v3: regulator-3p3v {
2 compatible regulator-fixed;
3 regulator-name v3v3;
4 regulator-min-microvolt 3300000;
5 regulator-max-microvolt 3300000;
6 regulator-always-on;
7 regulator-boot-on;
8 };最后在stm32mp157d-atk.dts 文件中向 adc 节点追加一些内容内容如下
示例代码 58.4.1.3 adc 节点
1 dac {
2 pinctrl-names default;
3 pinctrl-0 dac_ch1_pins_a;
4 vref-supply v3v3;
5 status okay;
6 dac1: dac1 {
7 status okay;
8 };
9 };第3行配置dac引脚。
第4行设置电压属性。
第6-8行dac1子节点设置很简单直接将status属性设置为“okay”即可。
使能DAC驱动
同样的使能Linux内核中的ST32MP157 DAC驱动打开Linux内核配置界面配置路 径如下 - Device Drivers - Industrial I/O support (IIO [y]) - Digital to analog converters - *STMicroelectronics STM32 DAC //使能 STM32 DAC
如下图所示 编写测试APP
编译修改后的设备树然后使用新的设备树启动系统。进入/sys/bus/iio/devices目录下此目录下就有DAC对应的iio设备iio:deviceX本章例程如下图所示 上图中有两个IIO设备iio:device0和iio:device1可以依次进入这两个目录查 看分别对应什么外设。教程中当前所使用的开发板中iio:device0为ADC(上一章实验使能的 ADC驱动)iio:device1为本章使能的DAC设备。
进入“iio:device1”目录内容如下图所示 标准的IIO设备文件目录只关心三个文件
out_voltage1_powerdownDAC输出使能文件写0打开DAC写1关闭DAC默认为1也就是关闭DAC。out_voltage1_rawDAC1通道 1原始值文件。out_voltage1_scaleDAC1比例文件(分辨率)单位为mV。实际输出电压值(mV)out_voltage1_raw * out_voltage1_scale。out_voltage1_scale默认值如下图所示 从上图可以看出out_voltage1_scale默认为0.805664062。
DAC1默认12位因此可设置范围为0-4095。向out_voltage1_raw写入2000命令如下 echo 0 /sys/bus/iio/devices/iio:device1/out_voltage1_powerdown //开启 DAC echo 2000 /sys/bus/iio/devices/iio:device1/out_voltage1_raw //设置 DAC
此时DAC输出的理论电压值为2000*0.805664062≈1611.328mV。 那么DAC输出是否正确呢直接使用上一章编写的adcAPP.c读取DAC引脚电压值就行了。这里注意一定要先按照之前的连接示意图所示将JP2的右边两根排针连接起来也就是将DAC和ADC引脚连接在一起。
运行上一章的adcApp.c结果如下图所示 从上图可以看出ADC采集到的电压为1.61V和设置的DAC理论值基本一致。这里要注意DAC1是12位的而ADC是16位的因此可以看到他们的原始值会不一样。
接下来编译一个简单的DAC测试APPAPP等待用户输入DAC原始值一旦用户输入以后就调用ADC来采集DAC输出的电压值最后将DAC理论值与ADC采集到的实际值打印出来看一下是否正确。
这里的过程基本相似先设置char字符数组指针file_path放置iio框架对应的文件路径并enum对应的文件索引然后设置dac的设备结构体存一下raw、scale和act就可以了。
之后编写file_data_read是一样的操作fopen打开然后fscanf扫描遇到EOF就fseek调到头然后fclose。
之后写dac_add_dac_read函数来获取ADC、DAC数据这里就是file_data_read然后atoi、atof得到原始值和比例之后经过换算把实际值存到dac_dev结构体指针dev的adc_act成员变量中之后同样方法获取DAC的理论真实值存到dev-dac_act中。
之后编写dac_enable里面就是system来调用控制台进而使能DAC。dac_disable也是同理。
之后编写dac_set函数设置DAC这里就是sprintf将传入的value转为字符串然后fopen打开文件fseek把文件指针调整到文件头fwrite写入转为字符串的value之后fclose关闭文件。
最后写main函数argc就1个首先要dac_enable使能DAC之后再while中scanf获取输入的目标dac设置值然后通过fgets来获取输入值之后dac_set把这个值传给DAC调用dac_add_dac_read来获取数据成功后就打印当前dac和adc值。
运行测试
编译驱动程序和测试APP
输入如下编译dacApp.c这个测试程序 arm-none-linux-gnueabihf-gcc -marcharmv7-a -mfpuneon -mfloat-abihard dacApp.c -o dacApp
编译成功以后就会生成dacApp这个应用程序。
运行测试
注意在测试之前一定要先按照接线示意图所示将JP2跳线帽接到右边也就是将ADC1_CH19通道连接到开发板上DAC1引脚上
输入如下命令使用dacApp测试程序 ./dacApp
APP运行以后会等待输入要设置的DAC值每输入一次就会自动打印出ADC采集到的实际ADC值以及DAC的理论值如下图所示 上图中设置了0、500、1000、2000、3000和4095共6个DAC原始值可以看出DAC设置的理论值和ADC采集到的实际值基本一致。
总结
DAC和ADC总体就很接近都是ST官方已经写好了驱动总体就是platform驱动加上regmap配合IIO驱动来完成。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/84087.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!