pycharm控制STM32F103ZET6拍照并上位机接收显示(OV7670、照相机、STM32、TFTLCD)

基于STM32的照相机

  • 准备工作
  • 最终效果
  • 一、下位机
    • 1、主函数
    • 2、OV7670初始化
  • 二、上位机
    • 1、控制拍照
    • 2、接收图片数据
  • 三、资源获取

准备工作

一、硬件及片上资源:
1,串口1(波特率:921600,PA9/PA10通过usb转ttl连接电脑,或者其他方法)上传图片数据至上位机
2,串口2(波特率:115200,PA2/PA3通过usb转ttl连接电脑,或者其他方法)控制拍照
3,2.8寸TFTLCD模块
4,按键KEY1(PE3)
5,SD卡
6,外部中断8(PA8,用于检测OV7670的帧信号)
7,定时器6(用于打印摄像头帧率)
8,带FIFO的OV7670摄像头模块
9、STM32F103ET6
10、USB转TTL模块两个
11、STLINK(其他下载器也可以:DSP、JTAG…)
二、软件:
1、pycharm
2、keil5-MDK
3、串口调试助手(XCOM)
三、连线:
在代码中都有。

最终效果

开机的时候先检测字库,然后检测SD卡根目录是否存在PHOTO文件夹,如果不存在则创建,如果创建失败,则报错(提示拍照功能不可用)。在找到SD卡的PHOTO文件夹后,开始初始化OV7670,在初始化成功之后,就一直在TFTLCD上显示OV7670拍到的内容。当上位机按下拍照时,进行拍照,此时DS1亮,照片通过串口发送至上位机,当DS1灭之后,拍照成功。(也可以自己改一改用板子的按键控制拍照)
1、实物图:
在这里插入图片描述
2、上位机效果:
在这里插入图片描述

一、下位机

代码过多过长这里只展示重要的:

1、主函数

 int main(void){	 u8 res;	u8 *pname;				//带路径的文件名		   u16 i;	delay_init();	    	 //延时函数初始化	  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级uart_init1(921600);	 	//串口初始化为115200uart_init2(115200);	usmart_dev.init(72);		//初始化USMART		LED_Init();		  			//初始化与LED连接的硬件接口KEY_Init();					//初始化按键LCD_Init();			   		//初始化LCD    BEEP_Init();        		//蜂鸣器初始化	 W25QXX_Init();				//初始化W25Q128my_mem_init(SRAMIN);		//初始化内部内存池exfuns_init();				//为fatfs相关变量申请内存  f_mount(fs[0],"0:",1); 		//挂载SD卡 f_mount(fs[1],"1:",1); 		//挂载FLASH. EXTI8_Init();				//使能定时器捕获EXTIX_Init();POINT_COLOR=RED;      USART_SendData(USART2,0x31);while(USART_GetFlagStatus(USART2,USART_FLAG_TC)!=SET);//等待发送结束								   						    pname=mymalloc(SRAMIN,30);	//为带路径的文件名分配30个字节的内存		    while(pname==NULL)			//内存分配出错{	    Show_Str(30,190,240,16,"内存分配失败!",16,0);delay_ms(200);				  LCD_Fill(30,190,240,146,WHITE);//清除显示	     delay_ms(200);				  }   											  while(OV7670_Init())//初始化OV7670{Show_Str(30,190,240,16,"OV7670 错误!",16,0);delay_ms(2000);LCD_Fill(30,190,239,206,WHITE);delay_ms(2000);}delay_ms(10000);Show_Str(30,190,200,16,"OV7670 normal",16,0);delay_ms(14444);	delay_ms(14444);										  OV7670_Light_Mode(0);//0OV7670_Color_Saturation(0);OV7670_Brightness(2);//0OV7670_Contrast(2);//0OV7670_Special_Effects(0);OV7670_Window_Set(12,176,240,320);	//设置窗口	  OV7670_CS=0;				    		    LCD_Clear(BLACK);while(1){	if(Res_com2 == 0x31){delay_ms(1800);Res_com2 = 0;//Res_com = 0;LED1=0;	//点亮DS1,提示正在拍照res=bmp_encode(pname,(lcddev.width-240)/2,(lcddev.height-320)/2,240,320,0);Show_Str(40,130,240,12,"picture_capture_finish!",12,0);	LED1=1;//关闭DS1delay_ms(1800);//等待1.8秒钟LCD_Clear(BLACK);//jjj = 0;}else delay_ms(5);camera_refresh();//更新显示i++;if(i==10000)//DS0闪烁.{i=0;LED0=!LED0;}}	   										    
}

