【毕业设计】基于STM32的无线WIFI投影设计(解析BMP、TCP通讯)

文章介绍了在STM32平台上解析BMP文件并在屏幕上显示的过程,重点是BMP文件格式的解析和内存与屏幕显示的对应关系。硬件设计中,STM32通过IIC与屏幕连接,通过串口与ESP-01S无线模块通信。软件部分涉及main.c和bitmap.c的代码实现,包括文件头验证、图片大小检查以及像素值转换。难点在于将BMP像素数据转换为屏幕可识别的顺序。
摘要由CSDN通过智能技术生成

目录

0 引言

1 硬件设计

 框图:

2 软件设计

main.c

bitmap.c

3 重点难点(BMP文件格式解析、内存与屏幕显示的对应)

4 写在最后


 

 

0 引言

     有幸做过一个无线传输的设计,有关BMP文件格式在STM32上的解析,更难的在于文件中图片的像素值与屏幕的一一对应关系,在这里跟大家分享出来。

1 硬件设计

    这里没有什么难点,简要说明。

  1. STM32主控与屏幕使用IIC总线连接。
  2. STM32主控与ESP-01S无线透传模块通过串口进行连接。
  3. ULN2003驱动步进电机。(这里不赘述)

 框图:

9b04d3f80a6940fb923249758b94b8cf.png

2 软件设计

直接上代码。

main.c

#include "sys.h"
#include "delay.h"
#include "usart.h"	

#include "step_motor.h"
#include "oled.h"
#include "bmp.h"
#include "led.h"
#include "common.h"
#include "malloc.h"
#include "bitmap.h"

int main(void)
{	
	vu16 t = 0,cnt = 0;
	u8 constate=0;	//连接状态
	u8 res = 0;
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
	delay_init();	    	 //延时函数初始化	  
	uart_init(115200);	 //串口初始化为115200
	LED_Init();
	Step_Motor_GPIO_Init();
	mem_init();				//初始化内存池

	OLED_Init();
	OLED_ColorTurn(0);//0正常显示,1 反色显示
	OLED_DisplayTurn(1);//0正常显示 1 屏幕翻转显示

	//--------------------开始WIFI配置----------------------//
	while(atk_8266_send_cmd("AT","OK",20))//检查WIFI模块是否在线
	{	
		atk_8266_quit_trans();//退出透传
		atk_8266_send_cmd("AT+CIPMODE=0","OK",20);  //关闭透传模式	
		delay_ms(800);
	}
	delay_ms(200);
	while(atk_8266_send_cmd("ATE0","OK",20));//关闭回显	
	atk_8266_wifista_tcp();
	//--------------------结束WIFI配置----------------------//	
/*	OLED_ShowChinese(0,0,0,16,1);
	OLED_ShowChinese(16,0,1,16,1);
	OLED_ShowChinese(32,0,2,16,1);*/
	OLED_ShowString(0,0,"SSID:ESP8266",16,1);
	OLED_ShowString(0,16,"KEY:1234567890",16,1);
	OLED_ShowString(0,32,"IP:192.168.4.1",16,1);
	OLED_ShowString(0,48,"Port:8086",16,1);
	while(1)
	{			
		delay_ms(10);
		OLED_Refresh();
		if(USART_RX_STA&0X8000)		//接收到一次数据了
		{ 
			res = getDataFromUart();//  +IPD,0,1088:BM>......
			if(res)//若收到数据
			{
				res = 0;
				getBitmapInfo(bitmap_buf);
			}
//			rlen=USART_RX_STA&0X7FFF;	//得到本次接收到的数据长度
//			USART_RX_BUF[rlen]=0;		//添加结束符 
//			printf("%s",USART_RX_BUF);	//发送到串口   
			//sprintf((char*)p,"收到%d字节,内容如下",rlen);//接收到的字节数  
			USART_RX_STA=0;
			if(constate!='+')cnt=200;		//状态为还未连接,立即更新连接状态
			else cnt=0;                   //状态为已经连接了,10秒后再检查
		}  
		cnt++;
		t++;
		if(cnt>=200)//连续10秒钟没有收到任何数据,检查连接是不是还存在.
		{
			constate=atk_8266_consta_check();//得到连接状态
			cnt=0;
		}
		if(t==10)
		{
			t = 0;
			LED = !LED;
		}
//		OLED_Clear();
	}
}

