新聞中心

EEPW首頁(yè) > 設(shè)計(jì)應(yīng)用 > 功率監(jiān)測(cè)與控制系統(tǒng)DIY——實(shí)現(xiàn)OLED屏幕顯示信息

功率監(jiān)測(cè)與控制系統(tǒng)DIY——實(shí)現(xiàn)OLED屏幕顯示信息

作者:CoderX9527 時(shí)間:2025-07-16 來(lái)源:EEPW 收藏

1   任務(wù)目標(biāo)

實(shí)現(xiàn)OLED 屏幕顯示信息

2   OLED介紹

此款OLED是Seeed Studio 出品的Grove 接口的0.96英寸OLED 顯示屏,驅(qū)動(dòng)IC 為SSD1315.

OLEDDisplay 0.96” SSSD1315 V1.1分辨率為128×64。

供電為3.3 V 或者5 V,通信接口為I2C。

1752660559610148.png

考慮到電流表INA219也是I2C通信接口,在STM32開發(fā)板上使用同一組I2C 硬件,OLED和INA219配置不同的器件地址,就可以一個(gè)I2C控制器驅(qū)動(dòng)兩個(gè)I2C器件。

此開發(fā)板有Arduino接口,恰好把Seeed Base Shield擴(kuò)展板接上。

1752660614452574.png

3   STM32 I2C配置

3.1 選用I2C1

image.png

1752665013726317.png

Nucleo-F411RE管腳分配

3.2 STM32CubeMX工程配置

●   在Connecity 中選擇I2C1

●   在右側(cè)使能i2c

●   配置I2C 參數(shù)為Standard Mode,速率100 KHz,地址為7 比特,主要的從器件地址為0×78

1752665076520129.png

3.3 PB8配置為SCL

1752665129122692.png

3.4 PB9配置為SDA

1752665230614103.png

4   PCtoLCD漢字取模軟件

此次任務(wù)在OLED 上展示中文字符如下:

電子產(chǎn)品世界

得捷

你好

功率檢測(cè)

系統(tǒng)控制

電壓電流

所有取模的文字:

電子產(chǎn)品世界得捷你好功率監(jiān)測(cè)系統(tǒng)控制電壓流

PCtoLCD2002軟件配置如下:

●   點(diǎn)陣格式:陰碼

●   取模方式:列行式

●   取模走向:逆向(低位在前)

●   自定義格式:C51 格式,且行前綴、行后綴都為空。

1752665418993763.png

1752665443771541.png

在輸入框輸入文字后點(diǎn)擊“生成字?!保截惖焦こ讨屑纯?。

5 流程圖

樸信惠.jpg

6   關(guān)鍵代碼

6.1 主函數(shù)

●   HAL庫(kù)初始化

●   時(shí)鐘初始化

●   硬件初始化,如GPIO,TIM,UART,I2C 等

●   OLED 初始化,清屏

●   顯示界面,界面切換,死循環(huán)

view plaincopy to clipboardprint?

1.int main(void)

2.{

3./* USER CODE BEGIN 1 */

4.

5./*USER CODE END 1*/

6.

7. /* MCU Configuration--------------------------------------------------------*/

8.

9./*Reset of all peripherals, Initializes the Flash interface and the Systick.*/

10.HAL_Init();

11.

12./*USER CODE BEGIN Init*/

13.

14./*USER CODE END Init*/

15.

16./*Configure the system clock*/

17.SystemClock_Config();

18.

19./*USER CODE BEGIN SysInit*/

20.

21./*USER CODE END SysInit*/

22.

23./*Initialize all configured peripherals*/

24.MX_GPIO_Init();

25.MX_USART2_UART_Init();

26.MX_TIM1_Init();

27.MX_I2C1_Init();

28.

29./*USER CODE BEGIN 2*/

30.

31.printf(“rn”);

32.printf(“tt EEPW_2025_DIY1_Task2_OLED rn”);

33.printf(“tt Build: %s %s rn”, __DATE__, __TIME__);

34.printf(“rn”);

35.

36.HAL_TIM_Base_Start_IT(&htim1);

37.

38.OLED_Init();

39.

40./*USER CODE END 2*/

41.

42./*Infinite loop*/

43./*USER CODE BEGIN WHILE*/

44.while(1){

45.screen_00_welcome();

46.HAL_Delay(1000 * 3);

47.screen_01_welcome();

48.HAL_Delay(1000 * 3);

49.screen_02_diy_power_monitor();

50.HAL_Delay(1000 * 5);

51./*USER CODE END WHILE*/

52.

53./*USER CODE BEGIN 3*/

54.//HAL_Delay(2000);

55.}

56./*USER CODE END 3*/

57.}

