“高通”字库芯片的使用方法

STM32+字库

“高通”字库芯片的使用方法


前言

本文应用了这位大神的指导链接:https://blog.csdn.net/qq_40102829/article/details/105622434 再通过自己实践来的结果

测试平台:STM32F103C8T6
字库芯片型号:GT21L16S2W SPI协议
显示方式:0.96寸的OLED SPI协议

通常在小显示屏上显示中文字体需要一个专用的软件对其汉字进行取模,而且需要大量的工作一个一个取出对应汉字的数据,如果是大量的汉字要显示实在不方便,不如直接买一个别人已经将字库弄好的直接调用爽快多了。本次第一次购买掉进了一个坑,在此提醒下,注意购买的时候你要根据你的显示屏扫描的方式 如0.96寸的OLED扫描方式是从先从 下到上 后 左到右 的顺序规律扫描出来的,那些汉字取模软件也有类似的选项给你选择,所以购买时选择好点阵排列方式是竖置横排的还是横

在高通官网站查找不到芯片手册,只能通过百度文库中查找或在立创商城中找到。手册中也坑,在最新版本中要么不给出字体的地址或者是指定的汉字详细计算方法。所以只能在百度文库中找最早出现的A版本查询信息

说实话,我最终还是跟现实低下头,直接买别人现成的,真香。程序部分别人已经写好了有SPI和IIC注释也好看,而我合并了SPI和IIC的功能下次调用直接使能哪一个通讯方式就行。

改为:
测试平台:STM32F407系列
字库芯片型号:GT30L32S4W SPI协议
显示方式:2.08寸的OLED SPI协议

链接: “高通”字库芯片的使用方法


一、电路设计

电路设计:字库芯片跟SPI FLASH 存储器连接方式一样,注意MOSI和MISO与单片机连接对调就行了,没啥好说的
在这里插入图片描述

二、程序设计

先看看手册中的指令有哪些
在这里插入图片描述
这款芯片比较简单只有两个指令 Read Data Bytes(一般读取)和 Read Data Bytes at Higher Speed(快速读取点阵数据)

以最简单的方式 Read Data Bytes(一般读取) 来讲解

在这里插入图片描述
1个字节的命令字(03H)和 3个字节的地址(通过给出的公式计算出来传递给其)
1个字节 = 8位 —> 0000 0000 一共要发送24位数据给到字库芯片中去
从图象中可以看出高位先进去(MSB),发送完24位数据后 字库芯片会发送数据出来 (Data Out1)

代码如下:

//******************************************************************************
//    函数说明:向字库芯片发送指令
//    入口数据:AddrHigh 写地址高字节
//              AddrMid  写地址中字节
//              AddrLow  写地址低字节
//              *pBuff   读到的数据
//              DataLen  读取的长度
//    返回值:  无
//******************************************************************************
void get_n_bytes_data_from_ROM(u8 AddrHigh,u8 AddrMid,u8 AddrLow,u8 *pBuff,u8 DataLen )
{
	u8  i;
	ZK_CS_Clr(); //字库片选
	ZK_command(0x03);//写指令
	ZK_command(AddrHigh);//写地址高字节
	ZK_command(AddrMid);//写地址中字节
	ZK_command(AddrLow);//写地址低字节
	for(i = 0; i < DataLen; i++ )
	{
		*(pBuff+i) =get_data_from_ROM();//读一个字节数据
	}
	ZK_CS_Set();//取消字库片选
}

整体代码部分

1.字库初始化

OLED_IIC_MODE 和 LED_SPI_MODE 该定义即可更改为SPI模式或IIC模式通讯
代码如下(示例):

#include "oled.h"
#include "stdlib.h"
#include "oledfont.h"  	 
#include "delay.h"
#include "stm32f4xx_spi.h"
//************************************硬件连接线********************************
//              GND    电源地
//              VCC  3.3v电源
//              D0   PB3(SCL) 
//              D1   PB5(SDA) 
//              RES  PD6 	
//              DC   PD7  
//              CS1  PF9  
//              FS0  PB4  
//              CS2  PF10 
//******************************************************************************

