Files
UART_TEST_TOOL/DEV/iic.c
2025-07-24 17:16:22 +08:00

467 lines
11 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "iic.h"
#include "stm32f10x.h"
#include <stdint.h>
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 duty0x3F
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);
}
}