F373中的普通ADC功能
- STM32F373中的USB接口应用
- STM32F373的ADC功能
- STM32F373中的DAC信号产生模式
- STM32F373的DAC输出测试
- UART输出模拟量的高频电压 测试STM32F373的一个LED闪烁的简单程序
- 基于SWD开发STM32F373电路板
01 ADC功能
一、前言
在STM32F373中, 包括有普通的12位 的 ADC, 还有三个 高精度16位的ADC, 下面对它内部的 12位ADC的功能进行编程测试一下。
二、软件编程
先试用 STM32 Cube MX 配置 ADC的功能。 设置其中六个通道, 包括有四个输入管脚, 以及内部温度传感器和参考电压通道。 设置转换模式, 采用扫描连续转换的方式。 利用DMA把扫描转换的数据传送到内存。
在 ADC 参数设置中, 需要对每一个转换设置相应的采集通道, 采样时间。 这样设置可以使得采样非常灵活。
软件每隔 0.5 秒输出六个通道的AD采样数值。 通过杜邦线分别设置前面四个通道, 它们分别连接到3.3V, 地线, 以及两个来自于 DAC 输出的电压。 可以看到前面四个通道输出的数值各不相同。 后面两个分别是温度信号和参考电压。
使用热风枪对芯片加热, 可以注意到后面两个通道的数值都发生了改变。 这说明芯片内的温度传感器输出的电压由于温度的变化而改变。
使用 DH1766 设置 ADC 第一个通道电压, 读取不同电压下 ADC的数值, 可以看到呈现非常好的线性。 但在起始的位置, 电压比较小的时候, 似乎有一段ADC 的 死区。 重新进行测试, 这一次利用 DM3068读取 实际芯片ADC输入端口的电压, 可以看到 在电压比较小的时候, ADC的转换依然有一个死区。
▲ 图1.2.1 输入电压与ADC采用数值
#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# TEST1.PY -- by Dr. ZhuoQing 2024-02-09
#
# Note:
#============================================================
from headm import *
from tsmodule.tsvisa import *
from tsmodule.tsstm32 import *
import socket
import socket
#------------------------------------------------------------
#------------------------------------------------------------
UDP_HOST = '127.0.0.1'
UDP_PORT = 2244
UDP_BUFSIZE = 0x1000
d = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
d.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, UDP_BUFSIZE)
d.settimeout(0.2)
def dsend(data):
ADDR = (UDP_HOST, UDP_PORT)
if type(data) != str:
data = str(data)
data = bytes(data, 'gbk')
d.sendto(data, ADDR)
def drecv():
try:
data, ADDR = d.recvfrom(UDP_BUFSIZE)
except socket.timeout:
printf('Meter time out.')
data = ''
if len(data) > 0:
return data.decode('utf-8')
else: return ''
def dval():
dsend('MEMOS')
splitstr = drecv().split(' ')
data = []
for val in splitstr:
if len(val) > 0:
data.append(eval(val))
return data
#------------------------------------------------------------
vdim = linspace(0, 3.3, 200)
adcdim = []
for v in vdim:
dh1766volt1(v)
time.sleep(1)
dsend('CLEAR')
dsend('adc')
time.sleep(.1)
dsend("MEMOS")
sss = drecv().split('\r\n')[-1].split(' ')
printf(sss)
adcdim.append(int(sss[0]))
tspsave('adc', vdim=vdim, adcdim=adcdim)
plt.plot(vdim, adcdim, lw=3)
plt.xlabel("Set(N)")
plt.ylabel("ADC(V)")
plt.grid(True)
plt.tight_layout()
plt.show()
#------------------------------------------------------------
#------------------------------------------------------------
# END OF FILE : TEST1.PY
#============================================================
vdim=[0.0000,0.0166,0.0332,0.0497,0.0663,0.0829,0.0995,0.1161,0.1327,0.1492,0.1658,0.1824,0.1990,0.2156,0.2322,0.2487,0.2653,0.2819,0.2985,0.3151,0.3317,0.3482,0.3648,0.3814,0.3980,0.4146,0.4312,0.4477,0.4643,0.4809,0.4975,0.5141,0.5307,0.5472,0.5638,0.5804,0.5970,0.6136,0.6302,0.6467,0.6633,0.6799,0.6965,0.7131,0.7296,0.7462,0.7628,0.7794,0.7960,0.8126,0.8291,0.8457,0.8623,0.8789,0.8955,0.9121,0.9286,0.9452,0.9618,0.9784,0.9950,1.0116,1.0281,1.0447,1.0613,1.0779,1.0945,1.1111,1.1276,1.1442,1.1608,1.1774,1.1940,1.2106,1.2271,1.2437,1.2603,1.2769,1.2935,1.3101,1.3266,1.3432,1.3598,1.3764,1.3930,1.4095,1.4261,1.4427,1.4593,1.4759,1.4925,1.5090,1.5256,1.5422,1.5588,1.5754,1.5920,1.6085,1.6251,1.6417,1.6583,1.6749,1.6915,1.7080,1.7246,1.7412,1.7578,1.7744,1.7910,1.8075,1.8241,1.8407,1.8573,1.8739,1.8905,1.9070,1.9236,1.9402,1.9568,1.9734,1.9899,2.0065,2.0231,2.0397,2.0563,2.0729,2.0894,2.1060,2.1226,2.1392,2.1558,2.1724,2.1889,2.2055,2.2221,2.2387,2.2553,2.2719,2.2884,2.3050,2.3216,2.3382,2.3548,2.3714,2.3879,2.4045,2.4211,2.4377,2.4543,2.4709,2.4874,2.5040,2.5206,2.5372,2.5538,2.5704,2.5869,2.6035,2.6201,2.6367,2.6533,2.6698,2.6864,2.7030,2.7196,2.7362,2.7528,2.7693,2.7859,2.8025,2.8191,2.8357,2.8523,2.8688,2.8854,2.9020,2.9186,2.9352,2.9518,2.9683,2.9849,3.0015,3.0181,3.0347,3.0513,3.0678,3.0844,3.1010,3.1176,3.1342,3.1508,3.1673,3.1839,3.2005,3.2171,3.2337,3.2503,3.2668,3.2834,3.3000]
adcdim=[0.0000,9.0000,0.0000,11.0000,37.0000,59.0000,65.0000,105.0000,117.0000,137.0000,160.0000,175.0000,194.0000,215.0000,229.0000,238.0000,285.0000,294.0000,335.0000,338.0000,360.0000,377.0000,398.0000,421.0000,439.0000,460.0000,484.0000,501.0000,510.0000,530.0000,568.0000,579.0000,607.0000,617.0000,645.0000,661.0000,679.0000,704.0000,722.0000,744.0000,762.0000,774.0000,804.0000,825.0000,844.0000,860.0000,877.0000,898.0000,920.0000,950.0000,970.0000,983.0000,1008.0000,1023.0000,1048.0000,1064.0000,1089.0000,1105.0000,1126.0000,1149.0000,1171.0000,1178.0000,1208.0000,1230.0000,1249.0000,1277.0000,1286.0000,1311.0000,1325.0000,1358.0000,1369.0000,1382.0000,1405.0000,1424.0000,1459.0000,1471.0000,1491.0000,1510.0000,1525.0000,1556.0000,1578.0000,1591.0000,1615.0000,1623.0000,1656.0000,1682.0000,1694.0000,1717.0000,1724.0000,1754.0000,1774.0000,1800.0000,1812.0000,1846.0000,1850.0000,1883.0000,1889.0000,1917.0000,1934.0000,1960.0000,1977.0000,1997.0000,2019.0000,2040.0000,2060.0000,2081.0000,2103.0000,2114.0000,2142.0000,2162.0000,2185.0000,2192.0000,2209.0000,2246.0000,2256.0000,2276.0000,2298.0000,2332.0000,2342.0000,2373.0000,2384.0000,2403.0000,2424.0000,2438.0000,2470.0000,2476.0000,2503.0000,2511.0000,2538.0000,2558.0000,2594.0000,2611.0000,2619.0000,2634.0000,2670.0000,2687.0000,2713.0000,2728.0000,2745.0000,2775.0000,2790.0000,2821.0000,2838.0000,2859.0000,2877.0000,2889.0000,2911.0000,2936.0000,2958.0000,2968.0000,3001.0000,3011.0000,3040.0000,3051.0000,3076.0000,3100.0000,3108.0000,3145.0000,3161.0000,3180.0000,3193.0000,3216.0000,3241.0000,3252.0000,3281.0000,3300.0000,3301.0000,3336.0000,3353.0000,3376.0000,3400.0000,3419.0000,3440.0000,3450.0000,3477.0000,3501.0000,3532.0000,3534.0000,3562.0000,3586.0000,3609.0000,3624.0000,3648.0000,3669.0000,3691.0000,3706.0000,3741.0000,3750.0000,3766.0000,3787.0000,3811.0000,3829.0000,3846.0000,3872.0000,3888.0000,3911.0000,3934.0000,3952.0000,3962.0000,3987.0000]
▲ 图1.2.2 利用万用表测量输入和ADC输出
重新测量 0.25V之内的电压与ADC的数值, 数据测量结果显示, 当输入电压小于 50mV, ADC转换结果都是0。 为什么会有这个死区, 现在还不知道原因。
▲ 图1.2.3 输入与ADC的数值
三、采样时间
采样数值中存在着一些随机的噪声。 设置通道0 采样时间为 1.5个时钟周期, 对应的采样方差为 950. 设置采样时间周期为 239, 对应的数据方差为 1037, 这说明通道的采样时间对于数据的噪声没有太大的影响。 将采样 256 个数据进行平均, 输出数据的方差就可以降低到 6.8。 这说明在使用 ADC的时候, 引入平均滤波可以大大降低数据中的随机噪声。
▲ 图1.3.2 采样周期为1.5时对应的数据
-
采样时间与数据:
-
采样时间
:1.5
平均值
:1172
方差
:950
▲ 图1.3.2 采样时间为 239.5时对应的采样数据
-
采样时间与数据:
-
采样时间
:239.5
平均值
:1165
方案
:1037
▲ 图1.3.3 256个数据平均值后的采样数据
-
256个数据平均:
-
平均值
:1165
方差
:6.84
#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# TEST2.PY -- by Dr. ZhuoQing 2024-02-09
#
# Note:
#============================================================
from headm import *
from tsmodule.tsvisa import *
import socket
dh1766volt1(1)
#------------------------------------------------------------
UDP_HOST = '127.0.0.1'
UDP_PORT = 2244
UDP_BUFSIZE = 0x1000
db = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
db.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, UDP_BUFSIZE)
db.settimeout(0.2)
def dbsend(data):
ADDR = (UDP_HOST, UDP_PORT)
if type(data) != str:
data = str(data)
data = bytes(data, 'gbk')
db.sendto(data, ADDR)
def dbrecv():
try:
data, ADDR = db.recvfrom(UDP_BUFSIZE)
except socket.timeout:
printf('Meter time out.')
data = ''
if len(data) > 0:
return data.decode('utf-8')
else: return ''
def dbval():
dbsend('MEMOS')
splitstr = dbrecv().split(' ')
data = []
for val in splitstr:
if len(val) > 0:
data.append(eval(val))
return data
#------------------------------------------------------------
#dbsend('adc0')
#dbsend('CLEAR')
dbsend('COPY')
time.sleep(.2)
sss = clipboard.paste().split('\r\n')[-1].strip(" ").split(' ')
dim = [int(d) for d in sss]
printf(mean(dim), var(dim))
plt.plot(dim, lw=3)
plt.xlabel("N")
plt.ylabel("Value")
plt.grid(True)
plt.tight_layout()
plt.show()
printf(sss)
#------------------------------------------------------------
printf("\a")
#------------------------------------------------------------
# END OF FILE : TEST2.PY
#============================================================
※ 总 结 ※
本文对 STM32F373中的普通ADC进行了测试, 在输入电压小于 50mV 的时候出现了死区, 具体原因不太清楚。 需要通过数据的平均减少采集数据的随机波动。
● 相关图表链接: