IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 【联盛德W806上手笔记】七、I2C模块 -> 正文阅读

[嵌入式]【联盛德W806上手笔记】七、I2C模块

Windows 10 20H2
HLK-W806-V1.0-KIT
WM_SDK_W806_v0.6.0


???????摘自《W806 芯片设计指导书 V1.0》、《W806 MCU 芯片规格书 V2.0》、《WM_W800_寄存器手册 V2.1》

WM_SDK_W806_v0.6.0的库函数

我们打开wm_i2c.h,有如下的函数声明:

函数

HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c);
//用于配置所用I2C的引脚

HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c);
//将初始化之后的I2C引脚恢复成默认的状态–各个寄存器复位时的值

HAL_StatusTypeDef HAL_I2C_Write(I2C_HandleTypeDef *hi2c, uint8_t DevAddress, uint8_t MemAddress, uint8_t *pData, uint16_t Size);
//用于向从器件某地址写入数据

HAL_StatusTypeDef HAL_I2C_Read(I2C_HandleTypeDef *hi2c, uint8_t DevAddress, uint8_t MemAddress, uint8_t *pData, uint16_t Size);
//用于由从器件某地址读取数据

参数

结构体和枚举类型

typedef struct
{
	GPIO_TypeDef *SCL_Port;
	uint32_t SCL_Pin;
	GPIO_TypeDef *SDA_Port;
	uint32_t SDA_Pin;
} I2C_HandleTypeDef;

(看着是不是有点怪

#define I2C_SDA_H(HANDLE)	HAL_GPIO_WritePin(HANDLE->SDA_Port, HANDLE->SDA_Pin, GPIO_PIN_SET)

#define I2C_SDA_L(HANDLE)	HAL_GPIO_WritePin(HANDLE->SDA_Port, HANDLE->SDA_Pin, GPIO_PIN_RESET)

#define I2C_SCL_H(HANDLE)	HAL_GPIO_WritePin(HANDLE->SCL_Port, HANDLE->SCL_Pin, GPIO_PIN_SET)

#define I2C_SCL_L(HANDLE)	HAL_GPIO_WritePin(HANDLE->SCL_Port, HANDLE->SCL_Pin, GPIO_PIN_RESET)

#define I2C_SDA_OUT(HANDLE)	SET_BIT(HANDLE->SDA_Port->DIR, HANDLE->SDA_Pin)

#define I2C_SDA_IN(HANDLE)	CLEAR_BIT(HANDLE->SDA_Port->DIR, HANDLE->SDA_Pin)

#define I2C_SDA_GET(HANDLE)	HAL_GPIO_ReadPin(HANDLE->SDA_Port, HANDLE->SDA_Pin)

应用示例

初始化

I2C_HandleTypeDef hi2c;
//...
static void I2C_Init(void);
//...
static void I2C_Init(void)
{
	hi2c.SCL_Port = GPIOA;
	hi2c.SCL_Pin = GPIO_PIN_1;
	hi2c.SDA_Port = GPIOA;
	hi2c.SDA_Pin = GPIO_PIN_4;

	HAL_I2C_Init(&hi2c);
}

使用

    I2C_Init();
    //...
    HAL_I2C_Write(&hi2c, DEVICE_ADDR, 地址, 数据缓冲区首地址, 数据长度);
    //...
    HAL_I2C_Read(&hi2c, DEVICE_ADDR, 地址, 数据缓冲区首地址, 数据长度)

测试

这里用的测试程序见【51单片机快速入门指南】4.2: SSD1306 OLED屏(0.96寸、1.3寸)的I2C控制详解
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

我们再打开wm_i2c.c:
在这里插入图片描述
可以看到 WM_SDK_W806_v0.6.0 库函数里i2c的实现竟然是模拟i2c
在这里插入图片描述
但在数据手册中是有硬件i2c相关的描述的:

I2C 控制器

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

功能概述

???????I2C 总线是一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。
???????主器件用于启动总线传送数据,并产生时钟以开放传送的器件,此时任何被寻址的器件均被认为是从器件.在总线上主和从、发和收的关系不是恒定的,而取决于此时数据传送方向。如果主机要发送数据给从器件,则主机首先寻址从器件,然后主动发送数据至从器件,最后由主机终止数据传送;如果主机要接收从器件的数据,首先由主器件寻址从器件.然后主机接收从器件发送的数据,最后由主机终止接收过程。在这种情况下.主机负责产生定时时钟和终止数据传送。

主要特性

APB 总线协议标准接口
只可作为主设备控制器使用
I2C 工作速率可配,100KHz~400KHz
多路 GPIO 可复用成 I2C 的通信接口
可快速输出和检测时序信号

功能描述

传输速率选择

???????通过设置寄存器 PRERlo 和寄存器 PRERhi 就可以将 I2C 总线上的数据传输速率配置在 100KHz 到400KHz 之间的任意总线频率整数分频值。

中断及启动停止可控

???????通过设置寄存器 CTR 的 Bit6 允许或者禁止 I2C 控制器产生中断,并且还可以通过设置 Bit7 来随时启动或者停止 I2C 控制器的工作。

快速输出及检测信号

???????通过设置寄存器 CR_SR 的相应位可以使控制器快速输出或者检测总线 START 信号,总线 STOP 信号,总线 ACK 信号,总线 NACK 信号。在主模式下,I2C 接口启动数据传输并生成时钟信号。 一个串行数据传输始终以启动信号开始,以停止信号结束。一旦在总线上生成启动信号,就选择了主设备模式。

寄存器描述

寄存器列表

在这里插入图片描述
在这里插入图片描述

时钟分频寄存器_1

在这里插入图片描述

时钟分频寄存器_2

在这里插入图片描述
在这里插入图片描述

控制寄存器

在这里插入图片描述

数据寄存器

在这里插入图片描述
在这里插入图片描述

收发控制寄存器

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

TXR 读出寄存器

在这里插入图片描述

CR 读出寄存器

在这里插入图片描述

iosetting大佬 维护的wm-sdk-w806

IOsetting的CSDN主页

git clone https://gitee.com/iosetting/wm-sdk-w806.git

可以看到,已有硬件I2C的实现:
在这里插入图片描述

库函数

打开wm_i2c.h,有如下声明:

函数

HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c);
//用于配置I2C接口的引脚、速率、优先级等

HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c);
//将初始化之后的I2C接口恢复成默认的状态–各个寄存器复位时的值

void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c);
//用于启用I2C时钟,选择复用引脚

void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c);
//用于禁用I2C时钟,将对应引脚恢复成默认的状态

HAL_StatusTypeDef HAL_I2C_Write(I2C_HandleTypeDef *hi2c, uint8_t DevAddress, uint8_t MemAddress, uint8_t *pData, uint16_t Size);
//用于向从器件某地址写入数据

HAL_StatusTypeDef HAL_I2C_Read(I2C_HandleTypeDef *hi2c, uint8_t DevAddress, uint8_t MemAddress, uint8_t *pData, uint16_t Size);
//用于由从器件某地址读取数据

参数

结构体和枚举类型

typedef struct __I2C_HandleTypeDef
{
    I2C_TypeDef                 *Instance;      /*!< I2C registers base address               */
    uint32_t                    Frequency;
    HAL_LockTypeDef             Lock;           /*!< Object lock                              */
    __IO uint32_t               ErrorCode;      /*!< I2C Error code                           */
} I2C_HandleTypeDef;

宏参数

#define I2C                             ((I2C_TypeDef *)I2C_BASE)

应用示例

初始化

I2C_HandleTypeDef hi2c;
#define DEVICE_ADDR    0xA0 //八位地址

static void I2C_Init(void);
static void GPIO_Init(void);

//...

static void I2C_Init(void)
{
    hi2c.Instance = I2C;
    hi2c.Frequency = 400000;
    HAL_I2C_Init(&hi2c);
}

static void GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_GPIO_CLK_ENABLE();
    GPIO_InitStruct.Pin = GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    GPIO_InitStruct.Pin = GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

引脚复用

void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{
    __HAL_RCC_I2C_CLK_ENABLE();
    __HAL_AFIO_REMAP_I2C_SCL(GPIOA, GPIO_PIN_1);
    __HAL_AFIO_REMAP_I2C_SDA(GPIOA, GPIO_PIN_4);
}

void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c)
{
    __HAL_RCC_I2C_CLK_DISABLE();
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1);
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4);
}

使用

    GPIO_Init();
    I2C_Init();
    //...
    HAL_I2C_Write(&hi2c, DEVICE_ADDR, 地址, 数据缓冲区首地址, 数据长度);
    //...
    HAL_I2C_Read(&hi2c, DEVICE_ADDR, 地址, 数据缓冲区首地址, 数据长度)

测试

经过一晚上的测试,对于我手头上的这块W806,其硬件I2C的稳定性只能用悲剧来形容:
在测试中,两个引脚互相干扰的程度已经严重影响正常通讯(原因暂时未知)
在这里插入图片描述
即使是使用 iosetting大佬的OLED Demo(见联盛德 HLK-W806 (六): I2C驱动SSD1306 128x64 OLED液晶屏 —— IOsetting),我也只在通讯速率为1MHz下能跑通:
在这里插入图片描述在这里插入图片描述

尽管我已在运行Demo前事先延时5s以跳过电平不稳定阶段:
在这里插入图片描述

但在其他速率下仍难以通讯
400kHz:
在这里插入图片描述
在这里插入图片描述
100kHz:此情况下为完全黑屏
在这里插入图片描述

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-01-25 10:45:17  更:2022-01-25 10:46:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 10:31:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码