void OLED_Init(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;
  SPI_InitTypeDef  SPI_InitStructure;
	RCC_AHB1PeriphClockCmd(OLED_GPIO_ClockCmd, ENABLE);//使能GPIO时钟
	
	#if OLED_IIC_MODE 
	//RES、DC
  GPIO_InitStructure.GPIO_Pin = OLED_GPIO_RES_PIN|OLED_GPIO_DC_PIN;	 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;			//普通输出模式
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;		//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;			//上拉
  GPIO_Init(OLED_GPIO_RES_PORT, &GPIO_InitStructure);						//初始化
  GPIO_Init(OLED_GPIO_DC_PORT, &GPIO_InitStructure);						//初始化
	
	//CS1、CS2
	GPIO_InitStructure.GPIO_Pin = OLED_GPIO_CS_PIN|ZK_GPIO_CS_PIN;	 
  GPIO_Init(OLED_GPIO_CS_PORT, &GPIO_InitStructure);						//初始化
  GPIO_Init(ZK_GPIO_CS_PORT, &GPIO_InitStructure);						//初始化	

	//SCL、SDA
	GPIO_InitStructure.GPIO_Pin = OLED_GPIO_SCL_PIN|OLED_GPIO_SDA_PIN;	 
  GPIO_Init(OLED_GPIO_SCL_PORT, &GPIO_InitStructure);						//初始化	
  GPIO_Init(OLED_GPIO_SDA_PORT, &GPIO_InitStructure);						//初始化	
	
	//FS0
	GPIO_InitStructure.GPIO_Pin = ZK_GPIO_FS0_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;			//普通输入模式
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;		//下拉输入
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
 	GPIO_Init(GPIOA, &GPIO_InitStructure);	  				//初始化GPIOE8
	GPIO_SetBits(ZK_GPIO_FS0_PORT,ZK_GPIO_CS_PIN);
	#endif
	
	#if OLED_SPI_MODE

  RCC_APB2PeriphClockCmd(ZK_SPI_CLK, ENABLE);	//使能SPI1时钟

	//RES、DC
  GPIO_InitStructure.GPIO_Pin = OLED_GPIO_RES_PIN|OLED_GPIO_DC_PIN;	 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;			//普通输出模式
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;		//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;			//上拉
  GPIO_Init(OLED_GPIO_RES_PORT, &GPIO_InitStructure);						//初始化
  GPIO_Init(OLED_GPIO_DC_PORT, &GPIO_InitStructure);						//初始化
	
	//CS1、CS2
	GPIO_InitStructure.GPIO_Pin = OLED_GPIO_CS_PIN|ZK_GPIO_CS_PIN;	 
  GPIO_Init(OLED_GPIO_CS_PORT, &GPIO_InitStructure);						//初始化
  GPIO_Init(ZK_GPIO_CS_PORT, &GPIO_InitStructure);						//初始化	
 
 	//MOSI、MISO、SCK
	GPIO_InitStructure.GPIO_Pin = OLED_GPIO_SCL_PIN|OLED_GPIO_SDA_PIN|ZK_GPIO_FS0_PIN;	 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
	GPIO_Init(ZK_GPIO_FS0_PORT, &GPIO_InitStructure);		
	GPIO_Init(OLED_GPIO_SCL_PORT, &GPIO_InitStructure);		
	GPIO_Init(OLED_GPIO_SDA_PORT, &GPIO_InitStructure);		


 	GPIO_PinAFConfig(ZK_GPIO_FS0_PORT,ZK_GPIO_PinSource_SCL,ZK_SPI_GPIO_AF); //PB3复用为 SPI1
	GPIO_PinAFConfig(ZK_GPIO_FS0_PORT,ZK_GPIO_PinSource_FS0,ZK_SPI_GPIO_AF); //PB4复用为 SPI1
	GPIO_PinAFConfig(ZK_GPIO_FS0_PORT,ZK_GPIO_PinSource_SDA,ZK_SPI_GPIO_AF); //PB5复用为 SPI1
	//这里只针对SPI口初始化
	RCC_APB2PeriphResetCmd(ZK_SPI_CLK,ENABLE);									//复位SPI1
	RCC_APB2PeriphResetCmd(ZK_SPI_CLK,DISABLE);									//停止复位SPI1

	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;												//设置SPI工作模式:设置为主SPI
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;										//设置SPI的数据大小:SPI发送接收8位帧结构
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;													//串行同步时钟的空闲状态为高电平
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;												//串行同步时钟的第二个跳变沿(上升或下降)数据被采样
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;														//NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;	//定义波特率预分频的值:波特率预分频值为256
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;									//指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
	SPI_InitStructure.SPI_CRCPolynomial = 7;														//CRC值计算的多项式
	SPI_Init(ZK_SPIx, &SPI_InitStructure);  																//根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
 
	SPI_Cmd(ZK_SPIx, ENABLE); //使能SPI外设

	SPI1_ReadWriteByte(0xff);//启动传输		
	#endif
	
	OLED_RES_Clr();		//复位
	delay_ms(10);
	OLED_RES_Set();
	
	OLED_WR_REG(0xAE);//Set display off
	OLED_WR_REG(0xB0); //Row address Mode Setting
	OLED_WR_REG(0x00);
	OLED_WR_REG(0x10); //Set Higher Column Address of display RAM
	OLED_WR_REG(0x00); //Set Lower Column Address of display RAM
	OLED_WR_REG(0xD5); //Set Display Clock Divide Ratio/Oscillator Frequency
	OLED_WR_REG(0x50); //50 125hz
	OLED_WR_REG(0xD9); //Set Discharge/Precharge Period
	OLED_WR_REG(0x22);
	OLED_WR_REG(0x40); //Set Display Start Line
	OLED_WR_REG(0x81); //The Contrast Control Mode Set
	OLED_WR_REG(0xFF);
	if(USE_HORIZONTAL)
	{
		OLED_WR_REG(0xA1); //Set Segment Re-map
		OLED_WR_REG(0xC8); //Set Common Output Scan Direction
	  OLED_WR_REG(0xD3); //Set Display Offset
	  OLED_WR_REG(0x20);
	}else
	{
		OLED_WR_REG(0xA0); //Set Segment Re-map
		OLED_WR_REG(0xC0); //Set Common Output Scan Direction
	  OLED_WR_REG(0xD3); //Set Display Offset
	  OLED_WR_REG(0x00);
	}
	OLED_WR_REG(0xA4); //Set Entire Display OFF/ON
	OLED_WR_REG(0xA6); //Set Normal/Reverse Display
	OLED_WR_REG(0xA8); //Set Multiplex Ration
	OLED_WR_REG(0x3F);
	OLED_WR_REG(0xAD); //DC-DC Setting
	OLED_WR_REG(0x80); //DC-DC is disable
	OLED_WR_REG(0xDB); //Set VCOM Deselect Level
	OLED_WR_REG(0x30);
	OLED_WR_REG(0xDC); //Set VSEGM Level
	OLED_WR_REG(0x30);
	OLED_WR_REG(0x33); //Set Discharge VSL Level 1.8V
	OLED_Clear();
	OLED_WR_REG(0xAF); //Set Display On
}
//******************************************************************************
//    函数说明:硬件SPI读写一个字节
//    入口数据:要写入的字节
//    返回值:  读取到的字节
//******************************************************************************
	#if OLED_SPI_MODE
