oled.c
c
#include "oled.h"
#include "i2c.h"
#include "stm32f1xx_hal.h"
#include "stm32f1xx_hal_i2c.h"
#include "u8g2.h"
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
extern I2C_HandleTypeDef hi2c1;
uint8_t u8x8_byte_stm32_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,void *arg_ptr){
/* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and
* END_TRANSFER */
static uint8_t buffer[32];
static uint8_t buf_idx;
// static uint8_t dc_state; // 保存DC状态
uint8_t *data;
switch (msg) {
case U8X8_MSG_BYTE_SEND:// 发送数据
data = (uint8_t *)arg_ptr;
while (arg_int > 0) {
buffer[buf_idx++] = *data;
data++;
arg_int--;
}
break;
case U8X8_MSG_BYTE_INIT:
/* add your custom code to init i2c subsystem */
// MX_I2C1_Init(); // 注释掉,因为已经在main中初始化
break;
case U8X8_MSG_BYTE_START_TRANSFER:// 开始传输
buf_idx = 0;
break;
case U8X8_MSG_BYTE_END_TRANSFER:// 结束传输
// HAL库使用7位地址,需要左移1位转换为8位地址
if (HAL_I2C_Master_Transmit(&hi2c1, OLED_ADDRESS<<1, buffer, buf_idx, 1000) != HAL_OK)
return 0;
break;
case U8X8_MSG_BYTE_SET_DC:// 设置DC引脚
// 对于I2C,DC状态已经在CAD层通过控制字节处理
// 这里不需要做任何操作
break;
default:
return 0;
}
return 1;
}
uint8_t u8g2_gpio_and_delay_stm32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,void *arg_ptr)
{
switch (msg) {
case U8X8_MSG_DELAY_100NANO: // 延时100纳秒
__NOP();
break;
case U8X8_MSG_DELAY_10MICRO: // 延时10微秒
for (uint16_t n = 0; n < 320; n++) {
__NOP();
}
break;
case U8X8_MSG_DELAY_MILLI: // 延时arg_int毫秒
HAL_Delay(arg_int);
break;
// 硬件I2C不需要以下延时和GPIO控制
// case U8X8_MSG_DELAY_I2C: // 延时I2C时钟 - 硬件I2C不需要
// case U8X8_MSG_GPIO_I2C_CLOCK: // 输出I2C时钟 - 硬件I2C不需要
// case U8X8_MSG_GPIO_I2C_DATA: // 输出I2C数据 - 硬件I2C不需要
case U8X8_MSG_GPIO_MENU_SELECT:// 获取菜单选择引脚状态
u8x8_SetGPIOResult(u8x8, /* get menu select pin state */ 0);
break;
case U8X8_MSG_GPIO_MENU_NEXT:// 获取菜单下一页引脚状态
u8x8_SetGPIOResult(u8x8, /* get menu next pin state */ 0);
break;
case U8X8_MSG_GPIO_MENU_PREV:// 获取菜单上一页引脚状态
u8x8_SetGPIOResult(u8x8, /* get menu prev pin state */ 0);
break;
case U8X8_MSG_GPIO_MENU_HOME:// 获取菜单返回引脚状态
u8x8_SetGPIOResult(u8x8, /* get menu home pin state */ 0);
break;
default:
u8x8_SetGPIOResult(u8x8, 1); // default return value
break;
}
return 1;
}
void u8g2Init(u8g2_t *u8g2){
u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_stm32_hw_i2c,
u8g2_gpio_and_delay_stm32); // ssd1306 I2C初始化 u8g2 结构体
// u8g2_Setup_ssd1306_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_4wire_sw_spi,
// u8x8_gpio_and_delay); // SSD1306 SPI u8g2 结构体
//设置I2C地址(8位地址格式)
u8g2_SetI2CAddress(u8g2, OLED_ADDRESS<<1);
u8g2_InitDisplay(u8g2); // 根据所选的芯片进行初始化工作,初始化完成后,显示器处于关闭状态
u8g2_SetPowerSave(u8g2, 0); // 打开显示器
u8g2_ClearBuffer(u8g2); // 清除缓冲区
}oled.h
c
#ifndef __I2C_OLED_H__
#define __I2C_OLED_H__
#include "stm32f1xx_hal.h"
#include "i2c.h"
#include "u8g2.h"
// 显示模块,芯片是SSD1312,使用I2C通信,使用I2C驱动库
#define OLED_ADDRESS 0x3C // 0x78是8位地址,HAL库使用7位地址,所以右移一位
uint8_t u8x8_byte_stm32_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
uint8_t u8g2_gpio_and_delay_stm32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
void u8g2Init(u8g2_t *u8g2);
#endif