添加了些新模块

This commit is contained in:
RB 2025-04-27 01:29:21 +08:00
parent b27fc87089
commit 3f477172f2
9 changed files with 699 additions and 17 deletions

View File

@ -1,17 +0,0 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define BSP_OK (0)
#define BSP_ERR (-1)
#define BSP_ERR_NULL (-2)
#define BSP_ERR_INITED (-3)
#define BSP_ERR_NO_DEV (-4)
#define SIGNAL_BSP_USB_BUF_RECV (1u << 0)
#ifdef __cplusplus
}
#endif

104
User/bsp/i2c.c Normal file
View File

@ -0,0 +1,104 @@
/* Includes ----------------------------------------------------------------- */
#include "bsp\i2c.h"
/* Private define ----------------------------------------------------------- */
/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */
static void (*I2C_Callback[BSP_I2C_NUM][BSP_I2C_CB_NUM])(void);
/* Private function -------------------------------------------------------- */
static BSP_I2C_t I2C_Get(I2C_HandleTypeDef *hi2c) {
if (hi2c->Instance == I2C1) return BSP_I2C_OLED;
else
return BSP_I2C_ERR;
}
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c) {
BSP_I2C_t bsp_i2c = I2C_Get(hi2c);
if (bsp_i2c != BSP_I2C_ERR) {
if (I2C_Callback[bsp_i2c][HAL_I2C_MASTER_TX_CPLT_CB])
I2C_Callback[bsp_i2c][HAL_I2C_MASTER_TX_CPLT_CB]();
}
}
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c) {
BSP_I2C_t bsp_i2c = I2C_Get(hi2c);
if (bsp_i2c != BSP_I2C_ERR) {
if (I2C_Callback[bsp_i2c][HAL_I2C_MASTER_RX_CPLT_CB])
I2C_Callback[bsp_i2c][HAL_I2C_MASTER_RX_CPLT_CB]();
}
}
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c) {
BSP_I2C_t bsp_i2c = I2C_Get(hi2c);
if (bsp_i2c != BSP_I2C_ERR) {
if (I2C_Callback[bsp_i2c][HAL_I2C_SLAVE_TX_CPLT_CB])
I2C_Callback[bsp_i2c][HAL_I2C_SLAVE_TX_CPLT_CB]();
}
}
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) {
BSP_I2C_t bsp_i2c = I2C_Get(hi2c);
if (bsp_i2c != BSP_I2C_ERR) {
if (I2C_Callback[bsp_i2c][HAL_I2C_SLAVE_RX_CPLT_CB])
I2C_Callback[bsp_i2c][HAL_I2C_SLAVE_RX_CPLT_CB]();
}
}
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c) {
BSP_I2C_t bsp_i2c = I2C_Get(hi2c);
if (bsp_i2c != BSP_I2C_ERR) {
if (I2C_Callback[bsp_i2c][HAL_I2C_LISTEN_CPLT_CB])
I2C_Callback[bsp_i2c][HAL_I2C_LISTEN_CPLT_CB]();
}
}
void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c) {
BSP_I2C_t bsp_i2c = I2C_Get(hi2c);
if (bsp_i2c != BSP_I2C_ERR) {
if (I2C_Callback[bsp_i2c][HAL_I2C_MEM_TX_CPLT_CB])
I2C_Callback[bsp_i2c][HAL_I2C_MEM_TX_CPLT_CB]();
}
}
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c) {
BSP_I2C_t bsp_i2c = I2C_Get(hi2c);
if (bsp_i2c != BSP_I2C_ERR) {
if (I2C_Callback[bsp_i2c][HAL_I2C_MEM_RX_CPLT_CB])
I2C_Callback[bsp_i2c][HAL_I2C_MEM_RX_CPLT_CB]();
}
}
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) {
BSP_I2C_t bsp_i2c = I2C_Get(hi2c);
if (bsp_i2c != BSP_I2C_ERR) {
if (I2C_Callback[bsp_i2c][HAL_I2C_ERROR_CB])
I2C_Callback[bsp_i2c][HAL_I2C_ERROR_CB]();
}
}
void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c) {
BSP_I2C_t bsp_i2c = I2C_Get(hi2c);
if (bsp_i2c != BSP_I2C_ERR) {
if (I2C_Callback[bsp_i2c][HAL_I2C_ABORT_CPLT_CB])
I2C_Callback[bsp_i2c][HAL_I2C_ABORT_CPLT_CB]();
}
}
/* Exported functions ------------------------------------------------------- */
I2C_HandleTypeDef *BSP_I2C_GetHandle(BSP_I2C_t i2c) {
switch (i2c) {
case BSP_I2C_OLED:
return &hi2c1;
default:
return NULL;
}
}
int8_t BSP_I2C_RegisterCallback(BSP_I2C_t i2c, BSP_I2C_Callback_t type,
void (*callback)(void)) {
if (callback == NULL) return BSP_ERR_NULL;
I2C_Callback[i2c][type] = callback;
return BSP_OK;
}

43
User/bsp/i2c.h Normal file
View File

@ -0,0 +1,43 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ----------------------------------------------------------------- */
#include <i2c.h>
#include "bsp/bsp.h"
/* Exported constants ------------------------------------------------------- */
/* Exported macro ----------------------------------------------------------- */
/* Exported types ----------------------------------------------------------- */
/* I2C实体枚举与设备对应 */
typedef enum {
BSP_I2C_OLED,
BSP_I2C_NUM,
BSP_I2C_ERR,
} BSP_I2C_t;
/* I2C支持的中断回调函数类型具体参考HAL中定义 */
typedef enum {
HAL_I2C_MASTER_TX_CPLT_CB,
HAL_I2C_MASTER_RX_CPLT_CB,
HAL_I2C_SLAVE_TX_CPLT_CB,
HAL_I2C_SLAVE_RX_CPLT_CB,
HAL_I2C_LISTEN_CPLT_CB,
HAL_I2C_MEM_TX_CPLT_CB,
HAL_I2C_MEM_RX_CPLT_CB,
HAL_I2C_ERROR_CB,
HAL_I2C_ABORT_CPLT_CB,
BSP_I2C_CB_NUM,
} BSP_I2C_Callback_t;
/* Exported functions prototypes -------------------------------------------- */
I2C_HandleTypeDef *BSP_I2C_GetHandle(BSP_I2C_t i2c);
int8_t BSP_I2C_RegisterCallback(BSP_I2C_t i2c, BSP_I2C_Callback_t type,
void (*callback)(void));
#ifdef __cplusplus
}
#endif

61
User/bsp/led.c Normal file
View File

@ -0,0 +1,61 @@
/* Includes ----------------------------------------------------------------- */
#include "bsp\led.h"
#include <tim.h>
/* Private define ----------------------------------------------------------- */
/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */
static uint32_t led_stats;
/* Private function -------------------------------------------------------- */
/* Exported functions ------------------------------------------------------- */
int8_t BSP_LED_Set(BSP_LED_Channel_t ch, BSP_LED_Status_t s, float duty_cycle) {
if (duty_cycle > 1.0f) return BSP_ERR;
uint32_t tim_ch;
uint16_t pulse = (uint16_t)(duty_cycle * (float)UINT16_MAX);
switch (ch) {
case BSP_LED_1:
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, pulse);
tim_ch = TIM_CHANNEL_2;
break;
case BSP_LED_2:
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, pulse);
tim_ch = TIM_CHANNEL_3;
break;
case BSP_LED_3:
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, pulse);
tim_ch = TIM_CHANNEL_1;
break;
}
switch (s) {
case BSP_LED_ON:
HAL_TIM_PWM_Start(&htim2, tim_ch);
led_stats |= tim_ch;
break;
case BSP_LED_OFF:
HAL_TIM_PWM_Stop(&htim2, tim_ch);
led_stats &= ~tim_ch;
break;
case BSP_LED_TAGGLE:
if (led_stats & tim_ch) {
HAL_TIM_PWM_Stop(&htim2, tim_ch);
led_stats &= ~tim_ch;
} else {
HAL_TIM_PWM_Start(&htim2, tim_ch);
led_stats |= tim_ch;
}
break;
}
return BSP_OK;
}

36
User/bsp/led.h Normal file
View File

@ -0,0 +1,36 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ----------------------------------------------------------------- */
#include <stdint.h>
#include "bsp/bsp.h"
/* Exported constants ------------------------------------------------------- */
/* Exported macro ----------------------------------------------------------- */
/* Exported types ----------------------------------------------------------- */
/* LED灯状态设置用 */
typedef enum {
BSP_LED_ON,
BSP_LED_OFF,
BSP_LED_TAGGLE,
} BSP_LED_Status_t;
/* LED通道 */
typedef enum {
BSP_LED_1,
BSP_LED_2,
BSP_LED_3,
} BSP_LED_Channel_t;
/* Exported functions prototypes -------------------------------------------- */
int8_t BSP_LED_Set(BSP_LED_Channel_t ch, BSP_LED_Status_t s, float duty_cycle);
#ifdef __cplusplus
}
#endif

114
User/bsp/uart.c Normal file
View File

@ -0,0 +1,114 @@
/* Includes ----------------------------------------------------------------- */
#include "bsp\uart.h"
/* Private define ----------------------------------------------------------- */
/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */
static void (*UART_Callback[BSP_UART_NUM][BSP_UART_CB_NUM])(void);
/* Private function -------------------------------------------------------- */
static BSP_UART_t UART_Get(UART_HandleTypeDef *huart) {
if (huart->Instance == USART1)
return BSP_UART_SINDT;
else
return BSP_UART_ERR;
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
BSP_UART_t bsp_uart = UART_Get(huart);
if (bsp_uart != BSP_UART_ERR) {
if (UART_Callback[bsp_uart][BSP_UART_TX_CPLT_CB]) {
UART_Callback[bsp_uart][BSP_UART_TX_CPLT_CB]();
}
}
}
void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart) {
BSP_UART_t bsp_uart = UART_Get(huart);
if (bsp_uart != BSP_UART_ERR) {
if (UART_Callback[bsp_uart][BSP_UART_TX_HALF_CPLT_CB]) {
UART_Callback[bsp_uart][BSP_UART_TX_HALF_CPLT_CB]();
}
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
BSP_UART_t bsp_uart = UART_Get(huart);
if (bsp_uart != BSP_UART_ERR) {
if (UART_Callback[bsp_uart][BSP_UART_RX_CPLT_CB]) {
UART_Callback[bsp_uart][BSP_UART_RX_CPLT_CB]();
}
}
}
void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart) {
BSP_UART_t bsp_uart = UART_Get(huart);
if (bsp_uart != BSP_UART_ERR) {
if (UART_Callback[bsp_uart][BSP_UART_RX_HALF_CPLT_CB]) {
UART_Callback[bsp_uart][BSP_UART_RX_HALF_CPLT_CB]();
}
}
}
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
BSP_UART_t bsp_uart = UART_Get(huart);
if (bsp_uart != BSP_UART_ERR) {
if (UART_Callback[bsp_uart][BSP_UART_ERROR_CB]) {
UART_Callback[bsp_uart][BSP_UART_ERROR_CB]();
}
}
}
void HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart) {
BSP_UART_t bsp_uart = UART_Get(huart);
if (bsp_uart != BSP_UART_ERR) {
if (UART_Callback[bsp_uart][BSP_UART_ABORT_CPLT_CB]) {
UART_Callback[bsp_uart][BSP_UART_ABORT_CPLT_CB]();
}
}
}
void HAL_UART_AbortTransmitCpltCallback(UART_HandleTypeDef *huart) {
BSP_UART_t bsp_uart = UART_Get(huart);
if (bsp_uart != BSP_UART_ERR) {
if (UART_Callback[bsp_uart][BSP_UART_ABORT_TX_CPLT_CB]) {
UART_Callback[bsp_uart][BSP_UART_ABORT_TX_CPLT_CB]();
}
}
}
void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart) {
BSP_UART_t bsp_uart = UART_Get(huart);
if (bsp_uart != BSP_UART_ERR) {
if (UART_Callback[bsp_uart][BSP_UART_ABORT_RX_CPLT_CB]) {
UART_Callback[bsp_uart][BSP_UART_ABORT_RX_CPLT_CB]();
}
}
}
/* Exported functions ------------------------------------------------------- */
void BSP_UART_IRQHandler(UART_HandleTypeDef *huart) {
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE)) {
__HAL_UART_CLEAR_IDLEFLAG(huart);
if (UART_Callback[UART_Get(huart)][BSP_UART_IDLE_LINE_CB]) {
UART_Callback[UART_Get(huart)][BSP_UART_IDLE_LINE_CB]();
}
}
}
UART_HandleTypeDef *BSP_UART_GetHandle(BSP_UART_t uart) {
switch (uart) {
case BSP_UART_SINDT:
return &huart1;
default:
return NULL;
}
}
int8_t BSP_UART_RegisterCallback(BSP_UART_t uart, BSP_UART_Callback_t type,
void (*callback)(void)) {
if (callback == NULL) return BSP_ERR_NULL;
UART_Callback[uart][type] = callback;
return BSP_OK;
}

47
User/bsp/uart.h Normal file
View File

@ -0,0 +1,47 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ----------------------------------------------------------------- */
#include <usart.h>
#include "bsp/bsp.h"
/* Exported constants ------------------------------------------------------- */
/* Exported macro ----------------------------------------------------------- */
/* Exported types ----------------------------------------------------------- */
/* 要添加使用UART的新设备需要先在此添加对应的枚举值 */
/* UART实体枚举与设备对应 */
typedef enum {
BSP_UART_SINDT,
BSP_UART_NUM,
BSP_UART_ERR,
} BSP_UART_t;
/* UART支持的中断回调函数类型具体参考HAL中定义 */
typedef enum {
BSP_UART_TX_HALF_CPLT_CB,
BSP_UART_TX_CPLT_CB,
BSP_UART_RX_HALF_CPLT_CB,
BSP_UART_RX_CPLT_CB,
BSP_UART_ERROR_CB,
BSP_UART_ABORT_CPLT_CB,
BSP_UART_ABORT_TX_CPLT_CB,
BSP_UART_ABORT_RX_CPLT_CB,
BSP_UART_IDLE_LINE_CB,
BSP_UART_CB_NUM,
} BSP_UART_Callback_t;
/* Exported functions prototypes -------------------------------------------- */
UART_HandleTypeDef *BSP_UART_GetHandle(BSP_UART_t uart);
int8_t BSP_UART_RegisterCallback(BSP_UART_t uart, BSP_UART_Callback_t type,
void (*callback)(void));
#ifdef __cplusplus
}
#endif

268
User/device/oled.c Normal file
View File