u8 SPI1_ReadWriteByte(u8 TxData)
{		 			 
  while (SPI_I2S_GetFlagStatus(ZK_SPIx, SPI_I2S_FLAG_TXE) == RESET){}//等待发送区空  
	
	SPI_I2S_SendData(ZK_SPIx, TxData); //通过外设SPIx发送一个byte  数据
		
  while (SPI_I2S_GetFlagStatus(ZK_SPIx, SPI_I2S_FLAG_RXNE) == RESET){} //等待接收完一个byte  
 
	return SPI_I2S_ReceiveData(ZK_SPIx); //返回通过SPIx最近接收的数据		
}
	#endif

//******************************************************************************
//    函数说明:OLED写入一个指令
//    入口数据:dat 数据
//    返回值:  无
//******************************************************************************
void OLED_WR_Bus(u8 dat)
{
	u8 i;
	OLED_CS_Clr();
	#if OLED_IIC_MODE
	for(i=0;i<8;i++)
	{			  
		OLED_SCL_Clr();
		if(dat&0x80)
		{
		   OLED_SDA_Set();
		}
		else 
		{
		   OLED_SDA_Clr();
		}
		OLED_SCL_Set();
		dat<<=1;   
	}
//	printf("IIC\r");
	#endif
	
	#if OLED_SPI_MODE
	SPI1_ReadWriteByte(dat);	
//		printf("SPI\r");
	#endif
	OLED_CS_Set();
}

//******************************************************************************
//    函数说明:OLED写入一个指令
//    入口数据:reg 指令
//    返回值:  无
//******************************************************************************
void OLED_WR_REG(u8 reg)
{	  
	OLED_DC_Clr();		  
  OLED_WR_Bus(reg);
  OLED_DC_Set();	
}

//******************************************************************************
//    函数说明:OLED写入一个数据
//    入口数据:dat 数据
//    返回值:  无
//******************************************************************************
void OLED_WR_Byte(u8 dat)
{	  
  OLED_WR_Bus(dat);
}

//******************************************************************************
//    函数说明:OLED显示列的起始终止地址
//    入口数据:a  列的起始地址
//              b  列的终止地址
//    返回值:  无
//******************************************************************************
void OLED_AddressSet(u8 x,u8 y) 
{
	OLED_WR_REG(0xB0);
	OLED_WR_REG(y);
	OLED_WR_REG(((x&0xf0)>>4)|0x10);
	OLED_WR_REG((x&0x0f));
}

//******************************************************************************
//    函数说明:OLED清屏显示
//    入口数据:无
//    返回值:  无
//******************************************************************************
void OLED_Clear(void)
{
	u16 j,i;
	OLED_AddressSet(0,0);
	OLED_CS_Clr();
	for(i=0;i<64;i++)
	{
		#if OLED_IIC_MODE
		OLED_AddressSet(0,i);
		#endif	
		for(j=0;j<128;j++)
		{
			#if OLED_IIC_MODE
			OLED_WR_Byte(0x00);
			#endif	
			
			#if OLED_SPI_MODE
			SPI1_ReadWriteByte(0x00);	
			#endif			
		}
	}
	OLED_CS_Set();
}

//******************************************************************************
//    函数说明:OLED清屏显示
//    入口数据:x1,y1 起点坐标
//              x2,y2 结束坐标
//              color 填充的颜色值
//    返回值:  无
//******************************************************************************
void OLED_Fill(u16 x1,u8 y1,u16 x2,u8 y2,u8 color)
{
	u16 j,i;
	x1/=2;
	x2/=2;
	for(i=y1;i<y2;i++)
	{
		OLED_AddressSet(x1,i);
		for(j=x1;j<x2;j++)
		{
			OLED_WR_Byte(color);
		}
	}
}

//******************************************************************************
//    函数说明:OLED显示汉字
//    入口数据:x,y :起点坐标
//              *s  :要显示的汉字串
//              sizey 字符高度 
//              mode  0:正常显示;1:反色显示
//    返回值:  无
//******************************************************************************
void OLED_ShowChinese(u8 x,u8 y,u8 *s,u8 sizey,u8 mode)
{
	while(*s!=0)
	{
		if(sizey==16) OLED_ShowChinese16x16(x,y,s,sizey,mode);
		else if(sizey==24) OLED_ShowChinese24x24(x,y,s,sizey,mode);
		else if(sizey==32) OLED_ShowChinese32x32(x,y,s,sizey,mode);
		else return;
		s+=2;
		x+=sizey;
	}
}

