首先明确需求。用stm32调用OV7670获取图像,并且通过蓝牙传递至PC端。由此我们可以整理到以下几个模块。
这里我主要目的是实现功能,因此程序主要用的是开发板附带的例程,在其基础上做了一些小修改而已。修改部分会在下面提到。
买到的ov7670引脚与开发板不匹配,不能直接接入开发板带有的camera模块使用。因此得自己连线。此处没有太大问题,对照原理图用杜邦线接好就行了。这是我的连线。
然后用例程之后可以正常从液晶屏看到图像,如图
至于代码的话,毕竟是例程的代码,有stm32的话去对应的论坛上或者找淘宝都能找到。
问题是需要一步步地去解决的。
首先,先实验电脑端的蓝牙接收功能,这里我们先不采用stm32调用的蓝牙和电脑端的通信。而采用手机蓝牙与电脑蓝牙进行通信测试。我这里采用的python语言。
步骤我是参考另外一位博主的设置,这里附上原文链接:
https://blog.csdn.net/px_528/article/details/70782059
python关于serial有两个库,一个是serial另一个是pyserial,两者的使用都是import serial。两个都有的话可能会出现错误AttributeError: module ‘serial’ has no attribute ‘Serial’。我的解决办法是卸载了serial库,只安装pyserial库。但是在程序中的使用还是import serial。
我的测试程序如下:
import serial
ser = serial.Serial("com3", 9600, timeout=0.5)
f = open("F:/python/test.txt", "w+b")
while True:
data = ser.read()
if data == b'':
continue
elif data == b'i':
break
else:
f.write(data)
f.close()
ser.close()
从蓝牙获取输入,然后保存为一个txt文件。输入终止符号是"i"。
使用一款蓝牙调试APP,不知道怎么放下载包,名字是MiniBalance。等程序运行之后,再打开APP,与电脑蓝牙连接。
然后通过以下的键盘发送信息,终止键设置的发送是"i"
按下终止后,程序便会停止。
然后到文件的保存位置找到文件,可以查看其内容。
其实只是涉及到蓝牙模块的使用,也并不复杂。进行调试时,为了简化,使用手机上的APP和stm32通过蓝牙通信。蓝牙模块使用的是hc-05。
stm32使用蓝牙比较简单,将蓝牙与stm的串口相连就行。VCC,GND,RXD,TXD分别与stm32对应端口相连就行了。对应原理图,PA9和PA10分别是stm32的usart1的TX和RX,如图
测试时和普通串口没有太大区别,也只是向蓝牙发送一个数据后,stm32发送回一个数据。值得一提的是,蓝牙发送数据需要有一个’$'符号才能被手机端接受,这个我也没有弄清楚是什么回事。
图没有及时记录,也懒得在去照,参考一下上面过程就行。贴上串口中断的代码。
void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 r;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
{
r =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
USART_SendData(USART1,r);
while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);
USART_SendData(USART1,'$'); //发送'$'
while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);
}
USART_ClearFlag(USART1,USART_FLAG_TC);
}
也就是例程里加了两行发送’$'的代码,虽然接受到的数据里也有这个符号,但功能毕竟是实现了,可以进行下一步了。
这部分就是将三个模块功能整理起来。stm32通过ov7670获取图像数据,再将其通过串口蓝牙发送出去。由PC端接收。
这里就涉及到了格式问题。ov7670获取的图象的每个像素是16位RGB565格式,而电脑上比较类似的图片储存方式是16位bmp,像素是RGB555格式,于是要将像素格式进行转换,再发送。而且,串口发数据是每次发送一个字节。将一个像素分两次发送。涉及到电脑上的储存规律,像素的低八位在前,高八位在后,于是便先发送低八位,后发送高八位。具体格式的实现也是参考了其他博主的博客,我也不多赘述,代码如下:
//color是已经读取到的一个格式为RGB565格式的像素,类型为u16
//这里将其转换为RGB555格式的数据send
u8 r, g, b, temp;
u16 send;
r = 0x1f&(color>>11);
g = 0x1f&(color>>6);
b = 0x1f&color;
send = (r<<10)|(g<<5)|b;
temp = send&0x00ff; //准备发送数据,低八位
USART_SendData(USART1,temp);
while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);
temp = send>>8; //高八位
USART_SendData(USART1,temp);
while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);
然后需要做的就是在pc端接受并保存。
仍然使用python语言。这里涉及16位bmp格式图片的数据储存问题,除了像素之外还有文件头,具体格式我也说不太清,感兴趣的可以自行搜索一下,我这里采用的一个比较取巧的办法。
拜托一个同学用PS帮我生成了三张图片,纯黑,纯红,纯蓝的16位320240像素bmp格式图片各一张,这里也感谢一下我这个同学-v-。然后查看他们的16进制形式,其中相同的部分就是文件头。因为我要保存的就是16位320240像素的图片。读取它们的文件头写到我要保存的文件中,然后再写像素就行了。
这是红色:
下面是蓝色:
可以看到前54位是一样的。不一样的是后面像素的部分。
代码如下:
import serial
ser = serial.Serial("com6", 9600) # 和hc-05配对后就有了com6串口,而且只有这个串口
f = open("F:/python/test.bmp", "w+b") # 能实现功能下面附图
fr = open("D:/Users/13008/Desktop/test.bmp", "rb")
head = fr.read(54)
f.write(head)
i = 320 * 240 * 2
while i > 0:
data = ser.read()
if data == b'':
continue
else:
f.write(data)
i -= 1
只有com6能实现需要的功能。
但是仅是这样的代码还是出现了问题,图像出了问题,没有保存,也懒得再去弄······经过排查,觉得可能是传输过程中丢包了。并且发现比之前三张图片最后少了两个字节,三张图片里最后都是’0x00’‘0x00’,于是稍稍魔改了一下代码:
import serial
ser = serial.Serial("com6", 9600)
f = open("F:/python/test.bmp", "w+b")
fr = open("D:/Users/13008/Desktop/test.bmp", "rb")
head = fr.read(54)
f.write(head)
f.write(b'\x00')
for i in range(320 * 240 * 2 - 1)
data = ser.read()
if data == b'':
continue
else:
f.write(data)
i -= 1
f.write(b'\x00\x00')
然后,写blog真累······