使用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
}
初始化 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);
}
将数据传输到 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]