//******************************************************************************
//    函数说明:OLED显示汉字
//    入口数据:x,y :起点坐标
//              *s  :要显示的汉字
//              sizey 字符高度 
//              mode  0:正常显示;1:反色显示
//    返回值:  无
//******************************************************************************
void OLED_ShowChinese16x16(u8 x,u8 y,u8 *s,u8 sizey,u8 mode)
{
	u8 i,j,k,t,DATA=0,HZnum;
	u16 TypefaceNum;
	x/=2;
	TypefaceNum=(sizey/8+((sizey%8)?1:0))*sizey;//字符所占字节数
	HZnum=sizeof(tfont16)/sizeof(typFNT_GB16);	//统计汉字库数目
	t=sizey/8;
	for(k=0;k<HZnum;k++)
	{
		if ((tfont16[k].Index[0]==*(s))&&(tfont16[k].Index[1]==*(s+1)))
		{ 	
			for(i=0;i<TypefaceNum;i++)
			{
				if(i%t==0)
				{
					OLED_AddressSet(x,y);
					y++;
				}
				for(j=0;j<4;j++)
				{
					if(tfont16[k].Msk[i]&(0x01<<(j*2+0)))
					{
						DATA=0xf0;
					}
					if(tfont16[k].Msk[i]&(0x01<<(j*2+1)))
					{
						DATA|=0x0f;
					}
					if(mode)
					{
						OLED_WR_Byte(~DATA);
					}else
					{
						OLED_WR_Byte(DATA);
					}
					DATA=0;
				}
			}
		}				  	
		continue;  //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
	}
}

//******************************************************************************
//    函数说明:OLED显示汉字
//    入口数据:x,y :起点坐标
//              *s  :要显示的汉字
//              sizey 字符高度 
//              mode  0:正常显示;1:反色显示
//    返回值:  无
//******************************************************************************
void OLED_ShowChinese24x24(u8 x,u8 y,u8 *s,u8 sizey,u8 mode)
{
	u8 i,j,k,t,DATA=0,HZnum;
	u16 TypefaceNum;
	x/=2;
	TypefaceNum=(sizey/8+((sizey%8)?1:0))*sizey;//字符所占字节数
	HZnum=sizeof(tfont24)/sizeof(typFNT_GB24);	//统计汉字库数目
	t=sizey/8;
	for(k=0;k<HZnum;k++)
	{
		if ((tfont24[k].Index[0]==*(s))&&(tfont24[k].Index[1]==*(s+1)))
		{ 	
			for(i=0;i<TypefaceNum;i++)
			{
				if(i%t==0)
				{
					OLED_AddressSet(x,y);
					y++;
				}
				for(j=0;j<4;j++)
				{
					if(tfont24[k].Msk[i]&(0x01<<(j*2+0)))
					{
						DATA=0xf0;
					}
					if(tfont24[k].Msk[i]&(0x01<<(j*2+1)))
					{
						DATA|=0x0f;
					}
					if(mode)
					{
						OLED_WR_Byte(~DATA);
					}else
					{
						OLED_WR_Byte(DATA);
					}
					DATA=0;
				}
			}
		}				  	
		continue;  //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
	}
}

//******************************************************************************
//    函数说明:OLED显示汉字
//    入口数据:x,y :起点坐标
//              *s  :要显示的汉字
//              sizey 字符高度 
//              mode  0:正常显示;1:反色显示
//    返回值:  无
//******************************************************************************
void OLED_ShowChinese32x32(u8 x,u8 y,u8 *s,u8 sizey,u8 mode)
{
	u8 i,j,k,t,DATA=0,HZnum;
	u16 TypefaceNum;
	x/=2;
	TypefaceNum=(sizey/8+((sizey%8)?1:0))*sizey;//字符所占字节数
	HZnum=sizeof(tfont32)/sizeof(typFNT_GB32);	//统计汉字库数目
	t=sizey/8;
	for(k=0;k<HZnum;k++)
	{
		if ((tfont32[k].Index[0]==*(s))&&(tfont32[k].Index[1]==*(s+1)))
		{ 	
			for(i=0;i<TypefaceNum;i++)
			{
				if(i%t==0)
				{
					OLED_AddressSet(x,y);
					y++;
				}
				for(j=0;j<4;j++)
				{
					if(tfont32[k].Msk[i]&(0x01<<(j*2+0)))
					{
						DATA=0xf0;
					}
					if(tfont32[k].Msk[i]&(0x01<<(j*2+1)))
					{
						DATA|=0x0f;
					}
					if(mode)
					{
						OLED_WR_Byte(~DATA);
					}else
					{
						OLED_WR_Byte(DATA);
					}
					DATA=0;
				}
			}
		}				  	
		continue;  //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
	}
}

