0.96寸OLED12864显示汉字和图像(HAL库)

一、使用STM32CubeMx新建Keil工程

这个不详细介绍,网上一搜一大把,需要把PB8,PB9配置为开漏输出,初始电平为高电平

二、移植OLED驱动程序

我使用的是江协科技的OLED驱动程序,下载地址:0.96寸OLED显示屏_免费高速下载|百度网盘-分享无限制

下载程序源码后,选择一个版本解压

根据需要选择GB2312/UTF-8

进入Hardware目录,复制里面的四个文件,将其粘贴到自己的工程中

打开Keil工程,将这四个文件添加到工程中

添加头文件路径

需要注意的是:江协的程序是基于标准库的,要将其移植到HAL库中,只需要改动一些代码就行了

#include "stm32f1xx_hal.h" //将"stm32f10x.h"  替换为"stm32f1xx_hal.h"


void OLED_W_SCL(uint8_t BitValue)
{
	/*根据BitValue的值,将SCL置高电平或者低电平*/
	//GPIO_WriteBit(GPIOB, GPIO_Pin_8, (BitAction)BitValue);
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, (GPIO_PinState)BitValue); //把标准库的函数替换为HAL库的函数
	/*如果单片机速度过快,可在此添加适量延时,以避免超出I2C通信的最大速度*/
	//...
}

void OLED_W_SDA(uint8_t BitValue)
{
	/*根据BitValue的值,将SDA置高电平或者低电平*/
	//GPIO_WriteBit(GPIOB, GPIO_Pin_9, (BitAction)BitValue);
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, (GPIO_PinState)BitValue); //把标准库的函数替换为HAL库的函数
	/*如果单片机速度过快,可在此添加适量延时,以避免超出I2C通信的最大速度*/
	//...
}

void OLED_GPIO_Init(void)
{
	uint32_t i, j;
	
	/*在初始化前,加入适量延时,待OLED供电稳定*/
	for (i = 0; i < 1000; i ++)
	{
		for (j = 0; j < 1000; j ++);
	}

/*可以注释掉引脚配置,在STM32CubeMX中配置PB8,PB9*/
	
	/*将SCL和SDA引脚初始化为开漏模式*/
//    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
//	
//	GPIO_InitTypeDef GPIO_InitStructure;
// 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
//	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
// 	GPIO_Init(GPIOB, &GPIO_InitStructure);
//	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
// 	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	/*释放SCL和SDA*/
	OLED_W_SCL(1);
	OLED_W_SDA(1);
}

打开OLED.Data.h文件,检查宏定义OLED_CHN_CHAR_WIDTH的值是否正确

编译程序,如果出现这样的报错,那么就点击魔术棒→C/C++→在Misc Controls中填入--no-multibyte-chars

编译无错误

如果OLED显示中文逗号,或者,一个方框里面问号的图形,检查编码是否正确

如果还不能显示正确的文字,勾选Use MicroLIB

三、OLED显示汉字

先使用OLED显示一下你好,世界!

将程序下载到开发板中,可以看到,!的位置上显示了一个方框,内部一个问号的图形

打开OLED_Data.c文件,找到365行,发现是因为没有定义!的字模数据,所以显示了这个默认图形

打开取模软件,点击字模生成和液晶面板选项,点阵格式选择阴码,取模方式选择列行式,取模走向选择逆向,输出数制为十六进制,自定义格式选择C51格式,去掉行前缀和行后缀的花括号。

完成设置后,输入!,点击生成字模即可

把生成的字模数据复制到OLED_CF16x16数组中

可以看到,添加了!的字模数据后,!就可以显示出来了

如果想显示其他大小的汉字,比如32X32大小的汉字,可以这样做:

首先,打开取模软件,把字宽和字高设置为32,输入汉字,生成字模

然后,在OLED_Data.h文件中定义字模基本单元(结构体)

