根据这段代码帮我写一下OLED运行的流程图#ifndef __OLED_I2C_H #define __OLED_I2C_H #include "stm32f10x.h" #include "SysTick.h" #define OLED_ADDRESS 0x78 //默认0x78 //定义IIC总线连接的GPIO端口, 用户只需要修改下面代码即可任意改变SCL和SDA的引脚 #define OLED_SCL PBout(6) //SCL引脚 #define OLED_SDA PBout(7) //SDA引脚 #define OLED_SCL_GPIO_PORT GPIOB /* GPIO端口 */ #define OLED_SCL_RCC RCC_APB2Periph_GPIOB /* GPIO端口时钟 */ #define OLED_SCL_PIN GPIO_Pin_6 /* 连接到SCL时钟线的GPIO */ #define OLED_SDA_GPIO_PORT GPIOB /* GPIO端口 */ #define OLED_SDA_RCC RCC_APB2Periph_GPIOB /* GPIO端口时钟 */ #define OLED_SDA_PIN GPIO_Pin_7 /* 连接到SDA数据线的GPIO */ #define OLED_IIC_SDA_READ() GPIO_ReadInputDataBit(OLED_SDA_GPIO_PORT, OLED_SDA_PIN) /* 读SDA口线状态 */ extern unsigned int HZ; unsigned int GB16_NUM(void); void OLED_IIC_GPIO_Config(void); void OLED_IIC_Start(void); void OLED_IIC_Stop(void); uint8_t OLED_IIC_WaitAck(void); void OLED_Write_IIC_Byte(uint8_t _ucByte); void OLED_Write_IIC_Command(u8 IIC_Command); void OLED_Fill(u8 fill_Data); void OLED_Set_Pos(u8 x, u8 y); void OLED_ON(void); void OLED_OFF(void); void OLED_Clear(void); void OLED_ShowChar(u8 x, u8 y, u8 chr); void OLED_ShowNum(u8 x, u8 y, u32 num, u8 len,u8 mode); void OLED_ShowCH(u8 x, u8 y,u8 *chs); void OLED_Init(void); void OLED_DrawBMP(u8 x0,u8 y0,u8 x1,u8 y1,u8 BMP[]); void OLED_ShowStr6x8(char x,char y, char ch[]); #endif 和#include "OLED_I2C.h" #include "SysTick.h" #include "codetab.h" #include "string.h" unsigned int HZ=0; //返回GB16字库里汉字个数 unsigned int GB16_NUM(void) { unsigned int HZ_NUM; unsigned char *PT; PT = hz_index; while(*PT++ != '\0') { HZ_NUM++; } return HZ_NUM/2; } void OLED_IIC_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(OLED_SCL_RCC|OLED_SDA_RCC, ENABLE); /* 打开GPIO时钟 */ GPIO_InitStructure.GPIO_Pin = OLED_SCL_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; /* 开漏输出 */ GPIO_Init(OLED_SCL_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = OLED_SDA_PIN; GPIO_Init(OLED_SDA_GPIO_PORT, &GPIO_InitStructure); /* 给一个停止信号, 复位IIC总线上的所有设备到待机模式 */ OLED_IIC_Stop(); } static void OLED_IIC_Delay(void) { uint8_t i; /* 下面的时间是通过逻辑分析仪测试得到的。 工作条件:CPU主频72MHz ,MDK编译环境,1级优化 循环次数为10时,SCL频率 = 205KHz 循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us 循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us */ for (i = 0; i < 10; i++); } /* ********************************************************************************************************* * 函 数 名: IIC_Start * 功能说明: CPU发起IIC总线启动信号 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void OLED_IIC_Start(void) { /* 当SCL高电平时,SDA出现一个下跳沿表示IIC总线启动信号 */ OLED_SDA=1; OLED_SCL=1; OLED_IIC_Delay(); OLED_SDA=0; OLED_IIC_Delay(); OLED_SCL=0; OLED_IIC_Delay(); } /* ********************************************************************************************************* * 函 数 名: IIC_Start * 功能说明: CPU发起IIC总线停止信号 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void OLED_IIC_Stop(void) { /* 当SCL高电平时,SDA出现一个上跳沿表示IIC总线停止信号 */ OLED_SDA=0; OLED_SCL=1; OLED_IIC_Delay(); OLED_SDA=1; } /* ********************************************************************************************************* * 函 数 名: IIC_WaitAck * 功能说明: CPU产生一个时钟,并读取器件的ACK应答信号 * 形 参:无 * 返 回 值: 返回0表示正确应答,1表示无器件响应 ********************************************************************************************************* */ uint8_t OLED_IIC_WaitAck(void) { uint8_t re; OLED_SDA=1; /* CPU释放SDA总线 */ OLED_IIC_Delay(); OLED_SCL=1; /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */ OLED_IIC_Delay(); if (OLED_IIC_SDA_READ()) /* CPU读取SDA口线状态 */ { re = 1; } else { re = 0; } OLED_SCL=0; OLED_IIC_Delay(); return re; } //向IIC总线写数据 void OLED_Write_IIC_Byte(uint8_t _ucByte) { uint8_t i; /* 先发送字节的高位bit7 */ for (i = 0; i < 8; i++) { if (_ucByte & 0x80) { OLED_SDA=1; } else { OLED_SDA=0; } OLED_IIC_Delay(); OLED_SCL=1; OLED_IIC_Delay(); OLED_SCL=0; if (i == 7) { OLED_SDA=1; // 释放总线 } _ucByte <<= 1; /* 左移一个bit */ OLED_IIC_Delay(); } } //写命令 void OLED_Write_IIC_Command(u8 IIC_Command) { OLED_IIC_Start(); OLED_Write_IIC_Byte(OLED_ADDRESS);//OLED地址 OLED_IIC_WaitAck(); OLED_Write_IIC_Byte(0x00);//寄存器地址 OLED_IIC_WaitAck(); OLED_Write_IIC_Byte(IIC_Command); OLED_IIC_WaitAck(); OLED_IIC_Stop(); } //写数据 void OLED_Write_IIC_Data(u8 IIC_Data) { OLED_IIC_Start(); OLED_Write_IIC_Byte(OLED_ADDRESS);//OLED地址 OLED_IIC_WaitAck(); OLED_Write_IIC_Byte(0x40);//寄存器地址 OLED_IIC_WaitAck(); OLED_Write_IIC_Byte(IIC_Data); OLED_IIC_WaitAck(); OLED_IIC_Stop(); } //OLED全屏填充 void OLED_Fill(u8 fill_Data) { u8 m,n; for(m=0;m<8;m++) { OLED_Write_IIC_Command(0xb0+m); //page0-page1 OLED_Write_IIC_Command(0x00); //low column start address OLED_Write_IIC_Command(0x10); //high column start address for(n=0;n<130;n++) { OLED_Write_IIC_Data(fill_Data); } } } //设置起始点坐标 void OLED_Set_Pos(u8 x, u8 y) { OLED_Write_IIC_Command(0xb0+y); OLED_Write_IIC_Command((((x+2)&0xf0)>>4)|0x10); OLED_Write_IIC_Command(((x+2)&0x0f)|0x01); } //将OLED从休眠中唤醒 void OLED_ON(void) { OLED_Write_IIC_Command(0X8D); //设置电荷泵 OLED_Write_IIC_Command(0X14); //开启电荷泵 OLED_Write_IIC_Command(0XAF); //OLED唤醒 } //让OLED休眠 -- 休眠模式下,OLED功耗不到10uA void OLED_OFF(void) { OLED_Write_IIC_Command(0X8D); //设置电荷泵 OLED_Write_IIC_Command(0X10); //关闭电荷泵 OLED_Write_IIC_Command(0XAE); //OLED休眠 } //清屏 void OLED_Clear(void) { OLED_Fill(0x00); } //在指定位置显示一个字符,包括部分字符 //x:0~127 //y:0~63 void OLED_ShowChar(u8 x, u8 y, u8 chr) { u8 c = 0, i = 0; c = chr - ' '; //得到偏移后的值 if(x > 130 - 1) { x = 0; y = y + 2; } OLED_Set_Pos(x, y); for(i = 0; i < 8; i++) OLED_Write_IIC_Data(zf[c * 16 + i]); OLED_Set_Pos(x, y + 1); for(i = 0; i < 8; i++) OLED_Write_IIC_Data(zf[c * 16 + i + 8]); } //m^n函数 u32 oled_pow(u8 m, u8 n) { u32 result = 1; while(n--)result *= m; return result; } //显示个数字 //x,y :起点坐标 //len :数字的位数 //num:数值(0~4294967295); //mode: 为1:显示0 为0:显示空格 void OLED_ShowNum(u8 x, u8 y, u32 num, u8 len,u8 mode) { u8 t, temp; for(t = 0; t < len; t++) { temp = (num / oled_pow(10, len - t - 1)) % 10; if(temp == 0) { if(mode) OLED_ShowChar(x + 8*t, y, '0'); else OLED_ShowChar(x + 8*t, y, ' '); continue; } else OLED_ShowChar(x + 8*t, y, temp + '0'); } } //显示中英文字符 void OLED_ShowCH(u8 x, u8 y,u8 *chs) { u32 i=0; u32 j; char* m; while (*chs != '\0') { if (*chs > 0xa0) //汉字内码都是大于0xa0 { for (i=0 ;i < HZ;i++) { if(x>112) { x=0; y=y+2; } if ((*chs == hz_index[i*2]) && (*(chs+1) == hz_index[i*2+1])) { OLED_Set_Pos(x, y); for(j=0;j<16;j++) OLED_Write_IIC_Data(hz[i*32+j]); OLED_Set_Pos(x,y+1); for(j=0;j<16;j++) OLED_Write_IIC_Data(hz[i*32+j+16]); x +=16; break; } } chs+=2; } else { if(x>122) { x=0; y=y+2; } m=strchr(zf_index,*chs); if (m!=NULL) { OLED_Set_Pos(x, y); for(j = 0; j < 8; j++) OLED_Write_IIC_Data(zf[((u8)*m-' ') * 16 + j]); OLED_Set_Pos(x, y + 1); for(j = 0; j < 8; j++) OLED_Write_IIC_Data(zf[((u8)*m-' ') * 16 + j + 8]); x += 8; } chs++; } } } void OLED_ShowStr6x8(char x,char y, char ch[]) { char TextSize=1; char c = 0,i = 0,j = 0; switch(TextSize) { case 1: { while(ch[j] != '\0') { c = ch[j] - 32; if(x > 126) { x = 0; y++; } OLED_Set_Pos(x,y); for(i=0;i<6;i++) OLED_Write_IIC_Data(F6x8[c][i]); x += 6; j++; } }break; } } //初始化SSD1306 void OLED_Init(void) { HZ= GB16_NUM(); OLED_IIC_GPIO_Config(); OLED_Write_IIC_Command(0xAE); //--display off OLED_Write_IIC_Command(0x00); //---set low column address OLED_Write_IIC_Command(0x10); //---set high column address OLED_Write_IIC_Command(0x40); //--set start line address OLED_Write_IIC_Command(0xB0); //--set page address OLED_Write_IIC_Command(0x81); // contract control OLED_Write_IIC_Command(0xFF); //--128 OLED_Write_IIC_Command(0xA1); //set segment remap OLED_Write_IIC_Command(0xA6); //--normal / reverse OLED_Write_IIC_Command(0xA8); //--set multiplex ratio(1 to 64) OLED_Write_IIC_Command(0x3F); //--1/32 duty OLED_Write_IIC_Command(0xC8); //Com scan direction OLED_Write_IIC_Command(0xD3); //-set display offset OLED_Write_IIC_Command(0x00); // OLED_Write_IIC_Command(0xD5); //set osc division OLED_Write_IIC_Command(0x80); // OLED_Write_IIC_Command(0xD8); //set area color mode off OLED_Write_IIC_Command(0x05); // OLED_Write_IIC_Command(0xD9); //Set Pre-Charge Period OLED_Write_IIC_Command(0xF1); // OLED_Write_IIC_Command(0xDA); //set com pin configuartion OLED_Write_IIC_Command(0x12); // OLED_Write_IIC_Command(0xDB); //set Vcomh OLED_Write_IIC_Command(0x30); // OLED_Write_IIC_Command(0x8D); //set charge pump enable OLED_Write_IIC_Command(0x14); // OLED_Write_IIC_Command(0xAF); //--turn on oled panel } // x0,y0 -- 起始点坐标(x0:0~127, y0:0~7); x1,y1 -- 起点对角线(结束点)的坐标(x1:1~128,y1:1~8) void OLED_DrawBMP(u8 x0,u8 y0,u8 x1,u8 y1,u8 BMP[]) { u16 j=0; u8 x,y; if(y1%8==0) y = y1/8; else y = y1/8 + 1; for(y=y0;y<y1;y++) { OLED_Set_Pos(x0,y); for(x=x0;x<x1;x++) { OLED_Write_IIC_Data(BMP[j++]); } } }
时间: 2025-06-10 16:38:15 浏览: 19
### OLED运行流程图的绘制方法
为了根据给定的代码实现细节绘制OLED运行流程图,需要明确OLED与I2C通信协议的交互过程。以下是基于提供的引用内容和代码实现细节的详细说明。
#### 1. 初始化阶段
在OLED运行流程中,初始化是关键步骤之一。通过`OLED_IIC_Config`函数完成I2C配置[^5],包括以下操作:
- 启用APB1外设时钟。
- 配置GPIO引脚用于I2C通信。
- 设置I2C的应答模式为启用状态。
- 指定7位地址模式作为寻址方式。
- 配置通信速率为100kHz。
- 设置SCL时钟线的占空比为2:1。
- 确保I2C工作在标准模式下。
```c
void OLED_IIC_Config(void) {
I2C_Config_T I2C_ConfigStruct;
RCM_EnableAPB1PeriphClock(OLED_IIC_CLOCK);
OLED_GPIO_Config();
I2C_ConfigStruct.ack = I2C_ACK_ENABLE;
I2C_ConfigStruct.ackAddress = I2C_ACK_ADDRESS_7BIT;
I2C_ConfigStruct.clockSpeed = 100000;
I2C_ConfigStruct.dutyCycle = I2C_DUTYCYCLE_2;
I2C_ConfigStruct.mode = I2C_MODE_I2C;
I2C_Config(OLED_IIC, &I2C_ConfigStruct);
I2C_Enable(OLED_IIC);
}
```
#### 2. 数据发送阶段
初始化完成后,通过I2C协议向OLED屏幕发送数据。`SSD1306_ADDR`代表OLED屏幕的I2C地址[^1],使用`Wire.write()`函数发送命令字节到OLED屏幕。具体流程如下:
- 主设备(MCU)启动I2C通信。
- 发送OLED设备地址。
- 根据数据类型选择发送命令或数据。
- 完成传输后停止I2C通信。
#### 3. 显示更新阶段
显示更新阶段涉及将缓冲区中的数据刷新到OLED屏幕。此过程通常包括:
- 清除屏幕内容(可选)。
- 将字符、图形等数据写入缓冲区。
- 调用显示刷新函数将缓冲区数据同步到OLED屏幕。
#### 流程图描述
根据上述分析,OLED运行流程图可以分为以下主要步骤:
1. **初始化**:配置I2C参数并启用相关外设。
2. **数据发送**:通过I2C协议向OLED发送命令或数据。
3. **显示更新**:将缓冲区数据刷新到OLED屏幕。
以下是流程图的Markdown表示:
```mermaid
flowchart TD
A[开始] --> B[初始化I2C]
B --> C{是否完成初始化?}
C --是--> D[配置GPIO引脚]
D --> E[设置I2C参数]
E --> F[启用I2C外设]
F --> G[数据发送]
G --> H{是否为命令?}
H --是--> I[发送命令]
H --否--> J[发送数据]
J --> K[显示更新]
K --> L[结束]
```
### 注意事项
- 在实际绘制流程图时,可根据具体需求扩展细节,例如添加错误处理逻辑或优化步骤。
- 流程图应清晰展示各阶段之间的逻辑关系,便于理解OLED运行机制。
阅读全文
相关推荐