2、OV7670初始化

u8 OV7670_Init(void)
{u8 temp;u16 i=0;	  //设置IOGPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOG|RCC_APB2Periph_AFIO, ENABLE);	 //使能相关端口时钟GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_8; 	//PA8 输入 上拉GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_SetBits(GPIOA,GPIO_Pin_8);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4;				 // 端口配置GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB,GPIO_Pin_3|GPIO_Pin_4);	GPIO_InitStructure.GPIO_Pin  = 0xff; //PC0~7 输入 上拉GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_Init(GPIOC, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_6;  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOD, &GPIO_InitStructure);GPIO_SetBits(GPIOD,GPIO_Pin_6);GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_14|GPIO_Pin_15;  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOG, &GPIO_InitStructure);GPIO_SetBits(GPIOG,GPIO_Pin_14|GPIO_Pin_15);GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);	//SWDSCCB_Init();        		//初始化SCCB 的IO口	   	  if(SCCB_WR_Reg(0x12,0x80))return 1;	//复位SCCB	  delay_ms(50);  //读取产品型号temp=SCCB_RD_Reg(0x0b);   if(temp!=0x73)return 2;  temp=SCCB_RD_Reg(0x0a);   if(temp!=0x76)return 2;//初始化序列	  for(i=0;i<sizeof(ov7670_init_reg_tbl)/sizeof(ov7670_init_reg_tbl[0]);i++){SCCB_WR_Reg(ov7670_init_reg_tbl[i][0],ov7670_init_reg_tbl[i][1]);}return 0x00; 	//ok
} 

二、上位机

1、控制拍照

# 和另一个.py文件一起运行,点击可视化界面的拍照即可拍照
import serial
import time
import tkinter as tkdef send_command():command_to_send = b'\x31\r\n'ser.write(command_to_send)# You can add any additional actions or updates here# Create the serial connection
ser = serial.Serial('COM13', 115200)
time.sleep(2)# Create the Tkinter window
window = tk.Tk()
window.title("Serial control take photos")# Create a button to send the command
send_button = tk.Button(window, text="拍照", command=send_command)
send_button.pack(pady=20)# Run the Tkinter main loop
window.mainloop()# Close the serial connection when the window is closed
ser.close()

2、接收图片数据

# 用波特率为921600的串口接收下位机上传的图片数据,接受的图片会有一点色彩问题,怀疑是传输出现的问题,用高斯滤波就可以基本滤除。
# 注意要连接好串口,板子上好电,这个代码才能运行不然报错找不到串口
import serial
import struct
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
import cv2
import osser = serial.Serial('COM5', 921600)# 初始化一个空的二维数组,用于存储接收到的数据
received_data = np.zeros((320, 240), dtype=np.uint16)# 初始化图像计数器
image_counter = 1
# 全局变量,保存当前索引
image_index = 0
# 设置图像保存目录
save_dir = "pic_receive"# 如果目录不存在,则创建目录
if not os.path.exists(save_dir):os.makedirs(save_dir)while True:# 初始化索引和计数器received_index = 0row = 0col = 0# 接收数据直到收到足够的数据print("可以发送数据")while received_index < 240 * 320:# 读取两个字节的数据data = ser.read(2)# 解析uint16数据color_value = struct.unpack('>H', data)[0]  # '>H'表示大端字节序的uint16# 将数据存入二维数组received_data[row, col] = color_valuecol += 1received_index += 1# 判断是否接收完一行数据if col >= 240:col = 0row += 1# 如果接收完一帧数据,进行解析和显示if row >= 320:# 解析RGB565格式的数据为RGB888格式# 不知道什么原因发上来列发生错误,进行重组selected_columns1 = received_data[:, 0:47]selected_columns2 = received_data[:, 47:240]merged_array = np.concatenate((selected_columns2, selected_columns1), axis=1)rgb888_data = []for i in range(320):for j in range(240):color_value = merged_array[i, j]r = (color_value & 0xF800) >> 8g = (color_value & 0x07E0) >> 3b = (color_value & 0x001F) << 3rgb888_data.append((r, g, b))# 创建RGB888格式的图像对象image = Image.new('RGB', (240, 320))# 将RGB888格式的数据填充到图像对象中image.putdata(rgb888_data)# 保存图像到文件夹image_filename = os.path.join(save_dir, f"{image_counter:010d}.png")image.save(image_filename)# 增加图像计数器image_counter += 1# 显示图像#plt.imshow(image)#plt.show()# 重置二维数组,准备接收下一帧数据received_data = np.zeros((320, 240), dtype=np.uint16)row = 0col = 0# 清空串口接收缓冲区ser.flushInput()

