一、I2C程序层次
1.1 设备间的通信方式
- UART(异步 全双工)& 1.1.2 I2C(同步 半双工)
| UART串口 |
I2C 协议 |
 |
 |
1.2 硬件原理图
https:
| OLED实物图 |
OLED原理图 |
 |
 |
1.3 硬件框图和软件层次
| 硬件框图 |
 |
|
| 软件层次 |
 |
|
二、I2C 协议
2.1 硬件连接(一主多从)
| I2C在硬件上的接发 |
 |
|
2.2 数据传输 类比
| I2C 数据传输类比图 |
 |
|
2.3 IIC 传输数据的格式
| IIC 传输数据的格式 |
|
 |
|
|
|
| I2C 总线的信号类型 |
 |
|
| 芯片手册上的图 |
 |
- IIC 总线的 SDA 和 SCL 通常采用开漏输出结构(Open-Drain)。设备只能主动拉低总线,不能主动输出高电平;当需要输出高电平时,设备释放总线,由上拉电阻将信号线拉高。这样可以避免多个设备同时驱动总线时产生电平冲突。详情: 【STM32】HAL库的本质 及 芯片内部GPIO模块细节
| 输出 0 (驱动) |
输出 1 (释放) |
| GPIO 主动拉低 SDA/SCL |
GPIO 变成高阻态,由上拉电阻拉高(由外部电路决定) |
- 主从设备,任意一方 觉得要等一等,表示我这边还没准备好,都可以把 SCL (时钟)拉低;任意一方拉低,结果都是 0;
三、IIC HAL 编程
| IIC_读写 |
 |
|
3.1 STM32CubeMX 配置
- I2C1 ==> Parameter Settings ==> GPIO Settings
3.2 查询方式
3.2.1 Master 模式函数
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
uint8_t *pData, uint16_t Size, uint32_t Timeout);
| 参数 |
说明 |
| I2C_HandleTypeDef *hi2c |
使用哪个 I2C 控制器 |
| uint16_t DevAddress |
设备地址,需要把 7 位地址左移 1 位 |
| uint8_t *pData |
数据 buffer |
| uint16_t Size |
数据个数 |
| uint32_t Timeout |
超时时间,单位是 Tick,一般是 1ms |
| 返回值 |
HAL_OK:成功HAL_ERROR:错误HAL_BUSY:总线忙HAL_TIMEOUT:超时 |
3.2.2 MEM 模式函数
HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t
MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t
MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);
| 参数 |
说明 |
| I2C_HandleTypeDef *hi2c |
使用哪个 I2C 控制器 |
| uint16_t DevAddress |
设备地址,需要把 7 位地址左移 1 位 |
| uint16_t MemAddress |
存储地址, 即 I2C 设备上的寄存器地址或存储地址 |
| uint16_t MemAddSize |
存储地址的大小,有 2 种取值: I2C_MEMADD_SIZE_8BIT:存储地址为 1 字节,就是 MemAddress 的低字节I2C_MEMADD_SIZE_16BIT:存储地址为 2 字节,先发送 MemAddress 的高字节,再发送低字节 |
| uint8_t *pData |
数据 buffer |
| uint16_t Size |
数据个数 |
| uint32_t Timeout |
超时时间,单位是 Tick,一般是 1ms |
| 返回值 |
HAL_OK:成功HAL_ERROR:错误HAL_BUSY:总线忙HAL_TIMEOUT:超时 |
3.3 中断方式
3.3.1 Master 模式函数
HAL_StatusTypeDef HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_I2C_Master_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
uint8_t *pData, uint16_t Size);
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
| 参数 |
说明 |
| I2C_HandleTypeDef *hi2c |
使用哪个 I2C 控制器 |
| uint16_t DevAddress |
设备地址,需要把 7 位地址左移 1 位 |
| uint8_t *pData |
数据 buffer |
| uint16_t Size |
数据个数 |
| 返回值 |
HAL_OK:成功HAL_BUSY:总线忙 |
3.3.2 MEM 模式函数
HAL_StatusTypeDef HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t
MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size);
void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
| 参数 |
说明 |
| I2C_HandleTypeDef *hi2c |
使用哪个 I2C 控制器 |
| uint16_t DevAddress |
设备地址,需要把 7 位地址左移 1 位 |
| uint16_t MemAddress |
存储地址, 即 I2C 设备上的寄存器地址或存储地址 |
| uint16_t MemAddSize |
存储地址的大小,有 2 种取值: I2C_MEMADD_SIZE_8BIT:存储地址为 1 字节,就是 MemAddress 的低字节I2C_MEMADD_SIZE_16BIT:存储地址为 2 字节,先发送 MemAddress 的高字节,再发送低字节 |
| uint8_t *pData |
数据 buffer |
| uint16_t Size |
数据个数 |
| 返回值 |
HAL_OK:成功HAL_BUSY:总线忙 |
3.3.3 DMA 模式
四、OLED 操作原理
4.1 SOC控制OLED原理框架
| SOC控制OLED原理框架 |
 |
