#include "iic.h" #include "stm32f10x.h" #include const uint8_t Font6x8[][6] = { // SPACE (0x20) {0x00,0x00,0x00,0x00,0x00,0x00}, // ' ' {0x00,0x00,0x5F,0x00,0x00,0x00}, // '!' {0x00,0x07,0x00,0x07,0x00,0x00}, // '"' {0x14,0x7F,0x14,0x7F,0x14,0x00}, // '#' {0x24,0x2A,0x7F,0x2A,0x12,0x00}, // '$' {0x23,0x13,0x08,0x64,0x62,0x00}, // '%' {0x36,0x49,0x55,0x22,0x50,0x00}, // '&' {0x00,0x05,0x03,0x00,0x00,0x00}, // ''' {0x00,0x1C,0x22,0x41,0x00,0x00}, // '(' {0x00,0x41,0x22,0x1C,0x00,0x00}, // ')' {0x14,0x08,0x3E,0x08,0x14,0x00}, // '*' {0x08,0x08,0x3E,0x08,0x08,0x00}, // '+' {0x00,0x50,0x30,0x00,0x00,0x00}, // ',' {0x08,0x08,0x08,0x08,0x08,0x00}, // '-' {0x00,0x60,0x60,0x00,0x00,0x00}, // '.' {0x20,0x10,0x08,0x04,0x02,0x00}, // '/' {0x3E,0x51,0x49,0x45,0x3E,0x00}, // '0' (0x30) {0x00,0x42,0x7F,0x40,0x00,0x00}, // '1' {0x42,0x61,0x51,0x49,0x46,0x00}, // '2' {0x21,0x41,0x45,0x4B,0x31,0x00}, // '3' {0x18,0x14,0x12,0x7F,0x10,0x00}, // '4' {0x27,0x45,0x45,0x45,0x39,0x00}, // '5' {0x3C,0x4A,0x49,0x49,0x30,0x00}, // '6' {0x01,0x71,0x09,0x05,0x03,0x00}, // '7' {0x36,0x49,0x49,0x49,0x36,0x00}, // '8' {0x06,0x49,0x49,0x29,0x1E,0x00}, // '9' {0x00,0x36,0x36,0x00,0x00,0x00}, // ':' (0x3A) {0x00,0x56,0x36,0x00,0x00,0x00}, // ';' {0x08,0x14,0x22,0x41,0x00,0x00}, // '<' {0x14,0x14,0x14,0x14,0x14,0x00}, // '=' {0x00,0x41,0x22,0x14,0x08,0x00}, // '>' {0x02,0x01,0x51,0x09,0x06,0x00}, // '?' {0x32,0x49,0x79,0x41,0x3E,0x00}, // '@' (0x40) {0x7E,0x11,0x11,0x11,0x7E,0x00}, // 'A' {0x7F,0x49,0x49,0x49,0x36,0x00}, // 'B' {0x3E,0x41,0x41,0x41,0x22,0x00}, // 'C' {0x7F,0x41,0x41,0x22,0x1C,0x00}, // 'D' {0x7F,0x49,0x49,0x49,0x41,0x00}, // 'E' {0x7F,0x09,0x09,0x09,0x01,0x00}, // 'F' {0x3E,0x41,0x49,0x49,0x7A,0x00}, // 'G' {0x7F,0x08,0x08,0x08,0x7F,0x00}, // 'H' {0x00,0x41,0x7F,0x41,0x00,0x00}, // 'I' {0x20,0x40,0x41,0x3F,0x01,0x00}, // 'J' {0x7F,0x08,0x14,0x22,0x41,0x00}, // 'K' {0x7F,0x40,0x40,0x40,0x40,0x00}, // 'L' {0x7F,0x02,0x0C,0x02,0x7F,0x00}, // 'M' {0x7F,0x04,0x08,0x10,0x7F,0x00}, // 'N' {0x3E,0x41,0x41,0x41,0x3E,0x00}, // 'O' {0x7F,0x09,0x09,0x09,0x06,0x00}, // 'P' (0x50) {0x3E,0x41,0x51,0x21,0x5E,0x00}, // 'Q' {0x7F,0x09,0x19,0x29,0x46,0x00}, // 'R' {0x46,0x49,0x49,0x49,0x31,0x00}, // 'S' {0x01,0x01,0x7F,0x01,0x01,0x00}, // 'T' {0x3F,0x40,0x40,0x40,0x3F,0x00}, // 'U' {0x1F,0x20,0x40,0x20,0x1F,0x00}, // 'V' {0x3F,0x40,0x38,0x40,0x3F,0x00}, // 'W' {0x63,0x14,0x08,0x14,0x63,0x00}, // 'X' {0x07,0x08,0x70,0x08,0x07,0x00}, // 'Y' {0x61,0x51,0x49,0x45,0x43,0x00}, // 'Z' {0x00,0x7F,0x41,0x41,0x00,0x00}, // '[' {0x02,0x04,0x08,0x10,0x20,0x00}, // '\' {0x00,0x41,0x41,0x7F,0x00,0x00}, // ']' {0x04,0x02,0x01,0x02,0x04,0x00}, // '^' {0x80,0x80,0x80,0x80,0x80,0x00}, // '_' {0x00,0x03,0x05,0x00,0x00,0x00}, // '`' {0x20,0x54,0x54,0x54,0x78,0x00}, // 'a' (0x61) {0x7F,0x48,0x44,0x44,0x38,0x00}, // 'b' {0x38,0x44,0x44,0x44,0x20,0x00}, // 'c' {0x38,0x44,0x44,0x48,0x7F,0x00}, // 'd' {0x38,0x54,0x54,0x54,0x18,0x00}, // 'e' {0x08,0x7E,0x09,0x01,0x02,0x00}, // 'f' {0x0C,0x52,0x52,0x52,0x3E,0x00}, // 'g' {0x7F,0x08,0x04,0x04,0x78,0x00}, // 'h' {0x00,0x44,0x7D,0x40,0x00,0x00}, // 'i' {0x20,0x40,0x44,0x3D,0x00,0x00}, // 'j' {0x7F,0x10,0x28,0x44,0x00,0x00}, // 'k' {0x00,0x41,0x7F,0x40,0x00,0x00}, // 'l' {0x7C,0x04,0x18,0x04,0x78,0x00}, // 'm' {0x7C,0x08,0x04,0x04,0x78,0x00}, // 'n' {0x38,0x44,0x44,0x44,0x38,0x00}, // 'o' {0x7C,0x14,0x14,0x14,0x08,0x00}, // 'p' (0x70) {0x08,0x14,0x14,0x18,0x7C,0x00}, // 'q' {0x7C,0x08,0x04,0x04,0x08,0x00}, // 'r' {0x48,0x54,0x54,0x54,0x20,0x00}, // 's' {0x04,0x3F,0x44,0x40,0x20,0x00}, // 't' {0x3C,0x40,0x40,0x20,0x7C,0x00}, // 'u' {0x1C,0x20,0x40,0x20,0x1C,0x00}, // 'v' {0x3C,0x40,0x30,0x40,0x3C,0x00}, // 'w' {0x44,0x28,0x10,0x28,0x44,0x00}, // 'x' {0x0C,0x50,0x50,0x50,0x3C,0x00}, // 'y' {0x44,0x64,0x54,0x4C,0x44,0x00}, // 'z' {0x08,0x36,0x41,0x00,0x00,0x00}, // '{' {0x00,0x00,0x7F,0x00,0x00,0x00}, // '|' {0x00,0x41,0x36,0x08,0x00,0x00}, // '}' {0x02,0x01,0x02,0x04,0x02,0x00}, // '~' }; #define OLED_WIDTH 128 #define OLED_HEIGHT 64 // OLED 显存,1bit 表示一个像素(黑白屏) // 128 * 64 / 8 = 1024 字节 uint8_t OLED_GRAM[8][128]; // 8页,每页8行,共64行 #define SDA_PIN GPIO_Pin_8 #define SCL_PIN GPIO_Pin_9 #define I2C_PORT GPIOB #define SDA_HIGH() GPIO_SetBits(I2C_PORT, SDA_PIN) #define SDA_LOW() GPIO_ResetBits(I2C_PORT, SDA_PIN) #define SCL_HIGH() GPIO_SetBits(I2C_PORT, SCL_PIN) #define SCL_LOW() GPIO_ResetBits(I2C_PORT, SCL_PIN) #define READ_SDA() GPIO_ReadInputDataBit(I2C_PORT, SDA_PIN) void delay(){ __NOP(); } void delay_us_simple(uint32_t us) { uint32_t i; while(us--) { for(i = 0; i < 8; i++); // 简单调整这个数字以匹配频率 } } void delay_ms_simple(uint32_t ms) { while(ms--) { delay_us_simple(1000); // 1000 微秒 = 1 毫秒 } } void IIC_GPIO_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = SDA_PIN | SCL_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; // ???? GPIO_Init(I2C_PORT, &GPIO_InitStructure); SDA_HIGH(); SCL_HIGH(); } void IIC_Delay(void) { //delay(1); // 5us 延时,100kHz I2C } void IIC_Start(void) { SDA_HIGH(); SCL_HIGH(); IIC_Delay(); SDA_LOW(); IIC_Delay(); SCL_LOW(); IIC_Delay(); } void IIC_Stop(void) { SDA_LOW(); SCL_HIGH(); IIC_Delay(); SDA_HIGH(); IIC_Delay(); } void IIC_Send_Byte(uint8_t data) { for (int i = 0; i < 8; i++) { if (data & 0x80) SDA_HIGH(); else SDA_LOW(); data <<= 1; IIC_Delay(); SCL_HIGH(); IIC_Delay(); SCL_LOW(); IIC_Delay(); } } uint8_t IIC_Read_Byte(uint8_t ack) { uint8_t data = 0; SDA_HIGH(); // 释放 SDA for (int i = 0; i < 8; i++) { data <<= 1; SCL_HIGH(); IIC_Delay(); if (READ_SDA()) data |= 1; SCL_LOW(); IIC_Delay(); } // 发送 ACK 或 NACK if (ack) SDA_LOW(); else SDA_HIGH(); IIC_Delay(); SCL_HIGH(); IIC_Delay(); SCL_LOW(); SDA_HIGH(); // 释放 SDA return data; } uint8_t IIC_Wait_Ack(void) { uint8_t timeout = 0; SDA_HIGH(); // 释放 SDA IIC_Delay(); SCL_HIGH(); IIC_Delay(); while (READ_SDA()) { timeout++; if (timeout > 250) { IIC_Stop(); return 1; // 失败 } } SCL_LOW(); return 0; // 成功 } void IIC_Ack(void) { SDA_LOW(); IIC_Delay(); SCL_HIGH(); IIC_Delay(); SCL_LOW(); SDA_HIGH(); } void IIC_NAck(void) { SDA_HIGH(); IIC_Delay(); SCL_HIGH(); IIC_Delay(); SCL_LOW(); } void OLED_WriteCommand(uint8_t cmd) { IIC_Start(); IIC_Send_Byte(0x78); // I2C 地址 IIC_Wait_Ack(); IIC_Send_Byte(0x00); // 写命令 IIC_Wait_Ack(); IIC_Send_Byte(cmd); IIC_Wait_Ack(); IIC_Stop(); } void OLED_WriteData(uint8_t data) { IIC_Start(); IIC_Send_Byte(0x78); IIC_Wait_Ack(); IIC_Send_Byte(0x40); // 写数据 IIC_Wait_Ack(); IIC_Send_Byte(data); IIC_Wait_Ack(); IIC_Stop(); } void OLED_Fill(uint8_t data) { for(uint8_t page = 0; page < 8; page++) { OLED_WriteCommand(0xB0 + page); // 页地址 OLED_WriteCommand(0x00); // 列低地址 OLED_WriteCommand(0x10); // 列高地址 for(uint8_t col = 0; col < 128; col++) { OLED_WriteData(data); } } } void OLED_Init(void) { delay_ms_simple(100); // 等待 OLED 上电稳定 OLED_WriteCommand(0xAE); // 关闭显示 OLED_WriteCommand(0x20); // 设置内存地址模式 OLED_WriteCommand(0x10); // 00,水平地址模式; 01,垂直地址模式; 10,页地址模式(默认) OLED_WriteCommand(0xB0); // 设置页起始地址(0~7) OLED_WriteCommand(0xC8); // COM输出扫描方向:从 COM[N-1] 到 COM0 OLED_WriteCommand(0x00); // 设置低列起始地址 OLED_WriteCommand(0x10); // 设置高列起始地址 OLED_WriteCommand(0x40); // 设置起始行地址(0~63) OLED_WriteCommand(0x81); // 对比度设置 OLED_WriteCommand(0xFF); // 对比度值(0x00~0xFF) OLED_WriteCommand(0xA1); // 段重映射:正常(A0),反转(A1) OLED_WriteCommand(0xA6); // 显示正常(A6),反相显示(A7) OLED_WriteCommand(0xA8); // 多路复用率 OLED_WriteCommand(0x3F); // 1/64 duty(0x3F) OLED_WriteCommand(0xA4); // 全局显示开启,输出跟随 RAM 内容 OLED_WriteCommand(0xD3); // 设置显示偏移 OLED_WriteCommand(0x00); // 无偏移 OLED_WriteCommand(0xD5); // 设置显示时钟分频比/振荡器频率 OLED_WriteCommand(0x80); // 推荐值 OLED_WriteCommand(0xD9); // 设置预充电周期 OLED_WriteCommand(0xF1); // 推荐值 OLED_WriteCommand(0xDA); // 设置 COM 引脚配置 OLED_WriteCommand(0x12); OLED_WriteCommand(0xDB); // 设置 VCOMH 电压倍率 OLED_WriteCommand(0x40); // 推荐值 OLED_WriteCommand(0x8D); // 使能电荷泵 OLED_WriteCommand(0x14); // 开启 OLED_WriteCommand(0xAF); // 开启显示 OLED_Fill(0xFF); // 清屏 } void OLED_DrawPixel(uint8_t x, uint8_t y, uint8_t color) { if (x >= OLED_WIDTH || y >= OLED_HEIGHT) return; if (color) OLED_GRAM[y / 8][x] |= (1 << (y % 8)); else OLED_GRAM[y / 8][x] &= ~(1 << (y % 8)); } void OLED_Refresh(void) { for (uint8_t page = 0; page < 8; page++) { OLED_WriteCommand(0xB0 + page); // 设置页地址 OLED_WriteCommand(0x00); // 设置低列地址 OLED_WriteCommand(0x10); // 设置高列地址 for (uint8_t col = 0; col < OLED_WIDTH; col++) { OLED_WriteData(OLED_GRAM[page][col]); } } } void OLED_ShowChar(uint8_t x, uint8_t y, char chr) { if (x > OLED_WIDTH - 6 || y > 7) return; uint8_t c = chr - 32; // ASCII偏移 for (uint8_t i = 0; i < 6; i++) { OLED_GRAM[y][x + i] = Font6x8[c][i]; } } void lcd_show_all_ascii_lowercase() { uint16_t x = 0, y = 0; char ch = 'a'; for (int row = 0; row < 10; row++) { for (int col = 0; col < 16; col++) { OLED_ShowChar(x, y, ch); // 白色 x += 8; ch++; if (ch > 'z') ch = 'a'; // 循环 a-z } x = 0; y += 16; } } void test(){ IIC_GPIO_Init(); OLED_Init(); lcd_show_all_ascii_lowercase(); OLED_Refresh(); while(1){ //OLED_Fill(0xFF); // 清屏 //delay_ms_simple(1000); //OLED_Fill(0x00); //delay_ms_simple(1000); } }