三、资源获取

我用夸克网盘分享了「照相机+双串口+上位机接收并显示.rar」,点击链接即可保存。打开「夸克APP」,无需下载在线播放视频,畅享原画5倍速,支持电视投屏。
链接:https://pan.quark.cn/s/125911f5def1
提取码:Za2E

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/264631.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一文读懂:AWS 网络对等互连(VPC peering)实用操作指南

VPC peering connection-网络对等互连在您的 Atlas VPC 和云提供商的 VPC 之间建立私有连接。该连接将流量与公共网络隔离以提高安全性。本篇文章有VPC peering的操作指南以及价格等信息。如还有疑问请联系我们MongoDB的销售&#xff0c;客户成功经理或解决方案架构师。 1 使用…

【C之·预处理器】

系列文章目录 文章目录 前言一、预处理指令1. #line的用法1.1 概述 2. #error2.1 概述 二、预定义宏三、示例1. #line2. #error3. 预定义宏 总结 前言 C 预处理器不是编译器的组成部分&#xff0c;但是它是编译过程中一个单独的步骤。简言之&#xff0c;C 预处理器只不过是一个…

C++面试宝典第32题:零钱兑换

题目 给定不同面额的硬币coins和一个总金额amount,编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,则返回-1。说明:你可以认为每种硬币的数量是无限的。 示例1: 输入:coins = [1, 2, 5], amount = 11 输出:3 解释:11 = …

如何使用Douglas-042为威胁搜索和事件应急响应提速

关于Douglas-042 Douglas-042是一款功能强大的PowerShell脚本&#xff0c;该脚本可以提升数据分类的速度&#xff0c;并辅助广大研究人员迅速从取证数据中筛选和提取出关键数据。 该工具能够搜索和识别Windows生态系统中潜在的安全漏洞&#xff0c;Douglas-042会将注意力放在…

Mistral发布语言大模型Mistral Large;法国新星Mistral挑战 OpenAI 霸主地位

&#x1f989; AI新闻 &#x1f680; Mistral发布语言大模型Mistral Large 摘要&#xff1a;Mistral Large 是 Mistral AI 公司最新发布的旗舰语言模型&#xff0c;具备顶尖水平的推理能力。它主要被设计用于处理复杂的多语言推理任务&#xff0c;比如文本理解、转换和代码生…

HTTP---------状态码

当服务端返回 HTTP 响应时&#xff0c;会带有一个状态码&#xff0c;用于表示特定的请求结果。比如 HTTP/1.1 200 OK&#xff0c;里面的 HTTP/1.1 表示协议版本&#xff0c;200 则是状态码&#xff0c;OK 则是对状态码的描述。 由协议版本、状态码、描述信息组成的行被称为起始…

【算法与数据结构】684、685、LeetCode冗余连接I II

文章目录 一、684、冗余连接 I二、685、冗余连接 II三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、684、冗余连接 I 思路分析&#xff1a;题目给出一个无向有环图&#xff0c;要求去掉一个边以后构成一个树&#xf…

【iOS ARKit】ARWorldMap

ARWorldMap 用于存储 ARSession 检测扫描到的空间信息数据&#xff0c;包括地标&#xff08;Landmark&#xff09;、特征点&#xff08;Feature Point&#xff09;、平面&#xff08;Plane&#xff09;等&#xff0c;以及使用者的操作信息&#xff0c;如使用者添加的 ARAnchor …

【非比较排序】计算排序算法

目录 CountSort计数排序 整体思想 图解分析 代码实现 时间复杂度&优缺分析 CountSort计数排序 计数排序是一种非比较排序&#xff0c;不需要像前面的排序一样去比较。 计数排序的特性总结&#xff1a; 1. 计数排序在数据范围集中时&#xff0c;效率很高&#xff0c;但…

