这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【Let'sdo第1期-DIY功率检测与控制系统】04过程帖:基础任务2 实现

共3条 1/1 1 跳转至

【Let'sdo第1期-DIY功率检测与控制系统】04过程帖:基础任务2 实现OLED屏幕显示信息

高工
2025-06-01 15:12:05     打赏

在本次活动中,使用OLED屏幕对数据进行显示,这里和大家分享一下,屏幕的驱动经验:

一:OLED屏幕知识简单分享

OLED,即有机发光二极管(Organic Light-Emitting Diode),又称为有机电激光显示(Organic Electroluminesence Display, OELD)。因为具备轻薄、省电等特性,因此从 2003 年开始,这种显示设备在 MP3 播放器上得到了广泛应用,而对于同属数码类产品的 DC 与手机,此前只是在一些展会上展示过采用 OLED 屏幕的工程样品。自 2007 年后,寿命得 到很大提高,具备了许多 LCD 不可比拟的优势。

GND:电源地 VCC:2.2V~5.5V SCL(D0):CLK 时钟 (高电平 2.2V~5.5V) SDA(D1):MOSI 数据(高电平 2.2V~5.5V) RST:复位(高电平 2.2V~5.5V) D/C:数据/命令(高电平 2.2V~5.5V) 兼容 3.3V 和 5V 控制芯片的 I/O 电平(无需任何设置,直接兼容)。

3.jpg

这是本次活动使用的OLED屏幕,虽然背面标识的时SSD1315,但是和驱动SSD1306的方式大体相同,驱动的时候可以参考SSD1306的驱动方式进行驱动;

二:IIC协议的知识分享:

IIC通讯协议的了解

IIC(Inter-Integrated Circuit)是一种串行通信协议,主控制器和从器件间的主从通信。它使用两根线:SDA(数据线)和SCL(时钟线)。SDA(SerialData Line):用于传输数据。SCL(Serial Clock Line):用于同步数据传输的时钟信号。

注意:1.1C不同于485和CAN可长距离通讯,IIC只能短距离,常用干IC与IC通讯。例如存储芯片:24C02;传感器模块:ST30,气压模块MPL MPU6050,温度模块ATH20等等,有很多的模块,当时我们熟悉了IIC 的通讯方式,可以外扩很多模块,适用于电子爱好者和DIY;

2.IIC电路设计时,建议在SDA和SCL两根线外加上拉电阻,以保证时序通讯的稳定性。不过在本次的活动电路板上面并没有外接上拉电阻,也不知道是不是模块上面焊接好了。

2.1 IIC类型

IIC 总线在传送数据过程中共有三种类型信号,分别是:

1.开始信号:SCL 为高电平时,SDA由高电平向低电平跳变,开始传送数据。

2.结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。

3.应答信号:从机 在接收到 8bit 数据后,向发送数据的主机发出特定的低电平脉冲,表示已收到数据。主机向从机发出一个信号后等待从机发出一个应答信号,主机接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。

2.2 IIC的总时序图

2.png

起始条件是SCL保持高电平,SDA由高电平变为低电平后,延时(最少4us,这个和线长有关系),SCL变为低电平。只有当SCL线上的时钟信号为低时,数据线上的“高”或“低”状态才可以改变。输出到SDA线上的每个字节必须是8位,数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)。当传输完SDA马上拉低,接着输出低电平信号主机进而产生停止信号,结束传送过程。

2.3 IIC的 发送时序

3.png

1主机首先产生起开始信号,然后紧跟着发送一个从机地址,这个地址共有7位,紧接着的第8位是数据方向位(R/W),0表示主机发送数据(写),1表示主机接收数据(读)。

2.主机发送地址时,总线上的每个从机都将这7位地址码与自己的地址进行比较,若相同,则认为自已正在被主机寻址,根据R/T位将自己确定为发送器和接收器。这时候主机等待从机的应答信号,当主机收到应答信号时,发送要访问从机的那个地址,继续等待从机的应答信号,当主机收到应答信号时,发送N个字节的数据,继续等待从机的N次应答信号,主机产生停止信号,结束传送过程。

2.4 IIC的读时序

4.png



三:STM32 cube MX 软件配置

3.1 这里我是用硬件IIC 进行驱动

3.png

使用PB8 PB9 引脚作为IIC1的引脚,需要重映射到该引脚;

这里注意下,IIC的参数配置:

4.png

同时开启,硬件IIC的中断函数功能。

四:字库的制作:

4.1这里根据驱动函数,设置字体的大小即可,

5.png

4.2 图片的制作

这里我们需要在PS中绘制一张图片,然后再软件中打开

6.png

五:底层代码如下所示:

/***********************************************************************************************
  * @brief   static unsigned char OLED_send_byteS(unsigned char *data, unsigned char length)
  * @param    data:输入的数据  length:长度值,使用硬件IIC底层驱动函数
  * @retval  无
  * @author  聪聪哥哥
  * @version V1.1.0
  * @date     25-5-2025
*************************************************************************************************/
static unsigned char OLED_send_byteS(unsigned char *data, unsigned char length)
{
	if (HAL_I2C_Master_Transmit(&hi2c1, 0x78, data, length, 2) != HAL_OK)
	{
		return 0;
	}
	return 1;
}