|
4.1.1 如何分辨 cmd /data?
| 分辨 cmd / data |
 |
|
4.1.2 显存和像素的关系
| 像素点_显存(GDDRAM)大小 |
显存和像素的关系 |
 |
 |
4.2 自动设置行列 ==> 地址模式
五、在OLED上显示汉字
5.1 取模软件使用
//软件地址
通过网盘分享的文件:PCtoLCD2002.zip
链接: https://pan.baidu.com/s/1eORhBJW78vXzYZH6XJcWew?pwd=wjyf 提取码: wjyf
| 取模软件_PCtoLCD2022完美版 |
 |
|
坤(0) 坤(1)
{0x20,0x20,0x20,0xFF,0x20,0x20,0x00,0xF8,0x88,0x88,0xFF,0x88,0x88,0xF8,0x00,0x00},
{0x10,0x30,0x10,0x0F,0x08,0x08,0x00,0x1F,0x08,0x08,0xFF,0x08,0x08,0x1F,0x00,0x00},
{0x20,0x20,0x20,0xFF,0x20,0x20,0x00,0xF8,0x88,0x88,0xFF,0x88,0x88,0xF8,0x00,0x00},
{0x10,0x30,0x10,0x0F,0x08,0x08,0x00,0x1F,0x08,0x08,0xFF,0x08,0x08,0x1F,0x00,0x00},
5.2 完整程序
通过网盘分享的文件:i2c_chinese.7z
链接: https:
5.3 部分程序
void OLED_PrintChinese(uint8_t x, uint8_t y)
{
extern uint8_t g_chinese_fonts[5][32];
uint8_t page = y;
uint8_t col = x*8;
if (y > 7 || x > 15)
return;
int i;
for (i = 0; i < sizeof(g_chinese_fonts)/sizeof(g_chinese_fonts[0]); i++)
{
OLED_SetPosition(page, col);
OLED_WriteNBytes((uint8_t*)&g_chinese_fonts[i][0], 16);
OLED_SetPosition(page+1, col);
OLED_WriteNBytes((uint8_t*)&g_chinese_fonts[i][16], 16);
col += 16;
}
}
#include <stdint.h>
uint8_t g_chinese_fonts[2][32] = {
{0x20,0x20,0x20,0xFF,0x20,0x20,0x00,0xF8,0x88,0x88,0xFF,0x88,0x88,0xF8,0x00,0x00,
0x10,0x30,0x10,0x0F,0x08,0x08,0x00,0x1F,0x08,0x08,0xFF,0x08,0x08,0x1F,0x00,0x00},
{0x20,0x20,0x20,0xFF,0x20,0x20,0x00,0xF8,0x88,0x88,0xFF,0x88,0x88,0xF8,0x00,0x00,
0x10,0x30,0x10,0x0F,0x08,0x08,0x00,0x1F,0x08,0x08,0xFF,0x08,0x08,0x1F,0x00,0x00},
};
5.4 OLED显示 结果
| 显示结果 |
 |
欢迎大家一起交流讨论!
所有评论(0)