typedef struct 
{
	char Index[OLED_CHN_CHAR_WIDTH + 1];	//汉字索引
	uint8_t Data[128];						//字模数据
} ChineseCell32X32_t;

在OLED_Data.c中定义一个数组来存储汉字字模数据

不要忘记在OLED_Data.h中声明这个数组

在OLED.h中,定义两个宏,表示16X16和32X32的汉字大小

然后参考OLED_ShowChinese函数,编写OLED_ShowChinese2函数,尝试将16X16大小的汉字和32X32大小的汉字用一个函数显示出来

void OLED_ShowChinese2(int16_t X, int16_t Y, uint8_t CF_Size,char *Chinese)
{
	uint8_t pChinese = 0;
	uint8_t pIndex;
	uint8_t i;

	char SingleChinese[OLED_CHN_CHAR_WIDTH + 1] = {0};
	
	for (i = 0; Chinese[i] != '\0'; i ++)		//遍历汉字串
	{
		SingleChinese[pChinese] = Chinese[i];	//提取汉字串数据到单个汉字数组
		pChinese ++;							//计次自增
		
		/*当提取次数到达OLED_CHN_CHAR_WIDTH时,即代表提取到了一个完整的汉字*/
		if (pChinese >= OLED_CHN_CHAR_WIDTH)
		{
			pChinese = 0;		//计次归零
			
			/*遍历整个汉字字模库,寻找匹配的汉字*/
			/*如果找到最后一个汉字(定义为空字符串),则表示汉字未在字模库定义,停止寻找*/
			if(CF_Size == OLED_CF16X16)
			{
				for (pIndex = 0; strcmp(OLED_CF16x16[pIndex].Index, "") != 0; pIndex ++)
				{
					/*找到匹配的汉字*/
					if (strcmp(OLED_CF16x16[pIndex].Index, SingleChinese) == 0)
					{
						break;		//跳出循环,此时pIndex的值为指定汉字的索引
					}
				}
				
				/*将汉字字模库OLED_CF16x16的指定数据以16*16的图像格式显示*/
				OLED_ShowImage(X + ((i + 1) / OLED_CHN_CHAR_WIDTH - 1) * 16, Y, 16, 16, OLED_CF16x16[pIndex].Data);				
			}
			else if(CF_Size == OLED_CF32X32)
			{
				for (pIndex = 0; strcmp(OLED_CF32x32[pIndex].Index, "") != 0; pIndex ++)
				{
					/*找到匹配的汉字*/
					if (strcmp(OLED_CF32x32[pIndex].Index, SingleChinese) == 0)
					{
						break;		//跳出循环,此时pIndex的值为指定汉字的索引
					}
				}
				
				/*将汉字字模库OLED_CF16x16的指定数据以32*32的图像格式显示*/
				OLED_ShowImage(X + ((i + 1) / OLED_CHN_CHAR_WIDTH - 1) * 32, Y, 32, 32, OLED_CF32x32[pIndex].Data);				
			}
		}
	}
}

在OLED.h中声明这个函数

用OLED分别显示16X16大小的汉字:你好世界,32X32大小的汉字:世界你好

把程序下载到开发板上,现象如下

如果要显示其他大小的汉字也可以参照上面的方法

四、OLED显示图像

打开取模软件,点击模式→图形模式,新建图像,宽:16,高:16

绘制图像,点击鼠标左键绘制,鼠标右键取消

在OLED_Data.c中定义数组

在OLED_Data.h中声明数组

调用OLED_ShowImage函数显示图像

接下来是显示图片,我们可以用Matlab对图片进行一些处理

I = imread('OIP-C.bmp'); 
subplot(1,2,1);
imshow(I) % 显示原图
title('原图');

thresh1 = graythresh(I);
I1 = im2bw(I,thresh1); % 对图像直接进行二值化

I2 = imresize(I1,[64,64]);%调整图片大小,调整为宽64,高64

subplot(1,2,2);
imshow(I2);
title('最终图像');
imwrite(I2,'最终图像.bmp','bmp');

