STM32 OLED12864播放视频

作为一名爱困把哥哥放在屏幕上分为几步?

请添加图片描述

必要的工具得有

  1. 一块STM32的单片机或者开发板
  2. keill编译器
  3. VS studio 装有c++,python模块 ** 用别的工具也行**
  4. 图片处理的工具
  5. STM32 cubeMX
  6. 没了

第一步下载视频

这一步请自助选择喜欢的视频

第二步将视频分解成图片

  1. 打开VS studio新建一个python工程
    请添加图片描述
    请添加图片描述
  2. 然后输入下面的py代码
import cv2
def getpic(videoPath, svPath):#两个参数,视频源地址和图片保存地址
    cap = cv2.VideoCapture(videoPath)

    numFrame = 0
    while True:
        # 函数cv2.VideoCapture.grab()用来指向下一帧,其语法格式为:
        # 如果该函数成功指向下一帧,则返回值retval为True
        if cap.grab():
            # 函数cv2.VideoCapture.retrieve()用来解码,并返回函数cv2.VideoCapture.grab()捕获的视频帧。该函数的语法格式为:
            # retval, image = cv2.VideoCapture.retrieve()image为返回的视频帧,如果未成功,则返回一个空图像。retval为布尔类型,若未成功,返回False;否则返回True
            flag, frame = cap.retrieve()
            if not flag:
                continue
            else:
                numFrame += 1
                #设置图片存储路径
                newPath = svPath + str(numFrame).zfill(5) + ".jpg"
                #注意这块利用.zfill函数是为了填充图片名字,即如果不加这个,那么图片排序后大概就是1.png,10.png,...2.png,这种顺序合成视频就会造成闪烁,因此增加zfill,变为00001.png,00002.png;可以根据生成图片的数量大致调整zfill的值
                # cv2.imencode()函数是将图片格式转换(编码)成流数据,赋值到内存缓存中;主要用于图像数据格式的压缩,方便网络传输。
                cv2.imencode('.jpg', frame)[1].tofile(newPath)
                print(numFrame)
        else:
            break
getpic("C:\\Users\\Administrator\\Pictures\\坤哥.mp4", "C:\\Users\\Administrator\\Pictures\\坤哥")
print("all is ok")

** CV2报错的参考这位博主的方法
在这里插入图片描述
3. 然后 调试->开始执行(不调试)
在这里插入图片描述
在这里插入图片描述

第三步将图片转换成BMP文件并调整大小

  1. 打开图像处理软件
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

第四步将BMP转化并压缩成数组

  1. 打开VS studio新建一个C++程序
    在这里插入图片描述

在这里插入图片描述

#include"stdio.h"
#include"stdlib.h"