/***********************************************************************************************
  * @brief   static void I2C_WriteByte(uint8_t addr, uint8_t value)
  * @param    addr:IIC模块的地址,value :写入的数据
  * @retval  无
  * @author  聪聪哥哥
  * @version V1.1.0
  * @date     25-5-2025
*************************************************************************************************/
static void I2C_WriteByte(uint8_t addr, uint8_t value)
{
	unsigned char dta[2] = {0};
	dta[0] = addr;
	dta[1] = value;
	OLED_send_byteS(dta, 2);
}

/***********************************************************************************************
  * @brief   void WriteCmd(unsigned char I2C_Command)
  * @param    I2C_Command : IIC的命令
  * @retval  无
  * @author  聪聪哥哥
  * @version V1.1.0
  * @date     25-5-2025
*************************************************************************************************/
void WriteCmd(unsigned char I2C_Command)
{
	I2C_WriteByte(0x00, I2C_Command);
}

/***********************************************************************************************
  * @brief   void WriteDat(unsigned char I2C_Data)
  * @param    I2C_Data : IIC的数据
  * @retval  无
  * @author  聪聪哥哥
  * @version V1.1.0
  * @date     25-5-2025
*************************************************************************************************/
void WriteDat(unsigned char I2C_Data)//写数据
{
	I2C_WriteByte(0x40, I2C_Data);
}

对于屏幕的驱动,我们仅仅需要修改上述底层驱动代码,就可以对OLED进行显示。


显示数字汉字如下所示:

//--------------------------------------------------------------
// Prototype      : void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
// Calls          : 
// Parameters     : x,y -- 起始点坐标(x:0~127, y:0~7); N:汉字在codetab.h中的索引
// Description    : 显示codetab.h中的汉字,16*16点阵
//--------------------------------------------------------------
void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
{
	unsigned char wm=0;
	unsigned int  adder=32*N;
	OLED_SetPos(x , y);
	for(wm = 0;wm < 16;wm++)
	{
		WriteDat(F16x16[adder]);
		adder += 1;
	}
	OLED_SetPos(x,y + 1);
	for(wm = 0;wm < 16;wm++)
	{
		WriteDat(F16x16[adder]);
		adder += 1;
	}
}

显示图片的函数如下所示:

void OLED_ShowPicture(uint8_t x,uint8_t y,uint8_t sizex,uint8_t sizey,uint8_t BMP[])
{

	uint32_t j=0;
	uint8_t x1=0,y1=0;

	if(y1%8==0)y1=0;
	else y1+=1;
	for(y1=y;y1<sizey;y1++)
	 {
		 OLED_DrawPoint(x,y1);
		 for(x1=x;x1<sizex;x1++)
		 {
			 WriteDat(BMP[j]);
			 j++;
     }
	 }
}

界面显示函数如下:

extern unsigned char BMP1[];
/***********************************************************************************************
  * @brief   void StartDisPlay(void)
  * @param   开机界面显示
  * @retval  无
  * @author  聪聪哥哥
  * @version V1.1.0
  * @date     25-5-2025
*************************************************************************************************/
void StartDisPlay(void)
{
	OLED_ShowPicture(0,0,128,8,BMP1);
	HAL_Delay(2000);
	OLED_Clear();
}
/***********************************************************************************************
  * @brief   void WorkPageImmobility(void)
  * @param   工作界面固定显示
  * @retval  无
  * @author  聪聪哥哥
  * @version V1.1.0
  * @date     25-5-2025
*************************************************************************************************/
void WorkPageImmobility(void)
{

	OLED_ShowCN(0, 2, 6);
	OLED_ShowCN(16, 2, 7);

	OLED_ShowCN(0, 4, 8);
	OLED_ShowCN(16, 4, 9);

	OLED_ShowCN(0, 6, 10);
	OLED_ShowCN(16, 6, 11);

	OLED_ShowStr(100, 2, (uint8_t *)"MV", 2);
	OLED_ShowStr(100, 4, (uint8_t *)"MA", 2);
	OLED_ShowStr(100, 6, (uint8_t *)"MW", 2);

}
/***********************************************************************************************
  * @brief   void WorkPageDataDisplay(void)
  * @param   工作界面数据显示
  * @retval  无
  * @author  聪聪哥哥
  * @version V1.1.0
  * @date     25-5-2025
*************************************************************************************************/
const uint8_t test[] = "Hello world";
void WorkPageDataDisplay(void)
{
	uint16_t TempStr[16];

	sprintf((char*)TempStr,"%3d",iOriginalVoltageData); 
	OLED_ShowStr(40, 2, (uint8_t *)TempStr, 2);

	OLED_ShowNum(50,4,iOriginalElectriData,5,16);

	OLED_ShowNum(50,6,iOriginalPowerData,5,16);
}

主程序如下:

  OLED_Init();
  OLED_ColorTurn(0);//0?????????1 ??????
  OLED_DisplayTurn(0);//0??????? 1 ?????????
  OLED_Refresh();
  OLED_Clear();
  StartDisPlay();
  WorkPageImmobility();

实物测试图如下:

顺便说声,为了方便调试使用EDA绘制乐一个STM32F411的拓展板

由于开发的功能还没测试好,等测试好,将PCB的文件上传。

6.jpg

程序代码:

03_OLED_time.zip


助工
2025-06-09 11:39:57     打赏
2楼

给大佬点赞


菜鸟
2025-06-10 19:58:02     打赏
3楼

大佬也太牛了了吧,还搞了个拓展板


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]