捉虫天师 发表于 2025-2-25 14:59

使用STM32F103的DMA功能驱动I2C的SSD1306,分辨率为124*64

要使用 STM32F103 的 DMA 功能驱动 I2C 通信和控制 SSD1306 OLED 显示器(分辨率 128x64),可以通过以下几个步骤实现:

配置 I2C 外设,使其能够与 SSD1306 OLED 显示器进行通信。
使用 DMA 进行数据传输,将显示数据(例如图像或文本)从内存传输到 I2C 外设的缓冲区。
初始化 SSD1306 并配置 I2C DMA,以通过 I2C 协议将显示数据传输到 OLED 屏幕。
步骤 1: 配置 STM32F103 的 I2C 外设
首先,您需要启用 STM32F103 的 I2C 外设,并配置 DMA 来支持 I2C 数据传输。

配置 I2C 外设
#include "stm32f10x.h"

#define SSD1306_I2C_ADDRESS 0x3C// SSD1306 I2C 地址

// 配置I2C
void I2C_Init_Config(void)
{
    // 启动 I2C 时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    // 配置 I2C1 引脚(假设使用 PB6 (SCL) 和 PB7 (SDA))
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;// I2C SCL, SDA
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;// 开漏输出
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStruct);

    // 配置 I2C1 外设
    I2C_InitTypeDef I2C_InitStruct;
    I2C_InitStruct.I2C_ClockSpeed = 100000;// I2C 时钟频率 100kHz
    I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;// I2C 工作模式
    I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;// 标准模式 50% 占空比
    I2C_InitStruct.I2C_OwnAddress1 = 0x00;// 自己的地址
    I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;// 启用应答
    I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;// 7 位地址模式

    I2C_Init(I2C1, &I2C_InitStruct);
    I2C_Cmd(I2C1, ENABLE);// 启用 I2C1 外设
}
配置 DMA
void DMA_Init_Config(void)
{
    // 启动 DMA 时钟
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

    // 配置 DMA1 通道6(I2C1 数据传输)
    DMA_InitTypeDef DMA_InitStruct;
    DMA_StructInit(&DMA_InitStruct);
    DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&I2C1->DR;// 外设地址(I2C 数据寄存器)
    DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)I2C_TX_Buffer;   // 内存地址
    DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;// 外设数据传输方向
    DMA_InitStruct.DMA_BufferSize = sizeof(I2C_TX_Buffer);// 数据大小
    DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;// 外设地址不递增
    DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;// 内存地址递增
    DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;// 外设数据大小 8 位
    DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;// 内存数据大小 8 位
    DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;// 单次传输模式
    DMA_InitStruct.DMA_Priority = DMA_Priority_High;// 高优先级
    DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;// 非内存到内存传输

    DMA_Init(DMA1_Channel6, &DMA_InitStruct);// 初始化 DMA1 通道6
    DMA_Cmd(DMA1_Channel6, ENABLE);// 启动 DMA
}


捉虫天师 发表于 2025-2-25 15:00

初始化 SSD1306 OLED 显示器
你需要发送初始化命令序列到 SSD1306 显示器来配置它。SSD1306 初始化命令包括设置显示模式、对比度、屏幕反向显示等。
void SSD1306_Init(void)
{
    uint8_t init_cmds[] = {
      0xAE,// Display off
      0xD5, 0x80,// Set display clock divide ratio/oscillator frequency
      0xA8, 0x3F,// Set multiplex ratio
      0xD3, 0x00,// Set display offset
      0x40,// Set display start line
      0x8D, 0x14,// Charge pump setting
      0x20, 0x00,// Set memory addressing mode
      0xA0,// Set segment remap
      0xC0,// Set COM output scan direction
      0xDA, 0x12,// Set COM pins hardware configuration
      0x81, 0x7F,// Set contrast control
      0xA4,// Entire display ON (Resume to RAM content display)
      0xA6,// Set normal display mode
      0xD9, 0xF1,// Set pre-charge period
      0xDB, 0x40,// Set VCOMH deselect level
      0xAF   // Display ON
    };
   
    for (uint8_t i = 0; i < sizeof(init_cmds); i++) {
      I2C_Write(SSD1306_I2C_ADDRESS, init_cmds);
    }
}


配置 I2C DMA 传输
为了使用 DMA 传输数据到 SSD1306 显示器,您需要通过 I2C 使用 DMA 模式。以下是一个使用 I2C 和 DMA 传输显示数据的基本框架。
uint8_t I2C_TX_Buffer;// 用于传输的数据缓冲区

void I2C_Write(uint8_t addr, uint8_t data)
{
    uint8_t buf = {0x00, data};// 0x00 表示控制字节
    DMA_Init_Config();
    // 配置 DMA 进行传输
    DMA_Init(DMA1_Channel6, &DMA_InitStruct);// 初始化 DMA1 通道6
    DMA_Cmd(DMA1_Channel6, ENABLE);// 启动 DMA
    // 启动 I2C 传输
    I2C_GenerateSTART(I2C1, ENABLE);
    I2C_Send7bitAddress(I2C1, addr, I2C_Direction_Transmitter);
    I2C_SendData(I2C1, buf);
    while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == RESET);
    I2C_SendData(I2C1, buf);
}

捉虫天师 发表于 2025-2-25 15:00

将数据传输到 SSD1306
void SSD1306_Display(uint8_t* data)
{
    for (int i = 0; i < 8; i++) {// 控制行
      I2C_Write(SSD1306_I2C_ADDRESS, 0xB0 + i);// 设置页面地址(每个页面是 8 行)
      I2C_Write(SSD1306_I2C_ADDRESS, 0x00);// 设置低 4 位列地址
      I2C_Write(SSD1306_I2C_ADDRESS, 0x10);// 设置高 4 位列地址
      // 启动 DMA 传输图像数据
      for (int j = 0; j < 128; j++) {// 设置每行的 128 列
            I2C_TX_Buffer = data;// 填充数据缓冲区
      }
      DMA_Init_Config();
      DMA_Cmd(DMA1_Channel6, ENABLE);// 启动 DMA
    }
}


页: [1]
查看完整版本: 使用STM32F103的DMA功能驱动I2C的SSD1306,分辨率为124*64