这篇文章主要是个人的学习经验,想分享出来供大家提供思路,如果其中有不足之处请批评指正哈。
废话不多说直接开始主题,本人是基于STM32F407VET6芯片,但是意在你看懂这篇文章后,不管是F1,F4,H7等一系列系统硬件IIC配置都能明白如何通过参考手册、数据手册去学习配置。而不是Ctrl c,Ctrl v。这篇文章是对OLED 软件配置方面的介绍,如何参考数据手册编写代码。
废话不多说,直接开始根据上文的寄存器步骤指示编写代码。
一、CubeMX初始化工作
1)时钟配置
本人时钟使用的都是外部晶振,时钟树配置见下图。
2)下载器配置
3)IIC配置
4)项目地址
5)生成代码
以上就是工程的大致配置。
二、软件程序编写
1)按照数据手册指示,编写寄存器数据步骤,详见硬件篇
寄存器数组构建
/**********************************************************
* 初始化命令,根据芯片手册书写,详细步骤见上图以及注意事项
***********************************************************/
uint8_t CMD_Data[]={
0xAE, 0xD5, 0x80, 0xA8, 0x3F, 0xD3, 0x00, 0x40,0xA1, 0xC8, 0xDA,
0x12, 0x81, 0xCF, 0xD9, 0xF1, 0xDB, 0x40, 0xA4, 0xA6,0x8D, 0x14,
0xAF};
1.如果Co位设置为逻辑"0",则以下信息的传输将仅包含数据字节。
2.D/C#位决定下一个数据字节是作为命令还是数据。如果D/C#位设置为逻辑"0",则将以下数据字节定义为命令。如果D/C#位被设置为逻辑"1",则其将以下数据字节定义为将被存储在GDDRAM中的数据。GDDRAM列地址指针将在每次数据写入后自动增加1。
总结:发送命令时地址为0x00,发送数据时地址为0x40而且其会递增,这也是书写代码的关键部分。
详细请参考硬件篇------3)I2C总线时钟信号(SCL)
2)构造IIC发送函数 IIC1,地址0x78,命令格式地址0x00,数据格式地址0x40
//为数组命令发送方式
void WriteCmd(void)
{
uint8_t i = 0;
for(i=0; i<23; i++)
{
HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x00,I2C_MEMADD_SIZE_8BIT,&CMD_Data[i],1,0x100);
}
}
/**
* @function: void OLED_WR_CMD(uint8_t cmd)
* @description: 向设备写控制命令,单字节发送方式
* @param {uint8_t} cmd 芯片手册规定的命令
* @return {*}
*/
void OLED_WR_CMD(uint8_t cmd)
{
HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x00,I2C_MEMADD_SIZE_8BIT,&cmd,1,0x100);
}
/**
* @function: void OLED_WR_DATA(uint8_t data)
* @description: 向设备写控制数据
* @param {uint8_t} data 数据
* @return {*}
*/
void OLED_WR_DATA(uint8_t data)
{
HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x40,I2C_MEMADD_SIZE_8BIT,&data,1,0x100);
}
3)显示以及清空
1.设置页寻址模式的较高列起始地址(10 h ~1Fh)此命令指定页寻址模式下显示数据RAM的8位列起始地址的较高半字节。列地址将随着每次数据访问而递增。
2.设置页面寻址模式的页面起始地址(B 0 h ~ B7 h)此命令在页面寻址模式下将GDDRAM中的页面起始地址从0定位到7,不会递增。
在这段代码中,你就要明白寄存器地址0x00对应的是行,而且会不断递增,首先你要明白第一步需要设置页0xb0,然后设置列,从第零列开始0x00,它会自行递增所以只要配一个循环即可,通过写入0xff=1111,1111控制8个位都点亮。
void OLED_On(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_WR_CMD(0xb0+i); //设置页地址(0~7)
OLED_WR_CMD(0x00); //设置显示位置—列低地址
OLED_WR_CMD(0x10); //设置显示位置—列高地址
for(n=0;n<128;n++)
OLED_WR_DATA(0xff);
}
}
/**
* @function: OLED_Clear(void)
* @description: 清屏
* @return {*}
*/
void OLED_Clear(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_WR_CMD(0xb0+i); //设置页地址(0~7)
OLED_WR_CMD(0x00); //设置显示位置—列低地址
//OLED_WR_CMD(0x10); //设置显示位置—列高地址
for(n=0;n<128;n++)
OLED_WR_DATA(0x0);
}
}
4)坐标显示代码
坐标显示就得明白使用的是哪两个寄存器,一个是X坐标寄存器(列指标),一个是Y坐标寄存器(行坐标页)。(00h~1Fh)列坐标x、(B0-B7h)行坐标y。但是x坐标需要注意的是当想要点亮127列时,127=0x7f=0111,1111。0x7f这个数据需要拆分成高位数据以及低位数据。即命令行需要发送0x0f、0x17即可。基于此编写一种分别读取高位数据以及低位数据的算法并分别发送命令行。
OLED_Set_Pos(64,4); //居中显示函数
/**
* @function: void OLED_Set_Pos(uint8_t x, uint8_t y)
* @description: 坐标设置
* @param {uint8_t} x,y注意x是0-15,y是0-7
* @return {*}
*/
void OLED_Set_Pos(uint8_t x, uint8_t y)
{
OLED_WR_CMD(0xb0+y); //设置页地址(0~7)
OLED_WR_CMD(((x&0xf0)>>4)|0x10); //设置显示位置—列低地址
OLED_WR_CMD(x&0x0f); //设置显示位置—列高地址
OLED_WR_DATA(0X18); //00011000中间两个亮
}
5)显示图片
显示图片函数
/**
* @function: void OLED_DrawBMP(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t * BMP,uint8_t Color_Turn)
* @description: 在OLED特定区域显示BMP图片
* @param {uint8_t} x0图像开始显示横坐标 x0:0~127
* @param {uint8_t} y0图像开始显示纵坐标 y0:0~7
* @param {uint8_t} x1图像结束显示横坐标 x1:1~128
* @param {uint8_t} y1图像结束显示纵坐标 y1:1~8
* @param {uint8_t} *BMP待显示的图像数据
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_DrawBMP(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t * BMP,uint8_t Color_Turn)
{
uint32_t j = 0;
uint8_t x = 0, y = 0;
if(y1%8==0)
y = y1/8;
else
y = y1/8 + 1;
for(y=y0;y<y1;y++)
{
OLED_Set_Pos(x0,y);
for(x=x0;x<x1;x++)
{
if (Color_Turn)
OLED_WR_DATA(~BMP[j++]);//显示反相图片
else
OLED_WR_DATA(BMP[j++]);//显示图片
}
}
}
图片字符代码需要使用取模软件编写字符。
显示图片字模软件本人是用的视频中的网址链接此处加个引用符号:
led.baud-dance.com
点不开的话复制一下打开。
页面视图如下图所示
导入图片后,自动生成的字符代码
unsigned char bearData[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x5f, 0x9f, 0xdf, 0xef, 0xef, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0x17,
0xd7, 0xe7, 0x07, 0x0f, 0x9f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00, 0xfe, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xbf, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xf8, 0xe3,
0x8f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x07, 0xf3, 0xfd, 0xec, 0xe7, 0x91, 0x2f, 0x5d,
0x7c, 0xfc, 0xdc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7c, 0x01, 0x1f, 0xff, 0xff, 0xff, 0xff,
0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x07, 0x03, 0x01, 0x00, 0x01, 0x03, 0x07, 0x07, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x14, 0x0e, 0x1f, 0x1f, 0x1f, 0x0f, 0x07, 0x03, 0x00, 0x00, 0x00, 0x80, 0xc1, 0xe1, 0xff, 0xff, 0xfe, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xf8,
0xf8, 0xf8, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0xc0, 0xe0, 0xf0, 0xf8,
0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
//const Image bearImg = {64, 64, bearData};
图片显示如下。
至此OLED的基本工作原理大致有所了解,如有不足之处请批评指正哈。整体项目代码以及数据手册放在以下链接中了。
链接:https://pan.baidu.com/s/1l9G2n4-04w95X_IeJ7DZgg?pwd=1p8q
提取码:1p8q