目前IICOLED屏幕是初学者常用的外设,本文将介绍STM32F407(所有STM32都大同小异)方面的oled驱动,下一篇文章将会介绍linux的IIC驱动。
OLED启动主要分为以下几步:
①屏幕初始化
②开启屏幕显示
③清屏(不清屏的话屏幕将会出现一片雪花)
④发送要显示的字符串、数字、汉字等
首先利用Stm32CubeMX软件建立工程,因屏幕是i2c通信因此此工程只配置i2c和时钟即可。
时钟配置:


i2c配置,本次选用的为i2c1:

然后生成工程即可。
oled有写命令和写数据两种操作,写命令为配置某项功能时使用,写数据为向oled写显示内容时使用。具体实现代码如下:oled屏地址一般为0x78(可以根据屏幕后面有一电阻,看电阻连接0x78还是0x7A)。
//写命令
void OLED_WR_CMD(uint8_t cmd)
{
HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x00,I2C_MEMADD_SIZE_8BIT,&cmd,1,0x100);
}
//写数据
void OLED_WR_DATA(uint8_t data)
{
HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x40,I2C_MEMADD_SIZE_8BIT,&data,1,0x100);
}
①屏幕初始化部分
网上有各种各样的初始化代码,这个一个是匹配我手上的oled屏幕的配置,如果驱动不成功,可以试一下其他的初始化代码。
void WriteCmd()
{
OLED_WR_CMD(0xAE);//--turn off oled panel
OLED_WR_CMD(0x00);//---set low column address
OLED_WR_CMD(0x10);//---set high column address
OLED_WR_CMD(0x40);//--set start line address Set Mapping RAM Display Start Line
OLED_WR_CMD(0x81);//--set contrast control register
OLED_WR_CMD(0xCF);// Set SEG Output Current Brightness
OLED_WR_CMD(0xA1);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常
OLED_WR_CMD(0xC8);//Set COM/Row Scan Direction 0xc0上下反置 0xc8正常
OLED_WR_CMD(0xA6);//--set normal display
OLED_WR_CMD(0xA8);//--set multiplex ratio(1 to 64)
OLED_WR_CMD(0x3f);//--1/64 duty
OLED_WR_CMD(0xD3);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
OLED_WR_CMD(0x00);//-not offset
OLED_WR_CMD(0xd5);//--set display clock divide ratio/oscillator frequency
OLED_WR_CMD(0x80);//--set divide ratio, Set Clock as 100 Frames/Sec
OLED_WR_CMD(0xD9);//--set pre-charge period
OLED_WR_CMD(0xF1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
OLED_WR_CMD(0xDA);//--set com pins hardware configuration
OLED_WR_CMD(0x12);
OLED_WR_CMD(0xDB);//--set vcomh
OLED_WR_CMD(0x40);//Set VCOM Deselect Level
OLED_WR_CMD(0x20);//-Set Page Addressing Mode (0x00/0x01/0x02)
OLED_WR_CMD(0x02);//
OLED_WR_CMD(0x8D);//--set Charge Pump enable/disable
OLED_WR_CMD(0x14);//--set(0x10) disable
OLED_WR_CMD(0xA4);// Disable Entire Display On (0xa4/0xa5)
OLED_WR_CMD(0xA6);// Disable Inverse Display On (0xa6/a7)
OLED_Clear();
OLED_WR_CMD(0xAF);
}
②开启屏幕显示
//开启OLED显示
void OLED_Display_On(void)
{
OLED_WR_CMD(0X8D); //SET DCDC命令
OLED_WR_CMD(0X14); //DCDC ON
OLED_WR_CMD(0XAF); //DISPLAY ON
}
//关闭OLED显示
void OLED_Display_Off(void)
{
OLED_WR_CMD(0X8D); //SET DCDC命令
OLED_WR_CMD(0X10); //DCDC OFF
OLED_WR_CMD(0XAE); //DISPLAY OFF
}
③清屏操作:
void OLED_Clear()
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_WR_CMD(0xb0+i);
OLED_WR_CMD (0x00);
OLED_WR_CMD (0x10);
for(n=0;n<128;n++)
OLED_WR_DATA(0x00);
}
}
④配置显示内容:
其中F8x16和F6x8是自己添加的字符库。
/*
输入内容为oled屏幕的显示坐标,要显示的字符、字符大小
*/
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size)
{
unsigned char c=0,i=0;
c=chr-' ';//得到偏移后的值
if(x>128-1){x=0;y=y+2;}
if(Char_Size ==16)
{
OLED_Set_Pos(x,y);
for(i=0;i<8;i++)
OLED_WR_DATA(F8x16[c*16+i]);
OLED_Set_Pos(x,y+1);
for(i=0;i<8;i++)
OLED_WR_DATA(F8x16[c*16+i+8]);
}
else {
OLED_Set_Pos(x,y);
for(i=0;i<6;i++)
OLED_WR_DATA(F6x8[c][i]);
}
}
//显示一个字符号串
void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr,uint8_t Char_Size)
{
unsigned char j=0;
while (chr[j]!='\0')
{ OLED_ShowChar(x,y,chr[j],Char_Size);
x+=8;
if(x>120){x=0;y+=2;}
j++;
}
}
unsigned char Hzk[][16]=
{
{0x00,0x80,0xC0,0xBC,0x84,0x84,0x84,0xF4,0x82,0x82,0x83,0x82,0x80,0xC0,0x80,0x00},
{0x00,0x40,0x20,0x10,0x0C,0x40,0x80,0x7F,0x00,0x00,0x04,0x08,0x30,0x60,0x00,0x00},
{0x00,0xFE,0x22,0xFE,0x00,0xFE,0x22,0xFE,0x00,0xFC,0x06,0x55,0x84,0x7E,0x04,0x00},
{0x40,0x3F,0x02,0x3F,0x40,0x3F,0x42,0x7F,0x10,0x13,0x12,0x12,0x5A,0x92,0x7E,0x00},
};
//显示汉字
//hzk 用取模软件得出的数组
void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no)
{
uint8_t t,adder=0;
OLED_Set_Pos(x,y);
for(t=0;t<16;t++)
{
OLED_WR_DATA(Hzk[2*no][t]);
adder+=1;
}
OLED_Set_Pos(x,y+1);
for(t=0;t<16;t++)
{
OLED_WR_DATA(Hzk[2*no+1][t]);
adder+=1;
}
}
//水平滚动
void OLED_ver_scroll()
{
OLED_WR_CMD(0x2e);//关滚动
OLED_WR_CMD(0x27);//29向右,2a向左
OLED_WR_CMD(0x00);//A:空字节
OLED_WR_CMD(0x02);//B:水平起始页
OLED_WR_CMD(0x07);//C:水平滚动速度
OLED_WR_CMD(0x03);//D:水平结束页
OLED_WR_CMD(0x00);//E:每次垂直滚动位移
OLED_WR_CMD(0xFF);//E:每次垂直滚动位移
OLED_WR_CMD(0x2f);//开滚动
}
主函数为:
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
HAL_Delay(500);
OLED_Display_On();
uint8_t A[]="hellow world !!!!";
uint8_t B[]="hellow world !!";
OLED_Init();
HAL_Delay(500);
OLED_Display_On();pei
OLED_Clear();
/*OLED_ShowString(0,0,A,sizeof(A));
OLED_ShowString(0,4,A,sizeof(B));*/
OLED_ShowCHinese(0,2,0);
OLED_ShowCHinese(16,2,1);
OLED_ver_scroll();
while (1)
{
}
}
至此就可以实现OLED的简单驱动了,下一期将会更新此olde屏幕在linux系统上的驱动配置。
本人并称开源思想以下我将附上我的代码希望大家多读点赞收藏支持。如失效,请及时与我联系
链接:https://pan.baidu.com/s/1_CTN0VSClB4VggR8OyRIcA
提取码:lpfx
创作不易,未经许可禁止转载
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道rubyonrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim
本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01 客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02 数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit
文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,
LL库和HAL库简介LL:Low-Layer,底层库HAL:HardwareAbstractionLayer,硬件抽象层库LL库和hal库对比,很精简,这实际上是一个精简的库。LL库的配置选择如下:在STM32CUBEMX中,点击菜单的“ProjectManager”–>“AdvancedSettings”,在下面的界面中选择“AdvancedSettings”,然后在每个模块后面选择使用的库总结:1、如果使用的MCU是小容量的,那么STM32CubeLL将是最佳选择;2、如果结合可移植性和优化,使用STM32CubeHAL并使用特定的优化实现替换一些调用,可保持最大的可移植性。另外HAL和L
我使用的是最新版本的Chrome(32.0.1700.107)和Chrome驱动程序(V2.8)。但是当我在Ruby中使用以下代码运行示例测试时:require'selenium-webdriver'WAIT=Selenium::WebDriver::Wait.new(timeout:100)$driver=Selenium::WebDriver.for:chrome$driver.manage.window.maximize$driver.navigate.to'https://www.google.co.in'defapps_hoverele_hover=$driver.find_
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。多年来,我一直在使用多种语言进行编程,并且认为自己总体上相当擅长。但是,我从未编写过任何自动化测试:没有单元测试,没有TDD,没有BDD,什么都没有。我已经尝试开始为我的项目编写适当的测试套件。我可以看到在进行任何更改后能够自动测试项目中所有代码的理论值(value)。我可以看到像RSpec和Mocha这样的测试框架应该如何使设置和运行所述测试变得相当容易
如果我在功能规范中调用url_for,它会返回一个以http://www.example.com/开头的绝对URL.Capybara会很乐意尝试加载该站点上的页面,但这与我的应用程序无关。以下是重现该问题的最少步骤:从这个Gemfile开始:source'https://rubygems.org'gem"sqlite3"gem"jquery-rails"gem"draper"gem"rails",'4.1.0'gem"therubyracer"gem"uglifier"gem"rspec-rails"gem"capybara"gem"poltergeist"gem"launchy"运行
在笔者前面有一篇文章《驱动开发:断链隐藏驱动程序自身》通过摘除驱动的链表实现了断链隐藏自身的目的,但此方法恢复时会触发PG会蓝屏,偶然间在网上找到了一个作者介绍的一种方法,觉得有必要详细分析一下他是如何实现的进程隐藏的,总体来说作者的思路是最终寻找到MiProcessLoaderEntry的入口地址,该函数的作用是将驱动信息加入链表和移除链表,运用这个函数即可动态处理驱动的添加和移除问题。MiProcessLoaderEntry(pDriverObject->DriverSection,1)添加MiProcessLoaderEntry(pDriverObject->DriverSection,
目录一、ESP32简单介绍二、ESP32Wi-Fi模块介绍三、ESP32Wi-Fi编程模型四、ESP32Wi-Fi事件处理流程 五、ESP32Wi-Fi开发环境六、ESP32Wi-Fi具体代码七、ESP32Wi-Fi代码解读6.1主程序app_main7.2自定义代码wifi_init_sta()八、ESP32Wi-Fi连接验证8.1测试方法8.2服务器模拟工具sscom58.3测试代码8.4测试结果前言为了开发一款亚马逊物联网产品,开始入手ESP32模块。为了能够记录自己的学习过程,特记录如下操作过程。一、ESP32简单介绍ESP32是一套Wi-Fi(2.4GHz)和蓝牙(4.2)双模解决方
有道无术,术尚可求,有术无道,止于术。本系列SpringBoot版本3.0.4本系列SpringSecurity版本6.0.2本系列SpringAuthorizationServer版本1.0.2源码地址:https://gitee.com/pearl-organization/study-spring-security-demo文章目录前言1.OAuth2AuthorizationServerMetadataEndpointFilter2.OAuth2AuthorizationEndpointFilter3.OidcProviderConfigurationEndpointFilter4.N