//******************************************************************************
//    函数说明:OLED显示字符函数 
//    此函数适用范围:字符宽度是2的倍数  字符高度是宽度的2倍
//    入口数据:x,y   起始坐标
//              chr   要写入的字符
//              sizey 字符高度 
//    返回值:  无
//******************************************************************************
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 sizey,u8 mode)
{
	u8 i,j,c,k,t=4,temp,DATA=0;
	u16 num;
	x/=2;
	c=chr-' ';
	num=(sizey/16+((sizey%16)?1:0))*sizey;
	k=sizey/16;
	for(i=0;i<num;i++)
	{
		if(sizey==16)temp=ascii_1608[c][i];//调用8x16字符
		else if(sizey==24)temp=ascii_2412[c][i];//调用12x24字符
		else if(sizey==32)temp=ascii_3216[c][i];//调用16x32字符
//		else if(sizey==48)temp=ascii_4824[c][i];//调用24x48字符
		else return;
		if(sizey%16)
		{
			k=sizey/16+1;
			if(i%k) t=2;
			else t=4;
		}
		if(i%k==0)
		{
			OLED_AddressSet(x,y);
			y++;
		}
		for(j=0;j<t;j++)
		{
			if(temp&(0x01<<(j*2+0)))
			{
				DATA=0xf0;
			}
			if(temp&(0x01<<(j*2+1)))
			{
				DATA|=0x0f;
			}
			if(mode)
			{
				OLED_WR_Byte(~DATA);
			}else
			{
				OLED_WR_Byte(DATA);
			}
			DATA=0;
		}
	}
}

//******************************************************************************
//    函数说明:OLED显示字符串
//    入口数据:x,y  起始坐标
//              *dp   要写入的字符
//              sizey 字符高度 
//              mode  0:正常显示;1:反色显示
//    返回值:  无
//******************************************************************************
void OLED_ShowString(u8 x,u8 y,u8 *dp,u8 sizey,u8 mode)
{
	while(*dp!='\0')
	{
	  OLED_ShowChar(x,y,*dp,sizey,mode);
		dp++;
		x+=sizey/2;
	}
}


//******************************************************************************
//    函数说明:m^n
//    入口数据:m:底数 n:指数
//    返回值:  result
//******************************************************************************
u32 oled_pow(u16 m,u16 n)
{
	u32 result=1;
	while(n--)result*=m;    
	return result;
}


//******************************************************************************
//    函数说明:OLED显示变量
//    入口数据:x,y :起点坐标	 
//              num :要显示的变量
//              len :数字的位数
//              sizey 字符高度 
//              mode  0:正常显示;1:反色显示
//    返回值:  无
//******************************************************************************
void OLED_ShowNum(u8 x,u8 y,u32 num,u16 len,u8 sizey,u8 mode)
{         	
	u8 t,temp;
	u8 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+(sizey/2)*t,y,' ',sizey,mode);
				continue;
			}else enshow=1; 
		 	 
		}
	 	OLED_ShowChar(x+(sizey/2)*t,y,temp+'0',sizey,mode); 
	}
}

//******************************************************************************
//    函数说明:显示灰度图片
//    入口数据:x,y :起点坐标
//              length 图片长度
//              width  图片宽度
//              BMP[] :要显示图片
//              mode  0:正常显示;1:反色显示
//    返回值:  无
//******************************************************************************
void OLED_DrawBMP(u8 x,u8 y,u16 length,u8 width,const u8 BMP[],u8 mode)
{
	u8 i,j;
	u16 k=0;
	x/=2;
	length=length/2+((length%2)?1:0);
	for(i=0;i<width;i++)
	{
		OLED_AddressSet(x,y+i);
		for(j=0;j<length;j++)
		{
			if(mode)
			{
				OLED_WR_Byte(~BMP[k++]);
			}else
			{
				OLED_WR_Byte(BMP[k++]);
			}
	  }
	}
}


//******************************************************************************
//    函数说明:显示灰度图片
//    入口数据:x,y :起点坐标
//              length 图片长度
//              width  图片宽度
//              BMP[] :要显示图片
//              mode  0:正常显示;1:反色显示
//    返回值:  无
//******************************************************************************
void OLED_DrawSingleBMP(u8 x,u8 y,u16 length,u8 width,const u8 BMP[],u8 mode)
{
	u8 i,j,k,DATA=0;
	u16 m=0;
	length=length/8+((length%8)?1:0);
	x/=2;
	for(i=0;i<width;i++)
	{
		OLED_AddressSet(x,y+i);
		for(j=0;j<length;j++)
		{
			for(k=0;k<4;k++)
			{
				if(BMP[m]&(0x01<<(k*2+0)))
				{
					DATA=0xf0;
				}
				if(BMP[m]&(0x01<<(k*2+1)))
				{
					DATA|=0x0f;
				}
				if(mode)
				{
					OLED_WR_Byte(~DATA);
				}else
				{
					OLED_WR_Byte(DATA);
				}
				DATA=0;
			}
			m++;
		}
	}
}

以上SPI用到的是STM32的SPI2当中,时钟挂接在36M的PCLK1分频得到,预分频设置为最大值256(36M/256 = 0.14M)
SCLK的频率为140KHz,Tsclk:14.0us

2.字库头文件

代码如下(示例):

#ifndef __OLED_H
#define __OLED_H 