#include"string.h"
typedef struct {
	/* type : Magic identifier,一般为BM(0x42,0x4d) */
	unsigned char type[2];
	unsigned int size;/* 文件大小(以字节为单位),全部的档案大小 */
	unsigned int reserved1; /* 保留位 */
	unsigned int offset;/* 图像数据的偏移量,字节 */
}BMP;
typedef struct {
	unsigned int bitSize;//位图信息头大小
	unsigned int biWidth;//图象宽度,像素单位
	unsigned int biHeight;//图象高度,像素单位
	short int    biPlanes;//位平面树=1
	short int    biBitCount;//单位像素的位数,表示bmp图片的颜色位数,即24位图、32位图
	unsigned int biCompression;//图片的压缩属性,bmp图片是不压缩的,等于0
	unsigned int biSizeImage;//表示bmp图片数据区的大小,当上一个属性biCompression等于0时,这里的值可以省略不填
	unsigned int biXPlosPerMeter;//水平分辨率,可省略
	unsigned int biYPlosPerMeter;//垂直分辨率,可省略
	unsigned int biClrUsed;//表示使用了多少个颜色索引表,一般biBitCount属性小于16才会用到,等于0时表示有2^biBitCount个颜色索引表
	unsigned int biClrImportant;//表示有多少个重要的颜色,等于0时表示所有颜色都很重要
}BMPXINXI;//位图信息头,40字节
char zancun[64][128], * Zancun = (char*)zancun;//用来存放图片所有的点 
int byte_num = 0;//输出字节数计数
void ShuZu(short int* tu);
void BMPjie(FILE* fp)
{
	BMP JBMP = { 0 };
	BMPXINXI BMPxinxi = { 0 };//信息头结构 
	int i;
	JBMP.type[0] = fgetc(fp);//BM属性 
	JBMP.type[1] = fgetc(fp);
	for (i = 0; i < 4; i++)//文件大小 
	{
		JBMP.size >>= 8;
		JBMP.size |= fgetc(fp) << 24;
	}
	for (i = 0; i < 4; i++)fgetc(fp);
	for (i = 0; i < 4; i++)//数据偏移量 
	{
		JBMP.offset >>= 8;
		JBMP.offset += fgetc(fp) << 24;
	}
	printf("%c%c\n%dKB\n%x\n", JBMP.type[0], JBMP.type[1], JBMP.size / 1024, JBMP.offset);
	//下面信息头

	for (i = 0; i < 4; i++)
	{
		BMPxinxi.bitSize >>= 8;
		BMPxinxi.bitSize |= fgetc(fp) << 24;
	}
	for (i = 0; i < 4; i++)
	{
		BMPxinxi.biWidth >>= 8;
		BMPxinxi.biWidth |= fgetc(fp) << 24;
	}
	for (i = 0; i < 4; i++)
	{
		BMPxinxi.biHeight >>= 8;
		BMPxinxi.biHeight |= fgetc(fp) << 24;
	}
	for (i = 0; i < 2; i++)
	{
		BMPxinxi.biPlanes >>= 8;
		BMPxinxi.biPlanes |= fgetc(fp) << 8;
	}
	for (i = 0; i < 2; i++)
	{
		BMPxinxi.biBitCount >>= 8;
		BMPxinxi.biBitCount |= fgetc(fp) << 8;
	}
	for (i = 0; i < 4; i++)
	{
		BMPxinxi.biCompression >>= 8;
		BMPxinxi.biCompression |= fgetc(fp) << 24;
	}
	for (i = 0; i < 4; i++)
	{
		BMPxinxi.biSizeImage >>= 8;
		BMPxinxi.biSizeImage |= fgetc(fp) << 24;
	}
	for (i = 0; i < 4; i++)
	{
		BMPxinxi.biXPlosPerMeter >>= 8;
		BMPxinxi.biXPlosPerMeter |= fgetc(fp) << 24;
	}
	for (i = 0; i < 4; i++)
	{
		BMPxinxi.biYPlosPerMeter >>= 8;
		BMPxinxi.biYPlosPerMeter |= fgetc(fp) << 24;
	}
	for (i = 0; i < 4; i++)
	{
		BMPxinxi.biClrUsed >>= 8;
		BMPxinxi.biClrUsed |= fgetc(fp) << 24;
	}
	for (i = 0; i < 4; i++)
	{
		BMPxinxi.biClrImportant >>= 8;
		BMPxinxi.biClrImportant |= fgetc(fp) << 24;
	}
	for (i = 0; i < JBMP.offset - 54; i++)fgetc(fp);//补齐数据区	
	printf("\n位图信息头大小%d\n图象宽度%x\n图象高度%x\n%x\n单位像素的位数%d\n图片的压缩属性%x\n图片数据区的大小\
	 %x\n水平分辨率%x\n垂直分辨率%x\n多少个颜色索引表%x\n有多少个重要的颜色%x\n", BMPxinxi.bitSize, \
		BMPxinxi.biWidth, BMPxinxi.biHeight, BMPxinxi.biPlanes, BMPxinxi.biBitCount, \
		BMPxinxi.biCompression, BMPxinxi.biSizeImage, BMPxinxi.biXPlosPerMeter, BMPxinxi.biYPlosPerMeter, \
		BMPxinxi.biClrUsed, BMPxinxi.biClrImportant);

	if (BMPxinxi.biBitCount == 1)
	{
		unsigned int DATAX = (BMPxinxi.biBitCount * BMPxinxi.biWidth + 31) / 8;
		DATAX = DATAX / 4 * 4;
		unsigned int DATAY = BMPxinxi.biHeight;

		short int* bmp = (short int*)calloc((DATAY + 1) * DATAX, sizeof(short int));//申请内存存放图片信息 
		short int* tu = (short int*)calloc(16 * 64, sizeof(short int));//申请内存处理完成的图片 

		for (i = DATAY - 1; i >= 0; i--)//读取图片 
		{
			for (int j = 0; j < DATAX; j++)
			{
				bmp[i * DATAX + j] = fgetc(fp);
			}
		}
		int f = 0; printf("\n");
		for (i = 0; i < DATAY; i++)//把所有的点分开,存放到二维数组中 
		{
			for (int j = 0, p = 0; j < DATAX; j++)
			{
				for (int x = 0; x < 8; x++)
				{
					if (bmp[i * DATAX + j] & 0x80)
					{
						Zancun[f] = 0;
					}
					else {
						Zancun[f] = 1;
					}
					bmp[i * DATAX + j] <<= 1;
					p++;
					f++;
					if (p >= BMPxinxi.biWidth)break;
				}
				if (p >= BMPxinxi.biWidth)break;
			}
		}

		for (int f = 0; f < 8; f++)//把二维数组中的点转化为OLED所需的数据 
		{
			for (i = 0; i < 128; i++)
			{
				for (int b = 0; b < 8; b++)
				{
					tu[f * 128 + i] >>= 1;
					if (zancun[f * 8 + b][i])
						tu[f * 128 + i] |= 0x80;
				}
			}
		}
		printf("开始压缩数据");
		ShuZu(tu);//压缩并打印到文件 
		printf("压缩数据完成");

		free(tu);
		free(bmp);
		printf("%d\t%d\t", DATAX, DATAY);
	}
	fclose(fp);
}
struct {
	FILE* fp;//保存BMP.h的文件句柄用于写文件尾
	int shuliang; //保存处理了多上张图片 
}BMP_FLIE = { NULL,0 };

