- void I2C_GPIO_init(void)
- {
- // I2CA pins (SDAA / SCLA)
-
- GPIO_setPinConfig(DEVICE_GPIO_CFG_SDAA);
- GPIO_setDrivingCapability(DEVICE_GPIO_PIN_SDAA,GPIO_DRIVE_LEVEL_VERY_HIGH);
- GPIO_setPadConfig(DEVICE_GPIO_PIN_SDAA, GPIO_PIN_TYPE_PULLUP);
- GPIO_setQualificationMode(DEVICE_GPIO_PIN_SDAA, GPIO_QUAL_ASYNC);
- GPIO_setPinConfig(DEVICE_GPIO_CFG_SCLA);
- GPIO_setDrivingCapability(DEVICE_GPIO_PIN_SCLA,GPIO_DRIVE_LEVEL_VERY_HIGH);
- GPIO_setPadConfig(DEVICE_GPIO_PIN_SCLA, GPIO_PIN_TYPE_PULLUP);
- GPIO_setQualificationMode(DEVICE_GPIO_PIN_SCLA, GPIO_QUAL_ASYNC);
- }
SDA和SCL需要上拉,
3、I2C初始化
- void I2Cinit(void)
- {
- printf("=== I2C OLED初始化 ===\n");
-
- // 1. 禁用模块
- I2C_disableModule(I2C_BASE);
-
- // 2. 基础配置
- I2C_initMaster(I2C_BASE, DEVICE_APBCLK_FREQ, 400000, I2C_DUTYCYCLE_50);
- I2C_setAddressMode(I2C_BASE, I2C_ADDR_MODE_7BITS);
- I2C_setBitCount(I2C_BASE, I2C_BITCOUNT_8);
-
- // 3. FIFO配置(先配置,后使能)
- I2C_setFIFOInterruptLevel(I2C_BASE, I2C_FIFO_TX4, I2C_FIFO_RX4);
- I2C_enableFIFO(I2C_BASE);
-
- // 4. 使能模块
- I2C_enableModule(I2C_BASE);
- }
4、I2C FIFO发送函数
- // 发送函数
- bool I2C_FIFO_Send(uint8_t slaveAddr, uint8_t *buffer, uint16_t length, bool is_command)
- {
- uint32_t base = I2C_BASE;
- uint8_t control_byte = is_command ? 0x00 : 0x40;
-
- // 等待总线空闲
- uint32_t timeout = 10000;
- while (I2C_isBusBusy(base) && timeout--) ;
- if (timeout == 0) return false;
-
- // 配置I2C
- I2C_setSlaveAddress(base, slaveAddr);
-
-
- I2C_setDataCount(base, length + 1);
- I2C_setConfig(base, I2C_MASTER_SEND_MODE);
-
- // 清除状态
- I2C_clearInterruptStatus(base, I2C_INT_STOP_CONDITION);
-
- // 开始传输
- I2C_sendStartCondition(base);
-
- // 发送控制字节
- I2C_putData(base, control_byte);
-
- // 批量发送数据
- uint16_t sent = 0;
- while (sent < length)
- {
- // 检查FIFO空间
- uint8_t space = I2C_FIFO_SIZE - I2C_getTxFIFOStatus(base);
-
- if (space > 0)
- {
- // 一次尽可能多发送
- uint8_t chunk = (length - sent < space) ? (length - sent) : space;
-
- // 使用循环展开提高效率
- uint8_t i = 0;
- while (i < chunk)
- {
- I2C_putData(base, buffer[sent + i]);
- i++;
- }
- sent += chunk;
- }
- }
-
- // 等待传输完成
- timeout = 100;
- while (I2C_isBusBusy(base) && timeout--) ;
-
- if (timeout == 0)
- {
- I2C_sendStopCondition(base);
- return false;
- }
- // 发送STOP
- I2C_sendStopCondition(base);
-
- // 等待STOP完成
- timeout = 100;
- while (!(I2C_getInterruptStatus(base) & I2C_INT_STOP_CONDITION) && timeout--) ;
-
- if (timeout == 0) return false;
-
- I2C_clearInterruptStatus(base, I2C_INT_STOP_CONDITION);
- return true;
- }
5、OLED发送命令和数据函数
- // 发送命令
- static void OLED_SendCommand(uint8_t cmd)
- {
- I2C_FIFO_Send(OLED_I2C_ADDRESS, &cmd, 1, true);
- }
- // 发送数据
- static void OLED_SendData(uint8_t *data, uint16_t length)
- {
- // 分片发送(每次最多发送I2C_FIFO_SIZE字节)
- uint16_t offset = 0;
- while (offset < length)
- {
- uint16_t chunkSize = (length - offset > I2C_FIFO_SIZE) ?
- I2C_FIFO_SIZE : (length - offset);
- I2C_FIFO_Send(OLED_I2C_ADDRESS, &data[offset], chunkSize, false);
- offset += chunkSize;
- }
- }
6、OLED初始化
缓存及初始化参数
- // 显示缓冲区
- uint8_t oled_buffer[OLED_WIDTH * OLED_PAGES] = {0};
- // 初始化序列
- static const uint8_t oled_init_seq[] = {
- OLED_DISPLAY_OFF, // 关闭显示
- OLED_SET_DISPLAY_CLOCK, // 设置时钟分频
- 0x80, // 建议值
- OLED_SET_MULTIPLEX, // 设置复用率
- 0x3F, // 64行
- OLED_SET_DISPLAY_OFFSET, // 设置显示偏移
- 0x00, // 无偏移
- OLED_SET_START_LINE | 0x00,// 设置起始行
- OLED_CHARGE_PUMP, // 电荷泵设置
- 0x14, // 启用电荷泵
- OLED_MEMORY_MODE, // 内存模式
- 0x00, // 水平地址模式
- OLED_SEG_REMAP | 0x01, // 段重映射
- OLED_COM_SCAN_DEC, // 扫描方向
- OLED_SET_COM_PINS, // COM引脚配置
- 0x12, // 序列配置
- OLED_SET_CONTRAST, // 设置对比度
- 0xCF, // 对比度值
- OLED_SET_PRECHARGE, // 预充电周期
- 0xF1, // 建议值
- OLED_SET_VCOM_DETECT, // VCOMH检测器
- 0x40, // 建议值
- OLED_DISPLAY_ON, // 开启显示
- OLED_DEACTIVATE_SCROLL // 关闭滚动
- };
初始化函数
- // 初始化OLED
- void OLED_Init(void)
- {
- // 初始化I2C
-
- I2C_FIFO_Init();
- printf("I2C_FIFO_Init\r\n");
- // 发送初始化序列
- for (uint8_t i = 0; i < sizeof(oled_init_seq); i++)
- {
- OLED_SendCommand(oled_init_seq[i]);
-
- DEVICE_DELAY_US(600);
- }
- printf("OLED_Init\r\n");
- // 清屏
- OLED_Clear();
- OLED_Display();
- }
7、OLED显示相关函数
清屏
- // 清屏
- void OLED_Clear(void)
- {
- memset(oled_buffer, 0, sizeof(oled_buffer));
- }
更新显示
- // 更新显示
- void OLED_Display(void)
- {
-
- uint8_t i,n;
- for(i=0;i<8;i++)
- {
- OLED_SendCommand(0xb0+i); //设置行起始地址
- OLED_SendCommand(0x00); //设置低列起始地址
- OLED_SendCommand(0x10); //设置高列起始地址
- OLED_SendData(oled_buffer+i*128, 128);
- }
-
- }
画点
- // 设置像素点
- void OLED_SetPixel(uint8_t x, uint8_t y, bool on)
- {
- if (x >= OLED_WIDTH || y >= OLED_HEIGHT)
- return;
-
- uint16_t page = y / 8;
- uint8_t bit = y % 8;
-
- if (on)
- {
- oled_buffer[x + page * OLED_WIDTH] |= (1 << bit);
- }
- else
- {
- oled_buffer[x + page * OLED_WIDTH] &= ~(1 << bit);
- }
- }
绘制字符和字符串
- // 绘制字符(6x8字体)
- void OLED_DrawChar(uint8_t x, uint8_t y, char ch)
- {
- // 简单的字体数据(6x8)
- // 6x8 ASCII 字体数据(每个字符6字节)
- static const uint8_t font6x8[95][6] = {
- // 空格 (ASCII 32)
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- // ! (33)
- {0x00, 0x00, 0x5F, 0x00, 0x00, 0x00},
- // " (34)
- {0x00, 0x07, 0x00, 0x07, 0x00, 0x00},
- // # (35)
- {0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00},
- // $ (36)
- {0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00},
- // % (37)
- {0x23, 0x13, 0x08, 0x64, 0x62, 0x00},
- // & (38)
- {0x36, 0x49, 0x55, 0x22, 0x50, 0x00},
- // ' (39)
- {0x00, 0x05, 0x03, 0x00, 0x00, 0x00},
- // ( (40)
- {0x00, 0x1C, 0x22, 0x41, 0x00, 0x00},
- // ) (41)
- {0x00, 0x41, 0x22, 0x1C, 0x00, 0x00},
- // * (42)
- {0x14, 0x08, 0x3E, 0x08, 0x14, 0x00},
- // + (43)
- {0x08, 0x08, 0x3E, 0x08, 0x08, 0x00},
- // , (44)
- {0x00, 0x50, 0x30, 0x00, 0x00, 0x00},
- // - (45)
- {0x08, 0x08, 0x08, 0x08, 0x08, 0x00},
- // . (46)
- {0x00, 0x60, 0x60, 0x00, 0x00, 0x00},
- // / (47)
- {0x20, 0x10, 0x08, 0x04, 0x02, 0x00},
- // 0 (48)
- {0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00},
- // 1 (49)
- {0x00, 0x42, 0x7F, 0x40, 0x00, 0x00},
- // 2 (50)
- {0x42, 0x61, 0x51, 0x49, 0x46, 0x00},
- // 3 (51)
- {0x21, 0x41, 0x45, 0x4B, 0x31, 0x00},
- // 4 (52)
- {0x18, 0x14, 0x12, 0x7F, 0x10, 0x00},
- // 5 (53)
- {0x27, 0x45, 0x45, 0x45, 0x39, 0x00},
- // 6 (54)
- {0x3C, 0x4A, 0x49, 0x49, 0x30, 0x00},
- // 7 (55)
- {0x01, 0x71, 0x09, 0x05, 0x03, 0x00},
- // 8 (56)
- {0x36, 0x49, 0x49, 0x49, 0x36, 0x00},
- // 9 (57)
- {0x06, 0x49, 0x49, 0x29, 0x1E, 0x00},
- // : (58)
- {0x00, 0x36, 0x36, 0x00, 0x00, 0x00},
- // ; (59)
- {0x00, 0x56, 0x36, 0x00, 0x00, 0x00},
- // < (60)
- {0x08, 0x14, 0x22, 0x41, 0x00, 0x00},
- // = (61)
- {0x14, 0x14, 0x14, 0x14, 0x14, 0x00},
- // > (62)
- {0x00, 0x41, 0x22, 0x14, 0x08, 0x00},
- // ? (63)
- {0x02, 0x01, 0x51, 0x09, 0x06, 0x00},
- // [url=/u/]@[/url] (64)
- {0x32, 0x49, 0x79, 0x41, 0x3E, 0x00},
- // A (65)
- {0x7E, 0x11, 0x11, 0x11, 0x7E, 0x00},
- // B (66)
- {0x7F, 0x49, 0x49, 0x49, 0x36, 0x00},
- // C (67)
- {0x3E, 0x41, 0x41, 0x41, 0x22, 0x00},
- // D (68)
- {0x7F, 0x41, 0x41, 0x22, 0x1C, 0x00},
- // E (69)
- {0x7F, 0x49, 0x49, 0x49, 0x41, 0x00},
- // F (70)
- {0x7F, 0x09, 0x09, 0x09, 0x01, 0x00},
- // G (71)
- {0x3E, 0x41, 0x49, 0x49, 0x7A, 0x00},
- // H (72)
- {0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00},
- // I (73)
- {0x00, 0x41, 0x7F, 0x41, 0x00, 0x00},
- // J (74)
- {0x20, 0x40, 0x41, 0x3F, 0x01, 0x00},
- // K (75)
- {0x7F, 0x08, 0x14, 0x22, 0x41, 0x00},
- // L (76)
- {0x7F, 0x40, 0x40, 0x40, 0x40, 0x00},
- // M (77)
- {0x7F, 0x02, 0x0C, 0x02, 0x7F, 0x00},
- // N (78)
- {0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00},
- // O (79)
- {0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00},
- // P (80)
- {0x7F, 0x09, 0x09, 0x09, 0x06, 0x00},
- // Q (81)
- {0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00},
- // R (82)
- {0x7F, 0x09, 0x19, 0x29, 0x46, 0x00},
- // S (83)
- {0x46, 0x49, 0x49, 0x49, 0x31, 0x00},
- // T (84)
- {0x01, 0x01, 0x7F, 0x01, 0x01, 0x00},
- // U (85)
- {0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00},
- // V (86)
- {0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00},
- // W (87)
- {0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00},
- // X (88)
- {0x63, 0x14, 0x08, 0x14, 0x63, 0x00},
- // Y (89)
- {0x07, 0x08, 0x70, 0x08, 0x07, 0x00},
- // Z (90)
- {0x61, 0x51, 0x49, 0x45, 0x43, 0x00},
- // [ (91)
- {0x00, 0x7F, 0x41, 0x41, 0x00, 0x00},
- // \ (92)
- {0x02, 0x04, 0x08, 0x10, 0x20, 0x00},
- // ] (93)
- {0x00, 0x41, 0x41, 0x7F, 0x00, 0x00},
- // ^ (94)
- {0x04, 0x02, 0x01, 0x02, 0x04, 0x00},
- // _ (95)
- {0x40, 0x40, 0x40, 0x40, 0x40, 0x00},
- // ` (96)
- {0x00, 0x01, 0x02, 0x04, 0x00, 0x00},
- // a (97)
- {0x20, 0x54, 0x54, 0x54, 0x78, 0x00},
- // b (98)
- {0x7F, 0x48, 0x44, 0x44, 0x38, 0x00},
- // c (99)
- {0x38, 0x44, 0x44, 0x44, 0x20, 0x00},
- // d (100)
- {0x38, 0x44, 0x44, 0x48, 0x7F, 0x00},
- // e (101)
- {0x38, 0x54, 0x54, 0x54, 0x18, 0x00},
- // f (102)
- {0x08, 0x7E, 0x09, 0x01, 0x02, 0x00},
- // g (103)
- {0x0C, 0x52, 0x52, 0x52, 0x3E, 0x00},
- // h (104)
- {0x7F, 0x08, 0x04, 0x04, 0x78, 0x00},
- // i (105)
- {0x00, 0x44, 0x7D, 0x40, 0x00, 0x00},
- // j (106)
- {0x20, 0x40, 0x44, 0x3D, 0x00, 0x00},
- // k (107)
- {0x7F, 0x10, 0x28, 0x44, 0x00, 0x00},
- // l (108)
- {0x00, 0x41, 0x7F, 0x40, 0x00, 0x00},
- // m (109)
- {0x7C, 0x04, 0x18, 0x04, 0x78, 0x00},
- // n (110)
- {0x7C, 0x08, 0x04, 0x04, 0x78, 0x00},
- // o (111)
- {0x38, 0x44, 0x44, 0x44, 0x38, 0x00},
- // p (112)
- {0x7C, 0x14, 0x14, 0x14, 0x08, 0x00},
- // q (113)
- {0x08, 0x14, 0x14, 0x18, 0x7C, 0x00},
- // r (114)
- {0x7C, 0x08, 0x04, 0x04, 0x08, 0x00},
- // s (115)
- {0x48, 0x54, 0x54, 0x54, 0x20, 0x00},
- // t (116)
- {0x04, 0x3F, 0x44, 0x40, 0x20, 0x00},
- // u (117)
- {0x3C, 0x40, 0x40, 0x20, 0x7C, 0x00},
- // v (118)
- {0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00},
- // w (119)
- {0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00},
- // x (120)
- {0x44, 0x28, 0x10, 0x28, 0x44, 0x00},
- // y (121)
- {0x0C, 0x50, 0x50, 0x50, 0x3C, 0x00},
- // z (122)
- {0x44, 0x64, 0x54, 0x4C, 0x44, 0x00},
- // { (123)
- {0x00, 0x08, 0x36, 0x41, 0x00, 0x00},
- // | (124)
- {0x00, 0x00, 0x7F, 0x00, 0x00, 0x00},
- // } (125)
- {0x00, 0x41, 0x36, 0x08, 0x00, 0x00},
- // ~ (126)
- {0x10, 0x08, 0x08, 0x10, 0x08, 0x00}
- };
-
- if (ch < 32 || ch > 126) return;
-
- const uint8_t *charData = font6x8[ch - 32];
-
- for (uint8_t i = 0; i < 6; i++)
- {
- if (x + i < OLED_WIDTH)
- {
- oled_buffer[(x + i) + (y / 8) * OLED_WIDTH] = charData[i];
- }
- }
- }
- // 绘制字符串
- void OLED_DrawString(uint8_t x, uint8_t y, const char *str)
- {
- uint8_t currentX = x;
- while (*str)
- {
- OLED_DrawChar(currentX, y, *str++);
- currentX += 6; // 字符宽度+间距
- if (currentX >= OLED_WIDTH - 6)
- break;
- }
- }
三、运行验证
- OLED_DrawString(0, 0, "Hello G32R501!");
- OLED_DrawString(0, 16, "FIFO I2C Demo");
- OLED_DrawString(0, 32, "128x64 Display");
- OLED_Display();