6.2 I2C 初始化

這里的初始化代碼是STM32CubeMX生成的,初始化參數(shù)來(lái)自界面配置的參數(shù)。

●   函數(shù)MX_I2C1_Init() 先保存I2C 參數(shù)到hi2c1 結(jié)構(gòu)體上,調(diào)用HAL_I2C_Init() 初始化硬件

●   函數(shù)HAL_I2C_MspInit() 由HAL_I2C_Init() 函數(shù)調(diào)用,初始化I2C1 管腳,配置為復(fù)用功能

view plaincopy to clipboardprint?

1.void MX_I2C1_Init(void)

2.{

3.

4./*USER CODE BEGIN I2C1_Init 0*/

5.

6./*USER CODE END I2C1_Init 0*/

7.

8./*USER CODE BEGIN I2C1_Init 1*/

9.

10./*USER CODE END I2C1_Init 1*/

11. hi2c1.Instance = I2C1;

12.hi2c1.Init.ClockSpeed = 100000;

13.hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;

14.hi2c1.Init.OwnAddress1 = 240;

15.hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;

16.hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;

17.hi2c1.Init.OwnAddress2 = 0;

18.hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;

19.hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

20.if (HAL_I2C_Init(&hi2c1) != HAL_OK)

21.{

22.Error_Handler();

23.}

24./*USER CODE BEGIN I2C1_Init 2*/

25.

26./*USER CODE END I2C1_Init 2*/

27.

28.}

29.

30.void HAL_I2C_MspInit(I2C_HandleTypeDef*i2cHandle)

31.{

32.

33.GPIO_InitTypeDef GPIO_InitStruct = {0};

34.if(i2cHandle->Instance==I2C1)

35.{

36./*USER CODE BEGIN I2C1_MspInit 0*/

37.

38./*USER CODE END I2C1_MspInit 0*/

39.

40.__HAL_RCC_GPIOB_CLK_ENABLE();

41. /**I2C1 GPIO Configuration

42.PB8 ------>I2C1_SCL

43.PB9 ------>I2C1_SDA

44.*/

45.GPIO_InitStruct.Pin=OLED_SCL_Pin|OLED_SDA_Pin;

46.GPIO_InitStruct.Mode=GPIO_MODE_AF_OD;

47.GPIO_InitStruct.Pull=GPIO_NOPULL;

48.GPIO_InitStruct.Speed=GPIO_SPEED_FREQ_VERY_HIGH;

49.GPIO_InitStruct.Alternate=GPIO_AF4_I2C1;

50.HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

51.

52./*I2C1 clock enable*/

53.__HAL_RCC_I2C1_CLK_ENABLE();

54./*USER CODE BEGIN I2C1_MspInit 1*/

55.

56./*USER CODE END I2C1_MspInit 1*/

57.}

58.}

6.3 OLED接口函數(shù)

OLED接口層,主要實(shí)現(xiàn)兩個(gè)函數(shù),其他的OLED API都是依賴這兩個(gè)函數(shù)

●   Oled_Write_Data() 發(fā)送數(shù)據(jù)到OLED IC

●   Oled_Write_Cmd() 發(fā)送命令到OLED I

6.3.1 Oled_Write_Data() 實(shí)現(xiàn)

這里直接調(diào)用HAL API 往OLED 發(fā)送數(shù)據(jù)

view plaincopy to clipboardprint?

1.void Oled_Write_Data(uint8_t data)

2.{

3.HAL_I2C_Mem_Write(&HI2CX, OLED_ID,OLED_WR_DATA, I2C_MEMADD_SIZE_8BIT,&data, 1, 0×100);

4.}

6.3.2 Oled_Write_Cmd()實(shí)現(xiàn)

這里直接調(diào)用HAL API往OLED發(fā)送命令

view plaincopy to clipboardprint?

1. void Oled_Write_Cmd(uint8_t cmd)

2. {

3. HAL_I2C_Mem_Write(&HI2CX, OLED_ID,

OLED_WR_CMD, I2C_MEMADD_SIZE_8BIT,

&cmd, 1, 0×100);

4. }

6.4 OLED API

這里僅列舉幾個(gè)常用的API 實(shí)現(xiàn)。

6.4.1 OLED_Init()初始化

OLED 上電后需要發(fā)送命令配置參數(shù)

view plaincopy to clipboardprint?

1.void OLED_Init(void)