#include "sys.h"

#define USE_HORIZONTAL 0 					 //设置显示方向 0:正向显示;1:旋转180度显示

#define	OLED_SPI_MODE	0									//设置硬件SPI或软件IIC  0:硬件SPI; 1:软件IIC
#define	OLED_IIC_MODE	1									//设置硬件SPI或软件IIC  0:硬件SPI; 1:软件IIC

//SCL=SCLK 
//SDA=MOSI
//RES=RES
//DC=DC
//CS=CS1
//FS0=MOSI
//CS2=CS2
//-----------------OLED端口定义---------------- 

#define OLED_GPIO_ClockCmd                   				 RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB     
#define OLED_GPIO_SCL_PORT                   				 GPIOA  
#define OLED_GPIO_SCL_PIN                    				 GPIO_Pin_8
#define OLED_GPIO_SCL_CLK                    				 RCC_AHB1Periph_GPIOA 

#define OLED_GPIO_SDA_PORT                   				 GPIOA   
#define OLED_GPIO_SDA_PIN                    				 GPIO_Pin_5
#define OLED_GPIO_SDA_CLK                    				 RCC_AHB1Periph_GPIOA 
 
#define OLED_GPIO_RES_PORT                   				 GPIOA   
#define OLED_GPIO_RES_PIN                    				 GPIO_Pin_15
#define OLED_GPIO_RES_CLK                    				 RCC_APB1Periph_GPIOA 
 
#define OLED_GPIO_DC_PORT                   				 GPIOB   
#define OLED_GPIO_DC_PIN                    				 GPIO_Pin_6
#define OLED_GPIO_DC_CLK                    				 RCC_APB1Periph_GPIOB 

#define OLED_GPIO_CS_PORT                   				 GPIOB   
#define OLED_GPIO_CS_PIN                    				 GPIO_Pin_7
#define OLED_GPIO_CS_CLK                    				 RCC_APB1Periph_GPIOB 
  
#define ZK_GPIO_CS_PORT                   					 GPIOA   
#define ZK_GPIO_CS_PIN                    					 GPIO_Pin_0
#define ZK_GPIO_CS_CLK                    					 RCC_APB1Periph_GPIOA
																										 
#define ZK_GPIO_FS0_PORT                   					 GPIOA   
#define ZK_GPIO_FS0_PIN                    					 GPIO_Pin_4
#define ZK_GPIO_FS0_CLK                    					 RCC_APB1Periph_GPIOA

#define ZK_SPIx                        					 		 SPI1
#define ZK_SPI_APBxClock_FUN           							 RCC_APB2PeriphClockCmd
#define ZK_SPI_CLK                    							 RCC_APB2Periph_SPI1
#define ZK_SPI_GPIO_AF															 GPIO_AF_SPI1
#define ZK_GPIO_PinSource_SCL												 GPIO_PinSource3
#define ZK_GPIO_PinSource_SDA												 GPIO_PinSource5
#define ZK_GPIO_PinSource_FS0 											 GPIO_PinSource4

#define OLED_SCL_Clr() GPIO_ResetBits(OLED_GPIO_SCL_PORT,OLED_GPIO_SCL_PIN)//SCL
#define OLED_SCL_Set() GPIO_SetBits(OLED_GPIO_SCL_PORT,OLED_GPIO_SCL_PIN)

#define OLED_SDA_Clr() GPIO_ResetBits(OLED_GPIO_SDA_PORT,OLED_GPIO_SDA_PIN)//SDA
#define OLED_SDA_Set() GPIO_SetBits(OLED_GPIO_SDA_PORT,OLED_GPIO_SDA_PIN)

#define OLED_RES_Clr()  GPIO_ResetBits(OLED_GPIO_RES_PORT,OLED_GPIO_RES_PIN)//RES
#define OLED_RES_Set()  GPIO_SetBits(OLED_GPIO_RES_PORT,OLED_GPIO_RES_PIN)

#define OLED_DC_Clr()  GPIO_ResetBits(OLED_GPIO_DC_PORT,OLED_GPIO_DC_PIN)//DC
#define OLED_DC_Set()  GPIO_SetBits(OLED_GPIO_DC_PORT,OLED_GPIO_DC_PIN)
 		     
#define OLED_CS_Clr()  GPIO_ResetBits(OLED_GPIO_CS_PORT,OLED_GPIO_CS_PIN)//CS1
#define OLED_CS_Set()  GPIO_SetBits(OLED_GPIO_CS_PORT,OLED_GPIO_CS_PIN)

#define ZK_CS_Clr()  GPIO_ResetBits(ZK_GPIO_CS_PORT,ZK_GPIO_CS_PIN)//CS2
#define ZK_CS_Set()  GPIO_SetBits(ZK_GPIO_CS_PORT,ZK_GPIO_CS_PIN)

#define ZK_READ_FS0()   GPIO_ReadInputDataBit(ZK_GPIO_FS0_PORT,ZK_GPIO_FS0_PIN)//FS0

u8 SPI1_ReadWriteByte(u8 TxData);

