到手了一块某夕夕上一百三入手的STM32F407VE的开发板,一个字,香!把玩时发现了DAC这个看起来就很有意思的功能,软件输出了正弦波三角波之后突然想起了示波器的XY模式,刚好这个芯片有一个DAC两路通道,于是便折腾了一下用XY模式显示图形,可以显示图形了要播放视频也就没什么难度了。特此记录分享
简单来说,示波器XY模式就是通道一的电压为X轴,通道二的电压为Y轴,在两个通道确定的一个点上显示,两通道快速扫描就可以画点成线从而显示一些简单图形,DAC可以把坐标数据转换成电压值给示波器,那么我们只要把图形的黑白像素转换为坐标然后让单片机不断用DAC输出坐标,示波器画点成线就显示出图形了

所以示波器显示图形的重难点其实是软件,如何将图形的边缘转换为坐标值让STM32去输出,只需要有那么一个坐标数组,STM32不断地把数组内容输出到DAC寄存器即可。这里就要用到前几天学习的OPENCV知识了,首先考虑最简单的黑白图片,只要将黑线也就是色值为0的像素点坐标输出为C语言数组的格式然后复制到keil里就行了。然而很多图片不是纯黑白的,可能存在灰度,我们就需要先把灰度图经过边缘检测变成黑白单色图再进行上一步操作。代码如下,写得有点复杂大概只能我自己看得懂如果要用建议安装好OPENCV后直接CV
import cv2
MAX_VALUE = 4000
MIN_VALUE = 0
VIDEO = 0
if VIDEO:
fil = open('output.h','w')
def pic2xy(img):
width = img.shape[1]
heigth = img.shape[0]
cv2.imshow('vid', img)
if VIDEO == 0:
print('图片打开成功,图片尺寸为%dX%d像素'%(width,heigth))
cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img = cv2.Canny(img, 100, 200)
if VIDEO == 0:
cv2.imshow('pic', img)
cv2.waitKey(0)
point_list = get_point_list(img) #获取图像二进制点阵
output_list = []
for y in range(heigth):
for x in range(width):
if(point_list[y][x] == 1):
output_list.append([int(x*MAX_VALUE/width),4000-int(y*MAX_VALUE/heigth)])
#获取到XY通道列表
#以数组格式打印列表
i = 0
for data in output_list:
i += 2
print(data[0],end = ', ')
print(data[1],end = ', ')
if i%10 == 0 :
print()
print('\n4096,')
if VIDEO == 0:
print('\n总长度%d'%i)
cv2.waitKey(0)
def get_point_list(img):
global fil
width = img.shape[1]
heigth = img.shape[0]
point_list = [[0 for x in range(width)] for y in range(heigth)]
for y in range(heigth):
for x in range(width):
if img[y][x] == 255:
point_list[y][x] = 1
else:
point_list[y][x] = 0
return point_list
#单张图片
if VIDEO == 0:
img = cv2.imread('pic.png') #图片名
if img is None:
print('打开图片失败')
exit()
pic2xy(img)
if VIDEO == 1:
video = cv2.VideoCapture('bad apple.mp4')
if video.isOpened():
print('视频打开成功')
else:
open = False
print('视频打开失败')
exit()
while 1:
ret,frame = video.read()
if frame is None:
print('视频结束')
break
else:
pic2xy(frame)
可以看到代码只需要cv2一个模块即可,一开始通过VIDEO变量来切换视频或单张图片模式,因为视频是直接在图片的基础上改进,而事先写的图片的操作不太好调用,所以就采用了屎山大法if堆上去,视频部分目前也还没有完工,如果想用图片转坐标只需要把图片和代码放在相同目录下然后修改一下代码后面的图片名即可,代码会提取图片的边缘并且显示出提取后的效果,然后打印出XY坐标数组。



接下来只要在keil里创建一个数组把坐标数据全部复制进去即可,数组长度即为打印出的总长度,需要注意的是最后的4096是视频部分的测试功能在图片部分需要删掉,否则数组长度不匹配会报错。
然后只需要用STM32调用这个数组,把数组里的内容依次塞进XY通道即可,附STM32参考代码
//传入坐标数组和数组长度
void XY_play(unsigned short data_list[],unsigned int len)
{
unsigned int num = 0;
while(num < len)
{
DAC1->DHR12R1 = data_list[num++]; //X通道在前
DAC1->DHR12R2 = data_list[num++]; //Y通道在后
delay_10us; //延迟时间根据芯片性能而定,STM32F407转换时间大概在6us,我选择延迟10us稳定一些
}
}
STM32部分就是这么简单,要实现一个看起来比较硬件的功能没想到重难点居然是软件,所以说还得软硬结合才能融会贯通。虽然播放视频还没做出来,但最后也要传颂经典