STM32 STD/HAL库驱动W25Q64模块读写字库数据+OLED0.96显示例程

STM32 STD/HAL库驱动W25Q64 模块读写字库数据+OLED0.96显示例程


  • 🎬原创作者对W25Q64保存汉字字库演示:

W25Q64保存汉字字库


  • 🎞测试字体显示效果:

📑功能实现说明

利用W25Q64保存汉字字库,OLED显示汉字的时候,先通过SPI接口访问W25Q64,先将要显示的汉子字模数据,从SPI FLASH中读取出来,然后再显示到OLED屏幕上。

🛠W25Q64字库制作

  • 🍁W25Q64原理图:
  • 👉按照原创作者的思路制作SPI flash字库,需要准备一块足够大的字库SPI flash芯片以及flash足够大的MCU才行。这里选择:W25Q64 + STM32F103VET6
  • 🔱如果手上没有这么大的容量的mcu,可以选择使用SPI FLASH编程器单独烧录字库文件。(下面会提供本例程的单独的字库烧录文件.bin文件)前提是手上需要有一个SPI FLASH编程器。(SPI FLASH编程器TB也不过就10RMB左右。)

  • 📄使用单片机,将字模数据写入到SPI flash中,字模数据需要分2次编译上传,写入到W25Q64 SPI FLASH中。(对于stm32单片机容量需要选择至少STM32 XXXET6512KB)
c 复制代码
	
	/*字库写入*/
	/*字库需要分2次写入FLASH,一次写1半,写完上半部分后,把if 1 改为 if 0,再写下半部分*/
	/*CNFont.h也需要同步修改,写完注释掉这段代码*/	
	/*写完注释掉或者删除掉这段代码*/
	
	
//	#if 0
//		W25Q64_WriteData(W25Q64_GBK_ADDR,(uint8_t *)Chinses_16,383041);
//		printf("写字库上半部分 OK!\r\n");
//	#else
		W25Q64_WriteData(W25Q64_GBK_ADDR+383041,(uint8_t *)Chinses_16,383039);
		printf("写字库下半部分 OK!\r\n");
//	#endif
	/*写完注释掉或者删除掉这段代码*/
	
  • 👉通过MinPro-I编程器读取SPI FLASH ,写入的有效数据是767KB数据,到BB07F地址,对于存储16X16 Chinses_16字体,其实准备一颗1MB的 SPI FLASH 就足够了。
  • 📘这里提供程序中的Chinses_16字体库BIN文件,是从spi flash中提取出来的。如果自己有SPI flash编程器,可以直接烧录到SPI FLASH当中去。(经过验证,将裁剪后的bin文件烧录到4MB SPI FLASH中,挂载到mcu上,可以正确访问和读取数据。OLED显示正常).
c 复制代码
链接:https://pan.baidu.com/s/13uU5Uc7yiiHDMtMMNd71ew?pwd=v0l7 
提取码:v0l7
  • 🌿8M spi flash 全部提取(未裁剪)原字库
c 复制代码
链接:https://pan.baidu.com/s/1y8_p0PL-QeTQTkgahKGTXg?pwd=x324 
提取码:x324
  • W25QXX(针对WINBOND SPI FLASH)设备ID与容量关系
c 复制代码
 W25QXX Device ID
读取命令(0x90)
W25Q80的芯片ID为:0XEF13
W25Q16 的芯片ID为:0XEF14
W25Q32 的芯片ID为:0XEF15
W25Q64 的芯片ID为:0XEF16
W25Q128的芯片ID为:0XEF17
W25Q256的芯片ID为:0XEF18
W25Q512的芯片ID为:0XEF19

🔨字库文件(.BIN)制作

  • 🌿通过C代码将字库数组转换成.bin文件。(将下面的代码拷贝下来,通过VSCode软件创建.c文件将字库数组添加进来,然后运行,将自动生成.BIN文件。)(依赖插件c\C插件、Code Runner)
c 复制代码
const unsigned char Chinses_16[766080]={........};//字库数组
int main() {
    size_t size = sizeof(Chinses_16[0]);
    size_t count = sizeof(Chinses_16) / size;
    
    FILE *fp = fopen("output.bin", "wb");
    if (fp == NULL) {
        printf("Failed to open file.\n");
        return 1;
    }
    
    size_t elements_written = fwrite(Chinses_16, size, count, fp);
    if (elements_written != count) {
        printf("Failed to write data to file.\n");
        fclose(fp);
        return 1;
    }
    
    fclose(fp);
    printf("Data written successfully.\n");
    
    return 0;
}


  • 🌿由上面代码自动生成的字体文件:(经烧录测试,显示没有问题)
c 复制代码
链接:https://pan.baidu.com/s/1oqJ5WeaJKv6LI-p-LUPojA?pwd=0vfh 
提取码:0vfh
  • 🌿将生成的.bin文件通过SPI FLASH 编程器烧录到SPI FLASH(W25QXX)芯片中即可。
  • 🔑或者参考《将数组文件转换成bin格式文件》制作。测试过,此方法生成BIN文件时,会报非法字符情况,烧录后读取存在乱码的情况。

🌼OLED显示

  • 🍁接线说明:
c 复制代码
SPI FLASH    -----   STM32F103VET6
	CS  ---- PB12
	MOSI---- PB15
	MISO---- PB14
	 SCK ---- PB13
----------------------------------
	OLED I2C SSD1306  ---     STM32F103VET6
		SCL-----  PB8
		SDA ----  PB9
  • main.c:
c 复制代码
/*
引脚接线说明

SPI FLASH    -----   STM32F103VET6
	CS  ---- PB12
	MOSI---- PB15
	MISO---- PB14
	 SCK ---- PB13
----------------------------------
	OLED I2C SSD1306  ---     STM32F103VET6
		SCL-----  PB8
		SDA ----  PB9


*/

#include "main.h"
#include "usart1.h"
#include "systick.h"
#include "oled_i2c.h"
#include "w25q64.h"
#include "cnfont.h"
#include "codetab.h"

static void CLOCK_Config(void);
static void NVIC_Config(void);

int main(void)
{
	CLOCK_Config();		//时钟配置
	NVIC_Config();		//中断优先级配置
	W25Q64_InitConfig();//初始化W25Q64
	USART1_Config();

	printf("WRITE Start, FLASH ID=%X\r\n",W25Q64_GetID());
	

	
	/*字库写入*/
	/*字库需要分2次写入FLASH,一次写1半,写完上半部分后,把if 1 改为 if 0,再写下半部分*/
	/*CNFont.h也需要同步修改,写完注释掉这段代码*/
	
	/*写完注释掉或者删除掉这段代码*/
	
	
//	#if 1
//		W25Q64_WriteData(W25Q64_GBK_ADDR,(uint8_t *)Chinses_16,383041);
//		printf("写字库上半部分 OK!\r\n");
//	#else
//		W25Q64_WriteData(W25Q64_GBK_ADDR+383041,(uint8_t *)Chinses_16,383039);
//		printf("写字库下半部分 OK!\r\n");
//	#endif
	
	
	/*写完注释掉或者删除掉这段代码*/
	
	
	
	GPIO_ResetBits(GPIOB,GPIO_Pin_0);
	
	I2C_OLED_Cfg();
  OLED_Init();

  OLED_Fill(0xFF);//全屏点亮
  Delay_ms(50);
  OLED_Fill(0x00);//全屏灭
  Delay_ms(50);

  OLED_CLS();//清屏
  OLED_ShowStr(0, 0, (uint8_t *)"Loading now 1...", 2);
	
	Delay_ms(500);

	OLED_CLS();//清屏
	OLED_DrawBMP(0,0,128,8,LOGO_BMP);
	Delay_ms(2000);

	OLED_CLS();//清屏

		OLED_ShowChinese(0,0,"床前明月光,",16);
		OLED_ShowChinese(0,2,"疑是地上霜、",16);
		OLED_ShowChinese(0,4,"举头望明月?",16);
		OLED_ShowChinese(0,6,"疑是地上霜。",16);
	
	while(1)
	{
		
	}
}
//外设时钟配置
static void CLOCK_Config(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC,ENABLE);
	
	//1.配置GPIO 
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0| GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	GPIO_SetBits(GPIOB,GPIO_Pin_0);
	GPIO_SetBits(GPIOB,GPIO_Pin_1);
}

//中断优先级初始化
static void NVIC_IRQPriority_Init(uint8_t IRQChannel,uint8_t PreemptionPriority, uint8_t SubPriority)
{
	NVIC_InitTypeDef NVIC_IRQ_Init;
	NVIC_IRQ_Init.NVIC_IRQChannel = IRQChannel;
	NVIC_IRQ_Init.NVIC_IRQChannelPreemptionPriority = PreemptionPriority;
	NVIC_IRQ_Init.NVIC_IRQChannelSubPriority = SubPriority;
	NVIC_IRQ_Init.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_IRQ_Init);
}
//配置中断优先级
static void NVIC_Config(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置中断优先级分组
	NVIC_IRQPriority_Init(USART1_IRQn,1,1);
}

📚基于标准库驱动工程源码

c 复制代码
链接:https://pan.baidu.com/s/1SPauxXcXfs0JZvhfRF6zDw?pwd=hota 
提取码:hota

📘基于HAL库驱动(不包含字库文件)

  • 🔖采用标准I2C模式+SPI模式
c 复制代码
链接:https://pan.baidu.com/s/1sfs3LxUnYwfvZ8iVMaFeHQ?pwd=onky 
提取码:onky
  • 🔖采用快速I2C模式+SPI DMA模式:


c 复制代码
链接:https://pan.baidu.com/s/11Y9boVofu7Og9CnbV1_6oQ?pwd=quun 
提取码:quun
相关推荐
Deitymoon17 分钟前
STM32——外部中断按键控制led
stm32·单片机·嵌入式硬件
czwxkn24 分钟前
7STM32(stdl)flash内部闪存
stm32·单片机·嵌入式硬件
咕噜咕噜啦啦33 分钟前
STlink下载程序
stm32·单片机
Deitymoon2 小时前
STM32——串口中断接收
stm32·单片机·嵌入式硬件
Deitymoon4 小时前
STM32——串口通信发送数据
stm32·单片机·嵌入式硬件
czwxkn5 小时前
8STM32(stdl)低功耗模式
stm32·单片机·嵌入式硬件
czwxkn5 小时前
9STM32(stdl)看门狗
stm32·单片机·嵌入式硬件
LCG元6 小时前
STM32实战:基于STM32F103的SPI通信驱动W25Qxx Flash存储
stm32·单片机·嵌入式硬件
iCxhust7 小时前
led_pattern = (led_pattern << 1) | (led_pattern >> 7)执行顺序
stm32·单片机·嵌入式硬件·51单片机·微机原理
Deitymoon7 小时前
STM32——串口通信发送字符串
stm32·单片机·嵌入式硬件