void ShuZu(short int* tu)
{
	static int i = 1, flag = 1;
	FILE* fp = BMP_FLIE.fp;//保存BMP.h的文件句柄
	short int dat, j = 0, shu = 0, ge = 1;
	if (flag == 1)//打印文件头 
	{
		fprintf(fp, "#ifndef __BMP_H\n#define __BMP_H\n");
		fprintf(fp, "typedef struct //解码结构体\n{\n\tunsigned char len1;//数据长度\n\tunsigned char dat;//数据\n}JIEYA_char;\n");
		flag = 0;
	}
	BMP_FLIE.shuliang = i + 1;//保存处理了多上张图片  
	fprintf(fp, "const unsigned char BMP%d[] =                  // tuxiang%d\n{\n\t", i, i);//32单片机
	i++;
	j++;//行计数器自加 
	for (;;)
	{
		dat = *tu;
		while (*++tu == dat) {
			ge++;
			shu++;
			if (shu >= 16 * 64)break;
		}
		shu++;
		while (ge)
		{

			fprintf(fp, "0X%02X,0X%02X,", ge > 0xfe ? 0xfe : ge & 0xff, dat);
			if (ge > 0xfe)ge -= 0xfe;
			else ge = 0;
			byte_num += 2;//输出字节数计数
			j += 2;
			if (j >= 18) {
				j = 0;
				fprintf(fp, "\n\t");
			}
		}
		if (shu >= 16 * 64)break;
		ge = 1;
	}
	fprintf(fp, "0XFF,0XFF			//最后二位是结束符\n};\n");

}
int main()
{
	int i = 1;
	char mulu[100];
	FILE* fp = NULL;

	fopen_s(&BMP_FLIE.fp, "C:\\Users\\Administrator\\Pictures\\坤哥\\BMP\\BMP.h", "w");//打开要输出的目标文件

	if (BMP_FLIE.fp != NULL)printf("BMP打开成功\n");

	while (1)
	{
		fp = NULL;
		//if (i % 3 == 0)i++;//内存不够用这条代码剔除部分图片(每隔3张剔除一张)
		sprintf_s(mulu, 100, "C:\\Users\\Administrator\\Pictures\\坤哥\\BMP\\image%03d.bmp", i++);//BMP图片地址
		printf("%s\n", mulu);
		fopen_s(&fp, mulu, "rb");
		if (fp == NULL)break;

		BMPjie(fp);

	}

	fprintf(BMP_FLIE.fp, "const unsigned char *BMP[]={\n\t");
	for (i = 1; i < BMP_FLIE.shuliang; i++)
	{
		if (i % 15 == 0)fprintf(BMP_FLIE.fp, "\n\t");
		fprintf(BMP_FLIE.fp, "BMP%d,", i);
	}
	fprintf(BMP_FLIE.fp, "\n//byte_num=%d,BMP_num=%d\n", byte_num, BMP_FLIE.shuliang - 2);//输出字节数计数
	fprintf(BMP_FLIE.fp, "\n};\n\n#endif\n");
	fclose(BMP_FLIE.fp);//释放文件	
	return 0;
}
  1. 然后 调试->开始执行(不调试)
    在这里插入图片描述
    歘一下就好了
    在这里插入图片描述
    输出文件的最后有总的字节数和图片数量
    用byte_num/1024就是所占flash的大小