golang gin单独部署vue3.0前后端分离应用

概述 因为公司最近的项目前端使用vue 3.0&#xff0c;后端api使用golang gin框架。测试通过后&#xff0c;博文记录&#xff0c;用于备忘。 步骤 npm run build&#xff0c;构建出前端项目的dist目录&#xff0c;dist目录的结构具体如下图 将dist目录复制到后端程序同级目录…

Unity中URP下实现水体(水面高光)

文章目录 前言一、实现高光反射原理1、原理&#xff1a;2、公式&#xff1a; 二、实现1、定义 _SpecularColor 作为高光反射的颜色2、定义 _SpecularIntensity 作为反射系数&#xff0c;控制高光反射的强度3、定义 _Smoothness 作为高光指数&#xff0c;用于模型高光范围4、模拟…

紫外-可见吸收光谱法(UV-Vis)是最常用吸收光谱技术 市场持续扩大

紫外-可见吸收光谱法&#xff08;UV-Vis&#xff09;是最常用吸收光谱技术 市场持续扩大 紫外-可见吸收光谱法&#xff0c;也称为紫外-可见分光光度法&#xff0c;简称UV-Vis&#xff0c;利用样品分子在紫外和可见光激发下产生电子能级跃迁形成的吸收光谱&#xff0c;对元素进行…

Day 2.exec函数族和线程的基本概念、相关函数接口

exec函数族 extern char **environ; int execl(const char *path, const char *arg, ... /* (char *) NULL */); int execlp(const char *file, const char *arg, ... /* (char *) NULL */); int execle(const…

9.网络游戏逆向分析与漏洞攻防-游戏网络架构逆向分析-接管游戏连接服务器的操作

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;游戏底层功能对接类GameProc的实现 码云地址&#xff08;master 分支&#xff09;&#xff1a;https://gitee.com/dye_your_fingers/titan 码云版本号&#xff1a;44c54d30370d3621c1e9ec3d7fa1e2a0…

全球游戏市场回暖,Flat Ads推动海外获客增长

摘要:热门游戏品类分析,解读新兴市场与赛道 近日,中国音数协游戏工委发布了《2023年中国游戏出海研究报告》,据报告数据显示,2023年,全球游戏市场规模11773.79亿元,同比增长6.00%,呈现增长回暖趋势。 图源:伽马数据 1.SLG和RPG游戏热度居高不下,休闲游戏增长势头强劲 目前,S…

Java四大引用详解:强引用、软引用、弱引用、虚引用

在JDK1.2以前的版本中&#xff0c;当一个对象不被任何变量引用&#xff0c;那么程序就无法再使用这个对象。也就是说&#xff0c;只有对象处于可触及状态&#xff0c;程序才能使用它。这就像在商店购买了某样物品后&#xff0c;如果有用就一直保留它&#xff0c;否则就把它扔到…

进行模型测量这种量出来坡面的是平面面积还是真实面积?

斜面面积&#xff0c;不是表面积。 DasViewer是由大势智慧自主研发的免费的实景三维模型浏览器,采用多细节层次模型逐步自适应加载技术,让用户在极低的电脑配置下,也能流畅的加载较大规模实景三维模型,提供方便快捷的数据浏览操作。 #DasViewer##实景三维##三维重建##三维模型…

基于springboot+vue的音乐网站(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

Java优先级队列--堆

目录 1. 优先级队列 1.1 概念 2.优先级队列的模拟实现 2.1 堆的概念 2.2 堆的存储方式 2.3 堆的创建 2.3.1 堆向下调整 2.3.2 堆的创建 2.3.3 建堆的时间复杂度 2.4 堆的插入与删除 2.4.1 堆的插入 2.4.2 堆的删除 2.5 用堆模拟实现优先级队列 3.常用接口介绍 3…

【Excel PDF 系列】POI + iText 库实现 Excel 转换 PDF

你知道的越多&#xff0c;你不知道的越多 点赞再看&#xff0c;养成习惯 如果您有疑问或者见解&#xff0c;欢迎指教&#xff1a; 企鹅&#xff1a;869192208 文章目录 前言转换前后效果引入 pom 配置代码实现 前言 最近遇到生成 Excel 并转 pdf 的需求&#xff0c;磕磕碰碰总…