STM32F103+OLED曲线绘制

STM32F103+OLED曲线绘制

从本文的标题便能看出,此次分享的内容是以STM32F103C8T6芯片为控制核心,OLED则为0.96寸I2C通信的4针类型。其实OLED的类型不是重点,各种类型的操作基本大同小异,无非是读写通信方式的不同而已,接下来为大家详细介绍OLED屏除显示汉字、字符、数字外,绘图功能的实现,大体分为硬件连接与软件代码编写两大部分。

  • 硬件连接部分

0.96寸OLED屏如下图所示:

OLED硬件连接引脚图
根据上图我们可以看到,这个型号的OLED屏只有4个引脚,真正与MCU通信的信号线才2根,比较适合于通用I/O口资源较少的控制芯片。在本文中OLED与STM32F103C8T6芯片的硬件I2C相连接: PB6 – SCL;PB7 – SDA 。

  • 软件程序部分

1. OLED I2C通信代码

void I2C_Configuration(void)
{
	I2C_InitTypeDef  I2C_InitStructure;
	GPIO_InitTypeDef  GPIO_InitStructure; 

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

	/*STM32F103C8T6芯片的硬件I2C: PB6 -- SCL; PB7 -- SDA */
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//I2C必须开漏输出
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	I2C_DeInit(I2C1);//使用I2C1
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
	I2C_InitStructure.I2C_OwnAddress1 = 0x30;//主机的I2C地址,随便写的
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	I2C_InitStructure.I2C_ClockSpeed = 400000;//400K

	I2C_Cmd(I2C1, ENABLE);
	I2C_Init(I2C1, &I2C_InitStructure);
}


 /**
  * @brief  I2C_WriteByte,向OLED寄存器地址写一个byte的数据
  * @param  addr:寄存器地址
	*					data:要写入的数据
  * @retval 无
  */
void I2C_WriteByte(uint8_t addr,uint8_t data)
{
  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
	
	I2C_GenerateSTART(I2C1, ENABLE);//开启I2C1
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));/*EV5,主模式*/

	I2C_Send7bitAddress(I2C1, OLED_ADDRESS, I2C_Direction_Transmitter);//器件地址 -- 默认0x78
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

	I2C_SendData(I2C1, addr);//寄存器地址
	while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

	I2C_SendData(I2C1, data);//发送数据
	while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
	
	I2C_GenerateSTOP(I2C1, ENABLE);//关闭I2C1总线
}


 /**
  * @brief  WriteCmd,向OLED写入命令
  * @param  I2C_Command:命令代码
  * @retval 无
  */
void WriteCmd(unsigned char I2C_Command)//写命令
{
	I2C_WriteByte(0x00, I2C_Command);
}


 /**
  * @brief  WriteDat,向OLED写入数据
  * @param  I2C_Data:数据
  * @retval 无
  */
void WriteDat(unsigned char I2C_Data)//写数据
{
	I2C_WriteByte(0x40, I2C_Data);
}


 /**
  * @brief  OLED_Init,初始化OLED
  * @param  无
  * @retval 无
  */