第五步撸程序

打开STM32cube
新建工程什么的请自行百度
用到了一个硬件IIC
** 有好多没用到的东西,报错删就完了**


#include "oled.h"
#include "i2c.h" 
#include "ziku.h" 
#include "BMP.h"
#define OLED_ADDR 0x78
#define  uint8_t unsigned char 
#define  u32 unsigned int 
uint8_t daxiaoduan;


//OLED的显存
//存放格式如下.
//[0]0 1 2 3 ... 127	
//[1]0 1 2 3 ... 127	
//[2]0 1 2 3 ... 127	
//[3]0 1 2 3 ... 127	
//[4]0 1 2 3 ... 127	
//[5]0 1 2 3 ... 127	
//[6]0 1 2 3 ... 127	
//[7]0 1 2 3 ... 127 			   
void I2C_Write_Len(uint8_t addr,uint8_t jicun,uint16_t len,uint8_t *dat)
{
	HAL_I2C_Mem_Write(&hi2c2,addr,jicun,I2C_MEMADD_SIZE_8BIT,dat,len,1000);
}
void OLED_WR_Byte(unsigned char dat,unsigned char cmd)
{
	if(cmd)
	{
		HAL_I2C_Mem_Write(&hi2c2,OLED_ADDR,OLED_DATA,I2C_MEMADD_SIZE_8BIT,&dat,1,1000);
	}
	else {
		HAL_I2C_Mem_Write(&hi2c2,OLED_ADDR,OLED_CMD,I2C_MEMADD_SIZE_8BIT,&dat,1,1000);
	}
}

/********************************************
// fill_Picture
********************************************/
void fill_picture(unsigned char fill_Data)
{
	unsigned char m,n;
	for(m=0;m<8;m++)
	{
		OLED_WR_Byte(0xb0+m,0);		//page0-page1
		OLED_WR_Byte(0x00,0);		//low column start address
		OLED_WR_Byte(0x10,0);		//high column start address
		for(n=0;n<128;n++)
			{
				OLED_WR_Byte(fill_Data,1);
			}
	}
}
/***********************Delay****************************************/

void Delay_1ms(unsigned int Del_1ms)
{
	HAL_Delay(Del_1ms);
}

//坐标设置