//显示屏功能函数
void OLED_WR_REG(u8 reg);					//写入一个指令
void OLED_WR_Byte(u8 dat);				//写入一个数据
void OLED_AddressSet(u8 x,u8 y);	//设置起始坐标函数
void OLED_Clear(void);						//清平函数
void OLED_Fill(u16 x1,u8 y1,u16 x2,u8 y2,u8 color);				 	 //填充函数
void OLED_ShowChinese(u8 x,u8 y,u8 *s,u8 sizey,u8 mode);		 //显示汉字串
void OLED_ShowChinese16x16(u8 x,u8 y,u8 *s,u8 sizey,u8 mode);//显示16x16汉字
void OLED_ShowChinese24x24(u8 x,u8 y,u8 *s,u8 sizey,u8 mode);//显示24x24汉字
void OLED_ShowChinese32x32(u8 x,u8 y,u8 *s,u8 sizey,u8 mode);//显示32x32汉字
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 sizey,u8 mode);			 //显示单个字符
void OLED_ShowString(u8 x,u8 y,u8 *dp,u8 sizey,u8 mode);		 //显示字符串
void OLED_ShowNum(u8 x,u8 y,u32 num,u16 len,u8 sizey,u8 mode);//显示整数变量
void OLED_DrawBMP(u8 x,u8 y,u16 length,u8 width,const u8 BMP[],u8 mode);			//显示灰度图片
void OLED_DrawSingleBMP(u8 x,u8 y,u16 length,u8 width,const u8 BMP[],u8 mode);//显示单色图片
void OLED_Init(void);

//字库函数
void ZK_command(u8 dat);			//向字库发送命令
u8  get_data_from_ROM(void);	//从字库度一个数据
void get_n_bytes_data_from_ROM(u8 AddrHigh,u8 AddrMid,u8 AddrLow,u8 *pBuff,u8 DataLen );//从字库读DataLen个数据
void Display_GB2312_String(u16 x,u8 y,u8 text[],u8 zk_num,u8 mode);											//显示汉字字符串
void Display_GB2312(u16 x,u8 y,u8 zk_num,u8 mode);																			//显示汉字
void Display_Asc_String(u16 x,u8 y,u8 text[],u8 zk_num,u8 mode);												//显示ASCII 字符串
void Display_Asc(u16 x,u8 y,u8 zk_num,u8 mode);																					//显示ASCII
void Display_GBasc_String(u16 x,u8 y,u8 text[],u8 zk_num,u8 mode);											//显示GB2312 ascii 字符串
void Display_GBasc(u16 x,u8 y,u8 zk_num,u8 mode);																				//显示GB2312 ascii 



void SPI1_SetSpeed(u8 SPI_BaudRatePrescaler);
u8 SPI1_ReadWriteByte(u8 TxData);
void SPI1_Init(void);
void OLED1_Init(void);
#endif


3.主函数

//              GND    电源地
//              VCC  3.3v电源
//              D0   PB3(SCL) 
//              D1   PB5(SDA) 
//              RES  PD6 	
//              DC   PD7  
//              CS1  PF9  
//              FS0  PB4  
//              CS2  PF10 

#include "sys.h"
#include "delay.h"
#include "led.h"
#include "oled.h"
#include "bmp.h"

int main(void)
{
	delay_init(168);
//	uart_init(115200);            //初始化USART
	OLED_Init();
	while(1)
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_15);
		delay_ms(1000);
		GPIO_SetBits(GPIOA, GPIO_Pin_15);
		delay_ms(1000);
		OLED_DrawBMP(0,0,256,64,gImage_1,0);//灰度图片显示
		delay_ms(1000);
		OLED_Clear();
		OLED_DrawSingleBMP(0,0,256,64,gImage_2,0);//单色图片显示
		delay_ms(1000);
		OLED_Clear();
    Display_GB2312_String(0,26,"中",12,0);//GB2312_12*12
		Display_GB2312_String(12,24,"景",16,0);//GB2312_15*16
		Display_GB2312_String(28,20,"园",24,0);//GB2312_24*24
		Display_GB2312_String(52,16,"电",32,0);//GB2312_32*32
		Display_GB2312_String(84,16,"子",32,0);//GB2312_32*32
		
    Display_GB2312_String(128,16,"中",32,1);//GB2312_12*12
		Display_GB2312_String(160,16,"景",32,1);//GB2312_15*16
		Display_GB2312_String(192,20,"园",24,1);//GB2312_24*24
		Display_GB2312_String(216,24,"电",16,1);//GB2312_32*32
		Display_GB2312_String(232,26,"子",12,1);//GB2312_32*32
		delay_ms(1000);
		OLED_Clear();
		Display_Asc_String(0,0,"ASCII:5x7",7,0);//5x7 ASCII
		Display_Asc_String(0,13,"ASCII:7x8",8,0);//7x8 ASCII
		Display_Asc_String(0,26,"ASCII:6x12",12,0);//6x12 ASCII
		Display_Asc_String(0,43,"ASCII:8x16",16,0);//8x16 ASCII
		delay_ms(1000);
		OLED_Clear();
		Display_Asc_String(0,0,"ASCII:5x7",7,1);//5x7 ASCII
		Display_Asc_String(0,13,"ASCII:7x8",8,1);//7x8 ASCII
		Display_Asc_String(0,26,"ASCII:6x12",12,1);//6x12 ASCII
		Display_Asc_String(0,43,"ASCII:8x16",16,1);//8x16 ASCII
		delay_ms(1000);
		OLED_Clear();
		Display_Asc_String(0,0,"ASC12x24",24,0);//12x24 ASCII
		Display_Asc_String(0,30,"ASC16x32",32,0);//16x32 ASCII
		delay_ms(1000);
		OLED_Clear();
		Display_Asc_String(0,0,"ASC12x24",24,1);//12x24 ASCII
		Display_Asc_String(0,30,"ASC16x32",32,1);//16x32 ASCII
		delay_ms(1000);
		
