3. OLED模块¶
3.1. 模块简介¶
野火0.96寸黄蓝双色OLED模块通讯方式为IIC,分辨率为128*64。
3.3. 实验现象¶
这里不管你是用的野火哪款开发板,请打开对应的开发板LOED例程,打开 OLED_I2C.h,就可以看到I2C的引脚定义,这里以STM32F103霸道开发板为例,
可以看到,I2C的SCL引脚为PB6,SDA引脚为PB7。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /*I2C接口*/
#define OLED_I2C I2C1
#define OLED_I2C_CLK RCC_APB1Periph_I2C1
#define OLED_I2C_CLK_INIT RCC_APB1PeriphClockCmd
#define OLED_I2C_SCL_PIN GPIO_Pin_6
#define OLED_I2C_SCL_GPIO_PORT GPIOB
#define OLED_I2C_SCL_GPIO_CLK RCC_AHB1Periph_GPIOB
#define OLED_I2C_SCL_SOURCE GPIO_PinSource6
#define OLED_I2C_SCL_AF GPIO_AF_I2C1
#define OLED_I2C_SDA_PIN GPIO_Pin_7
#define OLED_I2C_SDA_GPIO_PORT GPIOB
#define OLED_I2C_SDA_GPIO_CLK RCC_AHB1Periph_GPIOB
#define OLED_I2C_SDA_SOURCE GPIO_PinSource7
#define OLED_I2C_SDA_AF GPIO_AF_I2C1
|
将OLED与开发板按照上面定义的方式连接,再用USB线连接开发板与电脑,打开电脑上的野火多功能上位机助手,与开发板进行连接,然后将程序下载到开发板, 上位机会打印如下信息,
同时,OLED上会显示如下内容,
3.4. 例程介绍¶
首先来看一下IIC的初始化,这里将SCL、SDA引脚都设置为开漏模式,将IIC设置为快速模式,代码如下,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | void I2C_Configuration(void)
{
I2C_InitTypeDef I2C_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
OLED_I2C_CLK_INIT(OLED_I2C_CLK,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin = OLED_I2C_SCL_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // 开漏输出
GPIO_Init(OLED_I2C_SCL_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = OLED_I2C_SDA_PIN;
GPIO_Init(OLED_I2C_SDA_GPIO_PORT, &GPIO_InitStructure);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;// 高电平数据稳定,低电平数据变化 SCL 时钟线的占空比
I2C_InitStructure.I2C_OwnAddress1 = OLED_ADDRESS; // OLED的I2C地址
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; // ACK使能
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;// I2C的寻址模式
I2C_InitStructure.I2C_ClockSpeed = I2C_Speed; // 设置为快捷模式
I2C_Init(I2C1, &I2C_InitStructure); // I2C1 初始化
I2C_Cmd(I2C1, ENABLE); // 使能 I2C1
}
|
再来看一下OLED的初始化,这里是对OLED的寄存器进行操作,这些参数不需要去了解,默认也不需要修改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | void OLED_Init(void)
{
Delay_s(1); // 1s,这里的延时很重要,上电后延时,没有错误的冗余设计
WriteCmd(0xAE); //display off
WriteCmd(0x20); //Set Memory Addressing Mode
WriteCmd(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
WriteCmd(0xb0); //Set Page Start Address for Page Addressing Mode,0-7
WriteCmd(0xc8); //Set COM Output Scan Direction
WriteCmd(0x00); //---set low column address
WriteCmd(0x10); //---set high column address
WriteCmd(0x40); //--set start line address
WriteCmd(0x81); //--set contrast control register
WriteCmd(0xff); //亮度调节 0x00~0xff
WriteCmd(0xa1); //--set segment re-map 0 to 127
WriteCmd(0xa6); //--set normal display
WriteCmd(0xa8); //--set multiplex ratio(1 to 64)
WriteCmd(0x3F); //
WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
WriteCmd(0xd3); //-set display offset
WriteCmd(0x00); //-not offset
WriteCmd(0xd5); //--set display clock divide ratio/oscillator frequency
WriteCmd(0xf0); //--set divide ratio
WriteCmd(0xd9); //--set pre-charge period
WriteCmd(0x22); //
WriteCmd(0xda); //--set com pins hardware configuration
WriteCmd(0x12);
WriteCmd(0xdb); //--set vcomh
WriteCmd(0x20); //0x20,0.77xVcc
WriteCmd(0x8d); //--set DC-DC enable
WriteCmd(0x14); //
WriteCmd(0xaf); //--turn on oled panel
}
|
最后来看一下main函数,在这里需要先初始化LED和串口,用于调试,初始化系统滴答定时器,用于调用延时函数, 再初始化IIC的配置及OLED。
在循环中点亮全屏,再息屏,然后用 OLED_ShowCN 函数在OLED上显示中文,用 OLED_ShowStr函数显示字符串,用 OLED_DrawBMP函数显示BMP位图。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | int main(void)
{
unsigned char i;
/*初始化LED、串口*/
LED_GPIO_Config();
USART_Config();
LED_BLUE;
printf("\r\n 欢迎使用野火 F103-霸道 STM32 开发板 \r\n");
printf("\r\n 这是一个I2C外设OLED测试例程! \r\n");
SysTick_Init(); //初始化延迟函数
I2C_Configuration();//配置CPU的硬件I2C
OLED_Init(); //初始化OLED
printf("\r\n OLED初始化成功,OLED正在工作! \r\n");
while(1)
{
OLED_Fill(0xFF);//全屏点亮
Delay_s(2); // 2s
OLED_Fill(0x00);//全屏灭
Delay_s(2); // 2s
LED_GREEN;
for(i=0;i<4;i++)
{
OLED_ShowCN(22+i*16,0,i); //测试显示中文
}
Delay_s(2); // 2s
OLED_ShowStr(0,3,(unsigned char*)"Wildfire Tech",1); //测试6*8字符
OLED_ShowStr(0,4,(unsigned char*)"Hello wildfire",2); //测试8*16字符
Delay_s(200); // 2*100=200s
OLED_CLS(); // 清屏
OLED_OFF(); // 测试OLED休眠
Delay_s(2); // 2s
OLED_ON();//测试OLED休眠后唤醒
OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP1);//测试BMP位图显示
Delay_s(200); // 2*100=200s
}
}
|
3.5. 汉字取模方法¶
3.6. 汉字显示函数分析¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | /**
* @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;
}
}
|
从函数里面可以看出,显示一个汉字总共分为两步,第一步先设置汉字的显示位置,注意这里的y坐标的范围是 0-7 ,整个屏幕的一共有64行,也就是说一个y坐标是以8行为一个单位的。 第一个for循环是显示汉字的上半部分,每调用一次 WriteDat();函数之后,就会显示汉字的一列像素点,同时x坐标自动加1。显示完汉字的上半部分之后将x坐标归位同时y坐标加1, 继续显示汉字的下半部分之后就完成了显示一个汉字的整个过程。