bitmap.c

#include "malloc.h"
#include "bitmap.h"
#include "oled.h"

u8 bitmap_buf[1088];


/****获取bmp格式文件信息*********/
/*	返回值 	0 	成功			*/
/*			1	失败			*/
/*		入口参数	缓冲区首地址*/
/********************************/
u16	getBitmapInfo(u8 *ptr)
{
	BITMAP_FILE_HEADER *fileHead;//文件头
	BITMAP_INFO_HEADER *infoHead;//信息头
	vu8 buf;
	vu8 buff=0x00;
	u8 *display_buf;
	u8 *p;
	volatile int i,j,k,l;
	
	fileHead = (BITMAP_FILE_HEADER*)ptr;
	infoHead = (BITMAP_INFO_HEADER*)(ptr + sizeof(BITMAP_FILE_HEADER));
	if(fileHead->bfType != 0x4D42)//验证文件头
    {
        return 1;//返回失败
    }
	if(infoHead->biWidth != 128 || infoHead->biHeight != 64)//验证图片大小
	{
		 return 1;//返回失败
	}
	display_buf = (u8*)mymalloc(infoHead->biSizeImage);//申请1024字节的内存用于存储
	p = display_buf;
	for(i=63;i>=0;i=i-8)//这里将bmp格式转换为oled可以识别的字节顺序
	{
		for(j=0;j<16;j++)
		{
			for(l = 0;l<8;l++)
			{
				buff = 0;
				for(k=0;k<8;k++)
				{
					buf = ((u8(*)[16])(ptr+fileHead->bfOffBits))[i-k][j];
					if(((~buf)&(0x80>>l)))
					{
						buff |= 1<<k;
					}
					else
					{
						buff &= ~(1<<k);
					}
				}
				*p++ = buff;
				if(p-display_buf>1023)
				{
					p = display_buf;
				}
			}
		}
	}
	OLED_ShowPicture(0,0,128,64,display_buf,1);

	myfree(display_buf);
	return 0;
}

3 重点难点(BMP文件格式解析、内存与屏幕显示的对应)

    光有代码没有用,主要是当时提取BMP文件的图片信息就耗费了很长时间;另外,还需要将像素矩阵的顺序跟屏幕刷新时的顺序相对应,具体要看用的什么屏幕驱动,这里是将像素矩阵转置后再把每行倒序输入进屏幕缓存就可以。

注:每个屏幕驱动都不一样,历经1年多我也忘记我的是什么顺序了,反正就是要调整顺序的意思。

首先,判断是都未BMP文件,判断文件头。

	if(fileHead->bfType != 0x4D42)//验证文件头
    {
        return 1;//返回失败
    }

 然后,判断图片大小,因为是128x64的屏幕,因此我这里只显示128x64的图片。

	if(infoHead->biWidth != 128 || infoHead->biHeight != 64)//验证图片大小
	{
		 return 1;//返回失败
	}

最后,重中之重,提取BMP文件的像素并转换成屏幕可以识别的顺序。(笨办法,多重for循环之术

    display_buf = (u8*)mymalloc(infoHead->biSizeImage);//申请1024字节的内存用于存储
	p = display_buf;
	for(i=63;i>=0;i=i-8)//这里将bmp格式转换为oled可以识别的字节顺序
	{
		for(j=0;j<16;j++)
		{
			for(l = 0;l<8;l++)
			{
				buff = 0;
				for(k=0;k<8;k++)
				{
					buf = ((u8(*)[16])(ptr+fileHead->bfOffBits))[i-k][j];
					if(((~buf)&(0x80>>l)))
					{
						buff |= 1<<k;
					}
					else
					{
						buff &= ~(1<<k);
					}
				}
				*p++ = buff;
				if(p-display_buf>1023)
				{
					p = display_buf;
				}
			}
		}
	}
	OLED_ShowPicture(0,0,128,64,display_buf,1);

	myfree(display_buf);

4 写在最后

难点解决了就很简单了,就是通过TCP将图片传输过来,单片机收到数据后进行数据解析。

演示视频稍后放出。


各位大佬,码字不易,如果需要完整代码,可以交流联系。

 

 

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AFeii2

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值