void OLED_Init(void)
{
	DelayMs(100); //这里的延时很重要
	
	WriteCmd(0xae);//--turn off oled panel"关闭led面板"
    WriteCmd(0x00);//---set low column address设置低列地址
    WriteCmd(0x10);//---set high column address设置高列地址
    WriteCmd(0x40);//--set start line address设置起始地址线  Set Mapping RAM Display Start Line (0x00~0x3F)
    WriteCmd(0x81);//--set contrast control register设置对比度控制寄存器
    WriteCmd(0xcf); // Set SEG Output Current Brightness设置亮度控制寄存器
    WriteCmd(0xa1);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
    WriteCmd(0xc8);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
    WriteCmd(0xa6);//--set normal display
    WriteCmd(0xa8);//--set multiplex ratio(1 to 64)设置多路复用
    WriteCmd(0x3f);//--1/64 duty
    WriteCmd(0xd3);//-set display offset	Shift Mapping RAM Counter设置显示的偏移映射内存计数器 (0x00~0x3F)
    WriteCmd(0x00);//-not offset取消偏移补偿
    WriteCmd(0xd5);//--set display clock divide ratio/oscillator frequency设置显示时钟分频比/振荡器频率
    WriteCmd(0x80);//--set divide ratio, Set Clock as 100 Frames/Sec设置分离比例,时钟设置为100帧/秒
    WriteCmd(0xd9);//--set pre-charge period预充电时间
    WriteCmd(0xf1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock预充电15钟及放电1时钟
    WriteCmd(0xda);//--set com pins hardware configurationCOM引脚设置硬件配置
    WriteCmd(0x12);
    WriteCmd(0xdb);//--set vcomh设置VCOM电平
    WriteCmd(0x40);//Set VCOM Deselect Level取消设置VCOM电平
    WriteCmd(0x20);//-Set Page Addressing Mode (0x00/0x01/0x02)设置页面寻址模式(0x00 /头/ 0x02)
    WriteCmd(0x02);//
    WriteCmd(0x8d);//--set Charge Pump enable/disable设置电荷泵启用/禁用
    WriteCmd(0x14);//--set(0x10) 设为0x10失能
    WriteCmd(0xa4);// Disable Entire Display On (0xa4/0xa5)禁用整个显示
    WriteCmd(0xa6);// Disable Inverse Display On (0xa6/a7) 禁用反显示
    WriteCmd(0xaf);//--turn on oled panel打开led面板
 
}

2.OLED的相关操作函数

2.1.基础函数

 /**
  * @brief  OLED_SetPos,设置光标
  * @param  x,光标x位置
	*					y,光标y位置
  * @retval 无
  */
void OLED_SetPos(unsigned char x, unsigned char y) //设置起始点坐标
{ 
	WriteCmd(0xb0+y);
	WriteCmd(((x&0xf0)>>4)|0x10);
	WriteCmd((x&0x0f)|0x01);
}

 /**
  * @brief  OLED_Fill,填充整个屏幕
  * @param  fill_Data:要填充的数据
	* @retval 无
  */
void OLED_Fill(unsigned char fill_Data)//全屏填充
{
	unsigned char m,n;
	for(m=0;m<8;m++)
	{
		WriteCmd(0xb0+m);		//page0-page1
		WriteCmd(0x00);		//low column start address
		WriteCmd(0x10);		//high column start address
		for(n=0;n<128;n++)
			{
				WriteDat(fill_Data);
			}
	}
}

 /**
  * @brief  OLED_CLS,清屏
  * @param  无
	* @retval 无
  */
void OLED_CLS(void)//清屏
{
	OLED_Fill(0x00);
}


 /**
  * @brief  OLED_ON,将OLED从休眠中唤醒
  * @param  无
	* @retval 无
  */
void OLED_ON(void)
{
	WriteCmd(0X8D);  //设置电荷泵
	WriteCmd(0X14);  //开启电荷泵
	WriteCmd(0XAF);  //OLED唤醒
}


 /**
  * @brief  OLED_OFF,让OLED休眠 -- 休眠模式下,OLED功耗不到10uA
  * @param  无
	* @retval 无
  */
void OLED_OFF(void)
{
	WriteCmd(0X8D);  //设置电荷泵
	WriteCmd(0X10);  //关闭电荷泵
	WriteCmd(0XAE);  //OLED休眠
}


 /**
  * @brief  OLED_ShowStr,显示codetab.h中的ASCII字符,有6*8和8*16可选择
  * @param  x,y : 起始点坐标(x:0~127, y:0~7);
	*					ch[] :- 要显示的字符串; 
	*					TextSize : 字符大小(1:6*8 ; 2:8*16)
	* @retval 无
  */
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
{
	unsigned char c = 0,i = 0,j = 0;
	switch(TextSize)
	{
		case 1:
		{
			while(ch[j] != '\0')
			{
				c = ch[j] - 32;
				if(x > 126)
				{
					x = 0;
					y++;
				}
				OLED_SetPos(x,y);
				for(i=0;i<6;i++)
					WriteDat(F6x8[c][i]);
				x += 6;
				j++;
			}
		}break;
		case 2:
		{
			while(ch[j] != '\0')
			{
				c = ch[j] - 32;
				if(x > 120)
				{
					x = 0;
					y++;
				}
				OLED_SetPos(x,y);
				for(i=0;i<8;i++)
					WriteDat(F8X16[c*16+i]);
				OLED_SetPos(x,y+1);
				for(i=0;i<8;i++)
					WriteDat(F8X16[c*16+i+8]);
				x += 8;
				j++;
			}
		}break;
	}
}

 /**
  * @brief  OLED_ShowCN,显示codetab.h中的汉字,16*16点阵
  * @param  x,y: 起始点坐标(x:0~127, y:0~7); 
	*					N:汉字在codetab.h中的索引
	* @retval 无
  */
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;
	}
}



 /**
  * @brief  OLED_DrawBMP,显示BMP位图
  * @param  x0,y0 :起始点坐标(x0:0~127, y0:0~7);
	*					x1,y1 : 起点对角线(结束点)的坐标(x1:1~128,y1:1~8)
	* @retval 无
  */
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_SetPos(x0,y);
    for(x=x0;x<x1;x++)
		{
			WriteDat(BMP[j++]);
		}
	}
}

