?? 文章作者:二土電子
?? 關注文末公眾號獲取其他資料和工程文件!
?? 期待大家一起學習交流!
一、OLED簡介
OLED是開發(fā)時常用的顯示器件,這里介紹的是0.96寸的四針腳OLED,IIC控制。
二、數(shù)據(jù)手冊分析
2.1 供電電壓
供電電壓在3V~5V,用3.3V即可。
2.2 引腳定義
2.3 原理圖介紹
I2C通信接口由從地址位DC、I2C總線數(shù)據(jù)信號SDA(輸出SDAOUT/D2輸出,SDAIN/D1輸入)和I2C總線時鐘信號SCL(D0)組成。數(shù)據(jù)信號和時鐘信號都必須連接到上拉電阻器上。
從屬地址位(SA0)必須在通過I2C總線傳輸或接收任何信息之前,先識別該從屬地址。設備將響應從地址,后面是從地址位(“SA0”位)和讀/寫選擇位(“R/W#”,具有以下字節(jié)格式的位)
“SA0”位為從屬地址提供了一個擴展位??梢赃x擇“0111100”或“0111101”作為OLED的從屬地址。D/C# pin作為SA0進行從屬地址的選擇”?!笆瞻l(fā)#”位用于確定I2c總線接口的操作模式。R/W#=1,它處于讀取模式。R/W#=0,它處于寫模式。
從屬地址 | DC | 說明 |
---|---|---|
0111 100(0x78) | DC = 0 | 默認值 |
0111 1010(0x7A) | DC = 1 | 用戶需要切換電阻位置來修改IIC地址 |
2.4 數(shù)據(jù)手冊程序
數(shù)據(jù)手冊中會給出一些底層程序,可以通過這寫程序快速的了解到如何使用。后面的程序設計中會詳細介紹這部分,這里就不再做介紹了。
三、IIC通信
3.1 什么是IIC
IIC(Inter-Integrated Circuit)其實是IICBus簡稱,中文是集成電路總線,它是一種串行通信總線,使用多主從架構,由飛利浦公司在1980年代為了讓主板、嵌入式系統(tǒng)或手機用以連接低速周邊設備而發(fā)展。IIC支持一主多從,主機通過尋址的方式呼叫從機,然后進行數(shù)據(jù)傳輸。
I2C串行總線一般有兩根信號線,一根是雙向的數(shù)據(jù)線SDA,另一根是時鐘線SCL。所有從設備的SDA和SLK都接到總線上。
3.2 IIC通信協(xié)議
IIC協(xié)議中有兩種幀,一種是地址幀,用來尋找從設備。一種是數(shù)據(jù)幀,用來作主從機之間的數(shù)據(jù)交互。IIC協(xié)議還規(guī)定了起始信號,終止信號和應答信號。
- 空閑狀態(tài)
I2C總線總線的SDA和SCL兩條信號線同時處于高電平時,規(guī)定為總線的空閑狀態(tài)。此時各個器件的輸出級場效應管均處在截止狀態(tài),即釋放總線,由兩條信號線各自的上拉電阻把電平拉高。 - 起始信號
SCL為高電平期間,SDA信號線由高電平向低電平的變化表示起始信號 - 終止信號
SCL為高電平期間,SDA由低電平向高電平的變化表示終止信號
起始信號和終止信號都是由主機發(fā)送的,起始信號產(chǎn)生之后,總線處于被占用的狀態(tài),在終止信號產(chǎn)生之后,總線就處于空閑狀態(tài)。
當從機接收完一幀時,會發(fā)送一個應答信號。應答信號為低電平時,規(guī)定為有效應答(ACK,簡稱應答位),表示接收器已經(jīng)成功地接受了該字節(jié)應答位為高電平時,規(guī)定為非應答信號(NACK),一般表示接收器接收該字節(jié)沒有成功。
IIC通信協(xié)議有自己的數(shù)據(jù)格式,每一個字節(jié)必須保證是8bit長度。數(shù)據(jù)傳送時,先傳送最高位,每一個被傳送的字節(jié)后面都必須跟隨1bit的應答位(即每一幀數(shù)據(jù)一共有9bit)。
3.3 IIC主從通信過程
3.3.1 寫入數(shù)據(jù)
主設備往從設備寫入數(shù)據(jù)需要有下面的過程
- 主設備發(fā)送一個起始信號(START)
- 主設備在數(shù)據(jù)線上廣播從設備地址
- 確定數(shù)據(jù)傳輸方向(R/W)
- 等待從設備應答信號(ACK)
- 主設備發(fā)送數(shù)據(jù)到從設備,從設備接收到后,會返回給主設備一個應答信號,直到主設備發(fā)送完數(shù)據(jù),或者從設備返回一個NACK信號,表示從設備不再接收數(shù)據(jù)
- 數(shù)據(jù)發(fā)送完畢,主設備發(fā)送終止信號(STOP)
3.3.2 讀取數(shù)據(jù)
- 主設備發(fā)送起始信號(START)
- 主設備在數(shù)據(jù)線上廣播從設備地址
- 確定數(shù)據(jù)傳輸方向(R/W)
- 等待從設備應答信號(ACK)
- 從機向主機發(fā)送需要讀取的數(shù)據(jù)
- 主設備每接收到一個字節(jié)數(shù)據(jù),后面就會跟著向從設備發(fā)送一個應答信號
- 接收完最后一個數(shù)據(jù)后,主機會發(fā)送一個無效應答信號(NACK)
- 主設備發(fā)送終止信號,數(shù)據(jù)讀取完畢
四、OLED程序設計
4.1 OLED初始化
OLED初始化包括兩部分,一部分是初始化STM32的GPIO,另一部分是根據(jù)數(shù)據(jù)手冊提供的程序初始化OLED。STM32F103ZET6提供了兩個IIC接口
SCL | SDA | |
---|---|---|
IIC1 | PB6 | PB7 |
IIC2 | PB10 | PB11 |
實際使用軟件模擬IIC時,使用任意的GPIO即可,不必要使用上面規(guī)定的IIC引腳。這里只是使用了IIC1的引腳而已。
首先是數(shù)據(jù)手冊提供的IIC相關函數(shù)
/*
*==============================================================================
*函數(shù)名稱:IIC_delay
*函數(shù)功能:IIC延時
*輸入?yún)?shù):無
*返回值:無
*備 注:數(shù)據(jù)手冊提供
*==============================================================================
*/
void IIC_delay (void)
{
u8 t = 1;
while (t--);
}
/*
*==============================================================================
*函數(shù)名稱:I2C_Start
*函數(shù)功能:IIC起始信號
*輸入?yún)?shù):無
*返回值:無
*備 注:數(shù)據(jù)手冊提供
*==============================================================================
*/
void I2C_Start (void)
{
OLED_SDA_Set();
OLED_SCL_Set();
IIC_delay();
OLED_SDA_Clr();
IIC_delay();
OLED_SCL_Clr();
IIC_delay();
}
/*
*==============================================================================
*函數(shù)名稱:I2C_Stop
*函數(shù)功能:IIC終止信號
*輸入?yún)?shù):無
*返回值:無
*備 注:數(shù)據(jù)手冊提供
*==============================================================================
*/
void I2C_Stop (void)
{
OLED_SDA_Clr();
OLED_SCL_Set();
IIC_delay();
OLED_SDA_Set();
}
/*
*==============================================================================
*函數(shù)名稱:I2C_WaitAck
*函數(shù)功能:IIC等待應答
*輸入?yún)?shù):無
*返回值:無
*備 注:數(shù)據(jù)手冊提供
*==============================================================================
*/
void I2C_WaitAck (void)
{
OLED_SDA_Set();
IIC_delay();
OLED_SCL_Set();
IIC_delay();
OLED_SCL_Clr();
IIC_delay();
}
/*
*==============================================================================
*函數(shù)名稱:Send_Byte
*函數(shù)功能:寫入一個字節(jié)
*輸入?yún)?shù):dat:需要寫入的數(shù)據(jù)
*返回值:無
*備 注:數(shù)據(jù)手冊提供
*==============================================================================
*/
void Send_Byte (u8 dat)
{
u8 i;
for (i = 0;i < 8;i ++)
{
// 發(fā)送數(shù)據(jù)時,從高位依次寫入
if (dat & 0x80)
{
OLED_SDA_Set();
}
else
{
OLED_SDA_Clr();
}
IIC_delay();
OLED_SCL_Set();
IIC_delay();
OLED_SCL_Clr();
// dat左移1位
dat <<= 1;
}
}
/*
*==============================================================================
*函數(shù)名稱:OLED_WR_Byte
*函數(shù)功能:IIC發(fā)送一個字節(jié)數(shù)據(jù)
*輸入?yún)?shù):dat:要發(fā)送的數(shù)據(jù);mode:0是指令,1是數(shù)據(jù)
*返回值:無
*備 注:無
*==============================================================================
*/
void OLED_WR_Byte (u8 dat,u8 mode)
{
I2C_Start();
Send_Byte(0x78); // 尋址
I2C_WaitAck();
// 發(fā)送數(shù)據(jù)
if (mode)
{
Send_Byte(0x40);
}
// 發(fā)送指令
else
{
Send_Byte(0x00);
}
I2C_WaitAck();
Send_Byte(dat);
I2C_WaitAck();
I2C_Stop();
}
/*
*==============================================================================
*函數(shù)名稱:Drv_Oled_Init
*函數(shù)功能:初始化OLED
*輸入?yún)?shù):無
*返回值:無
*備 注:無
*==============================================================================
*/
void Drv_Oled_Init (void)
{
// 結構體定義
GPIO_InitTypeDef GPIO_InitStructure;
// 開啟時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// 初始化GPIO結構體
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽式輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 全部拉高,IIC處于空閑狀態(tài)
GPIO_SetBits(GPIOB,GPIO_Pin_6 | GPIO_Pin_7);
// 根據(jù)數(shù)據(jù)手冊提供的例程,初始化OLED
delay_ms(200); // 延時200ms
OLED_WR_Byte(0xAE,OLED_CMD);//--display off
OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
OLED_WR_Byte(0x40,OLED_CMD);//--set start line address
OLED_WR_Byte(0xB0,OLED_CMD);//--set page address
OLED_WR_Byte(0x81,OLED_CMD); // contract control
OLED_WR_Byte(0xFF,OLED_CMD);//--128
OLED_WR_Byte(0xA1,OLED_CMD);//set segment remap
OLED_WR_Byte(0xA6,OLED_CMD);//--normal / reverse
OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
OLED_WR_Byte(0x3F,OLED_CMD);//--1/32 duty
OLED_WR_Byte(0xC8,OLED_CMD);//Com scan direction
OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset
OLED_WR_Byte(0x00,OLED_CMD);//
OLED_WR_Byte(0xD5,OLED_CMD);//set osc division
OLED_WR_Byte(0x80,OLED_CMD);//
OLED_WR_Byte(0xD8,OLED_CMD);//set area color mode off
OLED_WR_Byte(0x05,OLED_CMD);//
OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-Charge Period
OLED_WR_Byte(0xF1,OLED_CMD);//
OLED_WR_Byte(0xDA,OLED_CMD);//set com pin configuartion
OLED_WR_Byte(0x12,OLED_CMD);//
OLED_WR_Byte(0xDB,OLED_CMD);//set Vcomh
OLED_WR_Byte(0x30,OLED_CMD);//
OLED_WR_Byte(0x8D,OLED_CMD);//set charge pump enable
OLED_WR_Byte(0x14,OLED_CMD);//
OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
}
下面是相關宏定義
// SCL
#define OLED_SCL_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_6)
#define OLED_SCL_Set() GPIO_SetBits(GPIOB,GPIO_Pin_6)
// SDA
#define OLED_SDA_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_7)
#define OLED_SDA_Set() GPIO_SetBits(GPIOB,GPIO_Pin_7)
#define OLED_CMD 0 //寫命令
#define OLED_DATA 1 //寫數(shù)據(jù)
4.2 OLED控制函數(shù)編寫
數(shù)據(jù)手冊中提供了一些指令,在編寫OLED控制函數(shù)時可以參考。
4.2.1 OLED顯示開/關程序
根據(jù)數(shù)據(jù)手冊描述,發(fā)送指令“1010 111x0”,其中x0為0時,顯示關閉,x0為1時,顯示開啟。因此,顯示開關程序如下
/*
*==============================================================================
*函數(shù)名稱:Med_Oled_Display_On
*函數(shù)功能:開啟OLED顯示
*輸入?yún)?shù):無
*返回值:無
*備 注:無
*==============================================================================
*/
void Med_Oled_Display_On(void)
{
OLED_WR_Byte(0X8D,OLED_CMD); // 設置充電泵啟用/禁用
OLED_WR_Byte(0X14,OLED_CMD); // 設置(0x10)禁用
OLED_WR_Byte(0XAF,OLED_CMD); // DISPLAY ON
}
/*
*==============================================================================
*函數(shù)名稱:Med_Oled_Display_Off
*函數(shù)功能:關閉OLED顯示
*輸入?yún)?shù):無
*返回值:無
*備 注:無
*==============================================================================
*/
void OLED_Display_Off(void)
{
OLED_WR_Byte(0X8D,OLED_CMD); // 設置充電泵啟用/禁用
OLED_WR_Byte(0X10,OLED_CMD); // 設置高列地址
OLED_WR_Byte(0XAE,OLED_CMD); // DISPLAY OFF
}
4.2.2 OLED顯示一組漢字程序
想要顯示漢字,需要先創(chuàng)建字庫。漢字取模使用PCtoLCD2002完美版,取模時的配置已經(jīng)標注
// 漢字字模數(shù)據(jù)結構定義
struct Cn16CharTypeDef // 漢字字模數(shù)據(jù)結構
{
unsigned char Index[2]; // 漢字內碼索引,一個漢字占兩個字節(jié)
unsigned char Msk[32]; // 點陣碼數(shù)據(jù)(16*16/8)
};
// 漢字取模要求
// 陰碼,逆向,列行式,16X16
struct Cn16CharTypeDef const CnChar16x16[]=
{
"太",0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xFF,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,
0x80,0x80,0x40,0x20,0x10,0x0C,0x13,0x60,0x03,0x0C,0x10,0x20,0x40,0x80,0x80,0x00,/*"太",0*/
"陳",0x00,0xFE,0x22,0x5A,0x86,0x08,0x88,0x68,0x18,0x0F,0xE8,0x08,0x08,0x08,0x08,0x00,
0x00,0xFF,0x04,0x08,0x07,0x20,0x11,0x0D,0x41,0x81,0x7F,0x01,0x05,0x09,0x30,0x00,/*"陳",1*/
"抱",0x10,0x10,0x10,0xFF,0x90,0x20,0x10,0xEC,0x27,0x24,0x24,0xE4,0x04,0xFC,0x00,0x00,
0x02,0x42,0x81,0x7F,0x00,0x00,0x00,0x3F,0x42,0x42,0x4A,0x53,0x48,0x47,0x70,0x00,/*"抱",2*/
"不",0x00,0x02,0x02,0x02,0x02,0x82,0x42,0xF2,0x0E,0x42,0x82,0x02,0x02,0x02,0x00,0x00,
0x10,0x08,0x04,0x02,0x01,0x00,0x00,0xFF,0x00,0x00,0x00,0x01,0x02,0x0C,0x00,0x00,/*"不",3*/
"動",0x40,0x44,0xC4,0x44,0x44,0x44,0x40,0x10,0x10,0xFF,0x10,0x10,0x10,0xF0,0x00,0x00,
0x10,0x3C,0x13,0x10,0x14,0xB8,0x40,0x30,0x0E,0x01,0x40,0x80,0x40,0x3F,0x00,0x00,/*"動",4*/
};
漢字顯示函數(shù)如下
/*
*==============================================================================
*函數(shù)名稱:Med_Oled_ShowCHinese16x16
*函數(shù)功能:顯示一組16*16的漢字
*輸入?yún)?shù):x:橫坐標;y:縱坐標(0~3);cn:要顯示的漢字
*返回值:無
*備 注:無
*==============================================================================
*/
void Med_Oled_ShowCHinese16x16 (u8 x,u8 y,u8 *cn)
{
u8 i,num;
while (*cn != '\0')
{
// 掃描字庫
// 這里的100,是字庫所能容納的漢字上限,可修改
for (num = 0;num < 100;num ++)
{
// 如果找到匹配的漢字
if ((CnChar16x16[num].Index[0]==*cn)
&&(CnChar16x16[num].Index[1]==*(cn+1)))
{
// 顯示前16個點
Med_Oled_Set_Pos(x,y);
for(i=0;i<16;i++)
{
OLED_WR_Byte(CnChar16x16[num].Msk[i],OLED_DATA);
}
// 顯示后16個點
Med_Oled_Set_Pos(x,y+1);
for(i=16;i<32;i++)
{
OLED_WR_Byte(CnChar16x16[num].Msk[i],OLED_DATA);
}
}
}
cn += 2;
x += 16; //若改字號,需要改
}
}
當需要顯示漢字時,只需要寫下面的程序,即可直接顯示一組漢字
Med_Oled_ShowCHinese16x16(1,2,"太陳抱不動"); // 顯示一組漢字
4.2.3 OLED顯示一串字符串
要顯示字符串,也要有對應的字庫,這里提供了8號和16號字庫,就不再列出了。想要顯示一串字符串,需要先編寫顯示字符函數(shù)
/*
*==============================================================================
*函數(shù)名稱:Med_Oled_ShowChar
*函數(shù)功能:顯示一個字符
*輸入?yún)?shù):x:橫坐標;y:縱坐標;chr:要顯示的字符串;Char_Size:大?。?/16)
*返回值:無
*備 注:無
*==============================================================================
*/
void Med_Oled_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size)
{
u8 c=0,i=0;
c=chr-' ';//得到偏移后的值
if(x > Max_Column-1){x=0;y=y+2;}
if(Char_Size ==16)
{
Med_Oled_Set_Pos(x,y);
for(i=0;i<8;i++)
OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
Med_Oled_Set_Pos(x,y+1);
for(i=0;i<8;i++)
OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
}
else
{
Med_Oled_Set_Pos(x,y);
for(i=0;i<6;i++)
OLED_WR_Byte(F6x8[c][i],OLED_DATA);
}
}
顯示一串字符串函數(shù)如下
/*
*==============================================================================
*函數(shù)名稱:Med_Oled_ShowString
*函數(shù)功能:顯示一串字符串
*輸入?yún)?shù):x:橫坐標;y:縱坐標;chr:要顯示的字符串;Char_Size:大小(8/16)
*返回值:無
*備 注:無
*==============================================================================
*/
void Med_Oled_ShowString(u8 x,u8 y,u8 *chr,u8 Char_Size)
{
while (*chr!='\0')
{
Med_Oled_ShowChar(x,y,*chr,Char_Size);
x+=8;
if(x>120)
{
x=0;
y+=2;
}
chr++;
}
}
需要顯示一串字符串時,添加下面程序
Med_Oled_ShowString(2,6,"ertu-20230621",8); // 在OLED上顯示字符串
4.2.3 OLED顯示圖片
下面提供了顯示圖片的函數(shù)
/*
*==============================================================================
*函數(shù)名稱:Med_Oled_DrawBMP
*函數(shù)功能:顯示一張BMP圖片
*輸入?yún)?shù):x0:起始橫坐標;y:起始縱坐標;x1:終止橫坐標;y1:終止縱坐標;
BMP[]:要顯示的圖片
*返回值:無
*備 注:無
*==============================================================================
*/
void Med_Oled_DrawBMP(u8 x0, u8 y0, u8 x1, u8 y1,u8 BMP[])
{
u32 j=0;
u8 x,y;
if (y1%8==0)
{
y = y1 / 8;
}
else
{
y = y1 / 8 + 1;
}
for (y = y0;y < y1;y ++)
{
Med_Oled_Set_Pos(x0,y);
for(x = x0;x < x1;x ++)
{
OLED_WR_Byte(BMP[j++],OLED_DATA);
}
}
}
下面是圖片取模后的存儲文件,其中標注了取模軟件,以及取模時的配置
#ifndef __BMP_H
#define __BMP_H
// 圖片取模時,首先將圖片另存為.bmp格式
// 用Image2Lcd軟件取模
// 掃描模式設置為數(shù)據(jù)水平,字節(jié)垂直
// 輸出灰度為單色
// 40*40
// 只勾選字節(jié)內像素數(shù)據(jù)反序
unsigned char BMP1[] =
{ /* 0X22,0X01,0X28,0X00,0X28,0X00, */
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X80,
0XC0,0X60,0X30,0X10,0X10,0X30,0X20,0X20,0X20,0X00,0X40,0X40,0X40,0X40,0X00,0X00,
0X80,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0XC0,0X60,0X30,0X18,0X0C,0X06,0X03,0X01,0X08,0X04,0X02,0X12,0X02,0X04,0X24,0X24,
0X24,0X20,0X08,0X08,0X28,0X10,0X00,0X00,0X80,0X40,0X71,0X09,0XC7,0X00,0X00,0X00,
0X00,0X00,0X00,0XE0,0X18,0X04,0X82,0X40,0X00,0X80,0X80,0X80,0X80,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XC0,0X60,0X30,0X18,0X8C,0X44,0X11,
0X08,0X87,0X60,0X30,0X0F,0X00,0X00,0X00,0X00,0X00,0X00,0X0F,0X20,0X43,0X44,0X00,
0X90,0X90,0X90,0X20,0X20,0X20,0X41,0X41,0X03,0X82,0X82,0X80,0X84,0X04,0X04,0X42,
0X21,0X10,0X84,0X06,0X23,0X10,0X08,0X02,0X01,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0X00,0X02,0X02,
0X02,0X02,0X00,0X04,0X04,0X0C,0X08,0X0C,0X06,0X03,0X01,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,};
#endif
主程序中添加如下程序,最終顯示結果如下
Med_Oled_DrawBMP(10,1,50,6,BMP1); // 顯示圖片
五、OLED畫點/畫線
使用OLED時,也常用到畫點或者畫線,這里給出畫點和畫線的函數(shù)。
/*
*==============================================================================
*函數(shù)名稱:Med_Oled_Refresh_Gram
*函數(shù)功能:更新緩存顯示內容
*輸入?yún)?shù):無
*返回值:無
*備 注:無
*==============================================================================
*/
u8 OLED_GRAM[128][8];
void Med_Oled_Refresh_Gram(void)
{
u8 i,n;
for(i=0;i<8;i++)
{
OLED_WR_Byte (0xb0+i,OLED_CMD);
OLED_WR_Byte (0x00,OLED_CMD);
OLED_WR_Byte (0x10,OLED_CMD);
for(n=0;n<128;n++)
OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA);
}
}
/*
*==============================================================================
*函數(shù)名稱:Med_Oled_DrawPoint
*函數(shù)功能:畫點
*輸入?yún)?shù):x:橫坐標;y:縱坐標;t:清除(0)/填充(1)
*返回值:無
*備 注:無
*==============================================================================
*/
void Med_Oled_DrawPoint(u8 x,u8 y,u8 t)
{
u8 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; //第bx位,置1,其他位值不變
else
OLED_GRAM[x][pos]&=~temp; //第bx位,置0,其他位值不變
// 更新緩存
Med_Oled_Refresh_Gram();
}
/*
*==============================================================================
*函數(shù)名稱:Med_Oled_DrawLine
*函數(shù)功能:畫線
*輸入?yún)?shù):x1:起始點橫坐標;y1:起始點縱坐標;x2:結束點橫坐標;
y2:結束點縱坐標;x:0~128;y:0~64
*返回值:無
*備 注:無
*==============================================================================
*/
void Med_Oled_DrawLine(u8 x1, u8 y1, u8 x2,u8 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++ )//畫線輸出
{
Med_Oled_DrawPoint(uRow,uCol,1);//畫點
xerr+=delta_x ;
yerr+=delta_y ;
if(xerr>distance)
{
xerr-=distance;
uRow+=incx;
}
if(yerr>distance)
{
yerr-=distance;
uCol+=incy;
}
}
}
main函數(shù)添加如下代碼文章來源:http://www.zghlxwxcb.cn/news/detail-538075.html
Med_Oled_DrawPoint(10,20,1); // 畫點
Med_Oled_DrawLine(0,30,100,30); // 畫線
顯示內容如下文章來源地址http://www.zghlxwxcb.cn/news/detail-538075.html
到了這里,關于STM32外設系列—OLED的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!