2.{

3./*設(shè)置顯示打開/關(guān)閉

4.*AE--->顯示打開

5.*AF--->顯示關(guān)閉(休眠模式)

6.*/

7.Oled_Write_Cmd(0xAE);

8.

9./*==========基本命令表==========*/

10./*設(shè)置對(duì)比度

11.*0~255:數(shù)值越大 亮度越亮

12.*/

13.Oled_Write_Cmd(0×81);

14.Oled_Write_Cmd(0×FF);

15.

16./*使能全屏顯示

17.*A4--->恢復(fù)到RAM 內(nèi)容顯示

18.*A5--->忽略RAM 內(nèi)容顯示

19.*/

20.Oled_Write_Cmd(0×A4);

21.

22./*設(shè)置顯示模式

23.*A6--->正常顯示:0 滅1 亮

24.*A7--->逆顯示:1滅0亮

25.*/

26.Oled_Write_Cmd(0×A6);

27.

28./*==========滾動(dòng)命令表==========*/

29./*滾動(dòng)使能/ 失能

30.*2E--->失能

31.* 2F--->使能

32.*/

33.Oled_Write_Cmd(0×2E);

34.

35./*七字節(jié)命令: 連續(xù)水平滾動(dòng)設(shè)置 */

36.

37./*左/ 右水平滾動(dòng)設(shè)置

38.*26---> 右水平滾動(dòng)

39.*27---> 左水平滾動(dòng)

40.*/

41.Oled_Write_Cmd(0×26);

42./*虛擬字節(jié)*/

43.Oled_Write_Cmd(0×00);

44./*設(shè)置滾動(dòng)起始頁(yè)地址*/

45.Oled_Write_Cmd(0×00);

46./*設(shè)置滾動(dòng)間隔*/

47.Oled_Write_Cmd(0×03);

48./*設(shè)置滾動(dòng)結(jié)束地址 */

49.Oled_Write_Cmd(0×07);

50./*虛擬字節(jié)*/

51.Oled_Write_Cmd(0×00);

52.Oled_Write_Cmd(0×FF);

53.

54./*==========尋址設(shè)置命令表==========*/

55.

56./*雙字節(jié)命令: 寄存器尋址模式 */

57.Oled_Write_Cmd(0×20);

58.

59./* 10:頁(yè)尋址模式

60.* 01:垂直尋址模式

61.* 00:水平尋址模式

62.*/

63.Oled_Write_Cmd(0×10);

64./*單字節(jié)命令: 設(shè)置頁(yè)尋址的起始頁(yè)地址 */

65.Oled_Write_Cmd(0×B0);

66./* 單字節(jié)命令: 設(shè)置頁(yè)尋址的起始列地址低位 */

67.Oled_Write_Cmd(0×00);

68. /* 單字節(jié)命令: 設(shè)置頁(yè)尋址的起始列地址高位 */

69.Oled_Write_Cmd(0×10);

70.

71./*========== 硬件配置命令表 ==========*/

72.

73./*設(shè)置顯示開始線

74.*0×40~0×7F 對(duì)應(yīng)0~63

75.*/

76.Oled_Write_Cmd(0×40);

77.

78./*設(shè)置列重映射

79.*A0:addressX--->segX

80.*A1:addressX--->seg(127-X)

81.*/

82.Oled_Write_Cmd(0×A1);

83.

84./*設(shè)置多路復(fù)用比 */

85.Oled_Write_Cmd(0×A8);

86.Oled_Write_Cmd(0×3F);

87.

88./*設(shè)置COM 輸出掃描方向

89.*C0:COM0--->COM63( 從上往下掃描)

90.*C8:COM63--->COM0( 從下往上掃描)

91.*/

92.Oled_Write_Cmd(0×C8);

93.

94./*雙字節(jié)命令:設(shè)置COM 顯示偏移量 */

95.Oled_Write_Cmd(0×D3);

96.Oled_Write_Cmd(0×00); /* COM 不偏移 */

97.

98./*雙字節(jié)命令:配置COM 重映射 */

99.Oled_Write_Cmd(0×DA);

100.Oled_Write_Cmd(0×12);

101.

102./*雙字節(jié)命令:設(shè)置預(yù)充期 */

103.Oled_Write_Cmd(0×D9);

104.Oled_Write_Cmd(0×22); /* 階段一2 個(gè)無(wú)效DCLK 時(shí)鐘/ 階段二2 個(gè)無(wú)效DCLK 時(shí)鐘 */

105.

106./*設(shè)置VCOMH 取消選擇電平

107.*00:0.65xVcc

108.*20:0.77xVcc

109.*30:0.83xVcc

110.*/

111.Oled_Write_Cmd(0×DB);

112.Oled_Write_Cmd(0×20);

113.

114./*雙字節(jié)命令:設(shè)置電荷泵 */

115.Oled_Write_Cmd(0×8d);

116.Oled_Write_Cmd(0×14);

117.

118.Oled_Write_Cmd(0×AF);

119.}

