IIC相关介绍及oled实验(二)
//模块:OLED显示屏
1. 0.96寸OLED屏幕介绍
0.96 寸 4P OLED 屏幕模块是一种显示屏模块,它包括一个 0.96 英寸的 OLED 显示屏和四个引脚。这种 OLED 屏幕模块通常用于嵌入式系统和小型电子设备中,可以显示文本、图像和其他类型的信息。由于其小 尺寸和低功耗,也常用于智能手表、健康追踪器和其他便携式设备中。
0.96OLED 屏幕模块的优点有:
1. 高对比度和高亮度:OLED 屏幕模块可以提供深黑色背景和明亮的字色,因此可以实现高对比度和高亮 度的显示效果;
2. 自发光:OLED 屏幕模块不需要背光灯,因此可以实现更薄、更轻的设计;
3. 响应速度快:OLED 屏幕模块的响应速度非常快,可以实现流畅的动画和视频效果;
4. 视角宽:OLED 屏幕模块的视角非常宽,即使从不同角度观察,图像和文字也能保持清晰。
0.96OLED 屏幕模块的缺点有:
1. 显示寿命短:与 LCD 显示屏相比,OLED 的显示寿命相对较短,因为它的有机材料会随着时间的推移 而逐渐失效;
2. 显示面积小:0.96 寸 OLED 屏幕模块的显示面积相对较小,因此不适合用于需要大屏幕的应用。
2. 如何驱动OLED屏幕显示内容?
3. OLED通讯协议
4. SSD1306
5. GDDRAM
页地址模式:
水平地址模式:
垂直地址模式:
6. OLED命令
7. 如何取模
小实验:OLED实验
实验目的 驱动 OLED 屏幕,显示点、线、字符、字符串、汉字、图片等内容。
实现---点、线、A
/------oled.h---------/
#include "sys.h"
//SCL配置
#define OLED_I2C_SCL_CLK() __HAL_RCC_GPIOB_CLK_ENABLE();
#define OLED_I2C_SCL_PORT GPIOB
#define OLED_I2C_SCL_PIN GPIO_PIN_6
//SDA配置
#define OLED_I2C_SDA_CLK() __HAL_RCC_GPIOB_CLK_ENABLE();
#define OLED_I2C_SDA_PORT GPIOB
#define OLED_I2C_SDA_PIN GPIO_PIN_7
//SCL引脚拉高拉低
#define OLED_SCL_RESET() HAL_GPIO_WritePin(OLED_I2C_SCL_PORT, OLED_I2C_SCL_PIN, GPIO_PIN_RESET)
#define OLED_SCL_SET() HAL_GPIO_WritePin(OLED_I2C_SCL_PORT, OLED_I2C_SCL_PIN, GPIO_PIN_SET)
//SDA引脚使能
#define OLED_SDA_RESET() HAL_GPIO_WritePin(OLED_I2C_SDA_PORT, OLED_I2C_SDA_PIN, GPIO_PIN_RESET)
#define OLED_SDA_SET() HAL_GPIO_WritePin(OLED_I2C_SDA_PORT, OLED_I2C_SDA_PIN, GPIO_PIN_SET)
void oled_init(void);
void oled_write_cmd(uint8_t cmd);
void oled_write_data(uint8_t data);
void oled_fill(uint8_t data);
void oled_set_cursor(uint8_t x, uint8_t y);
/------oled.c---------/
1、oled_gpio_init初始化函数
void oled_gpio_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
OLED_I2C_SCL_CLK();
OLED_I2C_SDA_CLK();
gpio_initstruct.Pin = OLED_I2C_SCL_PIN; //PA7
gpio_initstruct.Mode = GPIO_MODE_OUTPUT_PP;
gpio_initstruct.Pull = GPIO_PULLUP;
gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(OLED_I2C_SCL_PORT, &gpio_initstruct);//GPIOB
gpio_initstruct.Pin = OLED_I2C_SDA_PIN;
HAL_GPIO_Init(OLED_I2C_SDA_PORT, &gpio_initstruct);
}
2、I2C起始信号:起始信号由主设备发起,用于通知总线上的所有设备即将开始数据传输
void oled_i2c_start(void)
{
OLED_SCL_SET(); //确保scl在高电平为拉低做准备
OLED_SDA_SET();//确保sda在高电平为拉低做准备
OLED_SDA_RESET();//只有在sda拉低的条件是才能传输数据,拉低
OLED_SCL_RESET();//当SCL为高电平时,SDA由高电平变为低电平,产生一个下降沿
}
3、I2C停止信号 由主设备发起,用于通知总线上的所有设备数据传输已经结束
void oled_i2c_stop(void)
{
/*当SCL为高电平时,SDA由低电平变为高电平,产生一个上升沿,表示停止信号的开始*/
OLED_SCL_SET();
OLED_SDA_RESET();
OLED_SDA_SET();
}
4、I2C响应信号
每当一个字节的数据传输完成后,接收方会向发送方发送一个应答信号(ACK)或非应答信号 (NACK)。
应答信号在SCL的第9个时钟周期(当SCL为高电平时)发送。
void oled_i2c_ack(void)
{
//默认低电平?
OLED_SCL_SET();
OLED_SCL_RESET();
}
/*如果SDA线为低电平,则表示ACK(有效应答),
表示接收方已成功接收该字节。 如果SDA线为高电平
则表示NACK(非应答),通常表示接收方接收该字节没有成功*/
5、I2C写byte ??
void oled_i2c_write_byte(uint8_t data)
{
uint8_t i, tmp;
tmp = data;
for(i = 0; i < 8; i++)
{
if((tmp & 0x80) == 0x80)
OLED_SDA_SET();
else
OLED_SDA_RESET();
tmp = tmp << 1;
OLED_SCL_SET();
OLED_SCL_RESET();
}
}
6、I2C写命令
void oled_write_cmd(uint8_t cmd)
{
oled_i2c_start();
oled_i2c_write_byte(0x78);
oled_i2c_ack();
oled_i2c_write_byte(0x00);
oled_i2c_ack();
oled_i2c_write_byte(cmd);
oled_i2c_ack();
oled_i2c_stop();
}
7、I2C写数据
void oled_write_data(uint8_t data)
{
oled_i2c_start();
oled_i2c_write_byte(0x78);
oled_i2c_ack();
oled_i2c_write_byte(0x40);
oled_i2c_ack();
oled_i2c_write_byte(data);
oled_i2c_ack();
oled_i2c_stop();
}
8、oled初始化
void oled_init(void)
{
oled_gpio_init();
delay_ms(100);
oled_write_cmd(0xAE); //设置显示开启/关闭,0xAE关闭,0xAF开启
oled_write_cmd(0xD5); //设置显示时钟分频比/振荡器频率
oled_write_cmd(0x80); //0x00~0xFF
oled_write_cmd(0xA8); //设置多路复用率
oled_write_cmd(0x3F); //0x0E~0x3F
oled_write_cmd(0xD3); //设置显示偏移
oled_write_cmd(0x00); //0x00~0x7F
oled_write_cmd(0x40); //设置显示开始行,0x40~0x7F
oled_write_cmd(0xA1); //设置左右方向,0xA1正常,0xA0左右反置
oled_write_cmd(0xC8); //设置上下方向,0xC8正常,0xC0上下反置
oled_write_cmd(0xDA); //设置COM引脚硬件配置
oled_write_cmd(0x12);
oled_write_cmd(0x81); //设置对比度
oled_write_cmd(0xCF); //0x00~0xFF
oled_write_cmd(0xD9); //设置预充电周期
oled_write_cmd(0xF1);
oled_write_cmd(0xDB); //设置VCOMH取消选择级别
oled_write_cmd(0x30);
oled_write_cmd(0xA4); //设置整个显示打开/关闭
oled_write_cmd(0xA6); //设置正常/反色显示,0xA6正常,0xA7反色
oled_write_cmd(0x8D); //设置充电泵
oled_write_cmd(0x14);
oled_write_cmd(0xAF); //开启显示
}
9、oled起始位置设施函数
void oled_set_cursor(uint8_t x, uint8_t y)
{
oled_write_cmd(0xB0 + y);
oled_write_cmd((x & 0x0F) | 0x00);
oled_write_cmd(((x & 0xF0) >> 4) | 0x10);
}
10、oled清屏函数
void oled_fill(uint8_t data)
{
uint8_t i, j;
for(i = 0; i < 8; i++)
{
oled_set_cursor(0, i);
for(j = 0; j < 128; j++)
oled_write_data(data);
}
}
//指定位置 行和列,外循环选择page ,内循环写里面的内容
void oled_show_char(uint8_t x, uint8_t y, uint8_t num, uint8_t size) //高度16 / 8
{
//定义两个循环判断有几个page
uint8_t i,j,page;
num = num - ' ';//做一个偏移显示我们的字符 空格的asci的值就是32
page = size / 8; //取整是多少确定有多少个page模式取出来
if(size % 8)//需要两个page,再判断余数是否为0保证至少有1个page
page++;
for(j = 0;j<page;j++)
{
oled_set_cursor(x,y + j);//如果y没有加j会只显示上半部分 位置显示
//数据是高度的一半
//size / 2 * (j + 1) j意思是第几个page
for(i=size / 2 * j; i < size / 2 * (j + 1); i++)//高度的一半*j j=0时size从0开始,下半部分除外除8,从第八个开始
{
//对不同尺寸做一个判断
if(size == 12)
oled_write_data(ascii_6X12[num][i]);
else if(size == 16)
oled_write_data(ascii_8X16[num][i]);
else if(size == 24)
}
}
}
打印一个字符
//指定位置 行和列,外循环选择page ,内循环写里面的内容
void oled_show_char(uint8_t x, uint8_t y, uint8_t num, uint8_t size) //高度16 / 8
{
//定义两个循环判断有几个page
uint8_t i,j,page;
num = num - ' ';//做一个偏移显示我们的字符 空格的asci的值就是32
page = size / 8; //取整是多少确定有多少个page模式取出来
if(size % 8)//需要两个page,再判断余数是否为0保证至少有1个page
page++;
for(j = 0;j<page;j++)
{
oled_set_cursor(x,y + j);//如果y没有加j会只显示上半部分 位置显示
//数据是高度的一半
//size / 2 * (j + 1) j意思是第几个page
for(i=size / 2 * j; i < size / 2 * (j + 1); i++)//高度的一半*j j=0时size从0开始,下半部分除外除8,从第八个开始
{
//对不同尺寸做一个判断
if(size == 12)
oled_write_data(ascii_6X12[num][i]);
else if(size == 16)
oled_write_data(ascii_8X16[num][i]);
else if(size == 24)
oled_write_data(ascii_12X24[num][i]);
}
}
}
//显示一个字符串
void oled_show_string(uint8_t x, uint8_t y,char *p,uint8_t size)
{
//遍历数组
while(*p != '\0')
{
//遍历字符
oled_show_char(x,y,*p,size);
//偏移字符 字符的宽度是高度的一半
x += size/2;
p++;
}
}
显示汉字
void oled_show_chinese(uint8_t x, uint8_t y,uint8_t N,uint8_t size)
{
uint16_t i,j;
for(j=0;j < size/8; j++)//第几个page
{
oled_set_cursor(x,y+j);//??
for(i = size * j;i < size * (j+1); i++)//判断尺寸
{
if(size == 16)
oled_write_data(chinese_16x16[N][i]);
else if(size == 24)
oled_write_data(chinese_24x24[N][i]);
}
}
}
图片显示,具体某图片
void oled_show_image(uint8_t x , uint8_t y, uint8_t width, uint8_t height, uint8_t *bmp)
{
uint16_t i,j,idx;//idx是索引把bmp中的东西提取出来
for(j = 0; j < height;j++)
{
oled_set_cursor(x,y+j);
for(i = 0;i < width; i++)//列
{
//指定坐标
oled_write_data(bmp[idx++]);
}
}
}
/-----main.c-----/
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "oled.h"
extern const unsigned char shuai_data[];
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* 初始化LED灯 */
uart1_init(115200);
oled_init();
printf("hello world!\r\n");
oled_fill(0x00);
oled_set_cursor(0, 0);
// oled_write_cmd(0xB0);
// oled_write_cmd(0x00);
// oled_write_cmd(0x10);
// oled_write_data(0x80);//显示一个点
/*显示字母 A */
oled_write_data(0x00);
oled_write_data(0x00);
oled_write_data(0xC0);
oled_write_data(0x38);
oled_write_data(0xE0);
oled_write_data(0x00);
oled_write_data(0x00);
oled_write_data(0x00);
oled_set_cursor(0, 1);//前面8个显示完后换到page
oled_write_data(0x20);
oled_write_data(0x3C);
oled_write_data(0x23);
oled_write_data(0x02);
oled_write_data(0x02);
oled_write_data(0x27);
oled_write_data(0x38);
oled_write_data(0x20);
uint8_t i;
for(i = 0;i < 5;i++)
oled_show_chinese(i*24,0,i,24);
//假如显示24号字符,一个占用 从0 开始,一个宽度24个字符
oled_show_image(0,0,128,8,(unsigned char*)shui_data);//8*8 64
while(1)
{
}
}
原文地址:https://blog.csdn.net/qq_65524926/article/details/144252771
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!