CubeMx配置
本程序通过I2C1来控制OLED的显示,所以先使能硬件I2C1。然后配置PB8,PB9为I2C通信的SCL和SDA线
。
OLED驱动编写
/**
* 函 数:OLED发送命令
* 参 数:cmd 要发送的命令
* 返 回 值:0 写入成功
*/
static int OledSendCmd(uint8_t cmd){
uint8_t data[] = {0x00,cmd};
HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(&hi2c1,0x78, data, 2, 0xFF);
if(status != HAL_OK){
LogDebug("%x Send Failed\r\n",cmd);
return -1;
}
return 0;
}
/**
* 函 数:OLED发送数据
* 参 数:Data 要写入的数据
* 参 数:count 要写入的数据的个数
* 返 回 值:0 写入成功
*/
static int OledSendData(uint8_t *Data,uint8_t count){
HAL_StatusTypeDef status = HAL_I2C_Mem_Write(&hi2c1, 0x78,0x40,1 ,Data,count, 0xff);
//HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(&hi2c1, (unsigned short)OLEDADD, data, count+1, 0xFF);
if(status != HAL_OK){
LogDebug("Send Failed\r\n");
return -1;
}
return 0;
}
OLED初始化
初始化代码
/**
* 函 数:OLED初始化
* 参 数:无
* 返 回 值:无
* 说 明:使用前,需要调用此初始化函数
*/
void OledInit(){
//关闭显示
OledSendCmd(0xAE);
//设置时钟分频
OledSendCmd(0xD5);
OledSendCmd(0x80);
//设置多路复用率
OledSendCmd(0xA8);
OledSendCmd(0x3F);
//设置显示偏差
OledSendCmd(0xD3);
OledSendCmd(0x00);
//设置开始行
OledSendCmd(0x40);
//设置左右方向,0xA1正常,0xA0左右反置
OledSendCmd(0xA1);
//设置上下方向,0xC8正常,0xC0上下反置
OledSendCmd(0xC8);
//设置COM引脚硬件配置
OledSendCmd(0xDA);
OledSendCmd(0x12);
//设置对比度
OledSendCmd(0x81);
OledSendCmd(0xCF);
//设置预充电周期
OledSendCmd(0xD9);
OledSendCmd(0xF1);
//设置VCOMH取消选择级别
OledSendCmd(0xDB);
OledSendCmd(0x30);
//屏幕完全显示
OledSendCmd(0xA4);
//正常模式 黑底白字
OledSendCmd(0xA6);
//使能电荷泵 内部的升压电路
OledSendCmd(0xBD);
OledSendCmd(0x14);
//打开显示
OledSendCmd(0xAF);
HAL_Delay(1000);
OledClear(); //清空显存数组
OledUpdate(); //更新显示,清屏,防止初始化后未显示内容时花屏
LogDebug("OLED Init Success\r\n");
}
字符显示函数
/**
* 函 数:OLED显示字符
* 参 数:x 字符显示列
* 参 数:y 字符显示行
* 参 数:ch 显示字符
* 参 数:FontSize 显示字体
* 返 回 值:无
*/
void OledShowChar(uint8_t x,uint8_t y,char ch,uint8_t FontSize){
if(FontSize == OLED_8X8){
OledShowImage(x,y,8,8,OLED_F8X8[ch-' ']);
}else if(FontSize == OLED_16X8){
OledShowImage(x,y,8,16,OLED_F16X8[ch-' ']);
}
}
字符串显示函数
void OledShowStr(uint8_t x,uint8_t y,char *str,uint8_t FontSize){
uint8_t ch;
uint8_t i,j;
i = x;
j = y;
ch = *str;
while(ch){
if(i > 127 || j > 63){
return;
}
OledShowChar(i,j,ch,FontSize);
i +=8;
str++;
ch = *str;
};
}
图像显示函数 : 将图像数据更新到显示器的显存缓冲区中
/**
* 函 数:OLED显示图像
* 参 数:x 字符显示列
* 参 数:y 字符显示行
* 参 数:Width 显示图像的宽度
* 参 数:Heigth 显示图像的高度
* 参 数:image 显示图像的数据·
* 返 回 值:无
*/
void OledShowImage(uint8_t x,uint8_t y,uint8_t Width,uint8_t Heigth,const uint8_t *image){
//参数 检查
if(x > 127 || y/8 >7){
LogDebug("OledShowImage x is %d y is %d\r\n",x,y);
return;
}
//遍历图像设计的相关页
//(Heigth-1)/8+1 是Heigth/8向上取整
for(uint8_t j = 0;j<((Heigth-1)/8+1);j++){
for(uint8_t i = 0;i<Width;i++){
if( x+i>127){
LogDebug("OledShowImage x is %d y is %d\r\n",x,y);
break;
}
if( y/8+j>64 ){
LogDebug("OledShowImage x is %d y is %d\r\n",x,y);
return;
}
//更新显存中当前页的内容
OLEDDisplayBuf[y/8+j][x+i] |= image[j*Width+i] << (y % 8);
//如果超出边界则退出
if(y/8+j+1 > 7){
continue;
}
//更新显存中下一页的内容
OLEDDisplayBuf[y/8+j+1][x+i] |= image[j*Width+i] >> (8 - (y % 8));
}
}
}
设置游标
/**
* 函 数:OLED设置光标显示
* 参 数:Page 显示行地址
* 参 数:X 显示列地址
* 返 回 值:无
*/
void OledSetCursor(uint8_t Page,uint8_t X){
if(Page>7){
LogDebug("OledSetCursor Page is %d \r\n",Page);
return;
}
//设置行地址
OledSendCmd(0xB0|Page);
//设置列地址 高四位
OledSendCmd(0x10|((X&0xF0)>>4) );
//设置列地址 低四位
OledSendCmd(0x00|(X&0x0F));
}
更新缓冲区
/**
* 函 数:将OLED缓存数据发送给OLED 更新显示的内容
* 参 数:无
* 返 回 值:无
*/
void OledUpdate(void){
for(uint8_t j = 0;j < 8;j++){
OledSetCursor(j,0);
OledSendData(OLEDDisplayBuf[j],128);
}
}