6.4.2 OLED_Fill()刷屏

m表示page地址,數(shù)值0~7,n 表示列地址,數(shù)值0~127。

填充的數(shù)據(jù)fill_data,設(shè)置為0,則屏幕為黑色;設(shè)置為1,則屏幕白色;設(shè)置為其他值,屏幕顯示條紋。

view plaincopy to clipboardprint?

1.void OLED_Fill(uint8_t fill_data) // 全屏填充

2.{

3.unsigned char m, n;

4.for (m = 0; m < 8; m++) {

5.Oled_Write_Cmd(0×b0 + m); // page0-page1

6.Oled_Write_Cmd(0×00); // low column st art address

7.Oled_Write_Cmd(0×10); // high column s tart address

8.for (n = 0; n < 128; n++) {

9.Oled_Write_Data(fill_data);

10.}

11.}

12.}

6.4.3 OLED_ShowStr()

這里支持兩種字體大小,分別是6×8 和8×16 大小。

view plaincopy to clipboardprint?

1./**

2.*@brief 顯示 ASCII 字符,有 6×8 和 8×16 字體大小可以選擇

3.*

4.*@param x起始點(diǎn)坐標(biāo)x[0, 127]

5.*@param y 起始點(diǎn)坐標(biāo) y [0, 7]

6.*@param ch 要顯示的字符串

7.*@param textsize 1 表示字體大小 6×8; 2 表示字體大小 8×16

8.*/

9.void OLED_ShowStr(uint16_t x, uint16_t y,uint8_t ch[], ascii_font_e font)

10. {

11.uint8_t c = 0, i = 0, j = 0;

12.switch (font) {

13.case ASCII_FONT_6×8: {

14.while (ch[j] != ‘?’) {

15.c=ch[j] - 32;

16.if (x > 126) {

17.x = 0;

18.y++;

19.}

20.OLED_SetPos(x, y);

21.for (i = 0; i < 6; i++)

22.Oled_Write_Data(FONT_ASCII_6×8[c][i]);

23.x= 6;

24.j++;

25.}

26.break;

27.}

28.

29.case ASCII_FONT_8×16: {

30.while (ch[j] != ‘?’) {

31.c=ch[j] - 32;

32.if (x > 120) {

33.x=0;

34.y++;

35.}

36.OLED_SetPos(x, y);

37.for (i = 0; i < 8; i++)

38.Oled_Write_Data(FONT_ASCII_8×16[c * 16 + i]);

39.OLED_SetPos(x, y + 1);

40.for (i = 0; i < 8; i++)

41.Oled_Write_Data(FONT_ASCII_8×16[c * 16 + i + 8]);

42.x=8;

43.j++;

44. }

45.break;

46.}

47.

48.default:

49.break;

50. }

51. }

6.4.4 OLED_ShowCN()

這里只支持一種中文字體大小,16×16。

/**

*@brief顯示oled_codetab.h中的漢字,16×16點(diǎn)陣

*

*@param x起始坐標(biāo)x[0, 127]

*@param y起始坐標(biāo)y[0, 7]

*@param n漢字在16×16點(diǎn)陣中的索引,下標(biāo)從0開始

*/

void OLED_ShowCN(uint16_t x, uint16_t y, uint16_t index)

{

unsigned char wm=0;

unsigned int adder = 32 * index;

OLED_SetPos(x, y);

for (wm = 0; wm < 16; wm++) {Oled_Write_Data(FONT_CN_16×16[adder]);

adder += 1;

}

OLED_SetPos(x, y + 1);

for (wm = 0; wm < 16; wm++) {Oled_Write_Data(FONT_CN_16×16[adder]);

adder += 1;

}

}

7   實(shí)操演示

顯示中文歡迎界面

1752666366835565.png

顯示英文歡迎界面

1752666650152621.png

顯示功率檢測(cè)界面,其中的電壓、電流和功率數(shù)值是預(yù)設(shè)值,并非實(shí)際測(cè)量的。

1752666281268787.png

(本文來(lái)源于《EEPW》


關(guān)鍵詞: 202507

評(píng)論


技術(shù)專區(qū)

關(guān)閉