stm32调用OV7670获取图像并通过蓝牙传输至PC

问题分析

首先明确需求。用stm32调用OV7670获取图像,并且通过蓝牙传递至PC端。由此我们可以整理到以下几个模块。

  1. 调用OV7670得到图像数据
  2. 将数据通过串口传输到蓝牙
  3. PC端调用蓝牙接收数据并储存

开始调试

1.stm32调用OV7670

这里我主要目的是实现功能,因此程序主要用的是开发板附带的例程,在其基础上做了一些小修改而已。修改部分会在下面提到。

1.1在开发板例程上修改有如下好处:

  1. 开发板的例程可以将图像显示在液晶屏上,便于调试。否则在看不到结果的情况下,调试也无从谈起。
  2. 不需要自己去了解液晶屏的使用,这个和需要的功能并不相关。
  3. 方便。毕竟例程已经是可以直接使用的程序,避免了自己调试移植程序时可能出现的更多bug。

1.2遇到的问题

买到的ov7670引脚与开发板不匹配,不能直接接入开发板带有的camera模块使用。因此得自己连线。此处没有太大问题,对照原理图用杜邦线接好就行了。这是我的连线。在这里插入图片描述
然后用例程之后可以正常从液晶屏看到图像,如图在这里插入图片描述
至于代码的话,毕竟是例程的代码,有stm32的话去对应的论坛上或者找淘宝都能找到。

2.PC端蓝牙接收

问题是需要一步步地去解决的。
首先,先实验电脑端的蓝牙接收功能,这里我们先不采用stm32调用的蓝牙和电脑端的通信。而采用手机蓝牙与电脑蓝牙进行通信测试。我这里采用的python语言。

2.1添加蓝牙虚拟串口

步骤我是参考另外一位博主的设置,这里附上原文链接:
https://blog.csdn.net/px_528/article/details/70782059

2.2使用python的serial库

python关于serial有两个库,一个是serial另一个是pyserial,两者的使用都是import serial。两个都有的话可能会出现错误AttributeError: module ‘serial’ has no attribute ‘Serial’。我的解决办法是卸载了serial库,只安装pyserial库。但是在程序中的使用还是import serial。

2.3运行程序

我的测试程序如下:

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"。

2.4手机输入

使用一款蓝牙调试APP,不知道怎么放下载包,名字是MiniBalance。等程序运行之后,再打开APP,与电脑蓝牙连接。选择第一项蓝牙,与电脑来连接
然后通过以下的键盘发送信息,终止键设置的发送是"i"在这里插入图片描述
按下终止后,程序便会停止。
然后到文件的保存位置找到文件,可以查看其内容。
在这里插入图片描述

3.stm32蓝牙通信

其实只是涉及到蓝牙模块的使用,也并不复杂。进行调试时,为了简化,使用手机上的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);
}

也就是例程里加了两行发送’$'的代码,虽然接受到的数据里也有这个符号,但功能毕竟是实现了,可以进行下一步了。

4.综合整理

这部分就是将三个模块功能整理起来。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')

然后······然后,就成功啦!!!!!
在这里插入图片描述
电脑上:
在这里插入图片描述

遇到的问题

已解决问题

  1. 最早是考虑使用ov7725模块的,但是在把代码对应于ov7725模块改了之后发现ov7725并不能正常工作。
    解决办法:之后用示波器检测过,在输出第一帧图像之后ov7725就再也没有信号输出了。有可能是极小概率碰到了坏模块,但也可能是不会使用,于是重新购买了一块ov7670模块,解决,可能还是ov7725损坏。(这个占据了大部分时间······等快递······)
  2. 图像的保存问题咯。
    解决办法:查资料,学习图片文件储存格式。并且分析现有图片的格式。最后在目的的驱动下使用取巧的方法。但是要适用更大的范围也得仔细了解一下图像格式的具体实现。

现存问题

  1. 传输速率太慢,波特率只有9600。可以通过AT指令调节蓝牙模块,以及其他对应的代码,提高波特率。这是可以解决的,不过,先发一篇blog再说吧hhhhh,等会再调。

然后,写blog真累······

评论 27
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值