处理结果如下:

点击打开一个bmp图像,这样取模软件就能自动绘制出图像

点击生成字模,重复上述定义数组等步骤,最后结果如下:

下载地址:【免费】江协科技0.96寸OLED驱动函数(HAL库移植)资源-优快云文库

好的,我可以为您提供一个简单的代码示例来实现您的要求。请注意,以下代码仅作为参考,您需要根据您的具体情况进行适当的修改和调整。 首先,我们需要在HTML页面中创建一个日历框架和样式,如下所示: ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Outlook Calendar Demo</title> <style> table { border-collapse: collapse; width: 100%; } th, td { text-align: center; padding: 8px; border: 1px solid #ddd; } th { background-color: #f2f2f2; } .today { background-color: #ffc107; } </style> </head> <body> <h1>Outlook Calendar Demo</h1> <table> <thead> <tr> <th>Sun</th> <th>Mon</th> <th>Tue</th> <th>Wed</th> <th>Thu</th> <th>Fri</th> <th>Sat</th> </tr> </thead> <tbody id="calendar-body"> </tbody> </table> </body> </html> ``` 接下来,我们需要编写JavaScript代码来动态生成日历并从MySQL数据库中获取事件数据。我们将使用jQuery库来简化代码。请确保您已经将jQuery库添加到您的HTML页面中。 ```javascript $(function() { // 获取当前日期 var today = new Date(); var year = today.getFullYear(); var month = today.getMonth() + 1; var date = today.getDate(); // 获取指定年月的天数 function getDaysInMonth(year, month) { return new Date(year, month, 0).getDate(); } // 获取指定日期的事件 function getEventsForDate(year, month, date) { // 这里需要根据您的具体情况连接到MySQL数据库,并执行查询操作 // 假设您已经获取到了对应日期的事件列表,存储在events数组中 var events = [ { employee_id: 1, event: 'Meeting with client' }, { employee_id: 2, event: 'Team building activity' }, { employee_id: 3, event: 'Project deadline' } ]; // 过滤出对应日期的事件 var filteredEvents = events.filter(function(event) { return event.date === year + '-' + month + '-' + date; }); // 返回事件列表 return filteredEvents; } // 动态生成日历 var calendarBody = $('#calendar-body'); var daysInMonth = getDaysInMonth(year, month); var dateCounter = 1; for (var i = 0; i < 6; i++) { var row = $('<tr></tr>'); for (var j = 0; j < 7; j++) { if (i === 0 && j < new Date(year, month - 1, 1).getDay()) { var cell = $('<td></td>'); row.append(cell); } else if (dateCounter > daysInMonth) { break; } else { var cell = $('<td></td>').text(dateCounter); if (dateCounter === date) { cell.addClass('today'); } var events = getEventsForDate(year, month, dateCounter); if (events.length > 0) { var eventList = $('<ul></ul>'); events.forEach(function(event) { var listItem = $('<li></li>').text(event.event); eventList.append(listItem); }); cell.append(eventList); } dateCounter++; row.append(cell); } } calendarBody.append(row); } }); ``` 在上面的代码中,我们首先获取当前日期,然后使用`getDaysInMonth()`函数获取对应年月的天数。接下来,我们动态生成日历表格,并为当前日期所在单元格添加`today`类以突出显示。最后,我们通过`getEventsForDate()`函数MySQL数据库中获取对应日期的事件,并将事件列表添加到对应单元格中。 请注意,上面的代码仅供参考,您需要根据您的具体情况进行适当的修改和调整,例如: - 您需要根据您的MySQL数据库连接方式和查询语句来实现`getEventsForDate()`函数。 - 您可以根据需要修改日历表格的样式和布局。 - 如果您希望支持跨年和跨月的日历显示,您需要修改`getDaysInMonth()`函数以处理这种情况。 - 如果您的事件数据包含起始时间和结束时间等更复杂的信息,您需要修改代码以支持这种情况。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值