void OLED_Set_Pos(unsigned char x, unsigned char y) 
{ 	OLED_WR_Byte(0xb0+y,OLED_CMD);
	OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
	OLED_WR_Byte((x&0x0f),OLED_CMD); 
}   	  
//开启OLED显示    
void OLED_Display_On(void)
{
	OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
	OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ON
	OLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON
}
//关闭OLED显示     
void OLED_Display_Off(void)
{
	OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
	OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFF
	OLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
}		
//清除行 
void OLED_Clear_Line(uint8_t y1,uint8_t y2)
{	
	uint8_t dat[128]={0};	
 for(;y1<=y2;y1++)  
	{  
		OLED_WR_Byte (0xb0+y1,OLED_CMD);    //设置页地址(0~7)
		OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
		OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址
		I2C_Write_Len(OLED_ADDR,OLED_DATA,128,dat);
	} //更新显示	
}
//清屏 
void OLED_Clear(void)  
{  
	OLED_Clear_Line(0,7);
	
}
void OLED_On(void)  
{  
	OLED_Clear() ;
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示				 
//size:选择字体 16/12 
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size)
{      	
	unsigned char c=0;	
	c=chr-' ';//得到偏移后的值			
	if(x>Max_Column-1){x=0;y=y+2;}
	if(Char_Size ==16)
	{
		OLED_Set_Pos(x,y);	
		I2C_Write_Len(OLED_ADDR,OLED_DATA,8,(uint8_t*)&F8X16[c*16]);;
		OLED_Set_Pos(x,y+1);
			I2C_Write_Len(OLED_ADDR,OLED_DATA,8,(uint8_t*)&F8X16[c*16+8]);;
	}
	else {	
			OLED_Set_Pos(x,y);
			I2C_Write_Len(OLED_ADDR,OLED_DATA,8,(uint8_t*)F6x8[c]);
			
	}
}
//m^n函数
u32 oled_pow(uint8_t m,uint8_t n)
{
	u32 result=1;	 
	while(n--)result*=m;    
	return result;
}				  
//显示2个数字
//x,y :起点坐标	 
//len :数字的位数
//size:字体大小
//mode:模式	0,填充模式;1,叠加模式
//num:数值(0~4294967295);	 		  
void OLED_ShowNum(uint8_t x,uint8_t y,u32 num,uint8_t len,uint8_t size2)
{         	
	uint8_t t,temp;
	uint8_t enshow=0;	
	for(t=0;t<len;t++)
	{
		temp=(num/oled_pow(10,len-t-1))%10;
		if(enshow==0&&t<(len-1))
		{
			if(temp==0)
			{
				OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
				continue;
			}else enshow=1; 
		 	 
		}
	 	OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2); 
	}
} 



uint8_t OLED_Display_str(uint8_t x,uint8_t y,uint8_t *no)
{      			    
	uint8_t i,j,ziku=sizeof(zk)/35;//计算字库数量
	uint8_t flag=0;
	for(i=0;*no;i++)
	{
		if(*no&0x80)//判断是不是汉字,是汉字执行下面
		{
			for(j=0;j<ziku;j++)//遍历字库
			{
				if(zk[j].Index[daxiaoduan]==*no)
				{
					flag=1;break;
				}else flag=0;//	没找着返回0	
			}
			if(flag)
			{
				OLED_Set_Pos(x,y);//设定坐标
				I2C_Write_Len(OLED_ADDR,OLED_DATA,16,(uint8_t*)zk[j].Msk);
				OLED_Set_Pos(x,y+1);	//设定第二行坐标
				I2C_Write_Len(OLED_ADDR,OLED_DATA,16,(uint8_t*)&zk[j].Msk[16]);
				
			}else return flag;
		}
		else //不是汉字执行下面显示ASCII码
		{
			OLED_ShowChar(x,y,*no,16);
		}
		
		if(*no&0x80)//判断下一个字符是不是汉字
		{
			no++;
			no++;x+=16;//是汉字指针再自加一次,同时x坐标加16
			if(x>(128-16))//判断坐标是否越界越界转去下一行
				{x=0;y+=2;}
		}
		else 
		{no++;
			x+=8;//ASCII码坐标加8
			if(x>120)//判断坐标是否越界越界转去下一行
			{x=0;y+=2;}
		}	
	}
	return flag;	
    					
}
/***********功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7*****************/
void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[])
{ 	
 unsigned int j=0;
 unsigned char x,y;
  
  if(y1%8==0) y=y1/8;      
  else y=y1/8+1;
	for(y=y0;y<y1;y++)
	{
		OLED_Set_Pos(x0,y);
    for(x=x0;x<x1;x++)
	    {      
	    	OLED_WR_Byte(BMP[j++],OLED_DATA);	    	
	    }
	}
}
/*就用到了这两个函数其他的报错删就好了*/
JIEYA_char *jieya_char=NULL;
const unsigned char **bmp=BMP;
unsigned char bmp_dat[1024];
void OLED_DrawBMP2(const unsigned char BMP[])
{ 	
 unsigned int j=0,i=0;

	jieya_char=(JIEYA_char*)BMP;
	while(1)
	{
		if(jieya_char->len1==0xff&&jieya_char->dat==0xff)break;
		for(j=0;j<jieya_char->len1;j++)
			bmp_dat[i++]=jieya_char->dat;
		jieya_char++;
	}
	for(i=0;i<8;i++)
	{
		OLED_Set_Pos(0,i);//设定坐标
		HAL_I2C_Mem_Write(&hi2c2,OLED_ADDR,OLED_DATA,I2C_MEMADD_SIZE_8BIT,&bmp_dat[i*128],128,1000);
	}
} 
//初始化SSD1306					    
void OLED_Init(void)
{ 	

	if("电"[0]==0xB5)//判断大小端
		daxiaoduan=0;
	else daxiaoduan=1;
OLED_WR_Byte(0xAE,OLED_CMD);//--display off
	OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
	OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
	OLED_WR_Byte(0x40,OLED_CMD);//--set start line address  
	OLED_WR_Byte(0xB0,OLED_CMD);//--set page address
	OLED_WR_Byte(0x81,OLED_CMD); // contract control
	OLED_WR_Byte(0xFF,OLED_CMD);//--128   
	OLED_WR_Byte(0xA1,OLED_CMD);//set segment remap 
	OLED_WR_Byte(0xA6,OLED_CMD);//--normal / reverse
	OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
	OLED_WR_Byte(0x3F,OLED_CMD);//--1/32 duty
	OLED_WR_Byte(0xC8,OLED_CMD);//Com scan direction
	OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset
	OLED_WR_Byte(0x00,OLED_CMD);//
	
	OLED_WR_Byte(0xD5,OLED_CMD);//set osc division
	OLED_WR_Byte(0x80,OLED_CMD);//
	
	OLED_WR_Byte(0xD8,OLED_CMD);//set area color mode off
	OLED_WR_Byte(0x05,OLED_CMD);//
	
	OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-Charge Period
	OLED_WR_Byte(0xF1,OLED_CMD);//
	
	OLED_WR_Byte(0xDA,OLED_CMD);//set com pin configuartion
	OLED_WR_Byte(0x12,OLED_CMD);//
	
	OLED_WR_Byte(0xDB,OLED_CMD);//set Vcomh
	OLED_WR_Byte(0x30,OLED_CMD);//
	
	OLED_WR_Byte(0x8D,OLED_CMD);//set charge pump enable
	OLED_WR_Byte(0x14,OLED_CMD);//
	
	OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
	OLED_Clear();
}  