2.2.描点函数
入口参数:
x:点的x坐标;
y:点的y坐标;
t:点的状态;“0”代表暗,“1”代表亮

void OLED_DrawDot(unsigned char x,unsigned char y,unsigned char t)
{
	    unsigned char pos,bx,temp=0;
		if(x>127||y>63) return;
		pos=(y)/8;
		bx=y%8;
		temp=1<<(bx);
		if(t) OLED_GRAM[x][pos]|=temp;
		else OLED_GRAM[x][pos]&=~temp;
		OLED_Refresh_Gram();	
}

2.3.连线函数
入口参数:
x1:起点的x坐标;
y1:起点的y坐标;
x2:终点的x坐标;
y2:终点的y坐标;

void LCD_DrawLine(unsigned int x1, unsigned int y1, unsigned int x2,unsigned int y2)
{
	unsigned int t; 
	int xerr=0,yerr=0,delta_x,delta_y,distance; 
	int incx,incy,uRow,uCol; 
	delta_x=x2-x1; //计算坐标增量 
	delta_y=y2-y1; 
	uRow=x1; 
	uCol=y1; 
	if(delta_x>0)incx=1; //设置单步方向 
	else if(delta_x==0)incx=0;//垂直线 
	else {incx=-1;delta_x=-delta_x;} 
	if(delta_y>0)incy=1; 
	else if(delta_y==0)incy=0;//水平线 
	else{incy=-1;delta_y=-delta_y;} 
	if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴 
	else distance=delta_y; 
	for(t=0;t<=distance+1;t++ )//画线输出 
	{  
		OLED_DrawDot(uRow,uCol,1);//画点 
		xerr+=delta_x ; 
		yerr+=delta_y ; 
		if(xerr>distance) 
		{ 
			xerr-=distance; 
			uRow+=incx; 
		} 
		if(yerr>distance) 
		{ 
			yerr-=distance; 
			uCol+=incy; 
		} 
	}  
}    

最后实际运行效果图如下:

在这里插入图片描述

  • 21
    点赞
  • 193
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
STM32F103是一款由意法半导体(STMicroelectronics)开发的Cortex-M3内核的32位微控制器。OLED(Organic Light-Emitting Diode,有机发光二极管)是一种新型的显示技术,具有高对比度、快速响应、极低功耗等优点,因此在许多应用领域中都有广泛的应用。 要驱动OLED显示屏,首先需要了解OLED显示屏的特性和通信方式。通常,OLED显示屏通过SPI或I2C接口与MCU通信,我们可以根据具体的OLED芯片型号选择相应的通信方式。 在STM32F103上驱动OLED显示屏的步骤如下: 1. 配置STM32F103的SPI或I2C总线,设置相应的引脚复用功能,使其可以与OLED通信。 2. 初始化OLED显示屏,包括发送初始化命令和参数,例如设置显示模式(点阵、点亮模式)、亮度、扫描方向等。这些初始化命令通常在OLED的数据手册中有详细说明。 3. 编写绘制函数,根据需求绘制图像、文本等元素。可以使用STM32F103上的GPIO口或DMA传输方式发送数据到OLED显示屏。这些操作可以通过编写C语言代码实现。 4. 更新显示内容,将绘制好的图像数据发送到OLED显示屏。可以使用DMA传输或轮询方式发送数据。 需要注意的是,OLED显示屏的引脚连接、通信协议及命令、参数设置等细节可能因OLED型号而异,在编写驱动程序时需要根据具体的OLED芯片手册进行调试和优化。 通过以上步骤,我们可以在STM32F103上成功驱动OLED显示屏,实现图像、文本等内容的显示。这样我们就可以利用STM32F103的强大处理能力和低功耗特性,结合OLED显示屏的优点,实现一些嵌入式设备的高质量图形界面。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值