@ -0,0 +1,268 @@
/* Includes ----------------------------------------------------------------- */
#include "device/oled.h"
#include "bsp/i2c.h"
#include <string.h>
#include <stdint.h>
/* Private define ----------------------------------------------------------- */
#define OLED_I2C_ADDR 0x78 // OLED I2C 地址
#define OLED_WIDTH 128
#define OLED_HEIGHT 64
/* Private variables -------------------------------------------------------- */
static uint8_t oled_buffer[OLED_WIDTH * OLED_HEIGHT / 8];
static struct {
uint8_t x_min;
uint8_t x_max;
uint8_t y_min;
uint8_t y_max;
uint8_t dirty; // 标志是否有脏区域
} dirty_rect = {0, 0, 0, 0, 0};
/* Private function prototypes ---------------------------------------------- */
static void OLED_WriteCommand(uint8_t cmd);
static void OLED_WriteData(uint8_t *data, uint16_t size);
static void OLED_MarkDirty(uint8_t x, uint8_t y);
static void OLED_UpdateDirtyScreen(void);
static const uint8_t oled_font[95][8] = {
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}, /* " ", 0 */
{0x00,0x00,0x00,0xcf,0xcf,0x00,0x00,0x00,}, /* "!", 1 */
{0x00,0x0c,0x06,0x00,0x0c,0x06,0x00,0x00,}, /* """, 2 */
{0x24,0xe4,0x3c,0x27,0xe4,0x3c,0x27,0x24,}, /* "#", 3 */
{0x00,0x20,0x46,0xf9,0x9f,0x62,0x04,0x00,}, /* "$", 4 */
{0x06,0x09,0xc6,0x30,0x0c,0x63,0x90,0x60,}, /* "%", 5 */
{0x00,0x00,0x6e,0x91,0xa9,0x46,0xa0,0x00,}, /* "&", 6 */
{0x00,0x00,0x00,0x1c,0x0e,0x00,0x00,0x00,}, /* "'", 7 */
{0x00,0x00,0x3c,0x42,0x81,0x00,0x00,0x00,}, /* "(", 8 */
{0x00,0x00,0x00,0x81,0x42,0x3c,0x00,0x00,}, /* ")", 9 */
{0x00,0x10,0x54,0x38,0x38,0x54,0x10,0x00,}, /* "*", 10 */
{0x00,0x10,0x10,0xfc,0x10,0x10,0x00,0x00,}, /* "+", 11 */
{0x00,0x00,0x00,0xc0,0x60,0x00,0x00,0x00,}, /* ",", 12 */
{0x00,0x00,0x10,0x10,0x10,0x10,0x00,0x00,}, /* "-", 13 */
{0x00,0x00,0x00,0x00,0xc0,0xc0,0x00,0x00,}, /* ".", 14 */
{0x00,0x00,0x00,0xc0,0x38,0x07,0x00,0x00,}, /* "/", 15 */
{0x00,0x00,0x7c,0x92,0x8a,0x7c,0x00,0x00,}, /* "0", 16 */
{0x00,0x00,0x00,0x84,0xfe,0x80,0x00,0x00,}, /* "1", 17 */
{0x00,0x00,0x8c,0xc2,0xa2,0x9c,0x00,0x00,}, /* "2", 18 */
{0x00,0x00,0x44,0x92,0x92,0x6c,0x00,0x00,}, /* "3", 19 */
{0x00,0x20,0x38,0x24,0xfe,0x20,0x00,0x00,}, /* "4", 20 */
{0x00,0x00,0x5e,0x92,0x92,0x62,0x00,0x00,}, /* "5", 21 */
{0x00,0x00,0x78,0x94,0x92,0x62,0x00,0x00,}, /* "6", 22 */
{0x00,0x00,0x82,0x62,0x1a,0x06,0x00,0x00,}, /* "7", 23 */
{0x00,0x00,0x6c,0x92,0x92,0x6c,0x00,0x00,}, /* "8", 24 */
{0x00,0x00,0x8c,0x52,0x32,0x1c,0x00,0x00,}, /* "9", 25 */
{0x00,0x00,0x00,0x6c,0x6c,0x00,0x00,0x00,}, /* ":", 26 */
{0x00,0x00,0x80,0xec,0x6c,0x00,0x00,0x00,}, /* ";", 27 */
{0x00,0x00,0x10,0x28,0x44,0x00,0x00,0x00,}, /* "<", 28 */
{0x00,0x00,0x24,0x24,0x24,0x24,0x00,0x00,}, /* "=", 29 */
{0x00,0x00,0x00,0x44,0x28,0x10,0x00,0x00,}, /* ">", 30 */
{0x00,0x00,0x0c,0xa2,0x92,0x1c,0x00,0x00,}, /* "?", 31 */
{0x00,0x3c,0x42,0x99,0xa5,0xa2,0x3c,0x00,}, /* "@", 32 */
{0x00,0xe0,0x1c,0x12,0x12,0x1c,0xe0,0x00,}, /* "A", 33 */
{0x00,0xfe,0x92,0x92,0x9c,0x90,0x60,0x00,}, /* "B", 34 */
{0x00,0x38,0x44,0x82,0x82,0x82,0x44,0x00,}, /* "C", 35 */
{0x00,0xfe,0x82,0x82,0x82,0x82,0x7c,0x00,}, /* "D", 36 */
{0x00,0xfe,0x92,0x92,0x92,0x92,0x92,0x00,}, /* "E", 37 */
{0x00,0xfe,0x12,0x12,0x12,0x12,0x02,0x00,}, /* "F", 38 */
{0x00,0x7c,0x82,0x92,0x92,0x72,0x00,0x00,}, /* "G", 39 */
{0x00,0xfe,0x10,0x10,0x10,0x10,0xfe,0x00,}, /* "H", 40 */
{0x00,0x82,0x82,0xfe,0x82,0x82,0x00,0x00,}, /* "I", 41 */
{0x00,0x82,0x82,0x7e,0x02,0x02,0x00,0x00,}, /* "J", 42 */
{0x00,0xfe,0x10,0x28,0x44,0x82,0x00,0x00,}, /* "K", 43 */
{0x00,0xfe,0x80,0x80,0x80,0x80,0x00,0x00,}, /* "L", 44 */
{0xfc,0x02,0x04,0xf8,0x04,0x02,0xfc,0x00,}, /* "M", 45 */
{0x00,0xfe,0x04,0x18,0x30,0x40,0xfe,0x00,}, /* "N", 46 */
{0x00,0x7c,0x82,0x82,0x82,0x82,0x7c,0x00,}, /* "O", 47 */
{0x00,0x00,0xfe,0x12,0x12,0x0c,0x00,0x00,}, /* "P", 48 */
{0x00,0x00,0x3c,0x42,0xc2,0xbc,0x00,0x00,}, /* "Q", 49 */
{0x00,0x00,0xfe,0x32,0x52,0x8c,0x00,0x00,}, /* "R", 50 */
{0x00,0x00,0x4c,0x92,0x92,0x64,0x00,0x00,}, /* "S", 51 */
{0x00,0x02,0x02,0xfe,0x02,0x02,0x00,0x00,}, /* "T", 52 */
{0x00,0x7e,0x80,0x80,0x80,0x80,0x7e,0x00,}, /* "U", 53 */
{0x00,0x0c,0x30,0xc0,0x30,0x0c,0x00,0x00,}, /* "V", 54 */
{0x7c,0x80,0x80,0x78,0x80,0x80,0x7c,0x00,}, /* "W", 55 */
{0x00,0x84,0x48,0x30,0x30,0x48,0x84,0x00,}, /* "X", 56 */
{0x00,0x06,0x08,0xf0,0x08,0x06,0x00,0x00,}, /* "Y", 57 */
{0x00,0x00,0xc2,0xa2,0x92,0x8e,0x00,0x00,}, /* "Z", 58 */
{0x00,0x00,0xfe,0x82,0x82,0x82,0x00,0x00,}, /* "[", 59 */
{0x00,0x00,0x06,0x18,0x60,0x80,0x00,0x00,}, /* "\", 60 */
{0x00,0x00,0x82,0x82,0x82,0xfe,0x00,0x00,}, /* "]", 61 */
{0x00,0x30,0x0c,0x02,0x0c,0x30,0x00,0x00,}, /* "^", 62 */
{0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,}, /* "_", 63 */
{0x00,0x00,0x04,0x0c,0x18,0x00,0x00,0x00,}, /* "`", 64 */
{0x00,0x00,0x60,0x90,0x90,0xe0,0x00,0x00,}, /* "a", 65 */
{0x00,0x00,0xf8,0xa0,0xe0,0x00,0x00,0x00,}, /* "b", 66 */
{0x00,0x00,0x60,0x90,0x90,0x00,0x00,0x00,}, /* "c", 67 */
{0x00,0x00,0xe0,0xa0,0xf8,0x00,0x00,0x00,}, /* "d", 68 */
{0x00,0x00,0x70,0xa8,0xa8,0x90,0x00,0x00,}, /* "e", 69 */
{0x00,0x00,0x10,0xf8,0x14,0x00,0x00,0x00,}, /* "f", 70 */
{0x00,0x00,0xd8,0xa4,0x7c,0x00,0x00,0x00,}, /* "g", 71 */
{0x00,0x00,0xf8,0x20,0xe0,0x00,0x00,0x00,}, /* "h", 72 */
{0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0x00,}, /* "i", 73 */
{0x00,0x00,0x40,0x90,0x74,0x00,0x00,0x00,}, /* "j", 74 */
{0x00,0x00,0xf8,0x60,0x90,0x00,0x00,0x00,}, /* "k", 75 */
{0x00,0x00,0x78,0x80,0x80,0x00,0x00,0x00,}, /* "l", 76 */
{0x00,0xe0,0x10,0xe0,0x10,0xe0,0x00,0x00,}, /* "m", 77 */
{0x00,0x00,0xf0,0x10,0x10,0xe0,0x00,0x00,}, /* "n", 78 */
{0x00,0x00,0x60,0x90,0x90,0x60,0x00,0x00,}, /* "o", 79 */
{0x00,0x00,0xf0,0x48,0x48,0x30,0x00,0x00,}, /* "p", 80 */
{0x00,0x00,0x30,0x48,0x48,0xf0,0x00,0x00,}, /* "q", 81 */
{0x00,0x00,0x00,0xf0,0x20,0x10,0x00,0x00,}, /* "r", 82 */
{0x00,0x00,0x90,0xa8,0xa8,0x48,0x00,0x00,}, /* "s", 83 */
{0x00,0x10,0x10,0xf8,0x90,0x90,0x00,0x00,}, /* "t", 84 */
{0x00,0x00,0x78,0x80,0x80,0xf8,0x00,0x00,}, /* "u", 85 */
{0x00,0x18,0x60,0x80,0x60,0x18,0x00,0x00,}, /* "v", 86 */
{0x00,0x38,0xc0,0x38,0xc0,0x38,0x00,0x00,}, /* "w", 87 */
{0x00,0x88,0x50,0x20,0x50,0x88,0x00,0x00,}, /* "x", 88 */
{0x00,0x8c,0x50,0x20,0x10,0x0c,0x00,0x00,}, /* "y", 89 */
{0x00,0x88,0xc8,0xa8,0x98,0x88,0x00,0x00,}, /* "z", 90 */
{0x00,0x00,0x10,0x7c,0x82,0x00,0x00,0x00,}, /* "{", 91 */
{0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,}, /* "|", 92 */
{0x00,0x00,0x00,0x82,0x7c,0x10,0x00,0x00,}, /* "}", 93 */
{0x00,0x08,0x04,0x04,0x08,0x10,0x10,0x08,}, /* "~", 94 */
};
/* Exported functions ------------------------------------------------------- */
void OLED_Init(void) {
OLED_WriteCommand(0xAE); // 关闭显示
OLED_WriteCommand(0x20); // 设置内存寻址模式
OLED_WriteCommand(0x10); // 页寻址模式
OLED_WriteCommand(0xB0); // 设置页起始地址
OLED_WriteCommand(0xC8); // 设置COM扫描方向
OLED_WriteCommand(0x00); // 设置低列地址
OLED_WriteCommand(0x10); // 设置高列地址
OLED_WriteCommand(0x40); // 设置显示起始行
OLED_WriteCommand(0x81); // 设置对比度
OLED_WriteCommand(0xFF); // 最大对比度
OLED_WriteCommand(0xA1); // 设置段重映射
OLED_WriteCommand(0xA6); // 正常显示
OLED_WriteCommand(0xA8); // 设置多路复用比率
OLED_WriteCommand(0x3F); // 1/64
OLED_WriteCommand(0xA4); // 输出跟随 RAM 内容
OLED_WriteCommand(0xD3); // 设置显示偏移
OLED_WriteCommand(0x00); // 无偏移
OLED_WriteCommand(0xD5); // 设置显示时钟分频比/振荡频率
OLED_WriteCommand(0xF0); // 高频
OLED_WriteCommand(0xD9); // 设置预充电周期
OLED_WriteCommand(0x22); // 修复缺少分号
OLED_WriteCommand(0xDA); // 设置COM引脚硬件配置
OLED_WriteCommand(0x12); // 修复缺少分号
OLED_WriteCommand(0xDB); // 设置VCOMH电压
OLED_WriteCommand(0x20); // 修复缺少分号
OLED_WriteCommand(0x8D); // 设置充电泵
OLED_WriteCommand(0x14); // 修复缺少分号
OLED_WriteCommand(0xAF); // 打开显示
}
void OLED_Clear(void) {
memset(oled_buffer, 0, sizeof(oled_buffer));
dirty_rect.x_min = 0;
dirty_rect.x_max = OLED_WIDTH - 1;
dirty_rect.y_min = 0;
dirty_rect.y_max = OLED_HEIGHT - 1;
dirty_rect.dirty = 1;
OLED_UpdateScreen();
}
void OLED_UpdateScreen(void) {
OLED_UpdateDirtyScreen();
}
void OLED_DrawPixel(uint8_t x, uint8_t y, uint8_t color) {
if (x >= OLED_WIDTH || y >= OLED_HEIGHT) return;
if (color) {
if (!(oled_buffer[x + (y / 8) * OLED_WIDTH] & (1 << (y % 8)))) {
oled_buffer[x + (y / 8) * OLED_WIDTH] |= (1 << (y % 8));
OLED_MarkDirty(x, y);
}
} else {
if (oled_buffer[x + (y / 8) * OLED_WIDTH] & (1 << (y % 8))) {
oled_buffer[x + (y / 8) * OLED_WIDTH] &= ~(1 << (y % 8));
OLED_MarkDirty(x, y);
}
}
}
void OLED_DrawChar(uint8_t x, uint8_t y, char ch, uint8_t color) {
if (ch < ' ' || ch > '~') return;
if (x >= OLED_WIDTH || y >= OLED_HEIGHT || x + 8 > OLED_WIDTH || y + 8 > OLED_HEIGHT) {
return;
}
const uint8_t *font_data = oled_font[ch - ' '];
for (uint8_t i = 0; i < 8; i++) {
uint8_t column_data = font_data[i];
for (uint8_t j = 0; j < 8; j++) {
if (column_data & (1 << j)) {
OLED_DrawPixel(x + i, y + j, color);
} else {
OLED_DrawPixel(x + i, y + j, !color);
}
}
}
}
void OLED_DrawString(uint8_t x, uint8_t y, const char *str, uint8_t color) {
while (*str) {
OLED_DrawChar(x, y, *str, color);
x += 8;
if (x + 8 > OLED_WIDTH) {
x = 0;
y += 8;
}
if (y + 8 > OLED_HEIGHT) {
break;
}
str++;
}
}
/* Private functions -------------------------------------------------------- */
static void OLED_MarkDirty(uint8_t x, uint8_t y) {
if (!dirty_rect.dirty) {
dirty_rect.x_min = x;
dirty_rect.x_max = x;
dirty_rect.y_min = y;
dirty_rect.y_max = y;
dirty_rect.dirty = 1;
} else {
if (x < dirty_rect.x_min) dirty_rect.x_min = x;
if (x > dirty_rect.x_max) dirty_rect.x_max = x;
if (y < dirty_rect.y_min) dirty_rect.y_min = y;
if (y > dirty_rect.y_max) dirty_rect.y_max = y;
}
}
static void OLED_UpdateDirtyScreen(void) {
if (!dirty_rect.dirty) return;
uint8_t y_start = dirty_rect.y_min / 8;
uint8_t y_end = dirty_rect.y_max / 8;
for (uint8_t i = y_start; i <= y_end; i++) {
OLED_WriteCommand(0xB0 + i);
OLED_WriteCommand(dirty_rect.x_min & 0x0F);
OLED_WriteCommand(0x10 | (dirty_rect.x_min >> 4));
uint8_t width = dirty_rect.x_max - dirty_rect.x_min + 1;
OLED_WriteData(&oled_buffer[dirty_rect.x_min + i * OLED_WIDTH], width);
}
dirty_rect.dirty = 0;
}
static void OLED_WriteCommand(uint8_t cmd) {
uint8_t data[2] = {0x00, cmd};
HAL_I2C_Master_Transmit(BSP_I2C_GetHandle(BSP_I2C_OLED), OLED_I2C_ADDR, data, 2, HAL_MAX_DELAY);
}
static void OLED_WriteData(uint8_t *data, uint16_t size) {
uint8_t buffer[size + 1];
buffer[0] = 0x40;
memcpy(&buffer[1], data, size);
HAL_I2C_Master_Transmit(BSP_I2C_GetHandle(BSP_I2C_OLED), OLED_I2C_ADDR, buffer, size + 1, HAL_MAX_DELAY);
}

26
User/device/oled.h Normal file
View File

@ -0,0 +1,26 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ----------------------------------------------------------------- */
#include <stdint.h>
/* Exported constants ------------------------------------------------------- */
#define OLED_COLOR_BLACK 0
#define OLED_COLOR_WHITE 1
/* Exported functions prototypes -------------------------------------------- */
void OLED_Init(void);
void OLED_Clear(void);
void OLED_UpdateScreen(void);
void OLED_DrawPixel(uint8_t x, uint8_t y, uint8_t color);
void OLED_DrawString(uint8_t x, uint8_t y, const char *str, uint8_t color);
void OLED_DrawChar(uint8_t x, uint8_t y, char ch, uint8_t color);
void OLED_ShowChinese(uint8_t x, uint8_t y, uint8_t index);
#ifdef __cplusplus
}
#endif