oled.h

#ifndef __OLED_H
#define __OLED_H	
#include "MAIN.h"		  	 
//#include "sys.h"
//#include "stdlib.h"	  

#define OLED_CMD  0x0	//写命令
#define OLED_DATA 0x40	//写数据
#define OLED_MODE 0


//OLED模式设置
//0:4线串行模式
//1:并行8080模式

#define SIZE 16
#define XLevelL		0x02
#define XLevelH		0x10
#define Max_Column	128
#define Max_Row		64
#define	Brightness	0xFF 
#define X_WIDTH 	128
#define Y_WIDTH 	64	    						  
//-----------------OLED端口定义----------------  					   

void delay_ms(unsigned int ms);


//OLED控制用函数
void OLED_WR_Byte(unsigned char dat,unsigned char cmd);
void OLED_Display_On(void);//开显示
void OLED_Display_Off(void);//关显示	   							   		    
void OLED_Init(void);//初始化
void OLED_Clear_Line(uint8_t y1,uint8_t y2);
void OLED_Clear(void);//清屏
void OLED_DrawPoint(uint8_t x,uint8_t y,uint8_t t);
void OLED_Fill(uint8_t x1,uint8_t y1,uint8_t x2,uint8_t y2,uint8_t dot);
void OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size2);//显示2个数字
void OLED_Set_Pos(unsigned char x, unsigned char y);//坐标设置
void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[]);//显示图片
void OLED_DrawBMP2(const unsigned char BMP[]);
void Delay_1ms(unsigned int Del_1ms);
void fill_picture(unsigned char fill_Data);

uint8_t OLED_Display_str(uint8_t x,uint8_t y,uint8_t *no);//显示一个字符串
#endif  

main.c

extern const unsigned char **bmp;
int main(void)
{
  /* USER CODE BEGIN 1 */
	
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C2_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	OLED_Init();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		KEY_Read();
		OLED_DrawBMP2(bmp[ye++]);
		if(ye>1781)ye=0;
		HAL_Delay(delay);
		HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
		
  }
  /* USER CODE END 3 */
}

第六步下载进去欣赏

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值