//		Display_GB2312_String(16*0,0,"当",16,0);//GB2312_32*32
//		Display_GB2312_String(16*1,0,"前",16,0);//GB2312_32*32
//		Display_GB2312_String(16*2,0,"距",16,0);//GB2312_32*32
//		Display_GB2312_String(16*3,0,"离",16,0);//GB2312_32*32
//		Display_GB2312_String(16*4,0,":",16,0);//GB2312_32*32
//		Display_Asc_String(16*5,0,"32",16,0);//16x32 ASCII

//		Display_GB2312_String(16*0,16,"设",16,0);//GB2312_32*32
//		Display_GB2312_String(16*1,16,"置",16,0);//GB2312_32*32
//		Display_GB2312_String(16*2,16,"距",16,0);//GB2312_32*32
//		Display_GB2312_String(16*3,16,"离",16,0);//GB2312_32*32
//		Display_GB2312_String(16*4,16,":",16,0);//GB2312_32*32
//		Display_Asc_String(16*5,16,"32",16,0);//16x32 ASCII

//		Display_GB2312_String((12*0)+34,52,"设",12,0);//GB2312_32*32
//		Display_GB2312_String((12*1)+34,52,"置",12,0);//GB2312_32*32
//		Display_GB2312_String((12*2)+34,52,"距",12,0);//GB2312_32*32
//		Display_GB2312_String((12*3)+34,52,"离",12,0);//GB2312_32*32
//		Display_GB2312_String((12*4)+34,52,":",12,0);//GB2312_32*32
		
//		Display_GB2312_String((12*0)+34,52,"设置",12,0);//GB2312_32*32
//		delay_ms(2000);
		OLED_Clear();
		
	}
}


  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 高通8295芯片JTAG是指该芯片的调试接口。JTAG是Joint Test Action Group的缩写,是一种用于数字电路的调试、测试和编程的标准。通过JTAG接口,可以对芯片进行调试和编程,以便在产品设计过程中进行验证和测试。 高通8295芯片是一款高性能的移动处理器,被广泛应用于智能手机和平板电脑等移动设备中。该芯片支持4G LTE网络,拥有8个Krait 450处理器核心,能够提供出色的性能和功耗控制。在芯片设计和调试过程中,JTAG接口起着重要的作用,可以帮助开发人员对芯片进行繁琐的检测和测试。 总的来说,高通8295芯片JTAG是指该芯片的调试接口,能够帮助开发人员进行芯片的调试和编程,确保芯片的稳定性和可靠性,是移动设备制造商不可或缺的工具之一。 ### 回答2: 高通8295芯片JTAG是指高通公司生产的8295芯片的JTAG接口。JTAG(Joint Test Action Group)是一种用于测试和调试集成电路的标准接口。它可以通过单个接口同时访问芯片内部的多个测试点,从而使测试和调试工作更加高效和方便,并且不需要在芯片上添加额外的测试电路。高通8295芯片是一款高性能的移动处理器芯片,采用了先进的Kryo CPU架构,支持最新的4G和5G通信技术,并具有强大的多媒体处理能力,可用于高端智能手机、平板电脑等移动终端产品。JTAG接口可以帮助测试人员对芯片进行各种测试和调试工作,包括检测芯片的电气特性、验证硬件设计的正确性、调试软件程序的运行问题等。在研发和生产过程中,JTAG接口也是必不可少的工具,它可以帮助加快产品上市的速度,并提高产品的质量和稳定性。 ### 回答3: 高通8295芯片是一款应用于移动设备的处理器芯片,它具有强大的性能和高效的处理能力。为了满足开发者和测试人员的需求,高通8295芯片还提供了一种重要的调试工具——JTAG。 JTAG,全称为Joint Test Action Group,即联合测试行动小组。它是一种用以调试半导体芯片的接口技术,可以让开发者通过访问芯片内部的控制和状态寄存器,进行调试和测试。 在高通8295芯片上,JTAG接口被用来进行硬件调试和固件升级。通过JTAG接口,开发者可以对芯片内部的硬件进行诊断和调试,比如检测信号线路的连通性、读取设备内存的内容、监视处理器的运行状态等等。 同时,在手机固件升级的过程中,JTAG也被广泛应用。通过该接口,测试人员可以提前对固件进行测试,并在发现问题后进行修复和升级,从而提高手机的稳定性和安全性。 总的来说,JTAG在高通8295芯片上是一项非常重要的调试工具,可以帮助开发者和测试人员快速诊断和解决问题,提高设备的性能和可靠性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

谢谢~谢先生

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

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

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

打赏作者

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

抵扣说明:

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

余额充值