关键芯片都驱动,且测试成功

This commit is contained in:
2026-07-18 16:09:06 +08:00
parent 3466c4c062
commit fe107ea9af
42 changed files with 16193 additions and 501 deletions

File diff suppressed because one or more lines are too long

View File

@@ -2,14 +2,44 @@
## 项目概述
STM32F407ZGTx (Cortex-M4 FPU) 基础固件项目,集成 CH395F 以太网控制器 SPI 驱动CH395F 自带 MAC+PHY 及 TCP/IP 协议栈固件)
STM32F407ZGTx (Cortex-M4 FPU) 基础固件项目,集成 CH395F 以太网控制器 SPI 驱动、GD5F2GQ5UE SPI NAND Flash 存储(含 FlashDB KVDB/TSDB 数据库)和 TPAFE5160 16位8通道同步采样 ADC 并行接口驱动
## 目录结构
```
STM32F4-Base/
├── Src/ # CubeMX 生成的外设初始化 + main
├── Inc/ # CubeMX 生成的头文件
├── Drivers/
│ ├── BSP/
│ │ ├── CH395F/ # CH395F 以太网芯片驱动(手写)
│ │ ├── GD5F2GQ5UE/ # GD5F2GQ5UE NAND Flash 驱动(手写)
│ │ │ ├── gd5f2gq5ue.h/c # 底层 SPI 驱动
│ │ │ ├── fal_flash_gd5f2gq5ue.c # FAL 设备适配层
│ │ │ ├── fal_cfg.h # FAL 设备表 + 分区表
│ │ │ └── fdb_cfg.h # FlashDB 功能配置
│ │ └── TPAFE5160/ # TPAFE5160 ADC 并行接口驱动(手写)
│ ├── STM32F4xx_HAL_Driver/ # ST HAL 库CubeMX 生成)
│ └── CMSIS/ # ARM CMSISCubeMX 生成)
├── Lib/
│ └── FlashDB/ # FlashDB 数据库库v2.2.99
│ ├── src/ # FlashDB 核心源码
│ ├── inc/ # FlashDB 头文件
│ └── port/fal/ # FAL 抽象层
├── MDK-ARM/ # Keil MDK 工程文件
├── docs/ # 参考文档
└── STM32F407-Demo.ioc # STM32CubeMX 项目源文件
```
## 关键文件
| 路径 | 说明 |
|---|---|
| `Src/main.c` | 程序入口,初始化序列及主循环 |
| `Src/ch395f.c` / `Inc/ch395f.h` | CH395F 以太网芯片 SPI 驱动(核心自定义代码) |
| `Drivers/BSP/CH395F/ch395f.c/h` | CH395F 以太网芯片 SPI 驱动 |
| `Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c/h` | GD5F2GQ5UE NAND Flash SPI 驱动 |
| `Drivers/BSP/GD5F2GQ5UE/fal_flash_gd5f2gq5ue.c` | FAL 设备适配层 |
| `Drivers/BSP/TPAFE5160/tpafe5160.c/h` | TPAFE5160 ADC 并行接口驱动 |
| `MDK-ARM/STM32F407-Demo.uvprojx` | Keil MDK 项目文件 |
| `STM32F407-Demo.ioc` | STM32CubeMX 项目源文件 |
@@ -27,12 +57,14 @@ STM32F407ZGTx (Cortex-M4 FPU) 基础固件项目,集成 CH395F 以太网控制
- **主频:** HSE 25MHz → PLL 168MHz (4/168/2)
- **6 个 LED** PC4, PC5, PB1, PB2, PF11, PF12低电平点亮
- **CH395F** SPI2 (PB12 CS, PB13 SCK, PB14 SDO, PB15 SDI)
- **GD5F2GQ5UE** SPI1 (PE0 CS, PB3 SCK, PB4 MISO, PB5 MOSI, PB8 WP, PE1 HOLD)
- **TPAFE5160** 并行16位 (PG0-PG15 数据, PD3 RD, PD4 CONVST, PD7 BUSY, PD1 FRSTDATA, PF13-15 OS[2:0])
- **USART1** PA9 TX, PA10 RX (115200bps)
## 启动顺序
```
HAL_Init() → SystemClock_Config() → MX_GPIO_Init() → MX_USART1_UART_Init() → MX_SPI2_Init() → ch395f_reset() → ch395f_init()
HAL_Init() → SystemClock_Config() → MX_GPIO_Init() → MX_USART1_UART_Init() → MX_SPI2_Init() → MX_SPI1_Init() → gd5f2gq5ue_init() → fdb_kvdb_init()
```
## 代码规范
@@ -43,13 +75,54 @@ HAL_Init() → SystemClock_Config() → MX_GPIO_Init() → MX_USART1_UART_Init()
- 命名:小写字母+下划线;全局变量 `g_` 前缀,静态 `s_`,指针 `p_`,数组 `a_`
- 函数注释块需包含:函数功能、入口参数、返回值、限定条件、函数说明
- 大括号K&R 风格(左大括号不换行)
- 文件头注释:模块名称、功能、平台、作者、日期、修改记录
- 头文件保护宏:`__MODULE_NAME_H` 格式,带 `extern "C"`
## 注意
- `Inc/``Src/` 中 CubeMX 生成的文件gpio, spi, usart, stm32f4xx_it, main 的骨架)带有 `USER CODE BEGIN`/`END` 标记,自定义代码应写在这些区域之间以免被 CubeMX 重新生成时覆盖
- `ch395f.c`/`ch395f.h` 为纯手工代码,不受 CubeMX 保护
- `Inc/``Src/` 中 CubeMX 生成的文件带有 `USER CODE BEGIN`/`END` 标记,自定义代码应写在这些区域之间
- `ch395f.c/h``gd5f2gq5ue.c/h``fal_flash_gd5f2gq5ue.c` 为纯手工代码,不受 CubeMX 保护
- `tpafe5160.c/h` 为纯手工代码,不受 CubeMX 保护
- CH395F 每次 SPI 事务需调用 `ch395f_spi_begin()` / `ch395f_spi_end()` 包裹
- GD5F2GQ5UE 的 `gd5f2gq5ue.c` 中声明了 `extern SPI_HandleTypeDef hspi1`,需确保 SPI1 已初始化
- FlashDB 使用 FAL 模式,`fdb_cfg.h` 中定义 `FDB_USING_FAL_MODE``fal_cfg.h` 中定义分区表
- FlashDB 详细使用说明见 `FlashDB使用说明.md`
- `sd2506.c/h` 为纯手工代码,不受 CubeMX 保护
## CH395F 驱动关键点
- 初始化必须按手册9.2.1节顺序:`SET_MAC``SET_IP/GWIP/MASK``INIT_CH395``SET_PHY`
- **IP/网关/掩码必须在 `INIT_CH395` 之前设置**INIT 会读取并锁定当前寄存器值到协议栈,之后再设 IP 无效
- **`SET_PHY` 必须在 `INIT_CH395` 之后**,它会复位 MAC/PHY 建立物理链路,不影响已锁定的协议栈参数
- **`CMD_PING_ENABLE` 不需要显式调用**INIT 后默认可用
- 每次 SPI 事务需调用 `ch395f_spi_begin()` / `ch395f_spi_end()` 包裹
- CH395F 命令执行时序参考 `ch395f.h` 中命令码注释及 `CH395F.md`
## GD5F2GQ5UE 驱动关键点
- SPI Mode 0CPOL=0, CPHA=0时钟 42MHz
- 初始化必须按顺序:复位 → 读 ID → 使能 ECCB0h=10h→ 解除块保护A0h=00h
- SET_FEATURE 命令前必须先发写使能06h
- 块擦除D8h参数是字节地址块编号 × 128KB不是块编号
- 读取 ID9Fh返回 3 字节,第 0 字节无意义,第 1 字节 MID第 2 字节 DID
## FlashDB 分区规划
| 分区名 | 偏移 | 大小 | 用途 |
|--------|------|------|------|
| fdb_kvdb1 | 0 | 64MB | KVDB 键值数据库 |
| fdb_tsdb1 | 64MB | 64MB | TSDB 时序数据库 |
## TPAFE5160 驱动关键点
- AD7606 P2P 兼容替代品,并行接口协议一致
- 并行模式CS 接地始终选中PAR/SER/BYTE SEL 接 GND并行DB15/BYTE SEL 接 GND非字节模式
- 数据总线 DB[15:0] 接 GPIOG[15:0],通过 `(uint16_t)GPIOG->IDR` 一次读取16位
- CONVST 上升沿触发全部8通道同步采样BUSY 高电平表示转换中
- RD 下降沿输出通道数据按通道1~8顺序依次输出
- FRSTDATA 在第一个 RD 下降沿变高指示通道1数据就绪
- 过采样 OS[2:0] 在 BUSY 下降沿锁存,无过采样时 tCONV=1.74µs64倍过采样时 tCONV=167µs
- 读取时序168MHz 下 GPIO 写操作 + 5个 NOP (~30ns) 覆盖 t10=22ns 和 t14=21ns 要求
- 硬件 RANGE 接 GND → ±5V 量程LSB=152.59µV
## 已知问题
@@ -57,11 +130,4 @@ HAL_Init() → SystemClock_Config() → MX_GPIO_Init() → MX_USART1_UART_Init()
CH395F 与 RTL8305NBI-CG 直连(经网络变压器)时,自动协商始终失败(返回 `PHY_DISCONN`),但强制 100M 全双工工作正常。强制 10M 全双工同样失败。
**诊断结果:**
- Auto-Neg: `0x01 (DISCONNECTED)`
- Force 100M-FULL: `0x08 (LINK OK)`
- Force 10M-FULL: `0x01 (DISCONNECTED)`
**解决方案:** 初始化协议栈后调用 `ch395f_set_phy(CH395F_PHY_100M_FULL)` 跳过自动协商。
**推测根因:** 不同厂家 PHY 直连时的自动协商实现差异CH395F WCH 固件 vs RTL8305NBI Realtek 硬件),物理层正常。

View File

@@ -493,6 +493,27 @@ void ch395f_set_phy(uint8_t phystat)
ch395f_spi_end();
}
/*
* 函数功能:使能/关闭 CH395 响应 PING
* 入口参数enable - 1 使能 PING 响应0 关闭
* 限定条件:芯片已初始化
* 函数说明:手册 5.37 CMD_PING_ENABLE默认关闭
*/
void ch395f_ping_enable(uint8_t enable)
{
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送 PING 使能命令 */
ch395f_write_cmd(CH395F_CMD_PING_ENABLE);
/* 发送使能标志 */
ch395f_write_data(enable);
/* 结束 SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:启用/禁用 DHCP
* 入口参数enable - 1 启用0 禁用 uint8_t

View File

@@ -350,6 +350,14 @@ uint8_t ch395f_get_phy_status(void);
*/
void ch395f_set_phy(uint8_t phystat);
/*
* 函数功能:使能/关闭 CH395 响应 PING
* 入口参数enable - 1 使能 PING 响应0 关闭
* 限定条件:芯片已初始化
* 函数说明:手册 5.37 CMD_PING_ENABLE默认关闭
*/
void ch395f_ping_enable(uint8_t enable);
/*
* 函数声明区 - DHCP
*/

View File

@@ -1,35 +1,51 @@
/**
******************************************************************************
* @file fal_cfg.h
* @brief FAL 配置Flash 设备表 + 分区表
******************************************************************************
*/
#ifndef __FAL_CFG_H
#define __FAL_CFG_H
#ifndef _FAL_CFG_H_
#define _FAL_CFG_H_
/*
* 模块名称FAL 配置
* 模块功能:定义 FAL Flash 设备表和分区表
* 适用平台STM32F407ZGT6
* 作者:王建锋
* 创建日期2026-07-16
* 修改记录:
* 2026-07-16 王建锋 创建初始版本
*/
#ifdef __cplusplus
extern "C" {
#endif
/* FAL 调试开关0-关闭1-开启 */
#define FAL_DEBUG 0
/* 启用分区表配置 */
#define FAL_PART_HAS_TABLE_CFG
/* ===================== Flash 设备表 ===================== */
/* ======================== Flash 设备表 ======================== */
extern const struct fal_flash_dev gd5f2gq5ue_flash;
#define FAL_FLASH_DEV_TABLE \
{ \
&gd5f2gq5ue_flash, \
#define FAL_FLASH_DEV_TABLE \
{ \
&gd5f2gq5ue_flash, \
}
/* ===================== 分区表 ===================== */
/* 分区名称 设备名称 偏移 大小 */
/* KVDB: 64MB @ 0 */
/* TSDB: 64MB @ 64MB */
/* ======================== 分区表 ======================== */
/*
* 分区名称 设备名称 偏移 大小
* KVDB: 64MB @ 0
* TSDB: 64MB @ 64MB
*/
#ifdef FAL_PART_HAS_TABLE_CFG
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WORD, "fdb_kvdb1", "gd5f2gq5ue", 0, 64*1024*1024, 0}, \
{FAL_PART_MAGIC_WORD, "fdb_tsdb1", "gd5f2gq5ue", 64*1024*1024, 64*1024*1024, 0}, \
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WORD, "fdb_kvdb1", "gd5f2gq5ue", 0, 64*1024*1024, 0}, \
{FAL_PART_MAGIC_WORD, "fdb_tsdb1", "gd5f2gq5ue", 64*1024*1024, 64*1024*1024, 0}, \
}
#endif
#endif /* _FAL_CFG_H_ */
#ifdef __cplusplus
}
#endif
#endif /* __FAL_CFG_H */

View File

@@ -1,42 +1,80 @@
/**
******************************************************************************
* @file fal_flash_gd5f2gq5ue.c
* @brief FAL 端口GD5F2GQ5UE SPI NAND Flash 适配层
******************************************************************************
*/
/*
* 模块名称FAL Flash 设备适配
* 模块功能:将 GD5F2GQ5UE 驱动接口适配到 FAL 框架
* 适用平台STM32F407ZGT6
* 作者:王建锋
* 创建日期2026-07-16
* 修改记录:
* 2026-07-16 王建锋 创建初始版本
*/
/* 头文件包含区 */
#include "fal_def.h"
#include "gd5f2gq5ue.h"
/* ===================== FAL Flash 设备操作函数 ===================== */
/* ======================== FAL 操作函数适配 ======================== */
/*
* 函数功能Flash 设备初始化适配
* 入口参数:无
* 返回值0 - 成功,其他 - 错误码
* 限定条件SPI 和 GPIO 已由 CubeMX 初始化完成
* 函数说明:调用底层驱动的初始化函数
*/
static int gd5f_fal_init(void)
{
return gd5f2gq5ue_init();
}
static int gd5f_fal_read(long offset, uint8_t *buf, size_t size)
/*
* 函数功能Flash 读取适配
* 入口参数offset - 起始字节偏移 long
* p_buf - 数据缓冲区 uint8_t*
* size - 读取字节数 size_t
* 返回值0 - 成功,其他 - 错误码
* 限定条件gd5f_fal_init() 已成功调用
* 函数说明:直接转发到底层驱动的读取函数
*/
static int gd5f_fal_read(long offset, uint8_t *p_buf, size_t size)
{
return gd5f2gq5ue_read(offset, buf, size);
return gd5f2gq5ue_read(offset, p_buf, size);
}
static int gd5f_fal_write(long offset, const uint8_t *buf, size_t size)
/*
* 函数功能Flash 写入适配
* 入口参数offset - 起始字节偏移 long
* p_buf - 数据缓冲区 const uint8_t*
* size - 写入字节数 size_t
* 返回值0 - 成功,其他 - 错误码
* 限定条件:目标区域已擦除
* 函数说明:直接转发到底层驱动的写入函数
*/
static int gd5f_fal_write(long offset, const uint8_t *p_buf, size_t size)
{
return gd5f2gq5ue_write(offset, buf, size);
return gd5f2gq5ue_write(offset, p_buf, size);
}
/*
* 函数功能Flash 擦除适配
* 入口参数offset - 起始字节偏移 long
* size - 擦除字节数 size_t
* 返回值0 - 成功,其他 - 错误码
* 限定条件gd5f_fal_init() 已成功调用
* 函数说明:直接转发到底层驱动的擦除函数
*/
static int gd5f_fal_erase(long offset, size_t size)
{
return gd5f2gq5ue_erase(offset, size);
}
/* ===================== FAL Flash 设备定义 ===================== */
/* ======================== FAL Flash 设备定义 ======================== */
/* GD5F2GQ5UE FAL 设备实例总容量256MB块大小128KB */
const struct fal_flash_dev gd5f2gq5ue_flash = {
.name = "gd5f2gq5ue",
.addr = 0,
.len = GD5F_TOTAL_SIZE, /* 256MB */
.blk_size = GD5F_BLOCK_SIZE, /* 128KB */
.len = GD5F_TOTAL_SIZE,
.blk_size = GD5F_BLOCK_SIZE,
.ops = {
.init = gd5f_fal_init,
.read = gd5f_fal_read,

View File

@@ -1,20 +1,25 @@
/**
******************************************************************************
* @file fdb_cfg.h
* @brief FlashDB 配置文件
******************************************************************************
*/
#ifndef __FDB_CFG_H
#define __FDB_CFG_H
#ifndef _FDB_CFG_H_
#define _FDB_CFG_H_
/*
* 模块名称FlashDB 配置
* 模块功能:配置 FlashDB 数据库功能开关和参数
* 适用平台STM32F407ZGT6
* 作者:王建锋
* 创建日期2026-07-16
* 修改记录:
* 2026-07-16 王建锋 创建初始版本
*/
#ifdef __cplusplus
extern "C" {
#endif
/* 启用 KVDB键值数据库 */
#define FDB_USING_KVDB
#ifdef FDB_USING_KVDB
/* 当 KVDB 版本号变化时自动更新到最新默认值 */
/* KVDB 版本号变化时自动更新到最新默认值(默认关闭) */
/* #define FDB_KV_AUTO_UPDATE */
#endif
/* 启用 TSDB时序数据库 */
#define FDB_USING_TSDB
@@ -22,11 +27,14 @@
/* 使用 FAL 存储模式(非文件模式) */
#define FDB_USING_FAL_MODE
/* Flash 写入粒度单位bit
* STM32F4 = 8字节可编程 */
#define FDB_WRITE_GRAN 8
/* Flash 写入粒度单位bitSTM32F4 字节可编程 = 8 */
#define FDB_WRITE_GRAN 8
/* 调试输出 */
#define FDB_DEBUG_ENABLE
/* 调试输出使能 */
/*#define FDB_DEBUG_ENABLE*/
#endif /* _FDB_CFG_H_ */
#ifdef __cplusplus
}
#endif
#endif /* __FDB_CFG_H */

View File

@@ -1,350 +1,450 @@
/**
******************************************************************************
* @file gd5f2gq5ue.c
* @brief GD5F2GQ5UE SPI NAND Flash 驱动实现
******************************************************************************
*/
/*
* 模块名称GD5F2GQ5UE SPI NAND Flash 驱动
* 模块功能:提供 GD5F2GQ5UE SPI NAND Flash 的初始化、读、写、擦除接口
* 适用平台STM32F407ZGT6 + SPI1 硬件 SPI
* 作者:王建锋
* 创建日期2026-07-16
* 修改记录:
* 2026-07-16 王建锋 创建初始版本
* 2026-07-17 王建锋 切换硬件 SPI修正擦除地址参考 NuttX 驱动
*/
/* 头文件包含区 */
#include "gd5f2gq5ue.h"
#include <string.h>
/* 私有宏定义区 */
#define GD5F_SPI_TIMEOUT 100
/* 外部 SPI 句柄声明 */
extern SPI_HandleTypeDef hspi1;
/* ===================== 内部辅助函数 ===================== */
/* ======================== 私有函数声明 ======================== */
/**
* @brief SPI 发送/接收单字节
*/
static uint8_t gd5f_spi_xfer(uint8_t tx)
{
uint8_t rx;
HAL_SPI_TransmitReceive(&hspi1, &tx, &rx, 1, 100);
return rx;
}
static int gd5f_wait_busy(uint32_t timeout_ms);
static int gd5f_write_enable(void);
static int gd5f_read_status(uint8_t *p_status);
static int gd5f_page_read(uint32_t page_addr);
static int gd5f_read_from_cache(uint16_t column, uint8_t *p_buf,
size_t size);
static int gd5f_page_program(uint32_t page_addr, uint16_t column,
const uint8_t *p_buf, size_t size);
static int gd5f_set_feature(uint8_t addr, uint8_t data);
static int gd5f_block_erase(uint32_t block_addr);
/**
* @brief SPI 发送缓冲区
*/
static void gd5f_spi_tx(const uint8_t *buf, size_t len)
{
HAL_SPI_Transmit(&hspi1, (uint8_t *)buf, len, 100);
}
/* ======================== 私有函数定义 ======================== */
/**
* @brief SPI 接收缓冲区
*/
static void gd5f_spi_rx(uint8_t *buf, size_t len)
{
HAL_SPI_Receive(&hspi1, buf, len, 100);
}
/**
* @brief 等待操作完成OIP 位清零)
* @param timeout_ms: 超时时间(毫秒)
* @retval GD5F_OK 成功, GD5F_BUSY_TIMEOUT 超时
/*
* 函数功能:等待芯片操作完成(轮询 OIP 位)
* 入口参数timeout_ms - 超时时间 uint32_t > 0
* 返回值0 - 操作完成,-2 - 超时
* 限定条件SPI 已初始化
* 函数说明:循环读取状态寄存器直到 OIP 位清零或超时
*/
static int gd5f_wait_busy(uint32_t timeout_ms)
{
uint8_t cmd = GD5F_CMD_GET_FEATURE;
uint8_t addr = GD5F_REG_STATUS;
uint8_t status;
uint32_t tickstart = HAL_GetTick();
uint8_t status = 0;
uint32_t tick_start = HAL_GetTick();
while (1) {
GD5F_CS_LOW();
gd5f_spi_tx(&cmd, 1);
gd5f_spi_tx(&addr, 1);
gd5f_spi_rx(&status, 1);
HAL_SPI_Transmit(&hspi1, &cmd, 1, GD5F_SPI_TIMEOUT);
HAL_SPI_Transmit(&hspi1, &addr, 1, GD5F_SPI_TIMEOUT);
HAL_SPI_Receive(&hspi1, &status, 1, GD5F_SPI_TIMEOUT);
GD5F_CS_HIGH();
if ((status & GD5F_STATUS_OIP) == 0) {
return GD5F_OK;
}
if ((HAL_GetTick() - tickstart) >= timeout_ms) {
if ((HAL_GetTick() - tick_start) >= timeout_ms) {
return GD5F_BUSY_TIMEOUT;
}
}
}
/**
* @brief 写使能
/*
* 函数功能:发送写使能命令
* 入口参数:无
* 返回值0 - 成功
* 限定条件SPI 已初始化
* 函数说明CS# 拉低后发送 06h 命令再拉高
*/
static int gd5f_write_enable(void)
{
uint8_t cmd = GD5F_CMD_WRITE_ENABLE;
GD5F_CS_LOW();
gd5f_spi_tx(&cmd, 1);
HAL_SPI_Transmit(&hspi1, &cmd, 1, GD5F_SPI_TIMEOUT);
GD5F_CS_HIGH();
return GD5F_OK;
}
/**
* @brief 读取状态寄存器
/*
* 函数功能:读取状态寄存器
* 入口参数p_status - 状态值输出指针 uint8_t* 不为 NULL
* 返回值0 - 成功
* 限定条件SPI 已初始化
* 函数说明:发送 0Fh + C0h 地址后读取1字节状态值
*/
static int gd5f_read_status(uint8_t *status)
static int gd5f_read_status(uint8_t *p_status)
{
uint8_t cmd = GD5F_CMD_GET_FEATURE;
uint8_t addr = GD5F_REG_STATUS;
GD5F_CS_LOW();
gd5f_spi_tx(&cmd, 1);
gd5f_spi_tx(&addr, 1);
gd5f_spi_rx(status, 1);
HAL_SPI_Transmit(&hspi1, &cmd, 1, GD5F_SPI_TIMEOUT);
HAL_SPI_Transmit(&hspi1, &addr, 1, GD5F_SPI_TIMEOUT);
HAL_SPI_Receive(&hspi1, p_status, 1, GD5F_SPI_TIMEOUT);
GD5F_CS_HIGH();
return GD5F_OK;
}
/**
* @brief 页读取到缓存Page Read to Cache
* @param page_addr: 页地址(行地址,包含 block + page
/*
* 函数功能:页读取(将数据从存储阵列加载到内部缓存
* 入口参数:page_addr - 页地址 uint32_t
* 返回值0 - 成功,其他 - 错误码
* 限定条件SPI 已初始化
* 函数说明:发送 13h + 3字节行地址等待 OIP 清零
*/
static int gd5f_page_read(uint32_t page_addr)
{
uint8_t cmd[4];
cmd[0] = GD5F_CMD_PAGE_READ;
cmd[1] = (page_addr >> 16) & 0xFF;
cmd[2] = (page_addr >> 8) & 0xFF;
cmd[3] = page_addr & 0xFF;
GD5F_CS_LOW();
gd5f_spi_tx(cmd, 4);
HAL_SPI_Transmit(&hspi1, cmd, 4, GD5F_SPI_TIMEOUT);
GD5F_CS_HIGH();
return gd5f_wait_busy(100);
}
/**
* @brief 从缓存读取数据Read from Cache
* @param column: 列地址(页内偏移)
* @param buf: 数据缓冲区
* @param size: 读取字节数
/*
* 函数功能:从内部缓存读取数据
* 入口参数:column - 列地址(页内偏移) uint16_t 0 - 2047
* p_buf - 数据输出缓冲区 uint8_t* 不为 NULL
* size - 读取字节数 size_t > 0
* 返回值0 - 成功
* 限定条件:必须先调用 gd5f_page_read 完成数据加载
* 函数说明:发送 0Bh + 2字节列地址 +1字节 dummy 后读取数据
*/
static int gd5f_read_from_cache(uint16_t column, uint8_t *buf, size_t size)
static int gd5f_read_from_cache(uint16_t column, uint8_t *p_buf,
size_t size)
{
uint8_t cmd[5];
uint8_t cmd[4];
cmd[0] = GD5F_CMD_READ_FROM_CACHE;
cmd[1] = (column >> 8) & 0xFF;
cmd[2] = column & 0xFF;
cmd[3] = 0x00; /* dummy byte */
cmd[3] = 0x00;
GD5F_CS_LOW();
gd5f_spi_tx(cmd, 4);
gd5f_spi_rx(buf, size);
HAL_SPI_Transmit(&hspi1, cmd, 4, GD5F_SPI_TIMEOUT);
HAL_SPI_Receive(&hspi1, p_buf, size, GD5F_SPI_TIMEOUT);
GD5F_CS_HIGH();
return GD5F_OK;
}
/**
* @brief 页编程(从缓存写入阵列
* @param page_addr: 页地址
* @param column: 列地址
* @param buf: 数据缓冲区
* @param size: 写入字节数
/*
* 函数功能:页编程(将数据写入指定页
* 入口参数:page_addr - 页地址 uint32_t
* column - 列地址 uint16_t 0 - 2047
* p_buf - 数据缓冲区 const uint8_t*
* size - 写入字节数 size_t > 0
* 返回值0 - 成功,其他 - 错误码
* 限定条件:目标区域已擦除
* 函数说明1. 写使能 - 02h 加载数据 - 10h 执行编程 - 等待完成
* 2. 编程完成后检查 P_FAIL 位
*/
static int gd5f_page_program(uint32_t page_addr, uint16_t column, const uint8_t *buf, size_t size)
static int gd5f_page_program(uint32_t page_addr, uint16_t column,
const uint8_t *p_buf, size_t size)
{
int ret;
int ret = GD5F_OK;
uint8_t cmd[4];
uint8_t status = 0;
/* 1. 写使能 */
gd5f_write_enable();
/* 2. 数据加载到缓存 (Program Load) */
cmd[0] = GD5F_CMD_PROGRAM_LOAD;
cmd[1] = (column >> 8) & 0xFF;
cmd[2] = column & 0xFF;
GD5F_CS_LOW();
gd5f_spi_tx(cmd, 3);
gd5f_spi_tx(buf, size);
HAL_SPI_Transmit(&hspi1, cmd, 3, GD5F_SPI_TIMEOUT);
HAL_SPI_Transmit(&hspi1, (uint8_t *)p_buf, size,
GD5F_SPI_TIMEOUT);
GD5F_CS_HIGH();
/* 3. 编程执行 (Program Execute) */
cmd[0] = GD5F_CMD_PROGRAM_EXEC;
cmd[1] = (page_addr >> 16) & 0xFF;
cmd[2] = (page_addr >> 8) & 0xFF;
cmd[3] = page_addr & 0xFF;
GD5F_CS_LOW();
gd5f_spi_tx(cmd, 4);
HAL_SPI_Transmit(&hspi1, cmd, 4, GD5F_SPI_TIMEOUT);
GD5F_CS_HIGH();
/* 4. 等待完成 */
ret = gd5f_wait_busy(1000);
if (ret != GD5F_OK) return ret;
if (ret != GD5F_OK) {
return ret;
}
/* 5. 检查编程结果 */
uint8_t status;
gd5f_read_status(&status);
if (status & GD5F_STATUS_P_FAIL) {
/* 清除 P_FAIL写使能 + 读状态 */
gd5f_write_enable();
return GD5F_PROGRAM_FAIL;
}
return GD5F_OK;
}
/**
* @brief 块擦除
* @param block_addr: 块地址 (0 ~ 2047)
/*
* 函数功能:设置 Feature 寄存器
* 入口参数addr - 寄存器地址 uint8_t
* data - 写入数据 uint8_t
* 返回值0 - 成功
* 限定条件SPI 已初始化
* 函数说明:先写使能,发送 1Fh + 地址 + 数据,等待操作完成
*/
static int gd5f_set_feature(uint8_t addr, uint8_t data)
{
uint8_t cmd[3];
gd5f_write_enable();
cmd[0] = GD5F_CMD_SET_FEATURE;
cmd[1] = addr;
cmd[2] = data;
GD5F_CS_LOW();
HAL_SPI_Transmit(&hspi1, cmd, 3, GD5F_SPI_TIMEOUT);
GD5F_CS_HIGH();
gd5f_wait_busy(100);
return GD5F_OK;
}
/*
* 函数功能块擦除擦除128KB块
* 入口参数block_addr - 块编号 uint32_t 0 - 2047
* 返回值0 - 成功,其他 - 错误码
* 限定条件gd5f2gq5ue_init() 已调用
* 函数说明1. 写使能 - D8h + 3字节字节地址 - 等待完成
* 2. 擦除完成后检查 E_FAIL 位
*/
static int gd5f_block_erase(uint32_t block_addr)
{
int ret;
int ret = GD5F_OK;
uint8_t cmd[4];
uint8_t status = 0;
uint32_t byte_addr = block_addr * GD5F_BLOCK_SIZE;
/* 1. 写使能 */
gd5f_write_enable();
/* 2. 块擦除命令 */
cmd[0] = GD5F_CMD_BLOCK_ERASE;
cmd[1] = (block_addr >> 8) & 0xFF;
cmd[2] = block_addr & 0xFF;
cmd[3] = 0x00;
cmd[1] = (byte_addr >> 16) & 0xFF;
cmd[2] = (byte_addr >> 8) & 0xFF;
cmd[3] = byte_addr & 0xFF;
GD5F_CS_LOW();
gd5f_spi_tx(cmd, 4);
HAL_SPI_Transmit(&hspi1, cmd, 4, GD5F_SPI_TIMEOUT);
GD5F_CS_HIGH();
/* 3. 等待完成(擦除较慢) */
ret = gd5f_wait_busy(5000);
if (ret != GD5F_OK) return ret;
if (ret != GD5F_OK) {
return ret;
}
/* 4. 检查擦除结果 */
uint8_t status;
gd5f_read_status(&status);
if (status & GD5F_STATUS_E_FAIL) {
gd5f_write_enable();
return GD5F_ERASE_FAIL;
}
return GD5F_OK;
}
/* ===================== 公共接口实现 ===================== */
/* ======================== 公共函数定义 ======================== */
/*
* 函数功能:初始化 GD5F2GQ5UE
* 入口参数:无
* 返回值0 - 成功,其他 - 错误码
* 限定条件SPI1 和相关 GPIO 已由 CubeMX 初始化完成
* 函数说明1. 发送复位命令并等待完成
* 2. 读取芯片 ID 并校验
* 3. 使能内部 ECC (B0h bit4)
* 4. 解除所有块保护 (A0h = 0x00)
*/
int gd5f2gq5ue_init(void)
{
int ret;
uint8_t mid, did;
int ret = GD5F_OK;
uint8_t mid = 0;
uint8_t did = 0;
/* 确保控制引脚处于非激活状态 */
GD5F_CS_HIGH();
GD5F_WP_HIGH();
GD5F_HOLD_HIGH();
/* 小延时等待上电稳定 */
HAL_Delay(10);
/* 复位芯片 */
ret = gd5f2gq5ue_reset();
if (ret != GD5F_OK) return ret;
if (ret != GD5F_OK) {
return ret;
}
HAL_Delay(5);
/* 读取 ID 验证通信 */
ret = gd5f2gq5ue_read_id(&mid, &did);
if (ret != GD5F_OK) return ret;
if (ret != GD5F_OK) {
return ret;
}
if (mid != GD5F_MANUFACTURER_ID || did != GD5F_DEVICE_ID) {
return GD5F_ID_MISMATCH;
}
gd5f_set_feature(0xB0, 0x10);
gd5f_wait_busy(100);
gd5f_set_feature(GD5F_REG_PROTECT, 0x00);
gd5f_wait_busy(100);
return GD5F_OK;
}
/*
* 函数功能:读取芯片 IDMID + DID
* 入口参数mid - 制造商 ID 输出指针 uint8_t* 不为 NULL
* did - 设备 ID 输出指针 uint8_t* 不为 NULL
* 返回值0 - 成功
* 限定条件SPI 已初始化
* 函数说明:发送 9Fh 命令后接收1个 dummy + MID + DID
*/
int gd5f2gq5ue_read_id(uint8_t *mid, uint8_t *did)
{
uint8_t cmd = GD5F_CMD_READ_ID;
uint8_t id_buf[3];
uint8_t id_buf[3] = {0};
GD5F_CS_LOW();
gd5f_spi_tx(&cmd, 1);
gd5f_spi_rx(id_buf, 3); /* dummy + MID + DID */
HAL_SPI_Transmit(&hspi1, &cmd, 1, GD5F_SPI_TIMEOUT);
HAL_SPI_Receive(&hspi1, id_buf, 3, GD5F_SPI_TIMEOUT);
GD5F_CS_HIGH();
*mid = id_buf[1]; /* id_buf[0] = dummy */
*mid = id_buf[1];
*did = id_buf[2];
return GD5F_OK;
}
int gd5f2gq5ue_read(long offset, uint8_t *buf, size_t size)
/*
* 函数功能:从 NAND 读取数据(支持跨页)
* 入口参数offset - 起始字节偏移 long 0 ~ 总容量-1
* p_buf - 数据缓冲区 uint8_t* 不为 NULL
* size - 读取字节数 size_t > 0
* 返回值0 - 成功,其他 - 错误码
* 限定条件gd5f2gq5ue_init() 已成功调用
* 函数说明:自动处理跨页读取
*/
int gd5f2gq5ue_read(long offset, uint8_t *p_buf, size_t size)
{
int ret;
int ret = GD5F_OK;
while (size > 0) {
/* 计算页地址和列偏移 */
uint32_t page_addr = offset / GD5F_PAGE_SIZE;
uint16_t column = offset % GD5F_PAGE_SIZE;
/* 本次读取字节数(不超过当前页剩余空间) */
size_t bytes = GD5F_PAGE_SIZE - column;
if (bytes > size) bytes = size;
/* Page Read to Cache */
if (bytes > size) {
bytes = size;
}
ret = gd5f_page_read(page_addr);
if (ret != GD5F_OK) return ret;
if (ret != GD5F_OK) {
return ret;
}
/* Read from Cache */
ret = gd5f_read_from_cache(column, buf, bytes);
if (ret != GD5F_OK) return ret;
ret = gd5f_read_from_cache(column, p_buf, bytes);
if (ret != GD5F_OK) {
return ret;
}
offset += bytes;
buf += bytes;
p_buf += bytes;
size -= bytes;
}
return GD5F_OK;
}
int gd5f2gq5ue_write(long offset, const uint8_t *buf, size_t size)
/*
* 函数功能:向 NAND 写入数据(支持跨页)
* 入口参数offset - 起始字节偏移 long 0 ~ 总容量-1
* p_buf - 数据缓冲区 const uint8_t* 不为 NULL
* size - 写入字节数 size_t > 0
* 返回值0 - 成功,其他 - 错误码
* 限定条件gd5f2gq5ue_init() 已成功调用,目标区域已擦除
* 函数说明:自动处理跨页写入
*/
int gd5f2gq5ue_write(long offset, const uint8_t *p_buf, size_t size)
{
int ret;
int ret = GD5F_OK;
while (size > 0) {
/* 计算页地址和列偏移 */
uint32_t page_addr = offset / GD5F_PAGE_SIZE;
uint16_t column = offset % GD5F_PAGE_SIZE;
/* 本次写入字节数(不超过当前页剩余空间) */
size_t bytes = GD5F_PAGE_SIZE - column;
if (bytes > size) bytes = size;
/* 页编程 */
ret = gd5f_page_program(page_addr, column, buf, bytes);
if (ret != GD5F_OK) return ret;
if (bytes > size) {
bytes = size;
}
ret = gd5f_page_program(page_addr, column, p_buf, bytes);
if (ret != GD5F_OK) {
return ret;
}
offset += bytes;
buf += bytes;
p_buf += bytes;
size -= bytes;
}
return GD5F_OK;
}
/*
* 函数功能:擦除块(按块擦除,最小单位 128KB
* 入口参数offset - 起始字节偏移 long 必须块对齐
* size - 擦除字节数 size_t 必须块大小整数倍
* 返回值0 - 成功,其他 - 错误码
* 限定条件gd5f2gq5ue_init() 已成功调用
* 函数说明:擦除操作以块为单位
*/
int gd5f2gq5ue_erase(long offset, size_t size)
{
int ret;
int ret = GD5F_OK;
/* 擦除起始地址必须块对齐 */
if (offset % GD5F_BLOCK_SIZE != 0) {
return GD5F_ERROR;
}
/* 擦除大小必须为块大小的整数倍 */
if (size % GD5F_BLOCK_SIZE != 0) {
return GD5F_ERROR;
}
/* 逐块擦除 */
while (size > 0) {
uint32_t block_addr = offset / GD5F_BLOCK_SIZE;
ret = gd5f_block_erase(block_addr);
if (ret != GD5F_OK) return ret;
if (ret != GD5F_OK) {
return ret;
}
offset += GD5F_BLOCK_SIZE;
size -= GD5F_BLOCK_SIZE;
@@ -353,12 +453,19 @@ int gd5f2gq5ue_erase(long offset, size_t size)
return GD5F_OK;
}
/*
* 函数功能:复位芯片
* 入口参数:无
* 返回值0 - 成功
* 限定条件SPI 已初始化
* 函数说明:发送 FFh 复位命令后等待 5ms
*/
int gd5f2gq5ue_reset(void)
{
uint8_t cmd = GD5F_CMD_RESET;
GD5F_CS_LOW();
gd5f_spi_tx(&cmd, 1);
HAL_SPI_Transmit(&hspi1, &cmd, 1, GD5F_SPI_TIMEOUT);
GD5F_CS_HIGH();
HAL_Delay(5);

View File

@@ -1,75 +1,70 @@
/**
******************************************************************************
* @file gd5f2gq5ue.h
* @brief GD5F2GQ5UE SPI NAND Flash 驱动头文件
******************************************************************************
*/
#ifndef __GD5F2GQ5UE_H
#define __GD5F2GQ5UE_H
/*
* 模块名称GD5F2GQ5UE SPI NAND Flash 驱动
* 模块功能:提供 GD5F2GQ5UE SPI NAND Flash 的初始化、读、写、擦除接口
* 适用平台STM32F407ZGT6 + SPI1 硬件 SPI
* 作者:王建锋
* 创建日期2026-07-16
* 修改记录:
* 2026-07-16 王建锋 创建初始版本
* 2026-07-17 王建锋 切换为硬件 SPI修正擦除地址参考 NuttX 驱动
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "main.h"
#include "spi.h"
/* ===================== 硬件引脚定义 ===================== */
#define GD5F_CS_LOW() HAL_GPIO_WritePin(GD_CS_GPIO_Port, GD_CS_Pin, GPIO_PIN_RESET)
#define GD5F_CS_HIGH() HAL_GPIO_WritePin(GD_CS_GPIO_Port, GD_CS_Pin, GPIO_PIN_SET)
#define GD5F_WP_HIGH() HAL_GPIO_WritePin(GD_WP_GPIO_Port, GD_WP_Pin, GPIO_PIN_SET)
#define GD5F_HOLD_HIGH() HAL_GPIO_WritePin(GD_HOLD_GPIO_Port, GD_HOLD_Pin, GPIO_PIN_SET)
/* ======================== 宏定义 ======================== */
/* ===================== SPI 命令码 ===================== */
/* SPI 命令码 */
#define GD5F_CMD_WRITE_ENABLE 0x06
#define GD5F_CMD_WRITE_DISABLE 0x04
#define GD5F_CMD_GET_FEATURE 0x0F
#define GD5F_CMD_SET_FEATURE 0x1F
#define GD5F_CMD_READ_ID 0x9F
#define GD5F_CMD_PAGE_READ 0x13
#define GD5F_CMD_READ_FROM_CACHE 0x0B /* Fast Read, 1 dummy byte */
#define GD5F_CMD_READ_FROM_CACHE 0x0B
#define GD5F_CMD_PROGRAM_LOAD 0x02
#define GD5F_CMD_PROGRAM_EXEC 0x10
#define GD5F_CMD_BLOCK_ERASE 0xD8
#define GD5F_CMD_RESET 0xFF
/* ===================== 寄存器地址 ===================== */
#define GD5F_REG_STATUS 0xC0
/* 寄存器地址 */
#define GD5F_REG_PROTECT 0xA0
#define GD5F_REG_FEATURE 0xB0
#define GD5F_REG_STATUS 0xC0
#define GD5F_REG_DRIVER 0xD0
/* ===================== 状态位定义 ===================== */
#define GD5F_STATUS_OIP (1 << 0) /* 操作进行中 */
#define GD5F_STATUS_WEL (1 << 1) /* 写使能锁存 */
#define GD5F_STATUS_E_FAIL (1 << 2) /* 擦除失败 */
#define GD5F_STATUS_P_FAIL (1 << 3) /* 编程失败 */
#define GD5F_STATUS_BIT4 (1 << 4)
#define GD5F_STATUS_ECCS0 (1 << 5)
#define GD5F_STATUS_ECCS1 (1 << 6)
#define GD5F_STATUS_ECCSE0 (1 << 4) /* ECC 单 bit 错误低位 */
#define GD5F_STATUS_ECCSE1 (1 << 5) /* ECC 单 bit 错误高位 */
#define GD5F_STATUS_ECCSE2 (1 << 6) /* ECC 单 bit 错误高位 */
/* 状态位定义 */
#define GD5F_STATUS_OIP (1 << 0)
#define GD5F_STATUS_WEL (1 << 1)
#define GD5F_STATUS_E_FAIL (1 << 2)
#define GD5F_STATUS_P_FAIL (1 << 3)
#define GD5F_STATUS_ECCS0 (1 << 4)
#define GD5F_STATUS_ECCS1 (1 << 5)
/* ===================== Feature 位定义 ===================== */
/* Feature 位定义 */
#define GD5F_FEATURE_ECC_EN (1 << 4)
#define GD5F_FEATURE_QE (1 << 0) /* Quad Enable, B0[0] */
#define GD5F_FEATURE_QE (1 << 0)
/* ===================== 芯片参数 ===================== */
#define GD5F_PAGE_SIZE 2048 /* 主数据区字节数 */
#define GD5F_SPARE_SIZE 64 /* ECC 启用时 spare 区 */
#define GD5F_TOTAL_PAGE_SIZE 2112 /* 2048 + 64 */
/* 芯片参数 */
#define GD5F_PAGE_SIZE 2048
#define GD5F_SPARE_SIZE 64
#define GD5F_TOTAL_PAGE_SIZE 2112
#define GD5F_PAGES_PER_BLOCK 64
#define GD5F_BLOCK_SIZE (GD5F_PAGES_PER_BLOCK * GD5F_PAGE_SIZE) /* 128KB */
#define GD5F_BLOCK_SIZE (GD5F_PAGES_PER_BLOCK * GD5F_PAGE_SIZE)
#define GD5F_TOTAL_BLOCKS 2048
#define GD5F_TOTAL_SIZE (GD5F_TOTAL_BLOCKS * GD5F_BLOCK_SIZE) /* 256MB */
#define GD5F_TOTAL_SIZE (GD5F_TOTAL_BLOCKS * GD5F_BLOCK_SIZE)
/* 制造商 ID 和设备 ID */
#define GD5F_MANUFACTURER_ID 0xC8
#define GD5F_DEVICE_ID 0x52
/* ===================== 返回值定义 ===================== */
/* 返回值定义 */
#define GD5F_OK 0
#define GD5F_ERROR -1
#define GD5F_BUSY_TIMEOUT -2
@@ -78,51 +73,74 @@ extern "C" {
#define GD5F_ERASE_FAIL -5
#define GD5F_ID_MISMATCH -6
/* ===================== 公共接口函数 ===================== */
/* 控制引脚宏 */
#define GD5F_CS_LOW() HAL_GPIO_WritePin(GD_CS_GPIO_Port, GD_CS_Pin, GPIO_PIN_RESET)
#define GD5F_CS_HIGH() HAL_GPIO_WritePin(GD_CS_GPIO_Port, GD_CS_Pin, GPIO_PIN_SET)
#define GD5F_WP_HIGH() HAL_GPIO_WritePin(GD_WP_GPIO_Port, GD_WP_Pin, GPIO_PIN_SET)
#define GD5F_HOLD_HIGH() HAL_GPIO_WritePin(GD_HOLD_GPIO_Port, GD_HOLD_Pin, GPIO_PIN_SET)
/**
* @brief 初始化 GD5F2GQ5UESPI + GPIO + 读 ID 验证)
* @retval GD5F_OK 成功, 其他为错误码
/* ======================== 函数声明 ======================== */
/*
* 函数功能:初始化 GD5F2GQ5UE读 ID + 使能 ECC + 解除块保护)
* 入口参数:无
* 返回值0 - 成功,其他 - 错误码
* 限定条件SPI1 和相关 GPIO 已由 CubeMX 初始化完成
* 函数说明1. 发送复位命令并等待完成
* 2. 读取芯片 ID 并校验
* 3. 使能内部 ECC (B0h bit4)
* 4. 解除所有块保护 (A0h = 0x00)
*/
int gd5f2gq5ue_init(void);
/**
* @brief 读取芯片 IDMID + DID
* @param mid: 制造商 ID 输出指针
* @param did: 设备 ID 输出指针
* @retval GD5F_OK 成功
/*
* 函数功能:读取芯片 IDMID + DID
* 入口参数:mid - 制造商 ID 输出指针 uint8_t* 不为 NULL
* did - 设备 ID 输出指针 uint8_t* 不为 NULL
* 返回值0 - 成功
* 限定条件SPI 已初始化
* 函数说明:发送 9Fh 命令后接收1个 dummy + MID + DID
*/
int gd5f2gq5ue_read_id(uint8_t *mid, uint8_t *did);
/**
* @brief 从 NAND 读取数据(支持跨页)
* @param offset: 起始字节偏移(相对于 Flash 起始地址)
* @param buf: 数据缓冲区
* @param size: 读取字节数
* @retval GD5F_OK 成功
/*
* 函数功能:从 NAND 读取数据(支持跨页)
* 入口参数:offset - 起始字节偏移 long 0 - GD5F_TOTAL_SIZE-1
* buf - 数据缓冲区 uint8_t* 不为 NULL
* size - 读取字节数 size_t > 0
* 返回值0 - 成功,其他 - 错误码
* 限定条件gd5f2gq5ue_init() 已成功调用
* 函数说明:自动处理跨页读取,每次读取不超过当前页剩余空间
*/
int gd5f2gq5ue_read(long offset, uint8_t *buf, size_t size);
/**
* @brief 向 NAND 写入数据(支持跨页)
* @param offset: 起始字节偏移
* @param buf: 数据缓冲区
* @param size: 写入字节数
* @retval GD5F_OK 成功
/*
* 函数功能:向 NAND 写入数据(支持跨页)
* 入口参数:offset - 起始字节偏移 long 0 - GD5F_TOTAL_SIZE-1
* buf - 数据缓冲区 uint8_t* 不为 NULL
* size - 写入字节数 size_t > 0
* 返回值0 - 成功,其他 - 错误码
* 限定条件gd5f2gq5ue_init() 已成功调用,目标区域已擦除
* 函数说明:自动处理跨页写入,每次写入不超过当前页剩余空间
*/
int gd5f2gq5ue_write(long offset, const uint8_t *buf, size_t size);
/**
* @brief 擦除块(按块擦除,最小单位 128KB
* @param offset: 起始字节偏移(必须块对齐
* @param size: 擦除字节数(必须为块大小的整数倍
* @retval GD5F_OK 成功
/*
* 函数功能:擦除块(按块擦除,最小单位 128KB
* 入口参数:offset - 起始字节偏移 long 必须 GD5F_BLOCK_SIZE 对齐
* size - 擦除字节数 size_t 必须 GD5F_BLOCK_SIZE 整数倍
* 返回值0 - 成功,其他 - 错误码
* 限定条件gd5f2gq5ue_init() 已成功调用
* 函数说明擦除操作以块为单位offset 和 size 必须块对齐
*/
int gd5f2gq5ue_erase(long offset, size_t size);
/**
* @brief 复位芯片
* @retval GD5F_OK 成功
/*
* 函数功能:复位芯片
* 入口参数:无
* 返回值0 - 成功
* 限定条件SPI 已初始化
* 函数说明:发送 FFh 复位命令后等待 5ms
*/
int gd5f2gq5ue_reset(void);

133
Drivers/BSP/RS485/rs485.c Normal file
View File

@@ -0,0 +1,133 @@
/*
* 模块名称RS-485 半双工通信驱动
* 模块功能RS-485 半双工通信驱动实现,核心要点:
* 1. 发送前拉高 DE切换到发送态
* 2. HAL_UART_Transmit 内部已等待 TC发送完成标志
* 3. 发送完毕后拉低 DE切回接收态
* 4. 使用 HAL_UARTEx_ReceiveToIdle_IT 实现变长帧接收
* 参考ST AN3070 应用笔记、controllerstech.com RS485 教程
* 适用平台STM32F4 系列
* 作者:王建锋
* 创建日期2026-07-18
* 修改记录:
* 2026-07-18 王建锋 创建初始版本
*/
#include "rs485.h"
/*
* 内部辅助宏 - 方向控制
*/
#define RS485_DIR_TX(h) HAL_GPIO_WritePin((h)->dir_port, (h)->dir_pin, GPIO_PIN_SET)
#define RS485_DIR_RX(h) HAL_GPIO_WritePin((h)->dir_port, (h)->dir_pin, GPIO_PIN_RESET)
/*
* 公共函数实现
*/
/*
* 函数功能:初始化 RS-485 句柄
* 入口参数handle - RS-485 句柄指针
* huart - UART 外设句柄
* dir_port - DE 引脚 GPIO 端口
* dir_pin - DE 引脚 GPIO 编号
* 返回值:无
* 限定条件UART 和 GPIO 须先由 CubeMX 完成初始化
* 函数说明:初始化后立即将 DE 拉低,使 RS-485 收发器处于接收状态
*/
void rs485_init(rs485_handle_t *handle,
UART_HandleTypeDef *huart,
GPIO_TypeDef *dir_port,
uint16_t dir_pin)
{
handle->huart = huart;
handle->dir_port = dir_port;
handle->dir_pin = dir_pin;
handle->rx_size = 0;
/* 默认进入接收状态 */
RS485_DIR_RX(handle);
}
/*
* 函数功能:阻塞方式发送数据
* 入口参数handle - RS-485 句柄指针
* data - 待发送数据缓冲区
* len - 待发送字节数
* timeout - 发送超时ms传 0 使用默认值
* 返回值HAL_OK / HAL_TIMEOUT / HAL_ERROR
* 限定条件:须在主循环或 RTOS 任务中调用,不可在 UART 中断中调用
* 函数说明:
* 时序DE=HIGH → UART 发送 N 字节 → 等 TC → DE=LOW
* HAL_UART_Transmit 内部会等待 TXE发送寄存器空逐字节搬数据
* 最后还会等待 TC发送完成标志确保最后一字节的停止位已移出。
* 因此返回后再拉低 DE 是安全的
*/
HAL_StatusTypeDef rs485_transmit(rs485_handle_t *handle,
const uint8_t *data,
uint16_t len,
uint32_t timeout)
{
HAL_StatusTypeDef status;
if (timeout == 0U) {
timeout = RS485_TIMEOUT_DEFAULT;
}
/* 1. 切换到发送状态 */
RS485_DIR_TX(handle);
/* 2. 阻塞发送(内部等待 TC */
status = HAL_UART_Transmit(handle->huart,
(uint8_t *)data,
len,
timeout);
/* 3. 发送完毕或超时,切回接收状态 */
RS485_DIR_RX(handle);
return status;
}
/*
* 函数功能启动中断方式接收IDLE 空闲帧检测)
* 入口参数handle - RS-485 句柄指针
* buf - 接收缓冲区
* buf_size - 缓冲区最大容量
* 返回值HAL_OK / HAL_ERROR
* 限定条件UART 须已开启全局中断NVIC 使能)
* 函数说明:
* 使用 HAL_UARTEx_ReceiveToIdle_IT 实现变长帧接收。
* 当 UART 总线空闲超过 1 个字符时间后,硬件触发 IDLE 中断,
* HAL 自动调用 HAL_UARTEx_RxEventCallback 并返回已接收字节数。
* 用户须在该回调中重新调用本函数重新开启接收
*/
HAL_StatusTypeDef rs485_receive_start(rs485_handle_t *handle,
uint8_t *buf,
uint16_t buf_size)
{
handle->rx_size = 0;
return HAL_UARTEx_ReceiveToIdle_IT(handle->huart, buf, buf_size);
}
/*
* 函数功能:缓存最近一次接收的字节数
* 入口参数handle - RS-485 句柄指针
* size - 本次接收到的字节数
* 返回值:无
* 限定条件:须在 HAL_UARTEx_RxEventCallback 中调用
*/
void rs485_rx_set_size(rs485_handle_t *handle, uint16_t size)
{
handle->rx_size = size;
}
/*
* 函数功能:获取最近一次接收的字节数
* 入口参数handle - RS-485 句柄指针
* 返回值:字节数
*/
uint16_t rs485_rx_get_size(const rs485_handle_t *handle)
{
return handle->rx_size;
}

110
Drivers/BSP/RS485/rs485.h Normal file
View File

@@ -0,0 +1,110 @@
/*
* 模块名称RS-485 半双工通信驱动
* 模块功能RS-485 半双工通信驱动,封装任意 UART 外设实现 485 方向控制,
* 提供阻塞发送、中断接收IDLE 空闲帧检测、DMA 发送等功能。
* 参考 ST AN3070 应用笔记《IO-Link master: USART communication》
* 及 controllerstech.com RS485 教程
* 适用平台STM32F4 系列
* 作者:王建锋
* 创建日期2026-07-18
* 修改记录:
* 2026-07-18 王建锋 创建初始版本
*/
#ifndef __RS485_H
#define __RS485_H
#ifdef __cplusplus
extern "C" {
#endif
#include "main.h"
/*
* 常量定义
*/
#define RS485_TIMEOUT_DEFAULT 1000U /* 默认发送超时ms */
/*
* RS-485 句柄结构体
* 将任意 UART + 任意 GPIO 组合绑定为一个 RS-485 半双工通信实例
*/
typedef struct {
UART_HandleTypeDef *huart; /* UART 外设句柄 */
GPIO_TypeDef *dir_port; /* 方向控制 GPIO 端口 */
uint16_t dir_pin; /* 方向控制 GPIO 引脚号 */
volatile uint16_t rx_size; /* 最近一次接收的字节数 */
} rs485_handle_t;
/*
* 公共函数声明
*/
/*
* 函数功能:初始化 RS-485 句柄,绑定 UART 和方向控制引脚
* 入口参数handle - RS-485 句柄指针
* huart - UART 外设句柄指针(已由 CubeMX 初始化)
* dir_port - 方向控制 GPIO 端口(如 GPIOD
* dir_pin - 方向控制 GPIO 引脚号(如 GPIO_PIN_0
* 返回值:无
* 限定条件UART 和 GPIO 须先由 CubeMX 完成初始化
* 函数说明初始化后默认处于接收状态DE 引脚拉低)
*/
void rs485_init(rs485_handle_t *handle,
UART_HandleTypeDef *huart,
GPIO_TypeDef *dir_port,
uint16_t dir_pin);
/*
* 函数功能:阻塞方式发送数据
* 入口参数handle - RS-485 句柄指针
* data - 待发送数据缓冲区
* len - 待发送字节数
* timeout - 发送超时ms传 0 使用 RS485_TIMEOUT_DEFAULT
* 返回值HAL_OK / HAL_TIMEOUT / HAL_ERROR
* 限定条件:在主循环或任务中调用,不可在 UART 中断中调用
* 函数说明:发送前自动拉高 DE发送完成后等待 TC 标志再拉低 DE
* 确保最后一字节完全移出后再切换到接收状态
*/
HAL_StatusTypeDef rs485_transmit(rs485_handle_t *handle,
const uint8_t *data,
uint16_t len,
uint32_t timeout);
/*
* 函数功能启动中断方式接收IDLE 空闲帧检测)
* 入口参数handle - RS-485 句柄指针
* buf - 接收缓冲区
* buf_size - 缓冲区大小
* 返回值HAL_OK / HAL_ERROR
* 限定条件UART 须已开启全局中断NVIC 中须使能对应 UART 中断
* 函数说明:使用 HAL_UARTEx_ReceiveToIdle_IT 实现变长帧接收,
* 收到完整帧后在 RxEventCallback 中通知用户。
* 用户须在回调中重新调用本函数重新开启接收
*/
HAL_StatusTypeDef rs485_receive_start(rs485_handle_t *handle,
uint8_t *buf,
uint16_t buf_size);
/*
* 函数功能:将 RS-485 句柄与 HAL 回调关联
* 入口参数handle - RS-485 句柄指针
* 返回值:无
* 限定条件:须在 HAL_UART_RxCpltCallback / HAL_UARTEx_RxEventCallback 中调用
* 函数说明:将 HAL 回调中接收到的数据大小回写到句柄的 rx_size 字段
*/
void rs485_rx_set_size(rs485_handle_t *handle, uint16_t size);
/*
* 函数功能:获取最近一次接收的字节数
* 入口参数handle - RS-485 句柄指针
* 返回值:最近一次接收的字节数
* 限定条件:须在 HAL_UARTEx_RxEventCallback 触发后调用
*/
uint16_t rs485_rx_get_size(const rs485_handle_t *handle);
#ifdef __cplusplus
}
#endif
#endif /* __RS485_H */

381
Drivers/BSP/SD2506/sd2506.c Normal file
View File

@@ -0,0 +1,381 @@
/*
* 模块名称SD2506API-G RTC 实时时钟驱动
* 模块功能SD2506API-G 高精度温补实时时钟模块 I2C 驱动
* 适用平台STM32F407ZGT6I2C1 接口 (PB6-SCL, PB7-SDA)
* 作者:王建锋
* 创建日期2026-07-17
* 修改记录:
* 2026-07-17 王建锋 创建初始版本,参考 SD2506API-G Ver2.0 手册
*/
#include "sd2506.h"
#include "i2c.h"
#include <string.h>
extern I2C_HandleTypeDef hi2c1;
/* ======================== 内部辅助函数 ======================== */
uint8_t sd2506_bcd_to_dec(uint8_t bcd)
{
return ((bcd >> 4) * 10) + (bcd & 0x0FU);
}
uint8_t sd2506_dec_to_bcd(uint8_t dec)
{
return ((dec / 10) << 4) | (dec % 10);
}
/*
* 写单字节寄存器
* reg: 寄存器地址 (00H~79H)
* val: 写入值
* 返回: 0=成功, -2=I2C错误
*/
static int sd2506_write_reg(uint8_t reg, uint8_t val)
{
if (HAL_I2C_Mem_Write(&hi2c1, SD2506_I2C_ADDR_WRITE, reg,
I2C_MEMADD_SIZE_8BIT, &val, 1,
SD2506_I2C_TIMEOUT_MS) != HAL_OK) {
return SD2506_I2C_ERROR;
}
return SD2506_OK;
}
/*
* 读单字节寄存器
* reg: 寄存器地址 (00H~79H)
* val: 读取值指针
* 返回: 0=成功, -2=I2C错误
*/
static int sd2506_read_reg(uint8_t reg, uint8_t *val)
{
if (HAL_I2C_Mem_Read(&hi2c1, SD2506_I2C_ADDR_READ, reg,
I2C_MEMADD_SIZE_8BIT, val, 1,
SD2506_I2C_TIMEOUT_MS) != HAL_OK) {
return SD2506_I2C_ERROR;
}
return SD2506_OK;
}
/*
* 写多字节寄存器 (从 reg 开始连续写入 len 字节)
* reg: 起始寄存器地址
* data: 数据缓冲区
* len: 数据长度
* 返回: 0=成功, -2=I2C错误
*/
static int sd2506_write_regs(uint8_t reg, const uint8_t *data, uint8_t len)
{
if (HAL_I2C_Mem_Write(&hi2c1, SD2506_I2C_ADDR_WRITE, reg,
I2C_MEMADD_SIZE_8BIT, (uint8_t *)data, len,
SD2506_I2C_TIMEOUT_MS) != HAL_OK) {
return SD2506_I2C_ERROR;
}
return SD2506_OK;
}
/*
* 读多字节寄存器 (从 reg 开始连续读取 len 字节)
* reg: 起始寄存器地址
* data: 数据缓冲区
* len: 数据长度
* 返回: 0=成功, -2=I2C错误
*/
static int sd2506_read_regs(uint8_t reg, uint8_t *data, uint8_t len)
{
if (HAL_I2C_Mem_Read(&hi2c1, SD2506_I2C_ADDR_READ, reg,
I2C_MEMADD_SIZE_8BIT, data, len,
SD2506_I2C_TIMEOUT_MS) != HAL_OK) {
return SD2506_I2C_ERROR;
}
return SD2506_OK;
}
/*
* 开启写保护 (允许写入 00H~71H 寄存器)
* 顺序: 先写 WRTC1=1, 再写 WRTC2=1 + WRTC3=1
*/
static int sd2506_write_enable(void)
{
int ret;
/* 先置 WRTC1=1 (bit6=1), 其它位参考手册: 0x84 */
ret = sd2506_write_reg(SD2506_REG_CTR1, 0x84U);
if (ret != SD2506_OK) return ret;
/* 再置 WRTC2=1(bit5) + WRTC3=1(bit4): 0x8C */
ret = sd2506_write_reg(SD2506_REG_CTR2, 0x8CU);
if (ret != SD2506_OK) return ret;
return SD2506_OK;
}
/*
* 关闭写保护 (禁止写入 00H~71H 寄存器)
* 顺序: 先写 WRTC2=0 + WRTC3=0, 再写 WRTC1=0
*/
static int sd2506_write_disable(void)
{
int ret;
/* 先清 WRTC2=0, WRTC3=0: 0x00 */
ret = sd2506_write_reg(SD2506_REG_CTR2, 0x00U);
if (ret != SD2506_OK) return ret;
/* 再清 WRTC1=0, 同时 ARST=1 使能自动复位: 0x20 */
ret = sd2506_write_reg(SD2506_REG_CTR1, SD2506_CTR1_WRITE_OFF);
if (ret != SD2506_OK) return ret;
return SD2506_OK;
}
/* ======================== 公共 API 实现 ======================== */
int sd2506_init(void)
{
int ret;
uint8_t id[8];
/* 验证 I2C 通信: 尝试读取 8 字节 ID */
ret = sd2506_read_regs(SD2506_REG_ID_START, id, SD2506_ID_SIZE);
if (ret != SD2506_OK) {
return ret;
}
/* 上电重置充电寄存器 18H = 82H (开启充电, 5K电阻)
* 手册强烈建议每次上电时重置此值 */
ret = sd2506_write_reg(SD2506_REG_CHARGE, 0x82U);
if (ret != SD2506_OK) {
return ret;
}
/* 配置: 24小时制, 自动复位使能
* 0FH = 0x20 (bit5=ARST=1, 其它标志位清零)
* 写入时需注意: 写允许状态下 0FH 的 WRTC 位必须为1
* 此处直接写入 0x20 即可 (ARST=1, 无 WRTC 位) */
ret = sd2506_write_reg(SD2506_REG_CTR1, SD2506_CTR1_WRITE_OFF);
if (ret != SD2506_OK) {
return ret;
}
return SD2506_OK;
}
int sd2506_set_time(const sd2506_time_t *time)
{
int ret;
uint8_t buf[7];
if (time == NULL) {
return SD2506_ERROR;
}
/* 组装 7 字节时间数据 (BCD 码) */
buf[0] = sd2506_dec_to_bcd(time->second); /* 00H: 秒 */
buf[1] = sd2506_dec_to_bcd(time->minute); /* 01H: 分 */
buf[2] = sd2506_dec_to_bcd(time->hour) | 0x80U; /* 02H: 时 (bit7=1, 24小时制) */
buf[3] = sd2506_dec_to_bcd(time->week); /* 03H: 星期 */
buf[4] = sd2506_dec_to_bcd(time->day); /* 04H: 日 */
buf[5] = sd2506_dec_to_bcd(time->month); /* 05H: 月 */
buf[6] = sd2506_dec_to_bcd(time->year - 2000U); /* 06H: 年 */
/* 开启写保护 */
ret = sd2506_write_enable();
if (ret != SD2506_OK) return ret;
/* 一次性写入 7 字节时间数据 (00H~06H)
* 手册要求: 不可单独写某一个时间寄存器,否则可能引起错误进位 */
ret = sd2506_write_regs(SD2506_REG_SEC, buf, 7);
if (ret != SD2506_OK) return ret;
/* 关闭写保护 */
ret = sd2506_write_disable();
if (ret != SD2506_OK) return ret;
return SD2506_OK;
}
int sd2506_get_time(sd2506_time_t *time)
{
int ret;
uint8_t buf[7];
if (time == NULL) {
return SD2506_ERROR;
}
/* 一次读取 7 字节时间数据 (00H~06H)
* 手册说明: 读取时所有实时数据被锁存,避免错读 */
ret = sd2506_read_regs(SD2506_REG_SEC, buf, 7);
if (ret != SD2506_OK) {
return ret;
}
time->second = sd2506_bcd_to_dec(buf[0] & 0x7FU); /* 00H: 秒 */
time->minute = sd2506_bcd_to_dec(buf[1] & 0x7FU); /* 01H: 分 */
time->hour = sd2506_bcd_to_dec(buf[2] & 0x7FU); /* 02H: 屏蔽 bit7 (12/24标志) */
time->week = sd2506_bcd_to_dec(buf[3] & 0x07U); /* 03H: 星期 */
time->day = sd2506_bcd_to_dec(buf[4] & 0x3FU); /* 04H: 日 */
time->month = sd2506_bcd_to_dec(buf[5] & 0x1FU); /* 05H: 月 */
time->year = sd2506_bcd_to_dec(buf[6]) + 2000U; /* 06H: 年 */
return SD2506_OK;
}
int sd2506_get_temperature(int8_t *temp)
{
int ret;
uint8_t val;
if (temp == NULL) {
return SD2506_ERROR;
}
ret = sd2506_read_reg(SD2506_REG_TEMP, &val);
if (ret != SD2506_OK) {
return ret;
}
/* bit7 为符号位, 其余为温度值 */
if (val & 0x80U) {
/* 负温度: 取补码 */
*temp = (int8_t)(val | 0xF0U);
} else {
/* 正温度 */
*temp = (int8_t)(val & 0x7FU);
}
return SD2506_OK;
}
int sd2506_get_battery_voltage(uint16_t *voltage)
{
int ret;
uint8_t val_high, val_low;
if (voltage == NULL) {
return SD2506_ERROR;
}
/* 读取 1AH bit7 (BAT8_VAL) 和 1BH (BAT_VL) */
ret = sd2506_read_reg(SD2506_REG_CTR5, &val_high);
if (ret != SD2506_OK) return ret;
ret = sd2506_read_reg(SD2506_REG_BAT_VAL, &val_low);
if (ret != SD2506_OK) return ret;
/* 组合 9 位: bit8=BAT8_VAL(1AH bit7), bit7~0=BAT_VL(1BH)
* 如 1AH=80H, 1BH=30H => 电压 = 0x130 = 304 => 3.04V => 3040mV */
uint16_t raw = ((val_high & 0x80U) << 1) | val_low;
*voltage = raw * 10; /* 转换为毫伏 (raw 单位 0.01V) */
return SD2506_OK;
}
int sd2506_get_id(uint8_t id[8])
{
if (id == NULL) {
return SD2506_ERROR;
}
return sd2506_read_regs(SD2506_REG_ID_START, id, SD2506_ID_SIZE);
}
int sd2506_read_sram(uint8_t addr, uint8_t *buf, uint8_t len)
{
if (buf == NULL || len == 0 || addr >= SD2506_SRAM_SIZE) {
return SD2506_ERROR;
}
if (addr + len > SD2506_SRAM_SIZE) {
return SD2506_ERROR;
}
return sd2506_read_regs(SD2506_REG_SRAM_START + addr, buf, len);
}
int sd2506_write_sram(uint8_t addr, const uint8_t *buf, uint8_t len)
{
if (buf == NULL || len == 0 || addr >= SD2506_SRAM_SIZE) {
return SD2506_ERROR;
}
if (addr + len > SD2506_SRAM_SIZE) {
return SD2506_ERROR;
}
/* SRAM 无需开写保护即可写入 (写保护仅对 00H~71H 有效, SRAM 是 2CH~71H)
* 但为安全起见, SRAM 写入也走写保护流程 */
int ret;
ret = sd2506_write_enable();
if (ret != SD2506_OK) return ret;
ret = sd2506_write_regs(SD2506_REG_SRAM_START + addr, buf, len);
if (ret != SD2506_OK) return ret;
ret = sd2506_write_disable();
return ret;
}
int sd2506_set_alarm(const sd2506_time_t *time, uint8_t mask)
{
int ret;
uint8_t buf[8];
if (time == NULL) {
return SD2506_ERROR;
}
/* 组装 8 字节报警数据 (07H~0EH) */
buf[0] = sd2506_dec_to_bcd(time->second) & 0x7FU; /* 07H: 秒报警 */
buf[1] = sd2506_dec_to_bcd(time->minute) & 0x7FU; /* 08H: 分报警 */
buf[2] = sd2506_dec_to_bcd(time->hour) & 0x3FU; /* 09H: 时报警 (最高位始终为0) */
buf[3] = 0x00U; /* 0AH: 星期报警 */
buf[4] = sd2506_dec_to_bcd(time->day) & 0x3FU; /* 0BH: 日报警 */
buf[5] = sd2506_dec_to_bcd(time->month) & 0x1FU; /* 0CH: 月报警 */
buf[6] = sd2506_dec_to_bcd(time->year - 2000U); /* 0DH: 年报警 */
buf[7] = mask; /* 0EH: 报警允许 */
/* 开启写保护 */
ret = sd2506_write_enable();
if (ret != SD2506_OK) return ret;
/* 写入报警寄存器 (07H~0EH) */
ret = sd2506_write_regs(SD2506_REG_AL_SEC, buf, 8);
if (ret != SD2506_OK) return ret;
/* 使能报警中断: CTR2 的 INTAE=1, INTS1=0, INTS0=1, IM=1 (周期性) */
ret = sd2506_write_reg(SD2506_REG_CTR2,
SD2506_CTR2_INTAE | SD2506_CTR2_INTS0 | SD2506_CTR2_IM);
if (ret != SD2506_OK) return ret;
/* 关闭写保护 */
ret = sd2506_write_disable();
if (ret != SD2506_OK) return ret;
return SD2506_OK;
}
int sd2506_clear_alarm(void)
{
int ret;
uint8_t val;
/* 读取 CTR1, ARST=1 时自动清除 INTAF */
ret = sd2506_read_reg(SD2506_REG_CTR1, &val);
if (ret != SD2506_OK) {
return ret;
}
return SD2506_OK;
}
int sd2506_read_ctr1(uint8_t *val)
{
if (val == NULL) {
return SD2506_ERROR;
}
return sd2506_read_reg(SD2506_REG_CTR1, val);
}

296
Drivers/BSP/SD2506/sd2506.h Normal file
View File

@@ -0,0 +1,296 @@
/*
* 模块名称SD2506API-G RTC 实时时钟驱动
* 模块功能SD2506API-G 高精度温补实时时钟模块 I2C 驱动,提供时间读写、
* 温度读取、电池电压检测、ID 读取等功能
* 适用平台STM32F407ZGT6I2C1 接口 (PB6-SCL, PB7-SDA)
* 作者:王建锋
* 创建日期2026-07-17
* 修改记录:
* 2026-07-17 王建锋 创建初始版本,参考 SD2506API-G Ver2.0 手册
*/
#ifndef __SD2506_H
#define __SD2506_H
#ifdef __cplusplus
extern "C" {
#endif
#include "main.h"
/* ======================== I2C 地址 ======================== */
/*
* SD2506API-G 7位器件地址: 0x32
* HAL库使用8位地址: 写 0x64, 读 0x65
*/
#define SD2506_I2C_ADDR 0x32U
#define SD2506_I2C_ADDR_WRITE 0x64U
#define SD2506_I2C_ADDR_READ 0x65U
/* ======================== 寄存器地址定义 ======================== */
/* 实时时钟寄存器 (00H~06H) */
#define SD2506_REG_SEC 0x00U /* 秒 00~59 BCD */
#define SD2506_REG_MIN 0x01U /* 分 00~59 BCD */
#define SD2506_REG_HOUR 0x02U /* 时 00~23 BCD, bit7=12/24 */
#define SD2506_REG_WEEK 0x03U /* 星期 00~06 BCD */
#define SD2506_REG_DAY 0x04U /* 日 01~31 BCD */
#define SD2506_REG_MON 0x05U /* 月 01~12 BCD */
#define SD2506_REG_YEAR 0x06U /* 年 00~99 BCD */
/* 报警寄存器 (07H~0EH) */
#define SD2506_REG_AL_SEC 0x07U /* 秒报警 */
#define SD2506_REG_AL_MIN 0x08U /* 分报警 */
#define SD2506_REG_AL_HOUR 0x09U /* 时报警 */
#define SD2506_REG_AL_WEEK 0x0AU /* 星期报警 */
#define SD2506_REG_AL_DAY 0x0BU /* 日报警 */
#define SD2506_REG_AL_MON 0x0CU /* 月报警 */
#define SD2506_REG_AL_YEAR 0x0DU /* 年报警 */
#define SD2506_REG_AL_EN 0x0EU /* 报警允许寄存器 */
/* 控制寄存器 */
#define SD2506_REG_CTR1 0x0FH /* 控制寄存器1 */
#define SD2506_REG_CTR2 0x10U /* 控制寄存器2 */
#define SD2506_REG_CTR3 0x11U /* 控制寄存器3 */
/* 倒计时寄存器 (13H~15H) */
#define SD2506_REG_CNT0 0x13U /* 倒计时字节0 (LSB) */
#define SD2506_REG_CNT1 0x14U /* 倒计时字节1 */
#define SD2506_REG_CNT2 0x15U /* 倒计时字节2 (MSB) */
/* 温度寄存器 */
#define SD2506_REG_TEMP 0x16U /* 温度值 (bit7=符号位) */
#define SD2506_REG_AGTC 0x17U /* IIC控制寄存器 AGTC */
#define SD2506_REG_CHARGE 0x18U /* 充电选择寄存器 */
#define SD2506_REG_CTR4 0x19U /* 扩展控制寄存器 CTR4 */
#define SD2506_REG_CTR5 0x1AU /* 控制寄存器 CTR5 */
#define SD2506_REG_BAT_VAL 0x1BU /* 电池电压低8位 */
/* 温度报警及历史 */
#define SD2506_REG_TEMP_AL 0x1CU /* 低温报警温度值 */
#define SD2506_REG_TEMP_AH 0x1DU /* 高温报警温度值 */
#define SD2506_REG_TEMP_HIS_L 0x1EU /* 历史低温 */
#define SD2506_REG_TEMP_HIS_H 0x1FU /* 历史高温 */
/* 用户 SRAM (2CH~71H) */
#define SD2506_REG_SRAM_START 0x2CU
#define SD2506_REG_SRAM_END 0x71U
#define SD2506_SRAM_SIZE 70U /* 70字节 */
/* ID 码 (72H~79H) */
#define SD2506_REG_ID_START 0x72U
#define SD2506_REG_ID_END 0x79U
#define SD2506_ID_SIZE 8U /* 8字节 */
/* ======================== 控制位定义 ======================== */
/* 控制寄存器 1 (0FH) */
#define SD2506_CTR1_ARST (1U << 5) /* 自动复位使能 */
#define SD2506_CTR1_INTAF (1U << 3) /* 报警中断标志 */
#define SD2506_CTR1_INTDF (1U << 2) /* 倒计时中断标志 */
#define SD2506_CTR1_BLF (1U << 0) /* 电池欠压标志 */
/* 控制寄存器 2 (10H) */
#define SD2506_CTR2_INTAE (1U << 5) /* 报警中断允许 */
#define SD2506_CTR2_INTFE (1U << 4) /* 频率中断允许 */
#define SD2506_CTR2_INTDE (1U << 3) /* 倒计时中断允许 */
#define SD2506_CTR2_IM (1U << 2) /* 中断模式: 0=单事件, 1=周期 */
#define SD2506_CTR2_INTS1 (1U << 1) /* INT输出选择 bit1 */
#define SD2506_CTR2_INTS0 (1U << 0) /* INT输出选择 bit0 */
/* 报警允许寄存器 (0EH) */
#define SD2506_AL_EN_EAY (1U << 6) /* 年报警允许 */
#define SD2506_AL_EN_EAMO (1U << 5) /* 月报警允许 */
#define SD2506_AL_EN_EAD (1U << 4) /* 日报警允许 */
#define SD2506_AL_EN_EAW (1U << 3) /* 星期报警允许 */
#define SD2506_AL_EN_EAH (1U << 2) /* 时报警允许 */
#define SD2506_AL_EN_EAMN (1U << 1) /* 分报警允许 */
#define SD2506_AL_EN_EAS (1U << 0) /* 秒报警允许 */
/* 24/12小时制位 */
#define SD2506_HOUR_24 (1U << 7) /* bit7=1 表示24小时制 */
/* ======================== 充电配置 ======================== */
/* 充电寄存器 (18H) 建议上电写入值: 0x82 (开启充电, 断开) */
#define SD2506_CHARGE_EN (1U << 7) /* 充电允许位 */
#define SD2506_CHARGE_2K (0U << 0) /* 2K电阻 */
#define SD2506_CHARGE_5K (1U << 0) /* 5K电阻 */
/* ======================== 写保护配置 ======================== */
/* 写允许时 0FH 寄存器建议值: 0xFF (WRTC1=1, WRTC2=1, WRTC3=1) */
#define SD2506_CTR1_WRITE_ON 0xFFU
/* 写禁止时 0FH 寄存器建议值: 0x7B (WRTC1=0, WRTC2=0, WRTC3=0, ARST=1) */
#define SD2506_CTR1_WRITE_OFF 0x7BU
/* ======================== 返回值定义 ======================== */
#define SD2506_OK 0
#define SD2506_ERROR -1
#define SD2506_I2C_ERROR -2
/* ======================== 超时时间 ======================== */
#define SD2506_I2C_TIMEOUT_MS 100
/* ======================== 数据结构 ======================== */
/*
* RTC 时间日期结构体
* year: 2000~2099
* month: 1~12
* day: 1~31
* hour: 0~23 (24小时制)
* minute: 0~59
* second: 0~59
* week: 0~6 (0=星期天, 1=星期一, ..., 6=星期六)
*/
typedef struct {
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t week;
} sd2506_time_t;
/* ======================== 函数声明 ======================== */
/*
* 函数功能:初始化 SD2506API-G RTC
* 入口参数:无
* 返回值0 - 成功,-2 - I2C 通信错误
* 限定条件CubeMX 已完成 I2C1 初始化
* 函数说明1. 读取芯片 ID 验证通信
* 2. 上电重置充电寄存器 18H=82H
* 3. 配置 24 小时制、开自动复位
*/
int sd2506_init(void);
/*
* 函数功能:设置 RTC 时间日期
* 入口参数time - 时间结构体指针,包含要设置的时间
* 返回值0 - 成功,-2 - I2C 通信错误
* 限定条件sd2506_init() 已调用
* 函数说明1. 先开写保护
* 2. 一次性写入 7 字节时间数据 (00H~06H)
* 3. 关闭写保护
* 注意:不可单独写某一个时间寄存器
*/
int sd2506_set_time(const sd2506_time_t *time);
/*
* 函数功能:读取 RTC 时间日期
* 入口参数time - 时间结构体指针,用于存储读取结果
* 返回值0 - 成功,-2 - I2C 通信错误
* 限定条件sd2506_init() 已调用
* 函数说明1. 一次读取 7 字节时间数据 (00H~06H)
* 2. BCD 转十进制
* 3. 屏蔽小时 bit7 (12/24标志位)
*/
int sd2506_get_time(sd2506_time_t *time);
/*
* 函数功能:读取芯片内部温度
* 入口参数temp - 温度输出指针 (整数部分, 有符号)
* 返回值0 - 成功,-2 - I2C 通信错误
* 限定条件sd2506_init() 已调用
* 函数说明:读取 16H 寄存器bit7 为符号位,范围 -40~+85
*/
int sd2506_get_temperature(int8_t *temp);
/*
* 函数功能:读取电池电压 (毫伏)
* 入口参数voltage - 电压输出指针 (单位: mV)
* 返回值0 - 成功,-2 - I2C 通信错误
* 限定条件sd2506_init() 已调用
* 函数说明1. 读取 1AH bit7 (BAT8_VAL) 和 1BH (BAT_VL)
* 2. 组合 9 位数据得到电压值 (如 0x135 = 309 = 3.09V)
*/
int sd2506_get_battery_voltage(uint16_t *voltage);
/*
* 函数功能:读取芯片 8 字节 ID
* 入口参数id - 8 字节输出缓冲区
* 返回值0 - 成功,-2 - I2C 通信错误
* 限定条件sd2506_init() 已调用
* 函数说明:读取 72H~79H 共 8 字节唯一 ID
*/
int sd2506_get_id(uint8_t id[8]);
/*
* 函数功能:读取用户 SRAM 数据
* 入口参数addr - SRAM 起始地址 (0~69)
* buf - 数据输出缓冲区
* len - 读取长度 (1~70)
* 返回值0 - 成功,-2 - I2C 通信错误,-1 - 参数错误
* 限定条件sd2506_init() 已调用
* 函数说明SRAM 地址范围 0~69对应寄存器 2CH~71H
*/
int sd2506_read_sram(uint8_t addr, uint8_t *buf, uint8_t len);
/*
* 函数功能:写入用户 SRAM 数据
* 入口参数addr - SRAM 起始地址 (0~69)
* buf - 数据输入缓冲区
* len - 写入长度 (1~70)
* 返回值0 - 成功,-2 - I2C 通信错误,-1 - 参数错误
* 限定条件sd2506_init() 已调用
* 函数说明SRAM 地址范围 0~69对应寄存器 2CH~71H
* SRAM 无需开写保护即可写入
*/
int sd2506_write_sram(uint8_t addr, const uint8_t *buf, uint8_t len);
/*
* 函数功能:设置报警中断
* 入口参数time - 报警时间结构体
* mask - 报警匹配掩码 (SD2506_AL_EN_xxx 位或组合)
* 返回值0 - 成功,-2 - I2C 通信错误
* 限定条件sd2506_init() 已调用
* 函数说明1. 开写保护
* 2. 写入报警寄存器 (07H~0EH)
* 3. 使能报警中断 INTAE
* 4. 关写保护
*/
int sd2506_set_alarm(const sd2506_time_t *time, uint8_t mask);
/*
* 函数功能:清除报警中断标志
* 入口参数:无
* 返回值0 - 成功,-2 - I2C 通信错误
* 限定条件sd2506_init() 已调用
* 函数说明:读取 CTR1 自动清除 INTAF (ARST=1 时)
*/
int sd2506_clear_alarm(void);
/*
* 函数功能:读取当前 0FH 控制寄存器1 状态
* 入口参数val - 输出值指针
* 返回值0 - 成功,-2 - I2C 通信错误
*/
int sd2506_read_ctr1(uint8_t *val);
/*
* 函数功能BCD 码转十进制
* 入口参数bcd - BCD 码值
* 返回值:十进制值
* 函数说明:内部辅助函数
*/
uint8_t sd2506_bcd_to_dec(uint8_t bcd);
/*
* 函数功能:十进制转 BCD 码
* 入口参数dec - 十进制值
* 返回值BCD 码值
* 函数说明:内部辅助函数
*/
uint8_t sd2506_dec_to_bcd(uint8_t dec);
#ifdef __cplusplus
}
#endif
#endif /* __SD2506_H */

View File

@@ -0,0 +1,354 @@
/*
* 模块名称TPAFE5160 16位8通道同步采样ADC驱动
* 模块功能:提供 TPAFE5160 并行接口模式下的初始化、过采样设置、转换启动、数据读取接口
* 适用平台STM32F407ZGT6并行16位数据总线接 GPIOG[15:0]
* 作者:王建锋
* 创建日期2026-07-17
* 修改记录:
* 2026-07-17 王建锋 创建初始版本,参考 AD7606 并行驱动及 TPAFE5160 手册
* 2026-07-17 王建锋 增加 EXTI 中断读取模式
*/
/* 头文件包含区 */
#include "tpafe5160.h"
/* ======================== 私有宏定义 ======================== */
/*
* 并行读取时序延时 (168MHz 主频1 NOP ≈ 5.95ns)
*
* TPAFE5160 并行时序要求 (VDRIVE > 2.7V)
* t10 (RD 低脉宽) ≥ 22ns
* t11 (RD 高脉宽) ≥ 10ns
* t14 (数据访问时间) ≤ 21ns (从 RD 下降沿算起)
* t15 (数据保持时间) ≥ 6ns (从 RD 下降沿算起)
*
* GPIO 写操作本身约 1 个 AHB 周期 (~6ns)
* 加上端口延迟 (~12-18ns),实际 RD 引脚翻转滞后约 18-24ns。
* 因此 NOP 延时只需覆盖数据建立时间即可。
*/
#define TP_NOP_5() __NOP(); __NOP(); __NOP(); __NOP(); __NOP()
/* RD 低脉宽延时GPIO写(~6ns) + 5NOP(~30ns) > 22ns */
#define TP_RD_LOW_DLY() do { TPAFE5160_RD_LOW(); TP_NOP_5(); } while (0)
/* RD 高脉宽延时GPIO写(~6ns) + 3NOP(~18ns) > 10ns */
#define TP_RD_HIGH_DLY() do { TPAFE5160_RD_HIGH(); __NOP(); __NOP(); __NOP(); } while (0)
/* CONVST 脉冲延时上升沿前需保证低电平5NOP 覆盖 t5 ≥ 20ns */
#define TP_CONVST_PULSE() do { \
TPAFE5160_CONVST_LOW(); \
TP_NOP_5(); \
TPAFE5160_CONVST_HIGH(); \
TP_NOP_5(); \
} while (0)
/* ======================== 私有函数声明 ======================== */
static void tpafe5160_read_channels(uint8_t count, int16_t *buf);
/* ======================== 公共函数定义 ======================== */
/*
* 函数功能:初始化 TPAFE5160设置过采样、等待就绪
* 入口参数:无
* 返回值0 - 成功,-2 - BUSY 超时
* 限定条件CubeMX 已完成 GPIO 初始化
* 函数说明1. 设置过采样为无过采样 (000)
* 2. 确保 RD 为高、CONVST 为低
* 3. 等待 BUSY 释放(转换空闲)
*/
int tpafe5160_init(void)
{
/* 设置默认过采样:无过采样 (OS[2:0] = 000) */
tpafe5160_set_os(TP_OS_NONE);
/* 确保控制引脚处于空闲状态 */
TPAFE5160_RD_HIGH();
TPAFE5160_CONVST_LOW();
/* 等待 BUSY 释放,确保上电后无残留转换 */
return tpafe5160_wait_busy(TPAFE5160_CONV_TIMEOUT_MS);
}
/*
* 函数功能:设置过采样率
* 入口参数os - 过采样率枚举值 tpafe5160_os_t
* 返回值:无
* 限定条件GPIO 已初始化
* 函数说明:通过 OS[2:0] 引脚设置过采样率,在下一次 BUSY 下降沿锁存生效
*/
void tpafe5160_set_os(tpafe5160_os_t os)
{
TPAFE5160_OS0(os & 0x01); /* OS0 = bit0 */
TPAFE5160_OS1((os >> 1) & 0x01); /* OS1 = bit1 */
TPAFE5160_OS2((os >> 2) & 0x01); /* OS2 = bit2 */
}
/*
* 函数功能启动一次转换CONVST 上升沿触发)
* 入口参数:无
* 返回值:无
* 限定条件GPIO 已初始化
* 函数说明:产生 CONVST 脉冲上升沿启动全部8通道同步采样与转换
*/
void tpafe5160_start_conv(void)
{
TP_CONVST_PULSE();
}
/*
* 函数功能:等待转换完成
* 入口参数timeout_ms - 超时时间 uint32_t > 0
* 返回值0 - 转换完成,-2 - 超时
* 限定条件:已调用 tpafe5160_start_conv()
* 函数说明:轮询 BUSY 引脚等待下降沿
*/
int tpafe5160_wait_busy(uint32_t timeout_ms)
{
uint32_t tick_start = HAL_GetTick();
/* 等待 BUSY 释放(低电平表示空闲) */
while (TPAFE5160_BUSY_READ() == GPIO_PIN_SET) {
if ((HAL_GetTick() - tick_start) >= timeout_ms) {
return TPAFE5160_BUSY_TIMEOUT;
}
}
return TPAFE5160_OK;
}
/*
* 函数功能:查询当前是否正在转换
* 入口参数:无
* 返回值1 - 正在转换0 - 空闲
* 限定条件GPIO 已初始化
* 函数说明:读取 BUSY 引脚电平
*/
uint8_t tpafe5160_is_busy(void)
{
return (TPAFE5160_BUSY_READ() == GPIO_PIN_SET) ? 1 : 0;
}
/*
* 函数功能读取全部8通道转换结果
* 入口参数buf - 8个int16_t的输出缓冲区 int16_t* 不为 NULL
* 返回值0 - 成功,-2 - BUSY 超时
* 限定条件GPIO 已初始化
* 函数说明1. 启动转换并等待 BUSY 释放
* 2. 连续8次拉低RD读取各通道数据
* 3. 通过 FRSTDATA 验证第一通道
*/
int tpafe5160_read_all(int16_t *buf)
{
int ret;
/* 启动转换 */
tpafe5160_start_conv();
/* 等待转换完成 */
ret = tpafe5160_wait_busy(TPAFE5160_CONV_TIMEOUT_MS);
if (ret != TPAFE5160_OK) {
return ret;
}
/* 连续读取8个通道 */
tpafe5160_read_channels(TPAFE5160_CH_NUM, buf);
return TPAFE5160_OK;
}
/*
* 函数功能:读取指定通道的转换结果
* 入口参数channel - 通道号 uint8_t 0 - 7
* value - 输出指针 int16_t* 不为 NULL
* 返回值0 - 成功,-1 - 通道号无效,-2 - BUSY 超时
* 限定条件GPIO 已初始化
* 函数说明:启动转换并等待完成后,连续读取至指定通道
*/
int tpafe5160_read_channel(uint8_t channel, int16_t *value)
{
int ret;
int16_t buf[TPAFE5160_CH_NUM];
if (channel >= TPAFE5160_CH_NUM || value == NULL) {
return TPAFE5160_ERROR;
}
ret = tpafe5160_read_all(buf);
if (ret != TPAFE5160_OK) {
return ret;
}
*value = buf[channel];
return TPAFE5160_OK;
}
/*
* 函数功能原始ADC值转电压值
* 入口参数raw - ADC原始值 int16_t 有符号补码
* 返回值:电压值 float 单位 V
* 限定条件:无
* 函数说明±5V量程时 LSB = 10V / 65536 ≈ 152.59μV
* ±10V量程时 LSB = 20V / 65536 ≈ 305.18μV
* 硬件 RANGE 引脚接 GND默认 ±5V 量程
*/
float tpafe5160_to_voltage(int16_t raw)
{
/* RANGE 接 GND → ±5V 量程,满量程 10V */
return (float)raw * (10.0f / 65536.0f);
}
/*
* 函数功能:直接读取并行数据总线(不启动转换)
* 入口参数:无
* 返回值16位原始数据 uint16_t
* 限定条件RD 为低或 CS 与 RD 已拉低
* 函数说明:读取 GPIOG->IDR 低16位对应 DB[15:0]
*/
uint16_t tpafe5160_read_bus(void)
{
return TPAFE5160_READ_BUS();
}
/* ======================== 私有函数定义 ======================== */
/*
* 函数功能:通过 RD 脉冲连续读取多个通道数据
* 入口参数count - 要读取的通道数 uint8_t 1 - 8
* buf - 输出缓冲区 int16_t* 不为 NULL
* 返回值:无
* 限定条件转换已完成BUSY 为低RD 初始为高
* 函数说明:每次 RD 下降沿输出一个通道数据按通道1~8顺序输出
* DB[15:0] 直接接 GPIOG[15:0],通过 IDR 寄存器一次读取
*
* 时序关键点 (VDRIVE > 2.7V, 168MHz 主频)
* GPIO 写操作 ~6ns + 端口延迟 ~18ns → RD 引脚实际翻转约 24ns 后
* t14 数据建立 ≤ 21ns → 数据在 RD 下降沿后 21ns 内有效
* 5 个 NOP (~30ns) 覆盖建立时间
*/
static void tpafe5160_read_channels(uint8_t count, int16_t *buf)
{
uint8_t i;
for (i = 0; i < count; i++) {
/* RD 下降沿ADC 输出当前通道数据到 DB[15:0] */
TP_RD_LOW_DLY();
/* 读取16位并行数据 */
buf[i] = (int16_t)TPAFE5160_READ_BUS();
/* RD 上升沿:准备下一通道 */
TP_RD_HIGH_DLY();
}
}
/* ======================== 中断模式实现 ======================== */
/* 双缓冲区ISR 写 s_buf_b主循环读 s_buf_a */
static int16_t s_buf_a[TPAFE5160_CH_NUM];
static int16_t s_buf_b[TPAFE5160_CH_NUM];
static volatile uint8_t s_ready = 0;
static volatile uint8_t s_buf_sel = 0; /* 0 = 写 B / 读 A, 1 = 写 A / 读 B */
/*
* 函数功能:使能 BUSY EXTI 中断(运行时重使能用)
* 入口参数:无
* 返回值:无
* 限定条件CubeMX 已完成 GPIO 和 NVIC 配置
* 函数说明:正常启动流程无需调用,仅在 irq_disable() 后需要重新使能时使用
*/
void tpafe5160_irq_enable(void)
{
HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
}
/*
* 函数功能:关闭 BUSY EXTI 中断
* 入口参数:无
* 返回值:无
* 限定条件:已调用 tpafe5160_irq_enable()
* 函数说明:仅禁用 NVIC 中断GPIO 配置保持 CubeMX 设定
*/
void tpafe5160_irq_disable(void)
{
HAL_NVIC_DisableIRQ(EXTI9_5_IRQn);
}
/*
* 函数功能:启动转换(中断模式)
* 入口参数:无
* 返回值:无
* 限定条件:已调用 tpafe5160_irq_enable()
* 函数说明:产生 CONVST 脉冲,转换完成后由 EXTI 中断自动读取 8 通道数据
*/
void tpafe5160_start_conv_irq(void)
{
s_ready = 0;
TP_CONVST_PULSE();
}
/*
* 函数功能:检查是否有新的转换数据
* 入口参数:无
* 返回值1 - 数据就绪0 - 无新数据
* 限定条件:中断模式已启用
* 函数说明:在 EXTI 回调中置位,主循环读取后需调用 tpafe5160_clear_ready() 清除
*/
uint8_t tpafe5160_data_ready(void)
{
return s_ready;
}
/*
* 函数功能:清除数据就绪标志
* 入口参数:无
* 返回值:无
* 限定条件:中断模式已启用
* 函数说明:主循环处理完数据后调用
*/
void tpafe5160_clear_ready(void)
{
s_ready = 0;
}
/*
* 函数功能:获取数据缓冲区指针
* 入口参数:无
* 返回值int16_t[8] 数据缓冲区的 const 指针
* 限定条件tpafe5160_data_ready() 返回 1 时调用
* 函数说明双缓冲切换ISR 写另一个缓冲区,主循环安全读取当前缓冲区
*/
const int16_t* tpafe5160_get_buf(void)
{
return (s_buf_sel == 0) ? s_buf_a : s_buf_b;
}
/*
* 函数功能BUSY 下降沿 EXTI 回调(由 HAL_GPIO_EXTI_IRQHandler 调用)
* 入口参数GPIO_Pin - 触发中断的引脚号
* 返回值:无
* 限定条件BUSY EXTI 已使能
* 函数说明:转换完成后自动读取 8 通道数据到缓冲区,耗时约 0.5µs (168MHz)
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin != TP_BUSY_Pin) {
return;
}
/* 双缓冲切换ISR 写与主循环读不同的缓冲区 */
int16_t *p_wr = (s_buf_sel == 0) ? s_buf_b : s_buf_a;
/* 连续读取8个通道约 0.5µs @ 168MHz */
uint8_t i;
for (i = 0; i < TPAFE5160_CH_NUM; i++) {
TP_RD_LOW_DLY();
p_wr[i] = (int16_t)TPAFE5160_READ_BUS();
TP_RD_HIGH_DLY();
}
/* 切换缓冲区并标记就绪 */
s_buf_sel ^= 1;
s_ready = 1;
}

View File

@@ -0,0 +1,224 @@
#ifndef __TPAFE5160_H
#define __TPAFE5160_H
/*
* 模块名称TPAFE5160 16位8通道同步采样ADC驱动
* 模块功能:提供 TPAFE5160 并行接口模式下的初始化、过采样设置、转换启动、数据读取接口
* 适用平台STM32F407ZGT6并行16位数据总线接 GPIOG[15:0]
* 作者:王建锋
* 创建日期2026-07-17
* 修改记录:
* 2026-07-17 王建锋 创建初始版本,参考 AD7606 并行驱动及 TPAFE5160 手册
* 2026-07-17 王建锋 增加 EXTI 中断读取模式
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "main.h"
/* ======================== 宏定义 ======================== */
/* 通道数量 */
#define TPAFE5160_CH_NUM 8
/* 控制引脚操作宏 —— RD (PD3) */
#define TPAFE5160_RD_LOW() HAL_GPIO_WritePin(TP_RD_GPIO_Port, TP_RD_Pin, GPIO_PIN_RESET)
#define TPAFE5160_RD_HIGH() HAL_GPIO_WritePin(TP_RD_GPIO_Port, TP_RD_Pin, GPIO_PIN_SET)
/* 控制引脚操作宏 —— CONVST (PD4) */
#define TPAFE5160_CONVST_LOW() HAL_GPIO_WritePin(TP_CONVST_GPIO_Port, TP_CONVST_Pin, GPIO_PIN_RESET)
#define TPAFE5160_CONVST_HIGH() HAL_GPIO_WritePin(TP_CONVST_GPIO_Port, TP_CONVST_Pin, GPIO_PIN_SET)
/* 状态引脚读取宏 */
#define TPAFE5160_BUSY_READ() HAL_GPIO_ReadPin(TP_BUSY_GPIO_Port, TP_BUSY_Pin)
#define TPAFE5160_FRSTDATA_READ() HAL_GPIO_ReadPin(TP_FRSTDATA_GPIO_Port, TP_FRSTDATA_Pin)
/* 过采样引脚操作宏 —— OS0 (PF13), OS1 (PF14), OS2 (PF15) */
#define TPAFE5160_OS0(val) HAL_GPIO_WritePin(TP_OS0_GPIO_Port, TP_OS0_Pin, \
(val) ? GPIO_PIN_SET : GPIO_PIN_RESET)
#define TPAFE5160_OS1(val) HAL_GPIO_WritePin(TP_OS1_GPIO_Port, TP_OS1_Pin, \
(val) ? GPIO_PIN_SET : GPIO_PIN_RESET)
#define TPAFE5160_OS2(val) HAL_GPIO_WritePin(TP_OS2_GPIO_Port, TP_OS2_Pin, \
(val) ? GPIO_PIN_SET : GPIO_PIN_RESET)
/* 并行数据总线读取 —— DB[15:0] 接 GPIOG[15:0]单次读取16位 */
#define TPAFE5160_READ_BUS() ((uint16_t)GPIOG->IDR)
/* 过采样率枚举 (OS[2:0] 编码OS2为MSB, OS0为LSB) */
typedef enum {
TP_OS_NONE = 0, /* 000 — 无过采样350 kSPS */
TP_OS_X2 = 1, /* 001 — 2倍过采样175 kSPS */
TP_OS_X4 = 2, /* 010 — 4倍过采样87.5 kSPS */
TP_OS_X8 = 3, /* 011 — 8倍过采样43.75 kSPS */
TP_OS_X16 = 4, /* 100 — 16倍过采样21.875 kSPS */
TP_OS_X32 = 5, /* 101 — 32倍过采样10.94 kSPS */
TP_OS_X64 = 6, /* 110 — 64倍过采样5.47 kSPS */
TP_OS_HBW = 7 /* 111 — 高带宽模式 (~30kHz)350 kSPS */
} tpafe5160_os_t;
/* 输入量程枚举 */
typedef enum {
TP_RANGE_5V = 0, /* ±5V (RANGE = LOW) */
TP_RANGE_10V = 1 /* ±10V (RANGE = HIGH) */
} tpafe5160_range_t;
/* 返回值定义 */
#define TPAFE5160_OK 0
#define TPAFE5160_ERROR -1
#define TPAFE5160_BUSY_TIMEOUT -2
/* 默认超时时间 (ms) */
#define TPAFE5160_CONV_TIMEOUT_MS 10
/* ======================== 函数声明 ======================== */
/*
* 函数功能:初始化 TPAFE5160设置过采样、等待就绪
* 入口参数:无
* 返回值0 - 成功,-2 - BUSY 超时
* 限定条件CubeMX 已完成 GPIO 初始化
* 函数说明1. 设置过采样为无过采样 (000)
* 2. 确保 RD 为高、CONVST 为低
* 3. 等待 BUSY 释放(转换空闲)
*/
int tpafe5160_init(void);
/*
* 函数功能:设置过采样率
* 入口参数os - 过采样率枚举值 tpafe5160_os_t
* 返回值:无
* 限定条件GPIO 已初始化
* 函数说明:通过 OS[2:0] 引脚设置过采样率,在下一次转换时生效
*/
void tpafe5160_set_os(tpafe5160_os_t os);
/*
* 函数功能启动一次转换CONVST 上升沿触发)
* 入口参数:无
* 返回值:无
* 限定条件GPIO 已初始化
* 函数说明:产生 CONVST 脉冲上升沿启动全部8通道同步采样与转换
*/
void tpafe5160_start_conv(void);
/*
* 函数功能:等待转换完成
* 入口参数timeout_ms - 超时时间 uint32_t > 0
* 返回值0 - 转换完成,-2 - 超时
* 限定条件:已调用 tpafe5160_start_conv()
* 函数说明:轮询 BUSY 引脚等待下降沿
*/
int tpafe5160_wait_busy(uint32_t timeout_ms);
/*
* 函数功能:查询当前是否正在转换
* 入口参数:无
* 返回值1 - 正在转换0 - 空闲
* 限定条件GPIO 已初始化
* 函数说明:读取 BUSY 引脚电平
*/
uint8_t tpafe5160_is_busy(void);
/*
* 函数功能读取全部8通道转换结果
* 入口参数buf - 8个int16_t的输出缓冲区 int16_t* 不为 NULL
* 返回值0 - 成功,-2 - BUSY 超时
* 限定条件GPIO 已初始化
* 函数说明1. 启动转换并等待 BUSY 释放
* 2. 连续8次拉低RD读取各通道数据
* 3. 通过 FRSTDATA 验证第一通道
*/
int tpafe5160_read_all(int16_t *buf);
/*
* 函数功能:读取指定通道的转换结果
* 入口参数channel - 通道号 uint8_t 0 - 7
* value - 输出指针 int16_t* 不为 NULL
* 返回值0 - 成功,-1 - 通道号无效,-2 - BUSY 超时
* 限定条件GPIO 已初始化
* 函数说明:启动转换并等待完成后,连续读取至指定通道
*/
int tpafe5160_read_channel(uint8_t channel, int16_t *value);
/*
* 函数功能原始ADC值转电压值
* 入口参数raw - ADC原始值 int16_t 有符号补码
* 返回值:电压值 float 单位 V
* 限定条件:无
* 函数说明±5V量程时 LSB=152.59μV±10V量程时 LSB=305.18μV
* 默认使用 ±5V 量程 (RANGE 接 GND)
*/
float tpafe5160_to_voltage(int16_t raw);
/*
* 函数功能:直接读取并行数据总线(不启动转换)
* 入口参数:无
* 返回值16位原始数据 uint16_t
* 限定条件RD 为低或CS与RD已拉低
* 函数说明用于读取当前总线上的数据需自行控制RD时序
*/
uint16_t tpafe5160_read_bus(void);
/* ======================== 中断模式 API ======================== */
/*
* 函数功能:使能 BUSY EXTI 中断(运行时重使能用)
* 入口参数:无
* 返回值:无
* 限定条件CubeMX 已完成 GPIO 和 NVIC 配置
* 函数说明:正常启动流程无需调用,仅在 irq_disable() 后需要重新使能时使用
*/
void tpafe5160_irq_enable(void);
/*
* 函数功能:关闭 BUSY EXTI 中断
* 入口参数:无
* 返回值:无
* 限定条件:已调用 tpafe5160_irq_enable()
* 函数说明:仅禁用 NVIC 中断GPIO 配置保持 CubeMX 设定
*/
void tpafe5160_irq_disable(void);
/*
* 函数功能:启动转换(中断模式)
* 入口参数:无
* 返回值:无
* 限定条件:已调用 tpafe5160_irq_enable()
* 函数说明:产生 CONVST 脉冲,转换完成后由 EXTI 中断自动读取 8 通道数据
*/
void tpafe5160_start_conv_irq(void);
/*
* 函数功能:检查是否有新的转换数据
* 入口参数:无
* 返回值1 - 数据就绪0 - 无新数据
* 限定条件:中断模式已启用
* 函数说明:在 EXTI 回调中置位,主循环读取后需调用 tpafe5160_clear_ready() 清除
*/
uint8_t tpafe5160_data_ready(void);
/*
* 函数功能:清除数据就绪标志
* 入口参数:无
* 返回值:无
* 限定条件:中断模式已启用
* 函数说明:主循环处理完数据后调用
*/
void tpafe5160_clear_ready(void);
/*
* 函数功能:获取数据缓冲区指针
* 入口参数:无
* 返回值int16_t[8] 数据缓冲区的 const 指针
* 限定条件tpafe5160_data_ready() 返回 1 时调用
* 函数说明:缓冲区由 EXTI 回调写入,主循环只读
*/
const int16_t* tpafe5160_get_buf(void);
#ifdef __cplusplus
}
#endif
#endif /* __TPAFE5160_H */

View File

@@ -0,0 +1,741 @@
/**
******************************************************************************
* @file stm32f4xx_hal_i2c.h
* @author MCD Application Team
* @brief Header file of I2C HAL module.
******************************************************************************
* @attention
*
* Copyright (c) 2016 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F4xx_HAL_I2C_H
#define __STM32F4xx_HAL_I2C_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal_def.h"
/** @addtogroup STM32F4xx_HAL_Driver
* @{
*/
/** @addtogroup I2C
* @{
*/
/* Exported types ------------------------------------------------------------*/
/** @defgroup I2C_Exported_Types I2C Exported Types
* @{
*/
/** @defgroup I2C_Configuration_Structure_definition I2C Configuration Structure definition
* @brief I2C Configuration Structure definition
* @{
*/
typedef struct
{
uint32_t ClockSpeed; /*!< Specifies the clock frequency.
This parameter must be set to a value lower than 400kHz */
uint32_t DutyCycle; /*!< Specifies the I2C fast mode duty cycle.
This parameter can be a value of @ref I2C_duty_cycle_in_fast_mode */
uint32_t OwnAddress1; /*!< Specifies the first device own address.
This parameter can be a 7-bit or 10-bit address. */
uint32_t AddressingMode; /*!< Specifies if 7-bit or 10-bit addressing mode is selected.
This parameter can be a value of @ref I2C_addressing_mode */
uint32_t DualAddressMode; /*!< Specifies if dual addressing mode is selected.
This parameter can be a value of @ref I2C_dual_addressing_mode */
uint32_t OwnAddress2; /*!< Specifies the second device own address if dual addressing mode is selected
This parameter can be a 7-bit address. */
uint32_t GeneralCallMode; /*!< Specifies if general call mode is selected.
This parameter can be a value of @ref I2C_general_call_addressing_mode */
uint32_t NoStretchMode; /*!< Specifies if nostretch mode is selected.
This parameter can be a value of @ref I2C_nostretch_mode */
} I2C_InitTypeDef;
/**
* @}
*/
/** @defgroup HAL_state_structure_definition HAL state structure definition
* @brief HAL State structure definition
* @note HAL I2C State value coding follow below described bitmap :
* b7-b6 Error information
* 00 : No Error
* 01 : Abort (Abort user request on going)
* 10 : Timeout
* 11 : Error
* b5 Peripheral initialization status
* 0 : Reset (Peripheral not initialized)
* 1 : Init done (Peripheral initialized and ready to use. HAL I2C Init function called)
* b4 (not used)
* x : Should be set to 0
* b3
* 0 : Ready or Busy (No Listen mode ongoing)
* 1 : Listen (Peripheral in Address Listen Mode)
* b2 Intrinsic process state
* 0 : Ready
* 1 : Busy (Peripheral busy with some configuration or internal operations)
* b1 Rx state
* 0 : Ready (no Rx operation ongoing)
* 1 : Busy (Rx operation ongoing)
* b0 Tx state
* 0 : Ready (no Tx operation ongoing)
* 1 : Busy (Tx operation ongoing)
* @{
*/
typedef enum
{
HAL_I2C_STATE_RESET = 0x00U, /*!< Peripheral is not yet Initialized */
HAL_I2C_STATE_READY = 0x20U, /*!< Peripheral Initialized and ready for use */
HAL_I2C_STATE_BUSY = 0x24U, /*!< An internal process is ongoing */
HAL_I2C_STATE_BUSY_TX = 0x21U, /*!< Data Transmission process is ongoing */
HAL_I2C_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing */
HAL_I2C_STATE_LISTEN = 0x28U, /*!< Address Listen Mode is ongoing */
HAL_I2C_STATE_BUSY_TX_LISTEN = 0x29U, /*!< Address Listen Mode and Data Transmission
process is ongoing */
HAL_I2C_STATE_BUSY_RX_LISTEN = 0x2AU, /*!< Address Listen Mode and Data Reception
process is ongoing */
HAL_I2C_STATE_ABORT = 0x60U, /*!< Abort user request ongoing */
HAL_I2C_STATE_TIMEOUT = 0xA0U, /*!< Timeout state */
HAL_I2C_STATE_ERROR = 0xE0U /*!< Error */
} HAL_I2C_StateTypeDef;
/**
* @}
*/
/** @defgroup HAL_mode_structure_definition HAL mode structure definition
* @brief HAL Mode structure definition
* @note HAL I2C Mode value coding follow below described bitmap :\n
* b7 (not used)\n
* x : Should be set to 0\n
* b6\n
* 0 : None\n
* 1 : Memory (HAL I2C communication is in Memory Mode)\n
* b5\n
* 0 : None\n
* 1 : Slave (HAL I2C communication is in Slave Mode)\n
* b4\n
* 0 : None\n
* 1 : Master (HAL I2C communication is in Master Mode)\n
* b3-b2-b1-b0 (not used)\n
* xxxx : Should be set to 0000
* @{
*/
typedef enum
{
HAL_I2C_MODE_NONE = 0x00U, /*!< No I2C communication on going */
HAL_I2C_MODE_MASTER = 0x10U, /*!< I2C communication is in Master Mode */
HAL_I2C_MODE_SLAVE = 0x20U, /*!< I2C communication is in Slave Mode */
HAL_I2C_MODE_MEM = 0x40U /*!< I2C communication is in Memory Mode */
} HAL_I2C_ModeTypeDef;
/**
* @}
*/
/** @defgroup I2C_Error_Code_definition I2C Error Code definition
* @brief I2C Error Code definition
* @{
*/
#define HAL_I2C_ERROR_NONE 0x00000000U /*!< No error */
#define HAL_I2C_ERROR_BERR 0x00000001U /*!< BERR error */
#define HAL_I2C_ERROR_ARLO 0x00000002U /*!< ARLO error */
#define HAL_I2C_ERROR_AF 0x00000004U /*!< AF error */
#define HAL_I2C_ERROR_OVR 0x00000008U /*!< OVR error */
#define HAL_I2C_ERROR_DMA 0x00000010U /*!< DMA transfer error */
#define HAL_I2C_ERROR_TIMEOUT 0x00000020U /*!< Timeout Error */
#define HAL_I2C_ERROR_SIZE 0x00000040U /*!< Size Management error */
#define HAL_I2C_ERROR_DMA_PARAM 0x00000080U /*!< DMA Parameter Error */
#define HAL_I2C_WRONG_START 0x00000200U /*!< Wrong start Error */
#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
#define HAL_I2C_ERROR_INVALID_CALLBACK 0x00000100U /*!< Invalid Callback error */
#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
/**
* @}
*/
/** @defgroup I2C_handle_Structure_definition I2C handle Structure definition
* @brief I2C handle Structure definition
* @{
*/
#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
typedef struct __I2C_HandleTypeDef
#else
typedef struct
#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
{
I2C_TypeDef *Instance; /*!< I2C registers base address */
I2C_InitTypeDef Init; /*!< I2C communication parameters */
uint8_t *pBuffPtr; /*!< Pointer to I2C transfer buffer */
uint16_t XferSize; /*!< I2C transfer size */
__IO uint16_t XferCount; /*!< I2C transfer counter */
__IO uint32_t XferOptions; /*!< I2C transfer options */
__IO uint32_t PreviousState; /*!< I2C communication Previous state and mode
context for internal usage */
DMA_HandleTypeDef *hdmatx; /*!< I2C Tx DMA handle parameters */
DMA_HandleTypeDef *hdmarx; /*!< I2C Rx DMA handle parameters */
HAL_LockTypeDef Lock; /*!< I2C locking object */
__IO HAL_I2C_StateTypeDef State; /*!< I2C communication state */
__IO HAL_I2C_ModeTypeDef Mode; /*!< I2C communication mode */
__IO uint32_t ErrorCode; /*!< I2C Error code */
__IO uint32_t Devaddress; /*!< I2C Target device address */
__IO uint32_t Memaddress; /*!< I2C Target memory address */
__IO uint32_t MemaddSize; /*!< I2C Target memory address size */
__IO uint32_t EventCount; /*!< I2C Event counter */
#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
void (* MasterTxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Master Tx Transfer completed callback */
void (* MasterRxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Master Rx Transfer completed callback */
void (* SlaveTxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Slave Tx Transfer completed callback */
void (* SlaveRxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Slave Rx Transfer completed callback */
void (* ListenCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Listen Complete callback */
void (* MemTxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Memory Tx Transfer completed callback */
void (* MemRxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Memory Rx Transfer completed callback */
void (* ErrorCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Error callback */
void (* AbortCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Abort callback */
void (* AddrCallback)(struct __I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode); /*!< I2C Slave Address Match callback */
void (* MspInitCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Msp Init callback */
void (* MspDeInitCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Msp DeInit callback */
#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
} I2C_HandleTypeDef;
#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
/**
* @brief HAL I2C Callback ID enumeration definition
*/
typedef enum
{
HAL_I2C_MASTER_TX_COMPLETE_CB_ID = 0x00U, /*!< I2C Master Tx Transfer completed callback ID */
HAL_I2C_MASTER_RX_COMPLETE_CB_ID = 0x01U, /*!< I2C Master Rx Transfer completed callback ID */
HAL_I2C_SLAVE_TX_COMPLETE_CB_ID = 0x02U, /*!< I2C Slave Tx Transfer completed callback ID */
HAL_I2C_SLAVE_RX_COMPLETE_CB_ID = 0x03U, /*!< I2C Slave Rx Transfer completed callback ID */
HAL_I2C_LISTEN_COMPLETE_CB_ID = 0x04U, /*!< I2C Listen Complete callback ID */
HAL_I2C_MEM_TX_COMPLETE_CB_ID = 0x05U, /*!< I2C Memory Tx Transfer callback ID */
HAL_I2C_MEM_RX_COMPLETE_CB_ID = 0x06U, /*!< I2C Memory Rx Transfer completed callback ID */
HAL_I2C_ERROR_CB_ID = 0x07U, /*!< I2C Error callback ID */
HAL_I2C_ABORT_CB_ID = 0x08U, /*!< I2C Abort callback ID */
HAL_I2C_MSPINIT_CB_ID = 0x09U, /*!< I2C Msp Init callback ID */
HAL_I2C_MSPDEINIT_CB_ID = 0x0AU /*!< I2C Msp DeInit callback ID */
} HAL_I2C_CallbackIDTypeDef;
/**
* @brief HAL I2C Callback pointer definition
*/
typedef void (*pI2C_CallbackTypeDef)(I2C_HandleTypeDef *hi2c); /*!< pointer to an I2C callback function */
typedef void (*pI2C_AddrCallbackTypeDef)(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode); /*!< pointer to an I2C Address Match callback function */
#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
/**
* @}
*/
/**
* @}
*/
/* Exported constants --------------------------------------------------------*/
/** @defgroup I2C_Exported_Constants I2C Exported Constants
* @{
*/
/** @defgroup I2C_duty_cycle_in_fast_mode I2C duty cycle in fast mode
* @{
*/
#define I2C_DUTYCYCLE_2 0x00000000U
#define I2C_DUTYCYCLE_16_9 I2C_CCR_DUTY
/**
* @}
*/
/** @defgroup I2C_addressing_mode I2C addressing mode
* @{
*/
#define I2C_ADDRESSINGMODE_7BIT 0x00004000U
#define I2C_ADDRESSINGMODE_10BIT (I2C_OAR1_ADDMODE | 0x00004000U)
/**
* @}
*/
/** @defgroup I2C_dual_addressing_mode I2C dual addressing mode
* @{
*/
#define I2C_DUALADDRESS_DISABLE 0x00000000U
#define I2C_DUALADDRESS_ENABLE I2C_OAR2_ENDUAL
/**
* @}
*/
/** @defgroup I2C_general_call_addressing_mode I2C general call addressing mode
* @{
*/
#define I2C_GENERALCALL_DISABLE 0x00000000U
#define I2C_GENERALCALL_ENABLE I2C_CR1_ENGC
/**
* @}
*/
/** @defgroup I2C_nostretch_mode I2C nostretch mode
* @{
*/
#define I2C_NOSTRETCH_DISABLE 0x00000000U
#define I2C_NOSTRETCH_ENABLE I2C_CR1_NOSTRETCH
/**
* @}
*/
/** @defgroup I2C_Memory_Address_Size I2C Memory Address Size
* @{
*/
#define I2C_MEMADD_SIZE_8BIT 0x00000001U
#define I2C_MEMADD_SIZE_16BIT 0x00000010U
/**
* @}
*/
/** @defgroup I2C_XferDirection_definition I2C XferDirection definition
* @{
*/
#define I2C_DIRECTION_RECEIVE 0x00000000U
#define I2C_DIRECTION_TRANSMIT 0x00000001U
/**
* @}
*/
/** @defgroup I2C_XferOptions_definition I2C XferOptions definition
* @{
*/
#define I2C_FIRST_FRAME 0x00000001U
#define I2C_FIRST_AND_NEXT_FRAME 0x00000002U
#define I2C_NEXT_FRAME 0x00000004U
#define I2C_FIRST_AND_LAST_FRAME 0x00000008U
#define I2C_LAST_FRAME_NO_STOP 0x00000010U
#define I2C_LAST_FRAME 0x00000020U
/* List of XferOptions in usage of :
* 1- Restart condition in all use cases (direction change or not)
*/
#define I2C_OTHER_FRAME (0x00AA0000U)
#define I2C_OTHER_AND_LAST_FRAME (0xAA000000U)
/**
* @}
*/
/** @defgroup I2C_Interrupt_configuration_definition I2C Interrupt configuration definition
* @brief I2C Interrupt definition
* Elements values convention: 0xXXXXXXXX
* - XXXXXXXX : Interrupt control mask
* @{
*/
#define I2C_IT_BUF I2C_CR2_ITBUFEN
#define I2C_IT_EVT I2C_CR2_ITEVTEN
#define I2C_IT_ERR I2C_CR2_ITERREN
/**
* @}
*/
/** @defgroup I2C_Flag_definition I2C Flag definition
* @{
*/
#define I2C_FLAG_OVR 0x00010800U
#define I2C_FLAG_AF 0x00010400U
#define I2C_FLAG_ARLO 0x00010200U
#define I2C_FLAG_BERR 0x00010100U
#define I2C_FLAG_TXE 0x00010080U
#define I2C_FLAG_RXNE 0x00010040U
#define I2C_FLAG_STOPF 0x00010010U
#define I2C_FLAG_ADD10 0x00010008U
#define I2C_FLAG_BTF 0x00010004U
#define I2C_FLAG_ADDR 0x00010002U
#define I2C_FLAG_SB 0x00010001U
#define I2C_FLAG_DUALF 0x00100080U
#define I2C_FLAG_GENCALL 0x00100010U
#define I2C_FLAG_TRA 0x00100004U
#define I2C_FLAG_BUSY 0x00100002U
#define I2C_FLAG_MSL 0x00100001U
/**
* @}
*/
/**
* @}
*/
/* Exported macros -----------------------------------------------------------*/
/** @defgroup I2C_Exported_Macros I2C Exported Macros
* @{
*/
/** @brief Reset I2C handle state.
* @param __HANDLE__ specifies the I2C Handle.
* @retval None
*/
#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
#define __HAL_I2C_RESET_HANDLE_STATE(__HANDLE__) do{ \
(__HANDLE__)->State = HAL_I2C_STATE_RESET; \
(__HANDLE__)->MspInitCallback = NULL; \
(__HANDLE__)->MspDeInitCallback = NULL; \
} while(0)
#else
#define __HAL_I2C_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_I2C_STATE_RESET)
#endif
/** @brief Enable or disable the specified I2C interrupts.
* @param __HANDLE__ specifies the I2C Handle.
* @param __INTERRUPT__ specifies the interrupt source to enable or disable.
* This parameter can be one of the following values:
* @arg I2C_IT_BUF: Buffer interrupt enable
* @arg I2C_IT_EVT: Event interrupt enable
* @arg I2C_IT_ERR: Error interrupt enable
* @retval None
*/
#define __HAL_I2C_ENABLE_IT(__HANDLE__, __INTERRUPT__) SET_BIT((__HANDLE__)->Instance->CR2,(__INTERRUPT__))
#define __HAL_I2C_DISABLE_IT(__HANDLE__, __INTERRUPT__) CLEAR_BIT((__HANDLE__)->Instance->CR2, (__INTERRUPT__))
/** @brief Checks if the specified I2C interrupt source is enabled or disabled.
* @param __HANDLE__ specifies the I2C Handle.
* @param __INTERRUPT__ specifies the I2C interrupt source to check.
* This parameter can be one of the following values:
* @arg I2C_IT_BUF: Buffer interrupt enable
* @arg I2C_IT_EVT: Event interrupt enable
* @arg I2C_IT_ERR: Error interrupt enable
* @retval The new state of __INTERRUPT__ (TRUE or FALSE).
*/
#define __HAL_I2C_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->CR2 & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET)
/** @brief Checks whether the specified I2C flag is set or not.
* @param __HANDLE__ specifies the I2C Handle.
* @param __FLAG__ specifies the flag to check.
* This parameter can be one of the following values:
* @arg I2C_FLAG_OVR: Overrun/Underrun flag
* @arg I2C_FLAG_AF: Acknowledge failure flag
* @arg I2C_FLAG_ARLO: Arbitration lost flag
* @arg I2C_FLAG_BERR: Bus error flag
* @arg I2C_FLAG_TXE: Data register empty flag
* @arg I2C_FLAG_RXNE: Data register not empty flag
* @arg I2C_FLAG_STOPF: Stop detection flag
* @arg I2C_FLAG_ADD10: 10-bit header sent flag
* @arg I2C_FLAG_BTF: Byte transfer finished flag
* @arg I2C_FLAG_ADDR: Address sent flag
* Address matched flag
* @arg I2C_FLAG_SB: Start bit flag
* @arg I2C_FLAG_DUALF: Dual flag
* @arg I2C_FLAG_GENCALL: General call header flag
* @arg I2C_FLAG_TRA: Transmitter/Receiver flag
* @arg I2C_FLAG_BUSY: Bus busy flag
* @arg I2C_FLAG_MSL: Master/Slave flag
* @retval The new state of __FLAG__ (TRUE or FALSE).
*/
#define __HAL_I2C_GET_FLAG(__HANDLE__, __FLAG__) ((((uint8_t)((__FLAG__) >> 16U)) == 0x01U) ? \
(((((__HANDLE__)->Instance->SR1) & ((__FLAG__) & I2C_FLAG_MASK)) == ((__FLAG__) & I2C_FLAG_MASK)) ? SET : RESET) : \
(((((__HANDLE__)->Instance->SR2) & ((__FLAG__) & I2C_FLAG_MASK)) == ((__FLAG__) & I2C_FLAG_MASK)) ? SET : RESET))
/** @brief Clears the I2C pending flags which are cleared by writing 0 in a specific bit.
* @param __HANDLE__ specifies the I2C Handle.
* @param __FLAG__ specifies the flag to clear.
* This parameter can be any combination of the following values:
* @arg I2C_FLAG_OVR: Overrun/Underrun flag (Slave mode)
* @arg I2C_FLAG_AF: Acknowledge failure flag
* @arg I2C_FLAG_ARLO: Arbitration lost flag (Master mode)
* @arg I2C_FLAG_BERR: Bus error flag
* @retval None
*/
#define __HAL_I2C_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->SR1 = ~((__FLAG__) & I2C_FLAG_MASK))
/** @brief Clears the I2C ADDR pending flag.
* @param __HANDLE__ specifies the I2C Handle.
* This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral.
* @retval None
*/
#define __HAL_I2C_CLEAR_ADDRFLAG(__HANDLE__) \
do{ \
__IO uint32_t tmpreg = 0x00U; \
tmpreg = (__HANDLE__)->Instance->SR1; \
tmpreg = (__HANDLE__)->Instance->SR2; \
UNUSED(tmpreg); \
} while(0)
/** @brief Clears the I2C STOPF pending flag.
* @param __HANDLE__ specifies the I2C Handle.
* @retval None
*/
#define __HAL_I2C_CLEAR_STOPFLAG(__HANDLE__) \
do{ \
__IO uint32_t tmpreg = 0x00U; \
tmpreg = (__HANDLE__)->Instance->SR1; \
SET_BIT((__HANDLE__)->Instance->CR1, I2C_CR1_PE); \
UNUSED(tmpreg); \
} while(0)
/** @brief Enable the specified I2C peripheral.
* @param __HANDLE__ specifies the I2C Handle.
* @retval None
*/
#define __HAL_I2C_ENABLE(__HANDLE__) SET_BIT((__HANDLE__)->Instance->CR1, I2C_CR1_PE)
/** @brief Disable the specified I2C peripheral.
* @param __HANDLE__ specifies the I2C Handle.
* @retval None
*/
#define __HAL_I2C_DISABLE(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->CR1, I2C_CR1_PE)
/**
* @}
*/
/* Include I2C HAL Extension module */
#include "stm32f4xx_hal_i2c_ex.h"
/* Exported functions --------------------------------------------------------*/
/** @addtogroup I2C_Exported_Functions
* @{
*/
/** @addtogroup I2C_Exported_Functions_Group1 Initialization and de-initialization functions
* @{
*/
/* Initialization and de-initialization functions******************************/
HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c);
HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c);
/* Callbacks Register/UnRegister functions ***********************************/
#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
HAL_StatusTypeDef HAL_I2C_RegisterCallback(I2C_HandleTypeDef *hi2c, HAL_I2C_CallbackIDTypeDef CallbackID, pI2C_CallbackTypeDef pCallback);
HAL_StatusTypeDef HAL_I2C_UnRegisterCallback(I2C_HandleTypeDef *hi2c, HAL_I2C_CallbackIDTypeDef CallbackID);
HAL_StatusTypeDef HAL_I2C_RegisterAddrCallback(I2C_HandleTypeDef *hi2c, pI2C_AddrCallbackTypeDef pCallback);
HAL_StatusTypeDef HAL_I2C_UnRegisterAddrCallback(I2C_HandleTypeDef *hi2c);
#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
/**
* @}
*/
/** @addtogroup I2C_Exported_Functions_Group2 Input and Output operation functions
* @{
*/
/* IO operation functions ****************************************************/
/******* Blocking mode: Polling */
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);
HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, 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);
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_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout);
/******* Non-Blocking mode: Interrupt */
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);
HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size);
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);
HAL_StatusTypeDef HAL_I2C_Master_Seq_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions);
HAL_StatusTypeDef HAL_I2C_Master_Seq_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions);
HAL_StatusTypeDef HAL_I2C_Slave_Seq_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions);
HAL_StatusTypeDef HAL_I2C_Slave_Seq_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions);
HAL_StatusTypeDef HAL_I2C_EnableListen_IT(I2C_HandleTypeDef *hi2c);
HAL_StatusTypeDef HAL_I2C_DisableListen_IT(I2C_HandleTypeDef *hi2c);
HAL_StatusTypeDef HAL_I2C_Master_Abort_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress);
/******* Non-Blocking mode: DMA */
HAL_StatusTypeDef HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_I2C_Master_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_I2C_Slave_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_I2C_Mem_Write_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_I2C_Master_Seq_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions);
HAL_StatusTypeDef HAL_I2C_Master_Seq_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions);
HAL_StatusTypeDef HAL_I2C_Slave_Seq_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions);
HAL_StatusTypeDef HAL_I2C_Slave_Seq_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions);
/**
* @}
*/
/** @addtogroup I2C_IRQ_Handler_and_Callbacks IRQ Handler and Callbacks
* @{
*/
/******* I2C IRQHandler and Callbacks used in non blocking modes (Interrupt and DMA) */
void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c);
void HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode);
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c);
void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c);
/**
* @}
*/
/** @addtogroup I2C_Exported_Functions_Group3 Peripheral State, Mode and Error functions
* @{
*/
/* Peripheral State, Mode and Error functions *********************************/
HAL_I2C_StateTypeDef HAL_I2C_GetState(I2C_HandleTypeDef *hi2c);
HAL_I2C_ModeTypeDef HAL_I2C_GetMode(I2C_HandleTypeDef *hi2c);
uint32_t HAL_I2C_GetError(I2C_HandleTypeDef *hi2c);
/**
* @}
*/
/**
* @}
*/
/* Private types -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/** @defgroup I2C_Private_Constants I2C Private Constants
* @{
*/
#define I2C_FLAG_MASK 0x0000FFFFU
#define I2C_MIN_PCLK_FREQ_STANDARD 2000000U /*!< 2 MHz */
#define I2C_MIN_PCLK_FREQ_FAST 4000000U /*!< 4 MHz */
/**
* @}
*/
/* Private macros ------------------------------------------------------------*/
/** @defgroup I2C_Private_Macros I2C Private Macros
* @{
*/
#define I2C_MIN_PCLK_FREQ(__PCLK__, __SPEED__) (((__SPEED__) <= 100000U) ? ((__PCLK__) < I2C_MIN_PCLK_FREQ_STANDARD) : ((__PCLK__) < I2C_MIN_PCLK_FREQ_FAST))
#define I2C_CCR_CALCULATION(__PCLK__, __SPEED__, __COEFF__) (((((__PCLK__) - 1U)/((__SPEED__) * (__COEFF__))) + 1U) & I2C_CCR_CCR)
#define I2C_FREQRANGE(__PCLK__) ((__PCLK__)/1000000U)
#define I2C_RISE_TIME(__FREQRANGE__, __SPEED__) (((__SPEED__) <= 100000U) ? ((__FREQRANGE__) + 1U) : ((((__FREQRANGE__) * 300U) / 1000U) + 1U))
#define I2C_SPEED_STANDARD(__PCLK__, __SPEED__) ((I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 2U) < 4U)? 4U:I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 2U))
#define I2C_SPEED_FAST(__PCLK__, __SPEED__, __DUTYCYCLE__) (((__DUTYCYCLE__) == I2C_DUTYCYCLE_2)? I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 3U) : (I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 25U) | I2C_DUTYCYCLE_16_9))
#define I2C_SPEED(__PCLK__, __SPEED__, __DUTYCYCLE__) (((__SPEED__) <= 100000U)? (I2C_SPEED_STANDARD((__PCLK__), (__SPEED__))) : \
((I2C_SPEED_FAST((__PCLK__), (__SPEED__), (__DUTYCYCLE__)) & I2C_CCR_CCR) == 0U)? 1U : \
((I2C_SPEED_FAST((__PCLK__), (__SPEED__), (__DUTYCYCLE__))) | I2C_CCR_FS))
#define I2C_7BIT_ADD_WRITE(__ADDRESS__) ((uint8_t)((__ADDRESS__) & (uint8_t)(~I2C_OAR1_ADD0)))
#define I2C_7BIT_ADD_READ(__ADDRESS__) ((uint8_t)((__ADDRESS__) | I2C_OAR1_ADD0))
#define I2C_10BIT_ADDRESS(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)0x00FF)))
#define I2C_10BIT_HEADER_WRITE(__ADDRESS__) ((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)0x0300)) >> 7) | (uint16_t)0x00F0)))
#define I2C_10BIT_HEADER_READ(__ADDRESS__) ((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)0x0300)) >> 7) | (uint16_t)(0x00F1))))
#define I2C_MEM_ADD_MSB(__ADDRESS__) ((uint8_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)0xFF00)) >> 8)))
#define I2C_MEM_ADD_LSB(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)0x00FF)))
/** @defgroup I2C_IS_RTC_Definitions I2C Private macros to check input parameters
* @{
*/
#define IS_I2C_DUTY_CYCLE(CYCLE) (((CYCLE) == I2C_DUTYCYCLE_2) || \
((CYCLE) == I2C_DUTYCYCLE_16_9))
#define IS_I2C_ADDRESSING_MODE(ADDRESS) (((ADDRESS) == I2C_ADDRESSINGMODE_7BIT) || \
((ADDRESS) == I2C_ADDRESSINGMODE_10BIT))
#define IS_I2C_DUAL_ADDRESS(ADDRESS) (((ADDRESS) == I2C_DUALADDRESS_DISABLE) || \
((ADDRESS) == I2C_DUALADDRESS_ENABLE))
#define IS_I2C_GENERAL_CALL(CALL) (((CALL) == I2C_GENERALCALL_DISABLE) || \
((CALL) == I2C_GENERALCALL_ENABLE))
#define IS_I2C_NO_STRETCH(STRETCH) (((STRETCH) == I2C_NOSTRETCH_DISABLE) || \
((STRETCH) == I2C_NOSTRETCH_ENABLE))
#define IS_I2C_MEMADD_SIZE(SIZE) (((SIZE) == I2C_MEMADD_SIZE_8BIT) || \
((SIZE) == I2C_MEMADD_SIZE_16BIT))
#define IS_I2C_CLOCK_SPEED(SPEED) (((SPEED) > 0U) && ((SPEED) <= 400000U))
#define IS_I2C_OWN_ADDRESS1(ADDRESS1) (((ADDRESS1) & 0xFFFFFC00U) == 0U)
#define IS_I2C_OWN_ADDRESS2(ADDRESS2) (((ADDRESS2) & 0xFFFFFF01U) == 0U)
#define IS_I2C_TRANSFER_OPTIONS_REQUEST(REQUEST) (((REQUEST) == I2C_FIRST_FRAME) || \
((REQUEST) == I2C_FIRST_AND_NEXT_FRAME) || \
((REQUEST) == I2C_NEXT_FRAME) || \
((REQUEST) == I2C_FIRST_AND_LAST_FRAME) || \
((REQUEST) == I2C_LAST_FRAME) || \
((REQUEST) == I2C_LAST_FRAME_NO_STOP) || \
IS_I2C_TRANSFER_OTHER_OPTIONS_REQUEST(REQUEST))
#define IS_I2C_TRANSFER_OTHER_OPTIONS_REQUEST(REQUEST) (((REQUEST) == I2C_OTHER_FRAME) || \
((REQUEST) == I2C_OTHER_AND_LAST_FRAME))
#define I2C_CHECK_FLAG(__ISR__, __FLAG__) ((((__ISR__) & ((__FLAG__) & I2C_FLAG_MASK)) == ((__FLAG__) & I2C_FLAG_MASK)) ? SET : RESET)
#define I2C_CHECK_IT_SOURCE(__CR1__, __IT__) ((((__CR1__) & (__IT__)) == (__IT__)) ? SET : RESET)
/**
* @}
*/
/**
* @}
*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup I2C_Private_Functions I2C Private Functions
* @{
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __STM32F4xx_HAL_I2C_H */

View File

@@ -0,0 +1,115 @@
/**
******************************************************************************
* @file stm32f4xx_hal_i2c_ex.h
* @author MCD Application Team
* @brief Header file of I2C HAL Extension module.
******************************************************************************
* @attention
*
* Copyright (c) 2016 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F4xx_HAL_I2C_EX_H
#define __STM32F4xx_HAL_I2C_EX_H
#ifdef __cplusplus
extern "C" {
#endif
#if defined(I2C_FLTR_ANOFF)&&defined(I2C_FLTR_DNF)
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal_def.h"
/** @addtogroup STM32F4xx_HAL_Driver
* @{
*/
/** @addtogroup I2CEx
* @{
*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/** @defgroup I2CEx_Exported_Constants I2C Exported Constants
* @{
*/
/** @defgroup I2CEx_Analog_Filter I2C Analog Filter
* @{
*/
#define I2C_ANALOGFILTER_ENABLE 0x00000000U
#define I2C_ANALOGFILTER_DISABLE I2C_FLTR_ANOFF
/**
* @}
*/
/**
* @}
*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/** @addtogroup I2CEx_Exported_Functions
* @{
*/
/** @addtogroup I2CEx_Exported_Functions_Group1
* @{
*/
/* Peripheral Control functions ************************************************/
HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter);
HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter);
/**
* @}
*/
/**
* @}
*/
/* Private types -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/** @defgroup I2CEx_Private_Constants I2C Private Constants
* @{
*/
/**
* @}
*/
/* Private macros ------------------------------------------------------------*/
/** @defgroup I2CEx_Private_Macros I2C Private Macros
* @{
*/
#define IS_I2C_ANALOG_FILTER(FILTER) (((FILTER) == I2C_ANALOGFILTER_ENABLE) || \
((FILTER) == I2C_ANALOGFILTER_DISABLE))
#define IS_I2C_DIGITAL_FILTER(FILTER) ((FILTER) <= 0x0000000FU)
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#endif
#ifdef __cplusplus
}
#endif
#endif /* __STM32F4xx_HAL_I2C_EX_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,182 @@
/**
******************************************************************************
* @file stm32f4xx_hal_i2c_ex.c
* @author MCD Application Team
* @brief I2C Extension HAL module driver.
* This file provides firmware functions to manage the following
* functionalities of I2C extension peripheral:
* + Extension features functions
*
******************************************************************************
* @attention
*
* Copyright (c) 2016 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
@verbatim
==============================================================================
##### I2C peripheral extension features #####
==============================================================================
[..] Comparing to other previous devices, the I2C interface for STM32F427xx/437xx/
429xx/439xx devices contains the following additional features :
(+) Possibility to disable or enable Analog Noise Filter
(+) Use of a configured Digital Noise Filter
##### How to use this driver #####
==============================================================================
[..] This driver provides functions to configure Noise Filter
(#) Configure I2C Analog noise filter using the function HAL_I2C_AnalogFilter_Config()
(#) Configure I2C Digital noise filter using the function HAL_I2C_DigitalFilter_Config()
@endverbatim
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
/** @addtogroup STM32F4xx_HAL_Driver
* @{
*/
/** @defgroup I2CEx I2CEx
* @brief I2C HAL module driver
* @{
*/
#ifdef HAL_I2C_MODULE_ENABLED
#if defined(I2C_FLTR_ANOFF)&&defined(I2C_FLTR_DNF)
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/** @defgroup I2CEx_Exported_Functions I2C Exported Functions
* @{
*/
/** @defgroup I2CEx_Exported_Functions_Group1 Extension features functions
* @brief Extension features functions
*
@verbatim
===============================================================================
##### Extension features functions #####
===============================================================================
[..] This section provides functions allowing to:
(+) Configure Noise Filters
@endverbatim
* @{
*/
/**
* @brief Configures I2C Analog noise filter.
* @param hi2c pointer to a I2C_HandleTypeDef structure that contains
* the configuration information for the specified I2Cx peripheral.
* @param AnalogFilter new state of the Analog filter.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
assert_param(IS_I2C_ANALOG_FILTER(AnalogFilter));
if (hi2c->State == HAL_I2C_STATE_READY)
{
hi2c->State = HAL_I2C_STATE_BUSY;
/* Disable the selected I2C peripheral */
__HAL_I2C_DISABLE(hi2c);
/* Reset I2Cx ANOFF bit */
hi2c->Instance->FLTR &= ~(I2C_FLTR_ANOFF);
/* Disable the analog filter */
hi2c->Instance->FLTR |= AnalogFilter;
__HAL_I2C_ENABLE(hi2c);
hi2c->State = HAL_I2C_STATE_READY;
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief Configures I2C Digital noise filter.
* @param hi2c pointer to a I2C_HandleTypeDef structure that contains
* the configuration information for the specified I2Cx peripheral.
* @param DigitalFilter Coefficient of digital noise filter between 0x00 and 0x0F.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter)
{
uint16_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
assert_param(IS_I2C_DIGITAL_FILTER(DigitalFilter));
if (hi2c->State == HAL_I2C_STATE_READY)
{
hi2c->State = HAL_I2C_STATE_BUSY;
/* Disable the selected I2C peripheral */
__HAL_I2C_DISABLE(hi2c);
/* Get the old register value */
tmpreg = hi2c->Instance->FLTR;
/* Reset I2Cx DNF bit [3:0] */
tmpreg &= ~(I2C_FLTR_DNF);
/* Set I2Cx DNF coefficient */
tmpreg |= DigitalFilter;
/* Store the new register value */
hi2c->Instance->FLTR = tmpreg;
__HAL_I2C_ENABLE(hi2c);
hi2c->State = HAL_I2C_STATE_READY;
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @}
*/
/**
* @}
*/
#endif
#endif /* HAL_I2C_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/

52
Inc/dma.h Normal file
View File

@@ -0,0 +1,52 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file dma.h
* @brief This file contains all the function prototypes for
* the dma.c file
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __DMA_H__
#define __DMA_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* DMA memory to memory transfer handles -------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_DMA_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __DMA_H__ */

52
Inc/i2c.h Normal file
View File

@@ -0,0 +1,52 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file i2c.h
* @brief This file contains all the function prototypes for
* the i2c.c file
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __I2C_H__
#define __I2C_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern I2C_HandleTypeDef hi2c1;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_I2C1_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __I2C_H__ */

View File

@@ -69,6 +69,20 @@ void Error_Handler(void);
#define LED5_GPIO_Port GPIOF
#define LED6_Pin GPIO_PIN_12
#define LED6_GPIO_Port GPIOF
#define TP_OS0_Pin GPIO_PIN_13
#define TP_OS0_GPIO_Port GPIOF
#define TP_OS1_Pin GPIO_PIN_14
#define TP_OS1_GPIO_Port GPIOF
#define TP_OS2_Pin GPIO_PIN_15
#define TP_OS2_GPIO_Port GPIOF
#define DB0_Pin GPIO_PIN_0
#define DB0_GPIO_Port GPIOG
#define DB1_Pin GPIO_PIN_1
#define DB1_GPIO_Port GPIOG
#define ST_TX2_Pin GPIO_PIN_10
#define ST_TX2_GPIO_Port GPIOB
#define ST_RX2_Pin GPIO_PIN_11
#define ST_RX2_GPIO_Port GPIOB
#define CH395_SCS_Pin GPIO_PIN_12
#define CH395_SCS_GPIO_Port GPIOB
#define CH395F_SCK_Pin GPIO_PIN_13
@@ -77,16 +91,67 @@ void Error_Handler(void);
#define CH395F_SDO_GPIO_Port GPIOB
#define CH395F_SDOB15_Pin GPIO_PIN_15
#define CH395F_SDOB15_GPIO_Port GPIOB
#define ST_TX0_Pin GPIO_PIN_9
#define ST_TX0_GPIO_Port GPIOA
#define ST_RX0_Pin GPIO_PIN_10
#define ST_RX0_GPIO_Port GPIOA
#define DB2_Pin GPIO_PIN_2
#define DB2_GPIO_Port GPIOG
#define DB3_Pin GPIO_PIN_3
#define DB3_GPIO_Port GPIOG
#define DB4_Pin GPIO_PIN_4
#define DB4_GPIO_Port GPIOG
#define DB5_Pin GPIO_PIN_5
#define DB5_GPIO_Port GPIOG
#define DB6_Pin GPIO_PIN_6
#define DB6_GPIO_Port GPIOG
#define DB7_Pin GPIO_PIN_7
#define DB7_GPIO_Port GPIOG
#define DB8_Pin GPIO_PIN_8
#define DB8_GPIO_Port GPIOG
#define ST_TX3_Pin GPIO_PIN_10
#define ST_TX3_GPIO_Port GPIOC
#define ST_RX3_Pin GPIO_PIN_11
#define ST_RX3_GPIO_Port GPIOC
#define ST_TX4_Pin GPIO_PIN_12
#define ST_TX4_GPIO_Port GPIOC
#define ST_DIR4_Pin GPIO_PIN_0
#define ST_DIR4_GPIO_Port GPIOD
#define TP_FRSTDATA_Pin GPIO_PIN_1
#define TP_FRSTDATA_GPIO_Port GPIOD
#define ST_RX4_Pin GPIO_PIN_2
#define ST_RX4_GPIO_Port GPIOD
#define TP_RD_Pin GPIO_PIN_3
#define TP_RD_GPIO_Port GPIOD
#define TP_CONVST_Pin GPIO_PIN_4
#define TP_CONVST_GPIO_Port GPIOD
#define ST_TX1_Pin GPIO_PIN_5
#define ST_TX1_GPIO_Port GPIOD
#define ST_RX1_Pin GPIO_PIN_6
#define ST_RX1_GPIO_Port GPIOD
#define TP_BUSY_Pin GPIO_PIN_7
#define TP_BUSY_GPIO_Port GPIOD
#define TP_BUSY_EXTI_IRQn EXTI9_5_IRQn
#define DB9_Pin GPIO_PIN_9
#define DB9_GPIO_Port GPIOG
#define DB10_Pin GPIO_PIN_10
#define DB10_GPIO_Port GPIOG
#define DB11_Pin GPIO_PIN_11
#define DB11_GPIO_Port GPIOG
#define DB12_Pin GPIO_PIN_12
#define DB12_GPIO_Port GPIOG
#define DB13_Pin GPIO_PIN_13
#define DB13_GPIO_Port GPIOG
#define DB14_Pin GPIO_PIN_14
#define DB14_GPIO_Port GPIOG
#define DB15_Pin GPIO_PIN_15
#define DB15_GPIO_Port GPIOG
#define GD_SCLK_Pin GPIO_PIN_3
#define GD_SCLK_GPIO_Port GPIOB
#define GD_SO_Pin GPIO_PIN_4
#define GD_SO_GPIO_Port GPIOB
#define GD_SI_Pin GPIO_PIN_5
#define GD_SI_GPIO_Port GPIOB
#define SD_SCL_Pin GPIO_PIN_6
#define SD_SCL_GPIO_Port GPIOB
#define SD_SDA_Pin GPIO_PIN_7
#define SD_SDA_GPIO_Port GPIOB
#define GD_WP_Pin GPIO_PIN_8
#define GD_WP_GPIO_Port GPIOB
#define GD_CS_Pin GPIO_PIN_0

View File

@@ -53,7 +53,7 @@
/* #define HAL_SRAM_MODULE_ENABLED */
/* #define HAL_SDRAM_MODULE_ENABLED */
/* #define HAL_HASH_MODULE_ENABLED */
/* #define HAL_I2C_MODULE_ENABLED */
#define HAL_I2C_MODULE_ENABLED
/* #define HAL_I2S_MODULE_ENABLED */
/* #define HAL_IWDG_MODULE_ENABLED */
/* #define HAL_LTDC_MODULE_ENABLED */

View File

@@ -55,6 +55,14 @@ void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
void EXTI9_5_IRQHandler(void);
void USART1_IRQHandler(void);
void USART2_IRQHandler(void);
void USART3_IRQHandler(void);
void UART4_IRQHandler(void);
void UART5_IRQHandler(void);
void DMA2_Stream2_IRQHandler(void);
void DMA2_Stream7_IRQHandler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */

View File

@@ -32,13 +32,25 @@ extern "C" {
/* USER CODE END Includes */
extern UART_HandleTypeDef huart4;
extern UART_HandleTypeDef huart5;
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
extern UART_HandleTypeDef huart3;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_UART4_Init(void);
void MX_UART5_Init(void);
void MX_USART1_UART_Init(void);
void MX_USART2_UART_Init(void);
void MX_USART3_UART_Init(void);
/* USER CODE BEGIN Prototypes */

Submodule Lib/fal deleted from aa02112186

View File

@@ -1,10 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_projx.xsd">
<?xml version="1.0" encoding="UTF-8"?>
<Project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" noNamespaceSchemaLocation="project_projx.xsd">
<SchemaVersion>2.1</SchemaVersion>
<Header>### uVision Project, (C) Keil Software</Header>
<Targets>
<Target>
<TargetName>STM32F407-Demo</TargetName>
@@ -19,28 +16,28 @@
<PackID>Keil.STM32F4xx_DFP.3.1.1</PackID>
<PackURL>https://www.keil.com/pack/</PackURL>
<Cpu>IRAM(0x20000000-0x2001BFFF) IRAM2(0x2001C000-0x2001FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) FPU2 CPUTYPE("Cortex-M4") TZ</Cpu>
<FlashUtilSpec></FlashUtilSpec>
<StartupFile></StartupFile>
<FlashDriverDll></FlashDriverDll>
<FlashUtilSpec />
<StartupFile />
<FlashDriverDll />
<DeviceId>0</DeviceId>
<RegisterFile></RegisterFile>
<MemoryEnv></MemoryEnv>
<Cmp></Cmp>
<Asm></Asm>
<Linker></Linker>
<OHString></OHString>
<InfinionOptionDll></InfinionOptionDll>
<SLE66CMisc></SLE66CMisc>
<SLE66AMisc></SLE66AMisc>
<SLE66LinkerMisc></SLE66LinkerMisc>
<RegisterFile />
<MemoryEnv />
<Cmp />
<Asm />
<Linker />
<OHString />
<InfinionOptionDll />
<SLE66CMisc />
<SLE66AMisc />
<SLE66LinkerMisc />
<SFDFile>$$Device:STM32F407ZGTx$CMSIS\SVD\STM32F407.svd</SFDFile>
<bCustSvd>0</bCustSvd>
<UseEnv>0</UseEnv>
<BinPath></BinPath>
<IncludePath></IncludePath>
<LibPath></LibPath>
<RegisterFilePath></RegisterFilePath>
<DBRegisterFilePath></DBRegisterFilePath>
<BinPath />
<IncludePath />
<LibPath />
<RegisterFilePath />
<DBRegisterFilePath />
<TargetStatus>
<Error>0</Error>
<ExitCodeStop>0</ExitCodeStop>
@@ -55,15 +52,15 @@
<CreateHexFile>1</CreateHexFile>
<DebugInformation>1</DebugInformation>
<BrowseInformation>1</BrowseInformation>
<ListingPath></ListingPath>
<ListingPath />
<HexFormatSelection>1</HexFormatSelection>
<Merge32K>0</Merge32K>
<CreateBatchFile>0</CreateBatchFile>
<BeforeCompile>
<RunUserProg1>0</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name></UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Name />
<UserProg2Name />
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopU1X>0</nStopU1X>
@@ -72,8 +69,8 @@
<BeforeMake>
<RunUserProg1>0</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name></UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Name />
<UserProg2Name />
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopB1X>0</nStopB1X>
@@ -82,15 +79,15 @@
<AfterMake>
<RunUserProg1>0</RunUserProg1>
<RunUserProg2>1</RunUserProg2>
<UserProg1Name></UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Name />
<UserProg2Name />
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopA1X>0</nStopA1X>
<nStopA2X>0</nStopA2X>
</AfterMake>
<SelectedForBatchBuild>1</SelectedForBatchBuild>
<SVCSIdString></SVCSIdString>
<SVCSIdString />
</TargetCommonOption>
<CommonProperty>
<UseCPPCompiler>0</UseCPPCompiler>
@@ -104,8 +101,8 @@
<AssembleAssemblyFile>0</AssembleAssemblyFile>
<PublicsOnly>0</PublicsOnly>
<StopOnExitCode>3</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<CustomArgument />
<IncludeLibraryModules />
<ComprImg>0</ComprImg>
</CommonProperty>
<DllOption>
@@ -139,10 +136,10 @@
<bUseTDR>1</bUseTDR>
<Flash2>BIN\UL2CM3.DLL</Flash2>
<Flash3>"" ()</Flash3>
<Flash4></Flash4>
<pFcarmOut></pFcarmOut>
<pFcarmGrp></pFcarmGrp>
<pFcArmRoot></pFcArmRoot>
<Flash4 />
<pFcarmOut />
<pFcarmGrp />
<pFcArmRoot />
<FcArmLst>0</FcArmLst>
</Utilities>
<TargetArmAds>
@@ -175,7 +172,7 @@
<RvctClst>0</RvctClst>
<GenPPlst>0</GenPPlst>
<AdsCpuType>"Cortex-M4"</AdsCpuType>
<RvctDeviceName></RvctDeviceName>
<RvctDeviceName />
<mOS>0</mOS>
<uocRom>0</uocRom>
<uocRam>0</uocRam>
@@ -310,7 +307,7 @@
<Size>0x4000</Size>
</OCR_RVCT10>
</OnChipMemories>
<RvctStartVector></RvctStartVector>
<RvctStartVector />
</ArmAdsMisc>
<Cads>
<interw>1</interw>
@@ -337,10 +334,10 @@
<v6WtE>0</v6WtE>
<v6Rtti>0</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<MiscControls />
<Define>USE_HAL_DRIVER,STM32F407xx</Define>
<Undefine></Undefine>
<IncludePath>../Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;../Drivers/BSP/CH395F;../Drivers/BSP/GD5F2GQ5UE;../Lib/FlashDB/port/fal/inc;../Lib/FlashDB/inc</IncludePath>
<Undefine />
<IncludePath>../Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;../Drivers/BSP/CH395F;../Drivers/BSP/GD5F2GQ5UE;../Lib/FlashDB/port/fal/inc;../Lib/FlashDB/inc;../Drivers/BSP/TPAFE5160;../Drivers/BSP/SD2506;../Drivers/BSP/RS485</IncludePath>
</VariousControls>
</Cads>
<Aads>
@@ -355,10 +352,10 @@
<useXO>0</useXO>
<ClangAsOpt>1</ClangAsOpt>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
<MiscControls />
<Define />
<Undefine />
<IncludePath />
</VariousControls>
</Aads>
<LDads>
@@ -368,15 +365,15 @@
<noStLib>0</noStLib>
<RepFail>1</RepFail>
<useFile>0</useFile>
<TextAddressRange></TextAddressRange>
<DataAddressRange></DataAddressRange>
<pXoBase></pXoBase>
<ScatterFile></ScatterFile>
<IncludeLibs></IncludeLibs>
<IncludeLibsPath></IncludeLibsPath>
<Misc></Misc>
<LinkerInputFile></LinkerInputFile>
<DisabledWarnings></DisabledWarnings>
<TextAddressRange />
<DataAddressRange />
<pXoBase />
<ScatterFile />
<IncludeLibs />
<IncludeLibsPath />
<Misc />
<LinkerInputFile />
<DisabledWarnings />
</LDads>
</TargetArmAds>
</TargetOption>
@@ -405,8 +402,116 @@
<FilePath>../Src/gpio.c</FilePath>
</File>
<File>
<FileName>spi.c</FileName>
<FileName>dma.c</FileName>
<FileType>1</FileType>
<FilePath>../Src/dma.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
</Cads>
<Aads>
<interw>2</interw>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<thumb>2</thumb>
<SplitLS>2</SplitLS>
<SwStkChk>2</SwStkChk>
<NoWarn>2</NoWarn>
<uSurpInc>2</uSurpInc>
<useXO>2</useXO>
<ClangAsOpt>1</ClangAsOpt>
</Aads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>i2c.c</FileName>
<FileType>1</FileType>
<FilePath>../Src/i2c.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>spi.c</FileName>
<FileType>1</FileType>
<FilePath>../Src/spi.c</FilePath>
<FileOption>
<CommonProperty>
@@ -421,8 +526,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
@@ -450,12 +553,6 @@
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
@@ -477,8 +574,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
@@ -506,12 +601,6 @@
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
@@ -532,9 +621,57 @@
<GroupName>Drivers/STM32F4xx_HAL_Driver</GroupName>
<Files>
<File>
<FileName>stm32f4xx_hal_spi.c</FileName>
<FileName>stm32f4xx_hal_i2c.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c</FilePath>
<FilePath>../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>stm32f4xx_hal_i2c_ex.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
@@ -548,8 +685,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
@@ -577,12 +712,6 @@
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
@@ -653,8 +782,56 @@
<FilePath>../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c</FilePath>
</File>
<File>
<FileName>stm32f4xx_hal_uart.c</FileName>
<FileName>stm32f4xx_hal_spi.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>stm32f4xx_hal_uart.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c</FilePath>
<FileOption>
<CommonProperty>
@@ -669,8 +846,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
@@ -698,12 +873,6 @@
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
@@ -738,6 +907,21 @@
<FileType>1</FileType>
<FilePath>..\Drivers\BSP\GD5F2GQ5UE\gd5f2gq5ue.c</FilePath>
</File>
<File>
<FileName>tpafe5160.c</FileName>
<FileType>1</FileType>
<FilePath>..\Drivers\BSP\TPAFE5160\tpafe5160.c</FilePath>
</File>
<File>
<FileName>sd2506.c</FileName>
<FileType>1</FileType>
<FilePath>..\Drivers\BSP\SD2506\sd2506.c</FilePath>
</File>
<File>
<FileName>rs485.c</FileName>
<FileType>1</FileType>
<FilePath>..\Drivers\BSP\RS485\rs485.c</FilePath>
</File>
</Files>
</Group>
<Group>
@@ -786,20 +970,18 @@
</Groups>
</Target>
</Targets>
<RTE>
<apis/>
<apis />
<components>
<component Cclass="CMSIS" Cgroup="CORE" Cvendor="ARM" Cversion="5.5.0" condition="ARMv6_7_8-M Device">
<package name="CMSIS" schemaVersion="1.3" url="http://www.keil.com/pack/" vendor="ARM" version="5.8.0"/>
<package name="CMSIS" schemaVersion="1.3" url="http://www.keil.com/pack/" vendor="ARM" version="5.8.0" />
<targetInfos>
<targetInfo name="STM32F407-Demo"/>
<targetInfo name="STM32F407-Demo" />
</targetInfos>
</component>
</components>
<files/>
<files />
</RTE>
<LayerInfo>
<Layers>
<Layer>
@@ -808,5 +990,5 @@
</Layer>
</Layers>
</LayerInfo>
</Project>

View File

@@ -2,51 +2,117 @@
CAD.formats=
CAD.pinconfig=
CAD.provider=
Dma.Request0=USART1_TX
Dma.Request1=USART1_RX
Dma.RequestsNb=2
Dma.USART1_RX.1.Direction=DMA_PERIPH_TO_MEMORY
Dma.USART1_RX.1.FIFOMode=DMA_FIFOMODE_DISABLE
Dma.USART1_RX.1.Instance=DMA2_Stream2
Dma.USART1_RX.1.MemDataAlignment=DMA_MDATAALIGN_BYTE
Dma.USART1_RX.1.MemInc=DMA_MINC_ENABLE
Dma.USART1_RX.1.Mode=DMA_CIRCULAR
Dma.USART1_RX.1.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
Dma.USART1_RX.1.PeriphInc=DMA_PINC_DISABLE
Dma.USART1_RX.1.Priority=DMA_PRIORITY_LOW
Dma.USART1_RX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
Dma.USART1_TX.0.Direction=DMA_MEMORY_TO_PERIPH
Dma.USART1_TX.0.FIFOMode=DMA_FIFOMODE_DISABLE
Dma.USART1_TX.0.Instance=DMA2_Stream7
Dma.USART1_TX.0.MemDataAlignment=DMA_MDATAALIGN_BYTE
Dma.USART1_TX.0.MemInc=DMA_MINC_ENABLE
Dma.USART1_TX.0.Mode=DMA_NORMAL
Dma.USART1_TX.0.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
Dma.USART1_TX.0.PeriphInc=DMA_PINC_DISABLE
Dma.USART1_TX.0.Priority=DMA_PRIORITY_LOW
Dma.USART1_TX.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
File.Version=6
GPIO.groupedBy=Group By Peripherals
KeepUserPlacement=false
Mcu.CPN=STM32F407ZGT6
Mcu.Family=STM32F4
Mcu.IP0=NVIC
Mcu.IP1=RCC
Mcu.IP2=SPI1
Mcu.IP3=SPI2
Mcu.IP4=SYS
Mcu.IP5=USART1
Mcu.IPNb=6
Mcu.IP0=DMA
Mcu.IP1=I2C1
Mcu.IP10=USART2
Mcu.IP11=USART3
Mcu.IP2=NVIC
Mcu.IP3=RCC
Mcu.IP4=SPI1
Mcu.IP5=SPI2
Mcu.IP6=SYS
Mcu.IP7=UART4
Mcu.IP8=UART5
Mcu.IP9=USART1
Mcu.IPNb=12
Mcu.Name=STM32F407Z(E-G)Tx
Mcu.Package=LQFP144
Mcu.Pin0=PH0-OSC_IN
Mcu.Pin1=PH1-OSC_OUT
Mcu.Pin10=PB14
Mcu.Pin11=PB15
Mcu.Pin12=PA9
Mcu.Pin13=PA10
Mcu.Pin14=PA13
Mcu.Pin15=PA14
Mcu.Pin16=PB3
Mcu.Pin17=PB4
Mcu.Pin18=PB5
Mcu.Pin19=PB8
Mcu.Pin10=PF15
Mcu.Pin11=PG0
Mcu.Pin12=PG1
Mcu.Pin13=PB10
Mcu.Pin14=PB11
Mcu.Pin15=PB12
Mcu.Pin16=PB13
Mcu.Pin17=PB14
Mcu.Pin18=PB15
Mcu.Pin19=PG2
Mcu.Pin2=PC4
Mcu.Pin20=PE0
Mcu.Pin21=PE1
Mcu.Pin22=VP_SYS_VS_Systick
Mcu.Pin20=PG3
Mcu.Pin21=PG4
Mcu.Pin22=PG5
Mcu.Pin23=PG6
Mcu.Pin24=PG7
Mcu.Pin25=PG8
Mcu.Pin26=PA9
Mcu.Pin27=PA10
Mcu.Pin28=PA13
Mcu.Pin29=PA14
Mcu.Pin3=PC5
Mcu.Pin30=PC10
Mcu.Pin31=PC11
Mcu.Pin32=PC12
Mcu.Pin33=PD0
Mcu.Pin34=PD1
Mcu.Pin35=PD2
Mcu.Pin36=PD3
Mcu.Pin37=PD4
Mcu.Pin38=PD5
Mcu.Pin39=PD6
Mcu.Pin4=PB1
Mcu.Pin40=PD7
Mcu.Pin41=PG9
Mcu.Pin42=PG10
Mcu.Pin43=PG11
Mcu.Pin44=PG12
Mcu.Pin45=PG13
Mcu.Pin46=PG14
Mcu.Pin47=PG15
Mcu.Pin48=PB3
Mcu.Pin49=PB4
Mcu.Pin5=PB2
Mcu.Pin50=PB5
Mcu.Pin51=PB6
Mcu.Pin52=PB7
Mcu.Pin53=PB8
Mcu.Pin54=PE0
Mcu.Pin55=PE1
Mcu.Pin56=VP_SYS_VS_Systick
Mcu.Pin6=PF11
Mcu.Pin7=PF12
Mcu.Pin8=PB12
Mcu.Pin9=PB13
Mcu.PinsNb=23
Mcu.Pin8=PF13
Mcu.Pin9=PF14
Mcu.PinsNb=57
Mcu.ThirdPartyNb=0
Mcu.UserConstants=
Mcu.UserName=STM32F407ZGTx
MxCube.Version=6.17.0
MxDb.Version=DB.6.0.170
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.DMA2_Stream2_IRQn=true\:3\:0\:true\:false\:true\:false\:true\:true
NVIC.DMA2_Stream7_IRQn=true\:3\:0\:true\:false\:true\:false\:true\:true
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.EXTI9_5_IRQn=true\:2\:0\:true\:false\:true\:true\:true\:true
NVIC.ForceEnableDMAVector=true
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
@@ -55,18 +121,26 @@ NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:false\:true\:false
NVIC.UART4_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true
NVIC.UART5_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true
NVIC.USART1_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true
NVIC.USART2_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true
NVIC.USART3_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
PA10.GPIOParameters=GPIO_PuPd,GPIO_Label
PA10.GPIO_Label=ST_RX0
PA10.GPIO_PuPd=GPIO_PULLUP
PA10.GPIOParameters=GPIO_ModeDefaultPP,GPIO_Speed,GPIO_PuPd
PA10.GPIO_ModeDefaultPP=GPIO_MODE_AF_PP
PA10.GPIO_PuPd=GPIO_NOPULL
PA10.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
PA10.Mode=Asynchronous
PA10.Signal=USART1_RX
PA13.Mode=Serial_Wire
PA13.Signal=SYS_JTMS-SWDIO
PA14.Mode=Serial_Wire
PA14.Signal=SYS_JTCK-SWCLK
PA9.GPIOParameters=GPIO_Label
PA9.GPIO_Label=ST_TX0
PA9.GPIOParameters=GPIO_ModeDefaultPP,GPIO_Speed,GPIO_PuPd
PA9.GPIO_ModeDefaultPP=GPIO_MODE_AF_PP
PA9.GPIO_PuPd=GPIO_NOPULL
PA9.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
PA9.Mode=Asynchronous
PA9.Signal=USART1_TX
PB1.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
@@ -76,6 +150,16 @@ PB1.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
PB1.Locked=true
PB1.PinState=GPIO_PIN_SET
PB1.Signal=GPIO_Output
PB10.GPIOParameters=GPIO_Label
PB10.GPIO_Label=ST_TX2
PB10.Locked=true
PB10.Mode=Asynchronous
PB10.Signal=USART3_TX
PB11.GPIOParameters=GPIO_Label
PB11.GPIO_Label=ST_RX2
PB11.Locked=true
PB11.Mode=Asynchronous
PB11.Signal=USART3_RX
PB12.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
PB12.GPIO_Label=CH395_SCS
PB12.GPIO_PuPd=GPIO_NOPULL
@@ -124,6 +208,16 @@ PB5.GPIO_PuPd=GPIO_PULLUP
PB5.Locked=true
PB5.Mode=Full_Duplex_Master
PB5.Signal=SPI1_MOSI
PB6.GPIOParameters=GPIO_Label
PB6.GPIO_Label=SD_SCL
PB6.Locked=true
PB6.Mode=I2C
PB6.Signal=I2C1_SCL
PB7.GPIOParameters=GPIO_Label
PB7.GPIO_Label=SD_SDA
PB7.Locked=true
PB7.Mode=I2C
PB7.Signal=I2C1_SDA
PB8.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
PB8.GPIO_Label=GD_WP
PB8.GPIO_PuPd=GPIO_PULLUP
@@ -131,6 +225,21 @@ PB8.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
PB8.Locked=true
PB8.PinState=GPIO_PIN_SET
PB8.Signal=GPIO_Output
PC10.GPIOParameters=GPIO_Label
PC10.GPIO_Label=ST_TX3
PC10.Locked=true
PC10.Mode=Asynchronous
PC10.Signal=UART4_TX
PC11.GPIOParameters=GPIO_Label
PC11.GPIO_Label=ST_RX3
PC11.Locked=true
PC11.Mode=Asynchronous
PC11.Signal=UART4_RX
PC12.GPIOParameters=GPIO_Label
PC12.GPIO_Label=ST_TX4
PC12.Locked=true
PC12.Mode=Asynchronous
PC12.Signal=UART5_TX
PC4.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
PC4.GPIO_Label=LED1
PC4.GPIO_PuPd=GPIO_PULLUP
@@ -153,6 +262,45 @@ PCC.PartNumber=STM32F407ZGTx
PCC.Series=STM32F4
PCC.Temperature=25
PCC.Vdd=3.3
PD0.GPIOParameters=GPIO_PuPd,GPIO_Label
PD0.GPIO_Label=ST_DIR4
PD0.GPIO_PuPd=GPIO_NOPULL
PD0.Locked=true
PD0.Signal=GPIO_Output
PD1.GPIOParameters=GPIO_Label
PD1.GPIO_Label=TP_FRSTDATA
PD1.Locked=true
PD1.Signal=GPIO_Input
PD2.GPIOParameters=GPIO_Label
PD2.GPIO_Label=ST_RX4
PD2.Mode=Asynchronous
PD2.Signal=UART5_RX
PD3.GPIOParameters=GPIO_Speed,PinState,GPIO_Label
PD3.GPIO_Label=TP_RD
PD3.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
PD3.Locked=true
PD3.PinState=GPIO_PIN_SET
PD3.Signal=GPIO_Output
PD4.GPIOParameters=GPIO_Speed,GPIO_Label
PD4.GPIO_Label=TP_CONVST
PD4.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
PD4.Locked=true
PD4.Signal=GPIO_Output
PD5.GPIOParameters=GPIO_Label
PD5.GPIO_Label=ST_TX1
PD5.Locked=true
PD5.Mode=Asynchronous
PD5.Signal=USART2_TX
PD6.GPIOParameters=GPIO_Label
PD6.GPIO_Label=ST_RX1
PD6.Locked=true
PD6.Mode=Asynchronous
PD6.Signal=USART2_RX
PD7.GPIOParameters=GPIO_Label,GPIO_ModeDefaultEXTI
PD7.GPIO_Label=TP_BUSY
PD7.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_FALLING
PD7.Locked=true
PD7.Signal=GPXTI7
PE0.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
PE0.GPIO_Label=GD_CS
PE0.GPIO_PuPd=GPIO_PULLUP
@@ -181,6 +329,85 @@ PF12.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
PF12.Locked=true
PF12.PinState=GPIO_PIN_SET
PF12.Signal=GPIO_Output
PF13.GPIOParameters=GPIO_Speed,GPIO_Label
PF13.GPIO_Label=TP_OS0
PF13.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
PF13.Locked=true
PF13.Signal=GPIO_Output
PF14.GPIOParameters=GPIO_Speed,GPIO_Label
PF14.GPIO_Label=TP_OS1
PF14.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
PF14.Locked=true
PF14.Signal=GPIO_Output
PF15.GPIOParameters=GPIO_Speed,GPIO_Label
PF15.GPIO_Label=TP_OS2
PF15.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
PF15.Locked=true
PF15.Signal=GPIO_Output
PG0.GPIOParameters=GPIO_Label
PG0.GPIO_Label=DB0
PG0.Locked=true
PG0.Signal=GPIO_Input
PG1.GPIOParameters=GPIO_Label
PG1.GPIO_Label=DB1
PG1.Locked=true
PG1.Signal=GPIO_Input
PG10.GPIOParameters=GPIO_Label
PG10.GPIO_Label=DB10
PG10.Locked=true
PG10.Signal=GPIO_Input
PG11.GPIOParameters=GPIO_Label
PG11.GPIO_Label=DB11
PG11.Locked=true
PG11.Signal=GPIO_Input
PG12.GPIOParameters=GPIO_Label
PG12.GPIO_Label=DB12
PG12.Locked=true
PG12.Signal=GPIO_Input
PG13.GPIOParameters=GPIO_Label
PG13.GPIO_Label=DB13
PG13.Locked=true
PG13.Signal=GPIO_Input
PG14.GPIOParameters=GPIO_Label
PG14.GPIO_Label=DB14
PG14.Locked=true
PG14.Signal=GPIO_Input
PG15.GPIOParameters=GPIO_Label
PG15.GPIO_Label=DB15
PG15.Locked=true
PG15.Signal=GPIO_Input
PG2.GPIOParameters=GPIO_Label
PG2.GPIO_Label=DB2
PG2.Locked=true
PG2.Signal=GPIO_Input
PG3.GPIOParameters=GPIO_Label
PG3.GPIO_Label=DB3
PG3.Locked=true
PG3.Signal=GPIO_Input
PG4.GPIOParameters=GPIO_Label
PG4.GPIO_Label=DB4
PG4.Locked=true
PG4.Signal=GPIO_Input
PG5.GPIOParameters=GPIO_Label
PG5.GPIO_Label=DB5
PG5.Locked=true
PG5.Signal=GPIO_Input
PG6.GPIOParameters=GPIO_Label
PG6.GPIO_Label=DB6
PG6.Locked=true
PG6.Signal=GPIO_Input
PG7.GPIOParameters=GPIO_Label
PG7.GPIO_Label=DB7
PG7.Locked=true
PG7.Signal=GPIO_Input
PG8.GPIOParameters=GPIO_Label
PG8.GPIO_Label=DB8
PG8.Locked=true
PG8.Signal=GPIO_Input
PG9.GPIOParameters=GPIO_Label
PG9.GPIO_Label=DB9
PG9.Locked=true
PG9.Signal=GPIO_Input
PH0-OSC_IN.Mode=HSE-External-Oscillator
PH0-OSC_IN.Signal=RCC_OSC_IN
PH1-OSC_OUT.Mode=HSE-External-Oscillator
@@ -218,7 +445,7 @@ ProjectManager.ToolChainLocation=
ProjectManager.UAScriptAfterPath=
ProjectManager.UAScriptBeforePath=
ProjectManager.UnderRoot=false
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_USART1_UART_Init-USART1-false-HAL-true,4-MX_SPI2_Init-SPI2-false-HAL-true,5-MX_SPI1_Init-SPI1-false-HAL-true
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_USART1_UART_Init-USART1-false-HAL-true,5-MX_SPI2_Init-SPI2-false-HAL-true,6-MX_SPI1_Init-SPI1-false-HAL-true,7-MX_I2C1_Init-I2C1-false-HAL-true,8-MX_UART4_Init-UART4-false-HAL-true,9-MX_UART5_Init-UART5-false-HAL-true,10-MX_USART2_UART_Init-USART2-false-HAL-true,11-MX_USART3_UART_Init-USART3-false-HAL-true
RCC.48MHZClocksFreq_Value=84000000
RCC.AHBFreq_Value=168000000
RCC.APB1CLKDivider=RCC_HCLK_DIV4
@@ -252,6 +479,8 @@ RCC.VCOI2SOutputFreq_Value=384000000
RCC.VCOInputFreq_Value=2000000
RCC.VCOOutputFreq_Value=336000000
RCC.VcooutputI2S=192000000
SH.GPXTI7.0=GPIO_EXTI7
SH.GPXTI7.ConfNb=1
SPI1.CalculateBaudRate=42.0 MBits/s
SPI1.Direction=SPI_DIRECTION_2LINES
SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate
@@ -262,8 +491,16 @@ SPI2.Direction=SPI_DIRECTION_2LINES
SPI2.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate
SPI2.Mode=SPI_MODE_MASTER
SPI2.VirtualType=VM_MASTER
UART4.IPParameters=VirtualMode
UART4.VirtualMode=Asynchronous
UART5.IPParameters=VirtualMode
UART5.VirtualMode=Asynchronous
USART1.IPParameters=VirtualMode
USART1.VirtualMode=VM_ASYNC
USART2.IPParameters=VirtualMode
USART2.VirtualMode=VM_ASYNC
USART3.IPParameters=VirtualMode
USART3.VirtualMode=VM_ASYNC
VP_SYS_VS_Systick.Mode=SysTick
VP_SYS_VS_Systick.Signal=SYS_VS_Systick
board=custom

58
Src/dma.c Normal file
View File

@@ -0,0 +1,58 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file dma.c
* @brief This file provides code for the configuration
* of all the requested memory to memory DMA transfers.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "dma.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/*----------------------------------------------------------------------------*/
/* Configure DMA */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/**
* Enable DMA controller clock
*/
void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA2_Stream2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
/* DMA2_Stream7_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);
}
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */

View File

@@ -49,7 +49,9 @@ void MX_GPIO_Init(void)
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
/*Configure GPIO pin Output Level */
@@ -61,6 +63,15 @@ void MX_GPIO_Init(void)
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOF, LED5_Pin|LED6_Pin, GPIO_PIN_SET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOF, TP_OS0_Pin|TP_OS1_Pin|TP_OS2_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOD, ST_DIR4_Pin|TP_CONVST_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(TP_RD_GPIO_Port, TP_RD_Pin, GPIO_PIN_SET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOE, GD_CS_Pin|GD_HOLD_Pin, GPIO_PIN_SET);
@@ -85,6 +96,25 @@ void MX_GPIO_Init(void)
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
/*Configure GPIO pins : TP_OS0_Pin TP_OS1_Pin TP_OS2_Pin */
GPIO_InitStruct.Pin = TP_OS0_Pin|TP_OS1_Pin|TP_OS2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
/*Configure GPIO pins : DB0_Pin DB1_Pin DB2_Pin DB3_Pin
DB4_Pin DB5_Pin DB6_Pin DB7_Pin
DB8_Pin DB9_Pin DB10_Pin DB11_Pin
DB12_Pin DB13_Pin DB14_Pin DB15_Pin */
GPIO_InitStruct.Pin = DB0_Pin|DB1_Pin|DB2_Pin|DB3_Pin
|DB4_Pin|DB5_Pin|DB6_Pin|DB7_Pin
|DB8_Pin|DB9_Pin|DB10_Pin|DB11_Pin
|DB12_Pin|DB13_Pin|DB14_Pin|DB15_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
/*Configure GPIO pin : CH395_SCS_Pin */
GPIO_InitStruct.Pin = CH395_SCS_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
@@ -92,6 +122,32 @@ void MX_GPIO_Init(void)
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(CH395_SCS_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : ST_DIR4_Pin */
GPIO_InitStruct.Pin = ST_DIR4_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(ST_DIR4_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : TP_FRSTDATA_Pin */
GPIO_InitStruct.Pin = TP_FRSTDATA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(TP_FRSTDATA_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : TP_RD_Pin TP_CONVST_Pin */
GPIO_InitStruct.Pin = TP_RD_Pin|TP_CONVST_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/*Configure GPIO pin : TP_BUSY_Pin */
GPIO_InitStruct.Pin = TP_BUSY_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(TP_BUSY_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : GD_WP_Pin */
GPIO_InitStruct.Pin = GD_WP_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
@@ -106,6 +162,10 @@ void MX_GPIO_Init(void)
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI9_5_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
}
/* USER CODE BEGIN 2 */

117
Src/i2c.c Normal file
View File

@@ -0,0 +1,117 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file i2c.c
* @brief This file provides code for the configuration
* of the I2C instances.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "i2c.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
I2C_HandleTypeDef hi2c1;
/* I2C1 init function */
void MX_I2C1_Init(void)
{
/* USER CODE BEGIN I2C1_Init 0 */
/* USER CODE END I2C1_Init 0 */
/* USER CODE BEGIN I2C1_Init 1 */
/* USER CODE END I2C1_Init 1 */
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN I2C1_Init 2 */
/* USER CODE END I2C1_Init 2 */
}
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(i2cHandle->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspInit 0 */
/* USER CODE END I2C1_MspInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE();
/**I2C1 GPIO Configuration
PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = SD_SCL_Pin|SD_SDA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* I2C1 clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
/* USER CODE BEGIN I2C1_MspInit 1 */
/* USER CODE END I2C1_MspInit 1 */
}
}
void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle)
{
if(i2cHandle->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspDeInit 0 */
/* USER CODE END I2C1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_I2C1_CLK_DISABLE();
/**I2C1 GPIO Configuration
PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA
*/
HAL_GPIO_DeInit(SD_SCL_GPIO_Port, SD_SCL_Pin);
HAL_GPIO_DeInit(SD_SDA_GPIO_Port, SD_SDA_Pin);
/* USER CODE BEGIN I2C1_MspDeInit 1 */
/* USER CODE END I2C1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

View File

@@ -18,6 +18,8 @@
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "i2c.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"
@@ -28,7 +30,9 @@
#include <stdio.h>
#include "ch395f.h"
#include "gd5f2gq5ue.h"
#include "flashdb.h"
#include "tpafe5160.h"
#include "sd2506.h"
#include "rs485.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
@@ -49,7 +53,10 @@
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* RS-485 通信实例UART5: PC12=TX, PD2=RX, PD0=DE */
rs485_handle_t g_rs485;
#define RS485_RX_BUF_SIZE 256
uint8_t g_rs485_rx_buf[RS485_RX_BUF_SIZE];
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
@@ -71,7 +78,6 @@ int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t str[] = "Hello World\n";
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
@@ -92,95 +98,123 @@ int main(void)
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
MX_SPI2_Init();
MX_SPI1_Init();
MX_I2C1_Init();
MX_UART4_Init();
MX_UART5_Init();
MX_USART2_UART_Init();
MX_USART3_UART_Init();
/* USER CODE BEGIN 2 */
char dbg[64];
uint8_t mac[6];
HAL_Delay(100);
ch395f_reset();
/* CH395F 硬件检测 */
ch395f_status_t ch395f_ret = ch395f_check_exist();
printf("[CH395F] SPI: %s\r\n",
(ch395f_ret == CH395F_STATUS_OK) ? "OK" : "FAIL");
/* [1/5] SPI 通信检测 */
sprintf(dbg, "[1/5] CH395F %s\r\n",
(ch395f_check_exist() == CH395F_STATUS_OK) ? "detected" : "ERROR: not detected");
HAL_UART_Transmit(&huart1, (uint8_t*)dbg, strlen(dbg), 1000);
printf("[CH395F] version: 0x%02X\r\n", ch395f_get_version());
/* [2/5] 芯片版本 */
sprintf(dbg, "[2/5] CH395F version: 0x%02X\r\n", ch395f_get_version());
HAL_UART_Transmit(&huart1, (uint8_t*)dbg, strlen(dbg), 1000);
if (ch395f_ret == CH395F_STATUS_OK) {
/* 1. 复位 */
ch395f_reset();
/* 配置 IP/网关/掩码 */
{
/* 2. 配置网络参数(必须在 INIT 之前INIT 会锁定协议栈参数) */
uint8_t ip[4] = {192, 168, 1, 100};
uint8_t gw[4] = {192, 168, 1, 1};
uint8_t mask[4] = {255, 255, 255, 0};
ch395f_set_ip_addr(ip);
ch395f_set_gwip_addr(gw);
ch395f_set_mask_addr(mask);
}
/* [3/5] 协议栈初始化 */
sprintf(dbg, "[3/5] Protocol stack init %s\r\n",
(ch395f_init() == CH395F_STATUS_OK) ? "OK" : "ERROR");
HAL_UART_Transmit(&huart1, (uint8_t*)dbg, strlen(dbg), 1000);
/* 3. 初始化协议栈(锁定 IP/GW/MASK 等参数) */
printf("[CH395F] init: %s\r\n",
(ch395f_init() == CH395F_STATUS_OK) ? "OK" : "FAIL");
/* [4/5] MAC 地址 */
ch395f_get_mac_addr(mac);
sprintf(dbg, "[4/5] MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
HAL_UART_Transmit(&huart1, (uint8_t*)dbg, strlen(dbg), 1000);
/* 4. 读取 MAC */
uint8_t mac[6];
ch395f_get_mac_addr(mac);
printf("[CH395F] MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
/* [5/5] 强制 100M 全双工后检测 PHY */
ch395f_set_phy(CH395F_PHY_100M_FULL);
HAL_Delay(3000);
{
uint8_t s = ch395f_get_phy_status();
const char *desc = (s == CH395F_PHY_DISCONN) ? "DISCONNECTED" :
(s == CH395F_PHY_100M_FULL) ? "100M FULL" :
(s == CH395F_PHY_100M_HALF) ? "100M HALF" :
(s == CH395F_PHY_10M_FULL) ? "10M FULL" :
(s == CH395F_PHY_10M_HALF) ? "10M HALF" : "RESERVED";
sprintf(dbg, "[5/5] PHY: 0x%02X (%s)\r\n", s, desc);
HAL_UART_Transmit(&huart1, (uint8_t*)dbg, strlen(dbg), 1000);
}
/* ===================== FlashDB KVDB 测试 ===================== */
{
uint8_t gd_mid, gd_did;
int ret;
/* 检测 GD5F2GQ5UE */
ret = gd5f2gq5ue_read_id(&gd_mid, &gd_did);
sprintf(dbg, "[GD5F] ID: MID=0x%02X DID=0x%02X %s\r\n",
gd_mid, gd_did,
(ret == GD5F_OK && gd_mid == 0xC8 && gd_did == 0x52) ? "OK" : "FAIL");
HAL_UART_Transmit(&huart1, (uint8_t*)dbg, strlen(dbg), 1000);
/* 初始化 FlashDB KVDB */
{
static struct fdb_kvdb kvdb;
ret = fdb_kvdb_init(&kvdb, "db", "fdb_kvdb1", NULL, NULL);
sprintf(dbg, "[FlashDB] KVDB init: %s\r\n",
(ret == FDB_NO_ERR) ? "OK" : "FAIL");
HAL_UART_Transmit(&huart1, (uint8_t*)dbg, strlen(dbg), 1000);
if (ret == FDB_NO_ERR) {
/* 写入测试 KV */
fdb_kv_set(&kvdb, "test_key", "hello_flashdb");
HAL_UART_Transmit(&huart1, (uint8_t*)"[FlashDB] KV set OK\r\n", 21, 1000);
/* 读取测试 KV */
char *val = fdb_kv_get(&kvdb, "test_key");
if (val) {
sprintf(dbg, "[FlashDB] KV get: %s\r\n", val);
} else {
sprintf(dbg, "[FlashDB] KV get: NULL\r\n");
}
HAL_UART_Transmit(&huart1, (uint8_t*)dbg, strlen(dbg), 1000);
}
/* 5. 强制 100M 全双工,建立 PHY 链路 */
ch395f_set_phy(CH395F_PHY_100M_FULL);
HAL_Delay(3000);
uint8_t phy = ch395f_get_phy_status();
const char *phy_str = "UNKNOWN";
switch (phy) {
case CH395F_PHY_DISCONN: phy_str = "DISCONNECT"; break;
case CH395F_PHY_10M_FULL: phy_str = "10M FULL"; break;
case CH395F_PHY_10M_HALF: phy_str = "10M HALF"; break;
case CH395F_PHY_100M_FULL: phy_str = "100M FULL"; break;
case CH395F_PHY_100M_HALF: phy_str = "100M HALF"; break;
}
printf("[CH395F] PHY: %s\r\n", phy_str);
}
/* GD5F 初始化测试 */
int ret = gd5f2gq5ue_init();
const char *gd5f_str = "UNKNOWN";
switch (ret) {
case GD5F_OK: gd5f_str = "OK"; break;
case GD5F_ERROR: gd5f_str = "ERROR"; break;
case GD5F_BUSY_TIMEOUT: gd5f_str = "BUSY TIMEOUT"; break;
case GD5F_ECC_ERROR: gd5f_str = "ECC ERROR"; break;
case GD5F_PROGRAM_FAIL: gd5f_str = "PROGRAM FAIL"; break;
case GD5F_ERASE_FAIL: gd5f_str = "ERASE FAIL"; break;
case GD5F_ID_MISMATCH: gd5f_str = "ID MISMATCH"; break;
}
printf("[GD5F] init: %s\r\n", gd5f_str);
/* TPAFE5160 ADC 测试 */
int tp_ret = tpafe5160_init();
printf("[TPAFE5160] init: %s\r\n",
(tp_ret == TPAFE5160_OK) ? "OK" : "TIMEOUT");
/* SD2506 RTC 初始化测试 */
int sd_ret = sd2506_init();
printf("[SD2506] init: %s\r\n",
(sd_ret == SD2506_OK) ? "OK" : "I2C ERROR");
if (sd_ret == SD2506_OK) {
/* 读取 ID */
uint8_t sd_id[8];
sd2506_get_id(sd_id);
printf("[SD2506] ID: %02X%02X%02X%02X%02X%02X%02X%02X\r\n",
sd_id[0], sd_id[1], sd_id[2], sd_id[3],
sd_id[4], sd_id[5], sd_id[6], sd_id[7]);
/* 读取当前时间 */
sd2506_time_t sd_time;
sd2506_get_time(&sd_time);
printf("[SD2506] time: %04d-%02d-%02d %02d:%02d:%02d (week %d)\r\n",
sd_time.year, sd_time.month, sd_time.day,
sd_time.hour, sd_time.minute, sd_time.second,
sd_time.week);
/* 读取温度 */
int8_t sd_temp;
sd2506_get_temperature(&sd_temp);
printf("[SD2506] temp: %d C\r\n", sd_temp);
/* 读取电池电压 */
uint16_t sd_vbat;
sd2506_get_battery_voltage(&sd_vbat);
printf("[SD2506] battery: %d.%02d V\r\n",
sd_vbat / 1000, (sd_vbat % 1000) / 10);
}
/* RS-485 初始化UART5 + PD0 方向控制) */
rs485_init(&g_rs485, &huart5, ST_DIR4_GPIO_Port, ST_DIR4_Pin);
printf("[RS485] init: OK (UART5, DE=PD0)\r\n");
/* 启动第一次 RS-485 接收 */
rs485_receive_start(&g_rs485, g_rs485_rx_buf, RS485_RX_BUF_SIZE);
/* 启动第一次转换CubeMX 已配置 BUSY EXTI 中断) */
tpafe5160_start_conv_irq();
/* USER CODE END 2 */
/* Infinite loop */
@@ -190,13 +224,21 @@ int main(void)
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
/* TPAFE5160 中断模式读取 */
if (tpafe5160_data_ready()) {
const int16_t *buf = tpafe5160_get_buf();
printf("[TPAFE5160] CH:");
for (int i = 0; i < 8; i++) {
printf(" %d", buf[i]);
}
printf("\r\n");
tpafe5160_clear_ready();
/* 启动下一次转换 */
tpafe5160_start_conv_irq();
}
/* 其他任务 */
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
HAL_GPIO_TogglePin(LED3_GPIO_Port, LED3_Pin);
HAL_GPIO_TogglePin(LED4_GPIO_Port, LED4_Pin);
HAL_GPIO_TogglePin(LED5_GPIO_Port, LED5_Pin);
HAL_GPIO_TogglePin(LED6_GPIO_Port, LED6_Pin);
//HAL_UART_Transmit(&huart1, str, strlen((char*)str), 1000);
HAL_Delay(500);
}
/* USER CODE END 3 */
@@ -248,7 +290,38 @@ void SystemClock_Config(void)
}
/* USER CODE BEGIN 4 */
/*
* HAL UART 扩展接收回调IDLE 空闲帧中断触发)
* 当 RS-485 总线空闲超过 1 个字符时间后触发
*/
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if (huart->Instance == UART5) {
rs485_rx_set_size(&g_rs485, Size);
/* TODO: 在此处处理接收到的 RS-485 数据
* g_rs485_rx_buf[0 .. Size-1] 为有效数据
* 例如rs485_transmit(&g_rs485, g_rs485_rx_buf, Size, 0);
*/
/* 重新开启接收 */
rs485_receive_start(&g_rs485, g_rs485_rx_buf, RS485_RX_BUF_SIZE);
}
}
/*
* HAL UART 错误回调
*/
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == UART5) {
/* STM32F4 通过读 SR + DR 清除 ORE/NE/FE/PE 错误标志 */
(void)huart->Instance->SR;
(void)huart->Instance->DR;
/* 重新开启接收 */
rs485_receive_start(&g_rs485, g_rs485_rx_buf, RS485_RX_BUF_SIZE);
}
}
/* USER CODE END 4 */
/**

View File

@@ -55,7 +55,13 @@
/* USER CODE END 0 */
/* External variables --------------------------------------------------------*/
extern DMA_HandleTypeDef hdma_usart1_tx;
extern DMA_HandleTypeDef hdma_usart1_rx;
extern UART_HandleTypeDef huart4;
extern UART_HandleTypeDef huart5;
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
extern UART_HandleTypeDef huart3;
/* USER CODE BEGIN EV */
/* USER CODE END EV */
@@ -198,6 +204,118 @@ void SysTick_Handler(void)
/* please refer to the startup file (startup_stm32f4xx.s). */
/******************************************************************************/
/**
* @brief This function handles EXTI line[9:5] interrupts.
*/
void EXTI9_5_IRQHandler(void)
{
/* USER CODE BEGIN EXTI9_5_IRQn 0 */
/* USER CODE END EXTI9_5_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(TP_BUSY_Pin);
/* USER CODE BEGIN EXTI9_5_IRQn 1 */
/* USER CODE END EXTI9_5_IRQn 1 */
}
/**
* @brief This function handles USART1 global interrupt.
*/
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
/**
* @brief This function handles USART2 global interrupt.
*/
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
/* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
/* USER CODE END USART2_IRQn 1 */
}
/**
* @brief This function handles USART3 global interrupt.
*/
void USART3_IRQHandler(void)
{
/* USER CODE BEGIN USART3_IRQn 0 */
/* USER CODE END USART3_IRQn 0 */
HAL_UART_IRQHandler(&huart3);
/* USER CODE BEGIN USART3_IRQn 1 */
/* USER CODE END USART3_IRQn 1 */
}
/**
* @brief This function handles UART4 global interrupt.
*/
void UART4_IRQHandler(void)
{
/* USER CODE BEGIN UART4_IRQn 0 */
/* USER CODE END UART4_IRQn 0 */
HAL_UART_IRQHandler(&huart4);
/* USER CODE BEGIN UART4_IRQn 1 */
/* USER CODE END UART4_IRQn 1 */
}
/**
* @brief This function handles UART5 global interrupt.
*/
void UART5_IRQHandler(void)
{
/* USER CODE BEGIN UART5_IRQn 0 */
/* USER CODE END UART5_IRQn 0 */
HAL_UART_IRQHandler(&huart5);
/* USER CODE BEGIN UART5_IRQn 1 */
/* USER CODE END UART5_IRQn 1 */
}
/**
* @brief This function handles DMA2 stream2 global interrupt.
*/
void DMA2_Stream2_IRQHandler(void)
{
/* USER CODE BEGIN DMA2_Stream2_IRQn 0 */
/* USER CODE END DMA2_Stream2_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_usart1_rx);
/* USER CODE BEGIN DMA2_Stream2_IRQn 1 */
/* USER CODE END DMA2_Stream2_IRQn 1 */
}
/**
* @brief This function handles DMA2 stream7 global interrupt.
*/
void DMA2_Stream7_IRQHandler(void)
{
/* USER CODE BEGIN DMA2_Stream7_IRQn 0 */
/* USER CODE END DMA2_Stream7_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_usart1_tx);
/* USER CODE BEGIN DMA2_Stream7_IRQn 1 */
/* USER CODE END DMA2_Stream7_IRQn 1 */
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

View File

@@ -24,8 +24,70 @@
/* USER CODE END 0 */
UART_HandleTypeDef huart4;
UART_HandleTypeDef huart5;
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
UART_HandleTypeDef huart3;
DMA_HandleTypeDef hdma_usart1_tx;
DMA_HandleTypeDef hdma_usart1_rx;
/* UART4 init function */
void MX_UART4_Init(void)
{
/* USER CODE BEGIN UART4_Init 0 */
/* USER CODE END UART4_Init 0 */
/* USER CODE BEGIN UART4_Init 1 */
/* USER CODE END UART4_Init 1 */
huart4.Instance = UART4;
huart4.Init.BaudRate = 115200;
huart4.Init.WordLength = UART_WORDLENGTH_8B;
huart4.Init.StopBits = UART_STOPBITS_1;
huart4.Init.Parity = UART_PARITY_NONE;
huart4.Init.Mode = UART_MODE_TX_RX;
huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart4.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart4) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN UART4_Init 2 */
/* USER CODE END UART4_Init 2 */
}
/* UART5 init function */
void MX_UART5_Init(void)
{
/* USER CODE BEGIN UART5_Init 0 */
/* USER CODE END UART5_Init 0 */
/* USER CODE BEGIN UART5_Init 1 */
/* USER CODE END UART5_Init 1 */
huart5.Instance = UART5;
huart5.Init.BaudRate = 115200;
huart5.Init.WordLength = UART_WORDLENGTH_8B;
huart5.Init.StopBits = UART_STOPBITS_1;
huart5.Init.Parity = UART_PARITY_NONE;
huart5.Init.Mode = UART_MODE_TX_RX;
huart5.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart5.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart5) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN UART5_Init 2 */
/* USER CODE END UART5_Init 2 */
}
/* USART1 init function */
void MX_USART1_UART_Init(void)
@@ -54,13 +116,133 @@ void MX_USART1_UART_Init(void)
/* USER CODE END USART1_Init 2 */
}
/* USART2 init function */
void MX_USART2_UART_Init(void)
{
/* USER CODE BEGIN USART2_Init 0 */
/* USER CODE END USART2_Init 0 */
/* USER CODE BEGIN USART2_Init 1 */
/* USER CODE END USART2_Init 1 */
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART2_Init 2 */
/* USER CODE END USART2_Init 2 */
}
/* USART3 init function */
void MX_USART3_UART_Init(void)
{
/* USER CODE BEGIN USART3_Init 0 */
/* USER CODE END USART3_Init 0 */
/* USER CODE BEGIN USART3_Init 1 */
/* USER CODE END USART3_Init 1 */
huart3.Instance = USART3;
huart3.Init.BaudRate = 115200;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart3) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART3_Init 2 */
/* USER CODE END USART3_Init 2 */
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART1)
if(uartHandle->Instance==UART4)
{
/* USER CODE BEGIN UART4_MspInit 0 */
/* USER CODE END UART4_MspInit 0 */
/* UART4 clock enable */
__HAL_RCC_UART4_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/**UART4 GPIO Configuration
PC10 ------> UART4_TX
PC11 ------> UART4_RX
*/
GPIO_InitStruct.Pin = ST_TX3_Pin|ST_RX3_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* UART4 interrupt Init */
HAL_NVIC_SetPriority(UART4_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(UART4_IRQn);
/* USER CODE BEGIN UART4_MspInit 1 */
/* USER CODE END UART4_MspInit 1 */
}
else if(uartHandle->Instance==UART5)
{
/* USER CODE BEGIN UART5_MspInit 0 */
/* USER CODE END UART5_MspInit 0 */
/* UART5 clock enable */
__HAL_RCC_UART5_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/**UART5 GPIO Configuration
PC12 ------> UART5_TX
PD2 ------> UART5_RX
*/
GPIO_InitStruct.Pin = ST_TX4_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF8_UART5;
HAL_GPIO_Init(ST_TX4_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = ST_RX4_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF8_UART5;
HAL_GPIO_Init(ST_RX4_GPIO_Port, &GPIO_InitStruct);
/* UART5 interrupt Init */
HAL_NVIC_SetPriority(UART5_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(UART5_IRQn);
/* USER CODE BEGIN UART5_MspInit 1 */
/* USER CODE END UART5_MspInit 1 */
}
else if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
@@ -73,30 +255,159 @@ void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = ST_TX0_Pin;
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(ST_TX0_GPIO_Port, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = ST_RX0_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(ST_RX0_GPIO_Port, &GPIO_InitStruct);
/* USART1 DMA Init */
/* USART1_TX Init */
hdma_usart1_tx.Instance = DMA2_Stream7;
hdma_usart1_tx.Init.Channel = DMA_CHANNEL_4;
hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart1_tx.Init.Mode = DMA_NORMAL;
hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_usart1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx);
/* USART1_RX Init */
hdma_usart1_rx.Instance = DMA2_Stream2;
hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4;
hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart1_rx.Init.Mode = DMA_CIRCULAR;
hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx);
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
else if(uartHandle->Instance==USART2)
{
/* USER CODE BEGIN USART2_MspInit 0 */
/* USER CODE END USART2_MspInit 0 */
/* USART2 clock enable */
__HAL_RCC_USART2_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/**USART2 GPIO Configuration
PD5 ------> USART2_TX
PD6 ------> USART2_RX
*/
GPIO_InitStruct.Pin = ST_TX1_Pin|ST_RX1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/* USART2 interrupt Init */
HAL_NVIC_SetPriority(USART2_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USART2_IRQn);
/* USER CODE BEGIN USART2_MspInit 1 */
/* USER CODE END USART2_MspInit 1 */
}
else if(uartHandle->Instance==USART3)
{
/* USER CODE BEGIN USART3_MspInit 0 */
/* USER CODE END USART3_MspInit 0 */
/* USART3 clock enable */
__HAL_RCC_USART3_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**USART3 GPIO Configuration
PB10 ------> USART3_TX
PB11 ------> USART3_RX
*/
GPIO_InitStruct.Pin = ST_TX2_Pin|ST_RX2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USART3 interrupt Init */
HAL_NVIC_SetPriority(USART3_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USART3_IRQn);
/* USER CODE BEGIN USART3_MspInit 1 */
/* USER CODE END USART3_MspInit 1 */
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==USART1)
if(uartHandle->Instance==UART4)
{
/* USER CODE BEGIN UART4_MspDeInit 0 */
/* USER CODE END UART4_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_UART4_CLK_DISABLE();
/**UART4 GPIO Configuration
PC10 ------> UART4_TX
PC11 ------> UART4_RX
*/
HAL_GPIO_DeInit(GPIOC, ST_TX3_Pin|ST_RX3_Pin);
/* UART4 interrupt Deinit */
HAL_NVIC_DisableIRQ(UART4_IRQn);
/* USER CODE BEGIN UART4_MspDeInit 1 */
/* USER CODE END UART4_MspDeInit 1 */
}
else if(uartHandle->Instance==UART5)
{
/* USER CODE BEGIN UART5_MspDeInit 0 */
/* USER CODE END UART5_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_UART5_CLK_DISABLE();
/**UART5 GPIO Configuration
PC12 ------> UART5_TX
PD2 ------> UART5_RX
*/
HAL_GPIO_DeInit(ST_TX4_GPIO_Port, ST_TX4_Pin);
HAL_GPIO_DeInit(ST_RX4_GPIO_Port, ST_RX4_Pin);
/* UART5 interrupt Deinit */
HAL_NVIC_DisableIRQ(UART5_IRQn);
/* USER CODE BEGIN UART5_MspDeInit 1 */
/* USER CODE END UART5_MspDeInit 1 */
}
else if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspDeInit 0 */
@@ -108,12 +419,58 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOA, ST_TX0_Pin|ST_RX0_Pin);
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
/* USART1 DMA DeInit */
HAL_DMA_DeInit(uartHandle->hdmatx);
HAL_DMA_DeInit(uartHandle->hdmarx);
/* USART1 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */
}
else if(uartHandle->Instance==USART2)
{
/* USER CODE BEGIN USART2_MspDeInit 0 */
/* USER CODE END USART2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART2_CLK_DISABLE();
/**USART2 GPIO Configuration
PD5 ------> USART2_TX
PD6 ------> USART2_RX
*/
HAL_GPIO_DeInit(GPIOD, ST_TX1_Pin|ST_RX1_Pin);
/* USART2 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART2_IRQn);
/* USER CODE BEGIN USART2_MspDeInit 1 */
/* USER CODE END USART2_MspDeInit 1 */
}
else if(uartHandle->Instance==USART3)
{
/* USER CODE BEGIN USART3_MspDeInit 0 */
/* USER CODE END USART3_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART3_CLK_DISABLE();
/**USART3 GPIO Configuration
PB10 ------> USART3_TX
PB11 ------> USART3_RX
*/
HAL_GPIO_DeInit(GPIOB, ST_TX2_Pin|ST_RX2_Pin);
/* USART3 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART3_IRQn);
/* USER CODE BEGIN USART3_MspDeInit 1 */
/* USER CODE END USART3_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */

400
docs/FlashDB使用说明.md Normal file
View File

@@ -0,0 +1,400 @@
# FlashDB 使用说明
## 1. 概述
本项目使用 [FlashDB](https://github.com/armink/FlashDB) 嵌入式数据库,提供两种数据库:
- **KVDB**(键值数据库):存储键值对,类似 Redis 简化版
- **TSDB**(时序数据库):存储带时间戳的日志记录,支持按时间范围查询
底层存储介质为 GD5F2GQ5UE SPI NAND Flash256MB通过 FALFlash Abstraction Layer抽象层访问。
## 2. 软件架构
```
┌─────────────────────────────────────────┐
│ 用户应用main.c
├──────────────┬──────────────────────────┤
│ fdb_kvdb │ fdb_tsdb │
│ (键值数据库) │ (时序数据库) │
├──────────────┴──────────────────────────┤
│ FlashDB 核心 │
│ Lib/FlashDB/src/ │
├─────────────────────────────────────────┤
│ FAL 抽象层 │
│ Lib/FlashDB/port/fal/src/ │
├─────────────────────────────────────────┤
│ FAL 设备适配层 │
│ fal_flash_gd5f2gq5ue.c │
├─────────────────────────────────────────┤
│ GD5F2GQ5UE SPI NAND 驱动 │
│ gd5f2gq5ue.c │
├─────────────────────────────────────────┤
│ SPI1 硬件外设 + HAL 驱动 │
└─────────────────────────────────────────┘
```
## 3. 文件清单
| 文件 | 说明 | 是否自编 |
|------|------|----------|
| `Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h` | NAND 驱动头文件 | 是 |
| `Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c` | NAND 驱动实现 | 是 |
| `Drivers/BSP/GD5F2GQ5UE/fal_flash_gd5f2gq5ue.c` | FAL 设备适配 | 是 |
| `Drivers/BSP/GD5F2GQ5UE/fal_cfg.h` | FAL 设备表 + 分区表 | 是 |
| `Drivers/BSP/GD5F2GQ5UE/fdb_cfg.h` | FlashDB 功能配置 | 是 |
| `Lib/FlashDB/src/` | FlashDB 核心源码 | 否 |
| `Lib/FlashDB/port/fal/src/` | FAL 硬件抽象框架源码 | 否 |
## 4. 硬件配置
### 4.1 Flash 芯片参数
| 参数 | 值 |
|------|-----|
| 型号 | GD5F2GQ5UEGigaDevice |
| 总容量 | 2Gbit = 256MB |
| 页大小 | 2048 字节 |
| Spare 区 | 64 字节 |
| 每块页数 | 64 页 |
| 块大小 | 128KB64 × 2048 |
| 总块数 | 2048 |
| SPI 模式 | Mode 0CPOL=0, CPHA=0 |
| SPI 时钟 | 42MHzAPB2=84MHz, 分频=2 |
| MID | 0xC8 |
| DID | 0x52 |
### 4.2 引脚连接
| 信号 | STM32 引脚 | 方向 | 说明 |
|------|-----------|------|------|
| CS# | PE0 | OUT | 片选,低有效 |
| SCLK | PB3 | OUT | SPI1 时钟 |
| MOSI | PB5 | OUT | SPI1 主出从入 |
| MISO | PB4 | IN | SPI1 主入从出 |
| WP# | PB8 | OUT | 写保护,低有效(拉高禁用) |
| HOLD# | PE1 | OUT | 保持,低有效(拉高禁用) |
### 4.3 GPIO 初始化
CubeMX 中需确保以下 GPIO 上电默认电平:
- **CS#** (PE0):上电输出 **高电平**(未选中)
- **HOLD#** (PE1):上电输出 **高电平**(不保持)
- **WP#** (PB8):上电输出 **高电平**(不禁用写保护)
> 若 GPIO 初始电平错误SPI 通信将完全无响应。
## 5. 分区规划
| 分区名 | 设备 | 偏移 | 大小 | 用途 |
|--------|------|------|------|------|
| fdb_kvdb1 | gd5f2gq5ue | 0 | 64MB | KVDB 键值数据库 |
| fdb_tsdb1 | gd5f2gq5ue | 64MB | 64MB | TSDB 时序数据库 |
| (未分配) | - | 128MB | 128MB | 剩余空间 |
共使用 128MB / 256MB剩余 128MB 可扩展。
## 6. 初始化流程
```
1. HAL_Init()
2. SystemClock_Config()
3. MX_GPIO_Init() ← CS#/HOLD#/WP# 初始电平
4. MX_USART1_UART_Init() ← 调试串口
5. MX_SPI2_Init() ← CH395F 以太网
6. MX_SPI1_Init() ← GD5F2GQ5UE NAND
7. gd5f2gq5ue_init() ← NAND 初始化
8. fdb_kvdb_init() ← FlashDB KVDB 初始化
```
### 6.1 gd5f2gq5ue_init() 内部步骤
```
1. CS#/WP#/HOLD# 拉高
2. 发送复位命令FFh等待 5ms
3. 读取芯片 ID9Fh校验 MID=0xC8, DID=0x52
4. 使能内部 ECCSET_FEATURE(B0h, 10h)
5. 解除块保护SET_FEATURE(A0h, 00h)
```
> **关键点**SET_FEATURE 命令前必须先发写使能06h否则设置不生效。
## 7. KVDB 使用方法
### 7.1 初始化
```c
#include "flashdb.h"
static struct fdb_kvdb kvdb;
/* path 参数对应分区表中的分区名 "fdb_kvdb1" */
/* default_kv 传 NULL 表示不使用默认键值 */
int ret = fdb_kvdb_init(&kvdb, "db", "fdb_kvdb1", NULL, NULL);
if (ret != FDB_NO_ERR) {
/* 初始化失败处理 */
}
```
### 7.2 字符串读写
```c
/* 写入字符串 */
fdb_kv_set(&kvdb, "device_name", "STM32F407-DTU");
/* 读取字符串(返回内部缓存指针,下次写入同一 key 后失效) */
char *val = fdb_kv_get(&kvdb, "device_name");
if (val) {
printf("device_name = %s\n", val);
}
```
### 7.3 二进制数据读写Blob
```c
#include <string.h>
/* 写入二进制数据 */
uint32_t temp = 2560;
fdb_kv_set_blob(&kvdb, "temperature",
fdb_blob_make(NULL, &temp, sizeof(temp)));
/* 读取二进制数据 */
uint32_t read_temp = 0;
fdb_kv_get_blob(&kvdb, "temperature",
fdb_blob_make(NULL, &read_temp, sizeof(read_temp)));
printf("temperature = %u\n", read_temp);
```
### 7.4 删除键
```c
fdb_kv_del(&kvdb, "device_name");
```
### 7.5 遍历所有键
```c
struct fdb_kv kv;
struct fdb_kv_iterator itr;
fdb_kv_iterator_init(&kvdb, &itr);
while (fdb_kv_iterate(&kvdb, &itr)) {
kv = itr.curr;
printf("key: %s\n", kv.name);
}
```
### 7.6 打印所有键值
```c
fdb_kv_print(&kvdb);
```
## 8. TSDB 使用方法
### 8.1 获取时间戳
FlashDB 需要用户提供时间戳获取函数。本项目使用 HAL_GetTick()(毫秒):
```c
static fdb_time_t get_time(void)
{
return (fdb_time_t)HAL_GetTick();
}
```
### 8.2 初始化
```c
static struct fdb_tsdb tsdb;
/* max_len 参数限制单条记录最大长度 */
int ret = fdb_tsdb_init(&tsdb, "tsdb", "fdb_tsdb1",
get_time, 256, NULL);
```
### 8.3 追加记录
```c
/* 写入二进制数据,自动附加当前时间戳 */
uint32_t sensor_val = 3200;
fdb_tsl_append(&tsdb,
fdb_blob_make(NULL, &sensor_val, sizeof(sensor_val)));
```
### 8.4 遍历记录
```c
/* 正序遍历 */
fdb_tsl_iter(&tsdb, tsl_cb_func, NULL);
/* 逆序遍历 */
fdb_tsl_iter_reverse(&tsdb, tsl_cb_func, NULL);
/* 按时间范围遍历 */
fdb_tsl_iter_by_time(&tsdb, from_time, to_time, tsl_cb_func, NULL);
```
回调函数原型:
```c
static void tsl_cb_func(struct fdb_tsl *tsl, void *arg)
{
struct fdb_blob blob;
uint32_t val;
/* 读取数据 */
fdb_blob_read((fdb_db_t)&tsl,
fdb_tsl_to_blob(tsl, fdb_blob_make(&blob, &val, sizeof(val))));
printf("ts=%lu, val=%lu\n", tsl->time, val);
}
```
### 8.5 查询记录数量
```c
size_t count = fdb_tsl_query_count(&tsdb, from_time, to_time,
FDB_TSL_STATUS_APPEND);
```
### 8.6 清理所有记录
```c
fdb_tsl_clean(&tsdb);
```
## 9. 配置文件说明
### 9.1 fdb_cfg.h
| 宏 | 说明 |
|----|------|
| `FDB_USING_KVDB` | 启用 KVDB |
| `FDB_USING_TSDB` | 启用 TSDB |
| `FDB_USING_FAL_MODE` | 使用 FAL 模式(非文件系统) |
| `FDB_WRITE_GRAN` | 写入粒度 8字节可编程 |
| `FDB_DEBUG_ENABLE` | 启用调试输出 |
| `FDB_KV_AUTO_UPDATE` | KVDB 版本变化时自动更新(默认关闭) |
### 9.2 fal_cfg.h
分区表定义,修改分区大小需同时调整偏移和大小:
```c
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WORD, "fdb_kvdb1", "gd5f2gq5ue", 0, 64*1024*1024, 0}, \
{FAL_PART_MAGIC_WORD, "fdb_tsdb1", "gd5f2gq5ue", 64*1024*1024, 64*1024*1024, 0}, \
}
```
字段顺序:`{魔数, 分区名, 设备名, 偏移, 大小, 标志}`
## 10. Keil 工程配置
### 10.1 头文件搜索路径
在 Keil 工程 Options → C/C++ → Include Paths 中添加:
```
../Drivers/BSP/GD5F2GQ5UE
../Lib/FlashDB/inc
../Lib/FlashDB/port/fal/inc
```
### 10.2 编译的源文件
需在 Keil 工程中添加以下源文件:
```
Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c
Drivers/BSP/GD5F2GQ5UE/fal_flash_gd5f2gq5ue.c
Lib/FlashDB/src/fdb.c
Lib/FlashDB/src/fdb_kvdb.c
Lib/FlashDB/src/fdb_tsdb.c
Lib/FlashDB/src/fdb_utils.c
Lib/FlashDB/port/fal/src/fal.c
Lib/FlashDB/port/fal/src/fal_flash.c
Lib/FlashDB/port/fal/src/fal_partition.c
```
### 10.3 全局宏定义
确保工程中定义了:
```
USE_HAL_DRIVER, STM32F407xx
```
## 11. 注意事项
### 11.1 NAND Flash 特性
1. **写前必须擦除**NAND 只能将 1→0不能 0→1。写入前目标块必须先擦除全部变为 0xFF
2. **擦除单位是块**:最小擦除单位 128KB不能按页擦除
3. **写入单位是页**单次写入不超过一页2048 字节),跨页需驱动层拆分
4. **Spare 区不可直接访问**:驱动已使能内部 ECCSpare 区由芯片硬件管理
### 11.2 驱动层注意事项
1. **每次 SPI 事务前**:必须 `CS_LOW()` 拉低片选
2. **每次 SPI 事务后**:必须 `CS_HIGH()` 拉高片选
3. **SET_FEATURE 前必须写使能**:先发 06h再发 1Fh + 地址 + 数据
4. **块擦除地址是字节地址**D8h 命令的参数 = 块编号 × 128KB不是块编号本身
5. **读取 ID 需跳过 dummy 字节**9Fh 返回 3 字节,第 0 字节无意义,第 1 字节 MID第 2 字节 DID
### 11.3 FlashDB 使用注意事项
1. **fdb_kv_get 返回值是内部缓存**:下次对同一 key 写入后,之前返回的指针失效
2. **TSDB 需要用户提供时间戳**:通过 `get_time` 回调,本项目使用 `HAL_GetTick()`
3. **fdb_kvdb_init 的 path 参数**:对应分区表中的分区名 `"fdb_kvdb1"`
4. **FlashDB 开启 FDB_DEBUG_ENABLE 后**:会通过 `fdb_print()` 输出调试信息,需确保有可用的输出(如 printf 重定向到串口)
5. **分区大小修改后**:需同步更新 `fal_cfg.h` 中的偏移和大小
### 11.4 常见问题
| 现象 | 可能原因 | 解决方法 |
|------|----------|----------|
| init 返回 -6 (ID_MISMATCH) | SPI 通信失败或芯片未上电 | 检查接线、GPIO 初始电平、虚焊 |
| KVDB init 失败 | 分区名不匹配 | 确认 `fdb_kvdb_init` 的 path 与 `fal_cfg.h` 一致 |
| 写入后读取为空 | 未擦除或写入失败 | 检查写入返回值,确认目标块已擦除 |
| 读取数据异常 | ECC 错误 | 检查 `gd5f2gq5ue_init` 是否成功使能 ECC |
| SET_FEATURE 未生效 | 缺少写使能命令 | 确认 `gd5f_set_feature` 中先调用 `gd5f_write_enable()` |
## 12. 调试方法
### 12.1 串口调试输出
FlashDB 调试输出通过 `fdb_print` 宏实现。在 `fdb_cfg.h` 中定义 `FDB_DEBUG_ENABLE`FlashDB 内部操作会自动输出到标准输出。
确保 Keil 工程中 `printf` 已重定向到 USART1PA9/PA10, 115200bps
### 12.2 NAND 驱动调试
可通过串口输出以下信息验证驱动工作正常:
```c
/* 读取芯片 ID */
uint8_t mid, did;
gd5f2gq5ue_read_id(&mid, &did);
printf("MID=0x%02X DID=0x%02X\n", mid, did);
/* 预期输出MID=0xC8 DID=0x52 */
/* 初始化测试 */
int ret = gd5f2gq5ue_init();
printf("init ret=%d\n", ret);
/* 预期输出init ret=0 */
```
### 12.3 FAL 设备注册验证
```c
#include "fal.h"
/* 检查 FAL 是否初始化成功 */
int ret = fal_init();
printf("fal_init ret=%d\n", ret);
/* 预期输出fal_init ret=0 */
```

850
docs/SD2506API-G.md Normal file

File diff suppressed because one or more lines are too long

777
docs/TPAFE5160.md Normal file
View File

@@ -0,0 +1,777 @@
# 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
## Features
• 8 Simultaneously Sampled Inputs
- Single 5-V Analog Supply and 1.71-V to 5-V $V_{DRIVE}$
• 16-Bit ADC with 350 kSPS on All Channels
• Bipolar Inputs Ranges: ±10 V, ±5 V
- Analog Input Clamp Protection
• 1-MΩ Analog Input Impedance
- On-Chip Reference and Buffer
• On-Chip Oversampling Digital Filter
- SPI Compatible Interface
• Temperature Range: -40°C to 125°C
• Package: LQFP10×10-64
## Applications
- Power Line Monitor
• Power Line Protection Relays
- Motor Control
• Data Acquisition System (DAS)
• Industrial Automation and Controls
## Description
The TPAFE5160 is a 16-bit, 8-channel simultaneous sampling, successive approximation (SAR) ADC. Each channel has a complete analog front end, as well as an ADC operating at 350 kSPS per channel. The analog front end features the input clamp, a programmable gain amplifier (PGA) with a high input impedance of 1 MΩ, a low pass filter, and an ADC input driver.
The device features an internal precision reference with buffer to drive the ADC. A digital interface supports serial, parallel and parallel byte communication, which can be used with various host controllers.
The TPAFE5160 can accept ±10-V or ± 5-V true bipolar inputs with a single 5-V supply. Also, the high input impedance allows direct connection to transformers or other sensors without external driver circuits.
The zero-latency conversion with high performance also makes the device suitable for industrial automation and control applications.
Typical Application Circuit
![](images/2762ffa4db2bc51143440506cde64b960997e1a64f0903688628d389c1dc0a9d.jpg)
<details>
<summary>flowchart</summary>
This diagram illustrates the architecture and signal flow of an electronic circuit, specifically detailing the signal processing flow from input AIN to digital interface, including amplification, ADC driver, and feedback loops.
</details>
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
## Table of Contents
Features....1
Applications....1
Description....1
Typical Application Circuit....1
Product Family Table....3
Revision History....4
Pin Configuration and Functions....5
Specifications....8
Absolute Maximum Ratings (1)....8
ESD, Electrostatic Discharge Protection....8
Recommended Operating Conditions....8
Thermal Information....9
Electrical Characteristics....10
Timing Specifications....13
Timing Diagrams....16
Detailed Description....18
Overview....18
Feature Description....18
Device Functional Modes....19
Device Modes of Operation....21
Application and Implementation....24
Tape and Reel Information....25
Package Outline Dimensions....26
LQFP10x10-64....26
Order Information....27
IMPORTANT NOTICE AND DISCLAIMER....28
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
Product Family Table
<table><tr><td>Order Number</td><td>Input Range (V)</td><td>Package</td></tr><tr><td>TPAFE5160SI08-QP7R</td><td>±10, ±5</td><td>LQFP10×10-64</td></tr></table>
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
Revision History
<table><tr><td>Date</td><td>Revision</td><td>Notes</td></tr><tr><td>2021-11-15</td><td>Rev.Pre.0</td><td>Pre-release version.</td></tr><tr><td>2022-03-01</td><td>Rev.Pre.1</td><td>Updated the diagram and the EC table.</td></tr><tr><td>2022-05-10</td><td>Rev.Pre.2</td><td>Updated the EC table.</td></tr><tr><td>2022-05-22</td><td>Rev.Pre.3</td><td>Updated the tape and reel parameters.</td></tr><tr><td>2022-06-20</td><td>Rev.Pre.4</td><td>Updated the EC table.</td></tr><tr><td>2022-11-21</td><td>Rev.Pre.5</td><td>Updated Timing Specifications and Timing Diagrams.</td></tr><tr><td>2023-07-10</td><td>Rev.A.0</td><td>Initial released version.</td></tr><tr><td>2024-11-26</td><td>Rev.A.1</td><td>Updated to a new datasheet format.Updated Timing Specifications.</td></tr></table>
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
## Pin Configuration and Functions
![](images/2aeac05f6d00f0027a9c2e6424449079d7a39a39f2bd6ffad63e39265066bdef.jpg)
<details>
<summary>text_image</summary>
AIN_8GND
AIN_8P
AIN_7GND
AIN_7P
AIN_6GND
AIN_6P
AIN_5GND
AIN_5P
AIN_4GND
AIN_4P
AIN_3GND
AIN_3P
AIN_2GND
AIN_2P
AIN_1GND
AIN_1P
64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49
AVDD 1
AGND 2
OS0 3
OS1 4
OS2 5
PAR/SER/BYTE SEL 6
STBY 7
RANGE 8
CONVSTA 9
CONVSTB 10
RESET 11
RD/SCLK 12
OS 13
BUSY 14
FRSTDATA 15
DB0 16
48 AVDD
47 AGND
46 REF/GND
45 REF/CAPB
44 REF/CAPA
43 REF/GND
42 REF/IN/REFOUT
41 AGND
40 AGND
39 REGCAP2
38 AVDD
37 AVDD
36 REGCAP1
35 AGND
34 REF/SEL
33 DB15/BYTE SEL
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
DB1 DB2 DB3 DB4 DB5 DB6 DB7 DB8 DB9 DB10 DB11 DB12 DB13 DB14/HBEN
</details>
Table 1. Pin Functions
<table><tr><td colspan="2">Pin</td><td rowspan="2">I/O</td><td rowspan="2">Description</td></tr><tr><td>No.</td><td>Name</td></tr><tr><td>1</td><td>AVDD</td><td>P</td><td>Analog supply pin.</td></tr><tr><td>2</td><td>AGND</td><td>P</td><td>Analog ground pin.</td></tr><tr><td>3</td><td>OS0</td><td>DI</td><td>Oversampling control pin.</td></tr><tr><td>4</td><td>OS1</td><td>DI</td><td>Oversampling control pin.</td></tr><tr><td>5</td><td>OS2</td><td>DI</td><td>Oversampling control pin.</td></tr><tr><td>6</td><td> $\overline{PAR/SER/BYTE SEL}$ </td><td>DI</td><td>Control pin to select the serial, parallel, or parallel byte interface mode.</td></tr><tr><td>7</td><td> $\overline{STBY}$ </td><td>DI</td><td>Control pin to select the standby or shutdown mode, active low.</td></tr><tr><td>8</td><td>RANGE</td><td>DI</td><td>Multi-function logic input pin:When STBY is low, this pin selects between the standby and shutdown modes.When STBY is high, this pin selects an input range of ±10 V or ±5 V.</td></tr><tr><td>9</td><td>CONVSTA</td><td>DI</td><td>Active high logic input to control the start of the conversion for the first half count of the input channels of the device.</td></tr><tr><td>10</td><td>CONVSTB</td><td>DI</td><td>Active high logic input to control the start of the conversion for the second half count of the input channels of the device.</td></tr><tr><td>11</td><td>RESET</td><td>DI</td><td>Active high logic input to reset the digital logic of the device.</td></tr><tr><td>12</td><td> $\overline{RD/SCLK}$ </td><td>DI</td><td>Multi-function logic input pin:This pin is active-low ready input pin in the parallel and parallel byte interface.This pin is the clock input pin in the serial interface mode.</td></tr><tr><td>13</td><td> $\overline{CS}$ </td><td>DI</td><td>Active low logic input chip-select signal.</td></tr><tr><td>14</td><td>BUSY</td><td>DO</td><td>Active high digital output indicating ongoing conversion.</td></tr><tr><td>15</td><td>FRSTDATA</td><td>DO</td><td>Active high digital output indicating data read back from channel 1 of the device.</td></tr><tr><td>16</td><td>DB0</td><td>DO</td><td>Data output DB0 (LSB) in the parallel interface mode.</td></tr></table>
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
<table><tr><td colspan="2">Pin</td><td rowspan="2">I/O</td><td rowspan="2">Description</td></tr><tr><td>No.</td><td>Name</td></tr><tr><td>17</td><td>DB1</td><td>DO</td><td>Data output DB1 in the parallel interface mode.</td></tr><tr><td>18</td><td>DB2</td><td>DO</td><td>Data output DB2 in the parallel interface mode.</td></tr><tr><td>19</td><td>DB3</td><td>DO</td><td>Data output DB3 in the parallel interface mode.</td></tr><tr><td>20</td><td>DB4</td><td>DO</td><td>Data output DB4 in the parallel interface mode.</td></tr><tr><td>21</td><td>DB5</td><td>DO</td><td>Data output DB5 in the parallel interface mode.</td></tr><tr><td>22</td><td>DB6</td><td>DO</td><td>Data output DB6 in the parallel interface mode.</td></tr><tr><td>23</td><td>DVDD</td><td>P</td><td>Digital supply pin; decouple with AGND on pin 26.</td></tr><tr><td>24</td><td>DB7/ DOUTA</td><td>DO</td><td>Multi-function logic output pin:This pin is data output DB7 in the parallel and parallel byte interface mode.This pin is a data output pin in serial interface mode.</td></tr><tr><td>25</td><td>DB8/ DOUTB</td><td>DO</td><td>Multi-function logic output pin:This pin is data output DB8 in the parallel and parallel byte interface mode.This pin is a data output pin in the serial interface mode.</td></tr><tr><td>26</td><td>AGND</td><td>P</td><td>Analog ground pin.</td></tr><tr><td>27</td><td>DB9</td><td>DO</td><td>Data output DB9 in the parallel interface mode.</td></tr><tr><td>28</td><td>DB10</td><td>DO</td><td>Data output DB10 in the parallel interface mode.</td></tr><tr><td>29</td><td>DB11</td><td>DO</td><td>Data output DB11 in the parallel interface mode.</td></tr><tr><td>30</td><td>DB12</td><td>DO</td><td>Data output DB12 in the parallel interface mode.</td></tr><tr><td>31</td><td>DB13</td><td>DO</td><td>Data output DB13 in the parallel interface mode.</td></tr><tr><td>32</td><td>DB14/ HBEN</td><td>DO</td><td>Multi-function logic input or output pin:This pin is data output DB14 in the parallel interface mode.This pin is a control input pin for byte selection (high or low) in the parallel byte interface mode.</td></tr><tr><td>33</td><td>DB15/ BYTE SEL</td><td>DO</td><td>Multi-function logic input or output pin:This pin is data output DB15 (MSB) in parallel interface mode.This pin is an active high-control input pin to enable the parallel byte interface mode.</td></tr><tr><td>34</td><td>REFSEL</td><td>DI</td><td>Active high logic input to enable the internal reference.</td></tr><tr><td>35</td><td>AGND</td><td>P</td><td>Analog ground pin.</td></tr><tr><td>36</td><td>REGCAP1</td><td>AO</td><td>Output pin 1 for the internal voltage regulator; decouple separately to AGND using a 1-μF capacitor. Typical 4 V.</td></tr><tr><td>37</td><td>AVDD</td><td>P</td><td>Analog supply pin.</td></tr><tr><td>38</td><td>AVDD</td><td>P</td><td>Analog supply pin.</td></tr><tr><td>39</td><td>REGCAP2</td><td>AO</td><td>Output pin 2 for the internal voltage regulator; decouple separately to AGND using a 1-μF capacitor. Typical 4 V.</td></tr><tr><td>40</td><td>AGND</td><td>P</td><td>Analog ground pin.</td></tr><tr><td>41</td><td>AGND</td><td>P</td><td>Analog ground pin.</td></tr><tr><td>42</td><td>REFIN/ REFOUT</td><td>AIO</td><td>This pin acts as an internal 2.5 V reference output when REFSEL is high.This pin functions as an input pin for the external reference when REFSEL is low; decouple with REFGND on pin 43 using a 10-μF capacitor.</td></tr></table>
16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
<table><tr><td colspan="2">Pin</td><td rowspan="2">I/O</td><td rowspan="2">Description</td></tr><tr><td>No.</td><td>Name</td></tr><tr><td>43</td><td>REFGND</td><td>P</td><td>Reference GND pin. This pin must be shorted to the analog GND plane and decoupled with REFIN/REFOUT on pin 42 using a 10-μF capacitor.</td></tr><tr><td>44</td><td>REFCAPA</td><td>AO</td><td>Reference amplifier output pins. This pin must be shorted to REFCAPB and decoupled to AGND using a low ESR, 10-μF ceramic capacitor. Typical 4 V.</td></tr><tr><td>45</td><td>REFCAPB</td><td>AO</td><td>Reference amplifier output pins. This pin must be shorted to REFCAPA and decoupled to AGND using a low ESR, 10-μF ceramic capacitor. Typical 4 V.</td></tr><tr><td>46</td><td>REFGND</td><td>P</td><td>Reference GND pin. This pin must be shorted to the analog GND plane and decoupled with REFIN/REFOUT on pin 42 using a 10-μF capacitor.</td></tr><tr><td>47</td><td>AGND</td><td>P</td><td>Analog ground pin.</td></tr><tr><td>48</td><td>AVDD</td><td>P</td><td>Analog supply pin.</td></tr><tr><td>49</td><td>AIN_1P</td><td>AIO</td><td>Analog input channel 1: positive input.</td></tr><tr><td>50</td><td>AIN_1GND</td><td>AIO</td><td>Analog input channel 1: negative input.</td></tr><tr><td>51</td><td>AIN_2P</td><td>AIO</td><td>Analog input channel 2: positive input.</td></tr><tr><td>52</td><td>AIN_2GND</td><td>AIO</td><td>Analog input channel 2: negative input.</td></tr><tr><td>53</td><td>AIN_3P</td><td>AIO</td><td>Analog input channel 3: positive input.</td></tr><tr><td>54</td><td>AIN_3GND</td><td>AIO</td><td>Analog input channel 3: negative input.</td></tr><tr><td>55</td><td>AIN_4P</td><td>AIO</td><td>Analog input channel 4: positive input.</td></tr><tr><td>56</td><td>AIN_4GND</td><td>AIO</td><td>Analog input channel 4: negative input.</td></tr><tr><td>57</td><td>AIN_5P</td><td>AIO</td><td>Analog input channel 5: positive input.</td></tr><tr><td>58</td><td>AIN_5GND</td><td>AIO</td><td>Analog input channel 5: negative input.</td></tr><tr><td>59</td><td>AIN_6P</td><td>AIO</td><td>Analog input channel 6: positive input.</td></tr><tr><td>60</td><td>AIN_6GND</td><td>AIO</td><td>Analog input channel 6: negative input.</td></tr><tr><td>61</td><td>AIN_7P</td><td>AIO</td><td>Analog input channel 7: positive input.</td></tr><tr><td>62</td><td>AIN_7GND</td><td>AIO</td><td>Analog input channel 7: negative input.</td></tr><tr><td>63</td><td>AIN_8P</td><td>AIO</td><td>Analog input channel 8: positive input.</td></tr><tr><td>64</td><td>AIN_8GND</td><td>AIO</td><td>Analog input channel 8: negative input.</td></tr></table>
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
## Specifications
## Absolute Maximum Ratings (1)
All test conditions: $T_{A} = 25^{\circ}C$ , unless otherwise noted.
<table><tr><td colspan="2">Parameter</td><td>Min</td><td>Max</td><td>Unit</td></tr><tr><td></td><td>AVDD to AGND</td><td>-0.3</td><td>7</td><td>V</td></tr><tr><td></td><td>DVDD to DGND</td><td>-0.3</td><td>7</td><td>V</td></tr><tr><td></td><td>AGND to DGND</td><td>-0.3</td><td>0.3</td><td>V</td></tr><tr><td></td><td>Analog Input Voltage to AGND</td><td>-15</td><td>15</td><td>V</td></tr><tr><td></td><td>Digital Input to DGND</td><td>-0.3</td><td>DVDD + 0.3</td><td>V</td></tr><tr><td></td><td>REFIN to AGND</td><td>-0.3</td><td>AVDD + 0.3</td><td>V</td></tr><tr><td></td><td>Input Current to Any Pin Except Supplies</td><td>-10</td><td>10</td><td>mA</td></tr><tr><td> $T_J$ </td><td>Maximum Junction Temperature</td><td>-40</td><td>150</td><td>°C</td></tr><tr><td> $T_A$ </td><td>Operating Temperature Range</td><td>-40</td><td>125</td><td>°C</td></tr><tr><td> $T_{STG}$ </td><td>Storage Temperature Range</td><td>-65</td><td>150</td><td>°C</td></tr><tr><td> $T_L$ </td><td>Lead Temperature (Soldering, 10 sec)</td><td></td><td>260</td><td>°C</td></tr></table>
(1) Stresses beyond those listed under Absolute Maximum Ratings may cause permanent damage to the device. Exposure to any Absolute Maximum Rating condition for extended periods may affect device reliability and lifetime.
(2) This data was taken with the JEDEC low effective thermal conductivity test board.
(3) This data was taken with the JEDEC standard multilayer test boards.
ESD, Electrostatic Discharge Protection
<table><tr><td>Symbol</td><td>Parameter</td><td>Condition</td><td>Minimum Level</td><td>Unit</td></tr><tr><td>HBM</td><td>Human Body Model ESD for all pins except analog input pins</td><td>ANSI/ESDA/JEDEC JS-001 (1)</td><td>±5000</td><td>V</td></tr><tr><td>HBM</td><td>Human Body Model ESD for analog input pins only</td><td>ANSI/ESDA/JEDEC JS-001 (1)</td><td>±7000</td><td>V</td></tr><tr><td>CDM</td><td>Charged Device Model ESD</td><td>ANSI/ESDA/JEDEC JS-002 (2)</td><td>±1500</td><td>V</td></tr></table>
(1) JEDEC document JEP155 states that 500-V HBM allows safe manufacturing with a standard ESD control process.
(2) JEDEC document JEP157 states that 250-V CDM allows safe manufacturing with a standard ESD control process.
Recommended Operating Conditions
<table><tr><td colspan="2">Parameter</td><td>Min</td><td>Typ</td><td>Max</td><td>Unit</td></tr><tr><td>AVDD</td><td>Analog Supply Voltage</td><td>4.75</td><td>5</td><td>5.25</td><td>V</td></tr><tr><td>DVDD</td><td>Digital Supply Voltage</td><td>1.71</td><td>3.3</td><td>AVDD</td><td>V</td></tr></table>
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
Thermal Information
<table><tr><td>Package Type</td><td> $\theta_{JA}$ </td><td> $\theta_{JC}$ </td><td>Unit</td></tr><tr><td>LQFP10×10-64</td><td>46</td><td>7.8</td><td>°C/W</td></tr></table>
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
## Electrical Characteristics
All test conditions: $V_{REF} = 2.5$ V external/internal, AVDD = 4.75 V to 5.25 V, $V_{DRIVE} = 1.71$ V to AVDD, $f_{SAMPLE} = 350$ kSPS, $T_{A} = -40^{\circ}C$ to $125^{\circ}C$ , Low Bandwidth Mode, unless otherwise noted.
<table><tr><td>Symbol</td><td>Parameter</td><td colspan="2">Test condition</td><td>Min</td><td>Typ</td><td>Max</td><td>Unit</td></tr><tr><td colspan="8">Dynamic Performance</td></tr><tr><td rowspan="4">SNR</td><td rowspan="4">Signal-to-Noise Ratio</td><td rowspan="2">fin = 1 kHz sine wave, unless otherwise noted</td><td>±10 V No oversampling</td><td>86</td><td>89.7</td><td></td><td>dB</td></tr><tr><td>±5 V No oversampling</td><td>85.5</td><td>89.5</td><td></td><td>dB</td></tr><tr><td>fin = 130 Hz</td><td>Oversampling by 16, ±10-V Range</td><td>91</td><td>95.2</td><td></td><td>dB</td></tr><tr><td>fin = 130 Hz</td><td>Oversampling by 16, ±5-V Range</td><td>91</td><td>94.7</td><td></td><td>dB</td></tr><tr><td rowspan="2">SINAD</td><td rowspan="2">Signal to Noise + Distortion Ratio</td><td rowspan="2">fin = 1 kHz sine wave, unless otherwise noted</td><td>±10 V No oversampling</td><td></td><td>89.5</td><td></td><td>dB</td></tr><tr><td>±5 V No oversampling</td><td></td><td>89.4</td><td></td><td>dB</td></tr><tr><td>THD</td><td>Total Harmonic Distortion</td><td>All input range, fin =1 kHz</td><td></td><td></td><td>-106</td><td></td><td>dB</td></tr><tr><td>SFDR</td><td>Spurious Free Dynamic Range</td><td>fin = 1 kHz</td><td></td><td></td><td>-106</td><td></td><td>dB</td></tr><tr><td colspan="8">Analog Input Filter</td></tr><tr><td rowspan="4">BW (-3 dB)</td><td rowspan="4">Small Signal Bandwidth</td><td>Low Bandwidth Mode</td><td>-3 dB, ±10 V</td><td></td><td>20.0</td><td></td><td>kHz</td></tr><tr><td>Low Bandwidth Mode</td><td>-3 dB, ±5 V</td><td></td><td>12.7</td><td></td><td>kHz</td></tr><tr><td>High Bandwidth Mode</td><td>-3 dB, ±10 V</td><td></td><td>26.5</td><td></td><td>kHz</td></tr><tr><td>High Bandwidth Mode</td><td>-3 dB, ±5 V</td><td></td><td>16.4</td><td></td><td>kHz</td></tr><tr><td rowspan="4">BW (-0.1 dB)</td><td rowspan="4">Small Signal Bandwidth</td><td>Low Bandwidth Mode</td><td>-0.1 dB, ±10 V</td><td></td><td>3.3</td><td></td><td>kHz</td></tr><tr><td>Low Bandwidth Mode</td><td>-0.1 dB, ±5 V</td><td></td><td>2.2</td><td></td><td>kHz</td></tr><tr><td>High Bandwidth Mode</td><td>-0.1 dB, ±10 V</td><td></td><td>4.3</td><td></td><td>kHz</td></tr><tr><td>High Bandwidth Mode</td><td>-0.1 dB, ±5 V</td><td></td><td>2.6</td><td></td><td>kHz</td></tr><tr><td rowspan="4">Tgroup_delay</td><td rowspan="4">Group Delay</td><td>Low Bandwidth Mode</td><td>±10 V</td><td></td><td>10</td><td></td><td>μs</td></tr><tr><td>Low Bandwidth Mode</td><td>±5 V</td><td></td><td>16</td><td></td><td>μs</td></tr><tr><td>High Bandwidth Mode</td><td>±10 V</td><td></td><td>8</td><td></td><td>μs</td></tr><tr><td>High Bandwidth Mode</td><td>±5 V</td><td></td><td>12</td><td></td><td>μs</td></tr><tr><td colspan="8">DC Accuracy</td></tr><tr><td></td><td>Resolution</td><td></td><td>NO missing code</td><td></td><td>16</td><td></td><td>bit</td></tr><tr><td>DNL</td><td>Differential Nonlinearity</td><td colspan="2"> $f_{SAMPLE}$ = 200 kSPS, -40~85°C</td><td>-0.99</td><td>±0.5</td><td>1.5</td><td>LSB</td></tr><tr><td rowspan="2">INL</td><td rowspan="2">Integral Nonlinearity</td><td colspan="2"> $f_{SAMPLE}$ = 200 kSPS, -40~85°C</td><td></td><td>±0.7</td><td>±2</td><td>LSB</td></tr><tr><td colspan="2"> $f_{SAMPLE}$ = 350 kSPS, -40~85°C</td><td></td><td>±1</td><td>±2.5</td><td>LSB</td></tr></table>
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
<table><tr><td rowspan="2"></td><td rowspan="2">Positive and Negative Full-Scale Error</td><td>Ext reference</td><td></td><td></td><td>±4</td><td>±50</td><td>LSB</td></tr><tr><td>Int reference</td><td></td><td></td><td>±15</td><td></td><td>LSB</td></tr><tr><td rowspan="2"></td><td rowspan="2">Positive Full-Scale Error Drift</td><td>Ext reference</td><td></td><td></td><td>±2</td><td></td><td>ppm/C</td></tr><tr><td>Int reference</td><td></td><td></td><td>±10</td><td></td><td>ppm/C</td></tr><tr><td rowspan="2"></td><td rowspan="2">Negative Full-Scale Error Drift</td><td>Ext reference</td><td></td><td></td><td>±2</td><td></td><td>ppm/C</td></tr><tr><td>Int reference</td><td></td><td></td><td>±10</td><td></td><td>ppm/C</td></tr><tr><td rowspan="2"></td><td rowspan="2">Bipolar Zero Code Error</td><td></td><td>±10 V</td><td></td><td rowspan="2">±1</td><td rowspan="2">±15</td><td rowspan="2">LSB</td></tr><tr><td></td><td>±5 V</td><td></td></tr><tr><td rowspan="2"></td><td rowspan="2">Bipolar Zero Code Error Drift</td><td></td><td>±10 V</td><td></td><td>±10</td><td></td><td>μV/C</td></tr><tr><td></td><td>±5 V</td><td></td><td>±5</td><td></td><td>μV/C</td></tr><tr><td></td><td>Bipolar Full-Scale Error Matching</td><td></td><td></td><td></td><td>±6</td><td>±22</td><td>LSB</td></tr><tr><td></td><td>Bipolar Zero Code Error matching</td><td></td><td>±5 V±10 V</td><td></td><td>±3</td><td>±20</td><td>LSB</td></tr><tr><td colspan="8">Analog Input</td></tr><tr><td rowspan="2"></td><td rowspan="2">Input Range</td><td rowspan="2">Vx - VxGND</td><td>RANGE = 1, ±10-V range</td><td>-10</td><td></td><td>10</td><td rowspan="2">V</td></tr><tr><td>RANGE = 0, ±5-V range</td><td>-5</td><td></td><td>5</td></tr><tr><td rowspan="2"></td><td rowspan="2">Analog Input Current</td><td></td><td>10-V range</td><td></td><td rowspan="2">(VIN - 2) / RIN</td><td></td><td>μA</td></tr><tr><td></td><td>5-V range</td><td></td><td></td><td>μA</td></tr><tr><td>CIN</td><td>Input Capacitance</td><td></td><td></td><td></td><td>5</td><td></td><td>pF</td></tr><tr><td>RIN</td><td>Input Resistance</td><td></td><td></td><td></td><td>1</td><td></td><td>Mohm</td></tr><tr><td></td><td>Input Impedance Drift</td><td></td><td></td><td></td><td>±20</td><td></td><td>ppm/C</td></tr><tr><td colspan="8">Reference Input/Output</td></tr><tr><td></td><td>Reference Input Voltage</td><td colspan="2">REF SELECT = 0, select Ext Ref, force voltage on REFIN/REFOUT</td><td>2.475</td><td>2.5</td><td>2.525</td><td>V</td></tr><tr><td></td><td>Reference Output Voltage</td><td colspan="2">REF_SELECT = 1, REFIN/REFOUT output voltage TA = 25°C</td><td>2.495</td><td>2.5</td><td>2.505</td><td>V</td></tr><tr><td></td><td>Reference Voltage TC</td><td colspan="2"></td><td></td><td>±10</td><td></td><td>ppm/C</td></tr><tr><td></td><td>V (REFCAPA/B)</td><td colspan="2">Voltage on REFCAPA and REFCAPB, also used for ADC</td><td></td><td>4</td><td></td><td>V</td></tr><tr><td colspan="8">Logic Input</td></tr><tr><td>VIH</td><td>Input High Voltage</td><td>Input logic high voltage</td><td></td><td>0.7 × VDRIVE</td><td></td><td></td><td>V</td></tr><tr><td>VIL</td><td>Input Low Voltage</td><td>Input logic low voltage</td><td></td><td></td><td></td><td>0.3 × VDRIVE</td><td>V</td></tr><tr><td>CI</td><td>Input Capacitance</td><td>Input capacitance</td><td></td><td></td><td>5</td><td></td><td>pF</td></tr><tr><td>I1</td><td>Input Current</td><td>Input current</td><td></td><td></td><td></td><td>±2</td><td>μA</td></tr></table>
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
<table><tr><td colspan="8">Logic Output</td></tr><tr><td> $V_{OH}$ </td><td>Output High Voltage</td><td></td><td>Current source = 100 μA</td><td> $V_{DRIVE}$ - 0.2</td><td></td><td></td><td>V</td></tr><tr><td> $V_{OL}$ </td><td>Output Low Voltage</td><td></td><td>Current sink = 100 μA</td><td></td><td></td><td>0.2</td><td>V</td></tr><tr><td></td><td>Float State Leakage Current</td><td></td><td></td><td></td><td>±1</td><td>±20</td><td>μA</td></tr><tr><td> $C_O$ </td><td>Output Capacitance</td><td></td><td></td><td></td><td>5</td><td></td><td>pF</td></tr><tr><td colspan="8">Conversion Rate</td></tr><tr><td></td><td>Conversion Time</td><td></td><td></td><td></td><td>1.65</td><td></td><td>μs</td></tr><tr><td></td><td>Acquisition Time</td><td></td><td></td><td></td><td>1.2</td><td></td><td>μs</td></tr><tr><td></td><td>Throughput Rate</td><td>Per channel</td><td></td><td></td><td></td><td>350</td><td>kSPS</td></tr><tr><td colspan="8">Timing specifications</td></tr><tr><td rowspan="2">SCLK</td><td rowspan="2">Frequency of Serial Interface</td><td></td><td> $V_{DRIVE}$ &gt; 2.7 V</td><td></td><td></td><td>23.5</td><td>MHz</td></tr><tr><td></td><td> $V_{DRIVE}$ &gt; 1.7 V</td><td></td><td></td><td>15</td><td>MHz</td></tr><tr><td></td><td>AVCC Normal</td><td></td><td></td><td></td><td>41</td><td>51</td><td>mA</td></tr><tr><td></td><td>AVCC Standby</td><td></td><td></td><td></td><td>5</td><td>9</td><td>mA</td></tr><tr><td></td><td>AVCC Shutdown</td><td></td><td></td><td></td><td>11</td><td>25</td><td>μA</td></tr></table>
(1) 100% tested at $T_{A} = 25^{\circ}C$ .
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
## Timing Specifications
All test conditions: $AV_{CC} = 5 V$ , $V_{DRIVE} = 1.7 V$ to 5.5 V, $V_{REF} = 2.5 V$ , $T_{A} = T_{MIN}$ to $T_{MAX}$ , unless otherwise noted.
<table><tr><td rowspan="2">Parameter</td><td colspan="3">Limit at TMIN, TMAX (0.1 × VDRIVE and 0.9 × VDRIVE Logic Input Levels)</td><td rowspan="2">Unit</td><td rowspan="2">Description</td></tr><tr><td>Min</td><td>Typ</td><td>Max</td></tr><tr><td colspan="6">Parallel/Serial/Byte Mode</td></tr><tr><td rowspan="4">tCYCLE</td><td></td><td></td><td></td><td></td><td>1/throughput rate</td></tr><tr><td></td><td>2.85</td><td></td><td>μs</td><td>Parallel mode, reading during or after conversion; or serial mode: VDRIVE = 2.7 V to 5.5 V, reading during conversion using DOUTA and DOUTB lines</td></tr><tr><td></td><td>4.5</td><td></td><td>μs</td><td>Serial mode: VDRIVE = 2.7 V, reading after a conversion using DOUTA and DOUTB lines</td></tr><tr><td></td><td>6</td><td></td><td>μs</td><td>Serial mode: VDRIVE = 1.7 V, reading after a conversion using DOUTA and DOUTB lines</td></tr><tr><td rowspan="8">tCONV</td><td></td><td></td><td></td><td></td><td>Conversion time</td></tr><tr><td></td><td>1.74</td><td></td><td>μs</td><td>Oversampling off</td></tr><tr><td></td><td>4.4</td><td></td><td>μs</td><td>Oversampling by 2</td></tr><tr><td></td><td>9.6</td><td></td><td>μs</td><td>Oversampling by 4</td></tr><tr><td></td><td>20</td><td></td><td>μs</td><td>Oversampling by 8</td></tr><tr><td></td><td>41</td><td></td><td>μs</td><td>Oversampling by 16</td></tr><tr><td></td><td>83</td><td></td><td>μs</td><td>Oversampling by 32</td></tr><tr><td></td><td>167</td><td></td><td>μs</td><td>Oversampling by 64</td></tr><tr><td>tWAKE-UP STANDBY</td><td></td><td>100</td><td></td><td>μs</td><td>STBY rising edge to CONVST × rising edge; power-up time from standby mode</td></tr><tr><td>tWAKE-UP SHUTDOWN Internal Reference</td><td></td><td>180</td><td></td><td>ms</td><td>STBY rising edge to CONVST × rising edge; power-up time from shutdown mode</td></tr><tr><td>tWAKE-UP SHUTDOWN External Reference</td><td></td><td>13</td><td></td><td>ms</td><td>STBY rising edge to CONVST × rising edge; power-up time from shutdown mode</td></tr><tr><td>tRESET</td><td></td><td>100</td><td></td><td>ns</td><td>RESET high pulse width</td></tr><tr><td>t1</td><td></td><td>40</td><td></td><td>ns</td><td>CONVST × high to BUSY high</td></tr><tr><td>t2</td><td>25</td><td></td><td></td><td>ns</td><td>Minimum CONVST × low pulse</td></tr><tr><td>t3</td><td>25</td><td></td><td></td><td>ns</td><td>Minimum CONVST × high pulse</td></tr><tr><td>t4</td><td>45</td><td></td><td></td><td>ns</td><td>BUSY falling edge to CS falling edge setup time</td></tr><tr><td>t5</td><td></td><td>0.5</td><td></td><td>ms</td><td>Maximum delay allowed between CONVST A, CONVST B rising edges</td></tr></table>
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
<table><tr><td>t6</td><td>110</td><td></td><td></td><td>ns</td><td>Minimum time between last $\overline{CS}$ rising edge and BUSY falling edge</td></tr><tr><td>t7</td><td>200</td><td></td><td></td><td>ns</td><td>Minimum delay between RESET low to CONVST × high</td></tr><tr><td colspan="6">Parallel/Byte Read Operation</td></tr><tr><td>t8</td><td>0</td><td></td><td></td><td>ns</td><td> $\overline{CS}$ to $\overline{RD}$ setup time</td></tr><tr><td>t9</td><td>0</td><td></td><td></td><td>ns</td><td> $\overline{CS}$ to $\overline{RD}$ hold time</td></tr><tr><td rowspan="3">t10</td><td></td><td></td><td></td><td></td><td> $\overline{RD}$ low pulse width</td></tr><tr><td>22</td><td></td><td></td><td>ns</td><td> $V_{DRIVE}$ above 2.7 V</td></tr><tr><td>32</td><td></td><td></td><td>ns</td><td> $V_{DRIVE}$ above 1.7 V</td></tr><tr><td>t11</td><td>10</td><td></td><td></td><td>ns</td><td> $\overline{RD}$ high pulse width</td></tr><tr><td>t12</td><td>10</td><td></td><td></td><td>ns</td><td> $\overline{CS}$ high pulse width; $\overline{CS}$ and $\overline{RD}$ linked</td></tr><tr><td rowspan="3">t13</td><td></td><td></td><td></td><td></td><td>Delay from $\overline{CS}$ until DB [15:0] three-state disabled</td></tr><tr><td></td><td></td><td>21</td><td>ns</td><td> $V_{DRIVE}$ above 2.7 V</td></tr><tr><td></td><td></td><td>30</td><td>ns</td><td> $V_{DRIVE}$ above 1.7 V</td></tr><tr><td rowspan="3">t14</td><td></td><td></td><td></td><td></td><td>Data access time after $\overline{RD}$ falling edge</td></tr><tr><td></td><td></td><td>21</td><td>ns</td><td> $V_{DRIVE}$ above 2.7 V</td></tr><tr><td></td><td></td><td>30</td><td>ns</td><td> $V_{DRIVE}$ above 1.7 V</td></tr><tr><td>t15</td><td>6</td><td></td><td></td><td>ns</td><td>Data hold time after $\overline{RD}$ falling edge</td></tr><tr><td>t16</td><td>6</td><td></td><td></td><td>ns</td><td> $\overline{CS}$ to DB [15:0] hold time</td></tr><tr><td>t17</td><td></td><td></td><td>20</td><td>ns</td><td>Delay from $\overline{CS}$ rising edge to DB [15:0] three-state enabled</td></tr><tr><td colspan="6">Serial Read Operation</td></tr><tr><td rowspan="3">fSCLK</td><td></td><td></td><td></td><td></td><td>Frequency of serial read clock</td></tr><tr><td></td><td></td><td>23.5</td><td>MHz</td><td> $V_{DRIVE}$ above 2.7 V</td></tr><tr><td></td><td></td><td>15</td><td>MHz</td><td> $V_{DRIVE}$ above 1.7 V</td></tr><tr><td rowspan="3">t18</td><td></td><td></td><td></td><td></td><td>Delay from CS until $D_{OUTA}/D_{OUTB}$ three-state disabled/delay from $\overline{CS}$ until MSB valid</td></tr><tr><td></td><td></td><td>10</td><td>ns</td><td> $V_{DRIVE}$ above 2.7 V</td></tr><tr><td></td><td></td><td>15</td><td>ns</td><td> $V_{DRIVE}$ above 1.7 V</td></tr><tr><td rowspan="3">t19</td><td></td><td></td><td></td><td></td><td>Data access time after SCLK rising edge</td></tr><tr><td></td><td></td><td>21</td><td>ns</td><td> $V_{DRIVE}$ above 2.7 V</td></tr><tr><td></td><td></td><td>30</td><td>ns</td><td> $V_{DRIVE}$ above 1.7 V</td></tr><tr><td>t20</td><td>0.4tSCLK</td><td></td><td></td><td>ns</td><td>SCLK low pulse width</td></tr><tr><td>t21</td><td>0.4tSCLK</td><td></td><td></td><td>ns</td><td>SCLK high pulse width</td></tr><tr><td>t22</td><td>6</td><td></td><td></td><td>ns</td><td>SCLK rising edge to $D_{OUTA}/D_{OUTB}$ valid hold time</td></tr><tr><td>t23</td><td></td><td></td><td>15</td><td>ns</td><td> $\overline{CS}$ rising edge to $D_{OUTA}/D_{OUTB}$ three-state enabled</td></tr><tr><td colspan="6">FRATDATA Operation</td></tr><tr><td>t24</td><td></td><td></td><td></td><td></td><td>Delay from $\overline{CS}$ falling edge until FRSTDATA three-state disabled</td></tr></table>
16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
<table><tr><td rowspan="2">t24</td><td></td><td></td><td>11</td><td>ns</td><td>VDRIVE above 2.7 V</td></tr><tr><td></td><td></td><td>20</td><td>ns</td><td>VDRIVE above 1.7 V</td></tr><tr><td rowspan="3">t25</td><td></td><td></td><td></td><td></td><td>Delay from CS falling edge until FRSTDATA high, serial mode</td></tr><tr><td></td><td></td><td>11</td><td>ns</td><td>VDRIVE above 2.7 V</td></tr><tr><td></td><td></td><td>20</td><td>ns</td><td>VDRIVE above 1.7 V</td></tr><tr><td rowspan="3">t26</td><td></td><td></td><td></td><td></td><td>Delay from RD falling edge to FRSTDATA high</td></tr><tr><td></td><td></td><td>22</td><td>ns</td><td>VDRIVE above 2.7 V</td></tr><tr><td></td><td></td><td>32</td><td>ns</td><td>VDRIVE above 1.7 V</td></tr><tr><td rowspan="3">t27</td><td></td><td></td><td></td><td></td><td>Delay from RD falling edge to FRSTDATA low</td></tr><tr><td></td><td></td><td>22</td><td>ns</td><td>VDRIVE above 2.7 V</td></tr><tr><td></td><td></td><td>32</td><td>ns</td><td>VDRIVE above 1.7 V</td></tr><tr><td rowspan="3">t28</td><td></td><td></td><td></td><td></td><td>Delay from the 16th SCLK falling edge to FRSTDATA low</td></tr><tr><td></td><td></td><td>22</td><td>ns</td><td>VDRIVE above 2.7 V</td></tr><tr><td></td><td></td><td>32</td><td>ns</td><td>VDRIVE above 1.7 V</td></tr><tr><td>t29</td><td></td><td></td><td>20</td><td>ns</td><td>Delay from CS rising edge until FRSTDATA three-state enabled</td></tr></table>
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
Timing Diagrams
![](images/ab9ed3131120172d9148c4c79d2214382249a502455cbe52ed18950d9dacc404.jpg)
<details>
<summary>flowchart</summary>
```mermaid
graph LR
CONVST_A["CONVST A, CONVST B"] -->|t5| CONVST_B["CONVST A, CONVST B"]
CONVST_B -->|tCYCLE| CONVST_B
CONVST_B -->|t2| CONVST_B
CONVST_B -->|t3| BUSY["BUSY"]
BUSY -->|t1| CS["CS"]
CS -->|t4| CS
CONVST_B -->|tCONV| CS
CONVST_B -->|tRESET| RESET["RESET"]
```
</details>
Figure 1. CONVST Timing-Reading After a Conversion
![](images/1d86c3b520eb44528610b7cc420279851cd5fd4d70a7789894d9ae21c278099c.jpg)
<details>
<summary>flowchart</summary>
This diagram illustrates the timing relationships and signal flow between a system, including convolutional and busy states, reset, and synchronization intervals.
</details>
Figure 2. CONVST Timing-Reading During a Conversion
![](images/973d1c32a5a7d76853d3c30b0982a2f07c6b64dd6e97b492c94ff8a0ef94c0de.jpg)
<details>
<summary>text_image</summary>
CS
RD
DATA:
DB[15:0]
FRSTDATA
t8
t10
t11
t13
t14
t15
t16
t17
t24
t26
t27
t29
t8
t10
t11
t14
t15
t16
t17
V1
V2
V3
V4
V7
V8
</details>
Figure 3. Parallel Mode, Separate CS and RD Pulses
![](images/e4c998e58453c5f862866d953ac1e8da6de4b497a7140586ea5abc631c5e785d.jpg)
<details>
<summary>text_image</summary>
CS AND RD
DATA:
DB[15:0]
V1 V2 V3 V4 V5 V6 V7 V8
t12
t13
t16
t17
FRSTDATA
</details>
Figure 4. CS and RD, Linked Parallel Mode
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
![](images/684073195c572cb351c311f748a53c26dd1d8ea558bb372c334e20836006ada3.jpg)
<details>
<summary>text_image</summary>
CS
SCLK
DOUTA,
DOUTB
FRSTDATA
t18
t19
t21
t20
t22
t23
t25
DB15
DB14
DB13
DB1
DB0
t28
t29
</details>
Figure 5. Serial Read Operation (Channel 1)
![](images/e05c428f982b37656361ac07897016ea34d2e2eb7abe8c40ecde80503a89558c.jpg)
<details>
<summary>text_image</summary>
CS
RD
DATA:
DB[7:0]
FRSTDATA
t8
t10
t11
t9
t13
t14
t15
t16
t17
t24
t26
t27
t29
INVALID
HIGH BYTE V1
LOW BYTE V1
HIGH BYTE V8
LOW BYTE V8
</details>
Figure 6. BYTE Mode Read Operation
# 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
## Detailed Description
## Overview
The TPAFE5160 is a 16-bit, 8-channel simultaneous sampling, successive approximation (SAR) ADC. Each channel has a complete analog front end, as well as an ADC operating at 350 kSPS per channel. The analog front end features the input clamp, a programmable gain amplifier (PGA) with a high input impedance of 1 MΩ, a low pass filter, and an ADC input driver.
The device features an internal precision reference with a buffer to drive the ADC. A digital interface supports serial, parallel, and parallel byte communication, which can be used with various host controllers.
The TPAFE5160 can accept ±10-V or ±5-V true bipolar inputs with a single 5-V supply. Also, the high input impedance allows direct connection to transformers or other sensors without external driver circuits.
## Feature Description
## Analog Inputs
The TPAFE5160 has 8 analog input channels, and positive inputs AIN\_nP (n = 1 to 8) are the single-ended analog inputs. The negative inputs AIN\_nGND should be tied to GND.
The input voltage range can be configured to bipolar ±10 V or ±5 V by the RANGE pin.
The device allows a ±0.3-V range on the AIN\_nGND.
## Analog Input Impedance
Each analog input channel in the device presents a constant resistive impedance of 1 MΩ.
Matching the external source impedance on the AIN\_nP input pin with an equivalent resistance on the AIN\_nGND pin is recommended to cancel any additional offset error contributed by the external resistance.
## Input Clamp Protection Circuit
The input clamp protection circuit allows the analog input to swing up to ±30 V (typical). The input clamp circuit turns on beyond the clamp voltage.
For input voltages above the clamp threshold, make sure that the input current never exceeds the absolute maximum rating to prevent any damage to the device.
Don't keep the device in a state such that the clamp circuit is activated for extended periods of time, because this fault condition can degrade the performance and reliability of the device.
## Programmable Gain Amplifier (PGA)
The device has a programmable gain amplifier (PGA) at each individual input channel. The PGA converts the single-ended input signal into a fully-differential signal to drive internal ADC. The PGA also adjusts the common-mode voltage feeding into the ADC to ensure maximum usage of the ADC input dynamic range. The PGA gain is adjusted by configuring the RANGE pin of the ADC accordingly.
## Low Pass Filter
Each channel of the TPAFE5160 features a second-order antialiasing low pass filter (LPF) at the output of the PGA, to remove the noise of the front-end amplifiers and gain resistors of the PGA.
## ADC Driver
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
There is an integrated ADC input driver before each ADC channel. This integrated ADC driver eliminates the need of any external amplifier, helping inputs of the ADC to settle to better than 16-bit accuracy before any sampled analog voltage gets converted. And thus, the signal chain design for the user is simplified.
## Digital Filter
The TPAFE5160 has an optional digital averaging filter that can be used in slower throughput applications requiring lower noise and higher dynamic range. The oversampling ratio of the digital filter is determined by the configuration of the OS[2:0] pins.
In oversampling mode, the samples are averaged to reduce the noise of the signal chain as well as to improve the SNR of the ADC. The final output is also decimated to provide data for each channel.
<table><tr><td>OS [2:0]</td><td>OS RATIO</td><td>MAX THROUGHPUT PER CHANNEL (kSPS)</td></tr><tr><td>000</td><td>NO OS</td><td>350</td></tr><tr><td>001</td><td>2</td><td>175</td></tr><tr><td>010</td><td>4</td><td>87.5</td></tr><tr><td>011</td><td>8</td><td>43.75</td></tr><tr><td>100</td><td>16</td><td>21.875</td></tr><tr><td>101</td><td>32</td><td>10.94</td></tr><tr><td>110</td><td>64</td><td>5.47</td></tr><tr><td>111</td><td>NA</td><td>350</td></tr></table>
## Reference
The TPAFE5160 can operate with either an internal voltage reference or an external voltage reference. The internal or external reference selection is determined by an external REFSEL pin,
The REFIN/REFOUT pin outputs the internal band-gap voltage (in the internal reference mode) or functions as the input pin to the external reference voltage (in the external reference mode). The on-chip amplifier is enabled in both modes to drive the actual reference input of the internal ADC core. The REFCAPA and REFCAPB pins must be shorted together externally and a ceramic capacitor of a minimum 10 μF should be connected between this node and REFGND to ensure that the internal reference buffer is operating as a closed loop.
## ADC Transfer Function
The TPAFE5160 outputs 16-bit data in binary twos complement format for both bipolar input ranges. The format for the output codes is the same across all analog channels.
<table><tr><td>Input Range (V)</td><td>Full-Scale Range (V)</td><td>LSB (μV)</td></tr><tr><td>±10</td><td>20</td><td>305.18</td></tr><tr><td>±5</td><td>10</td><td>152.59</td></tr></table>
## Device Functional Modes
Device Interface: Pin Description
REFSEL (Input)
The REFSEL pin selects between the internal and external reference modes of the device.
If the REFSEL pin is set to logic high, then the internal reference is enabled and selected.
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
If the REFSEL pin is set to logic low, then the internal reference circuit is disabled and powered down. In this mode, an external reference voltage must be provided to the REFIN/REFOUT pin.
The internal reference buffer is always enabled under both conditions.
The reference mode after power-up depends on the state of the REFSEL input pin.
## RANGE (Input)
The RANGE pin selects the input range for all analog input channels.
If this pin is set to logic high, the device is configured to operate in the ±10-V input range.
If this pin is set to logic low, the device is configured to operate in the ±5-V input range.
The RANGE pin is also used to put the device in standby or shutdown mode depending on the state of the STBY input pin, as explained in the Power Down Modes.
## STBY (Input)
The STBY pin puts the device into one of the two power-down modes: standby and power down.
If this pin is set to logic high, the device is in normal operation mode.
If this pin is set to logic low, the device is in the standby or power down mode, depending on the state of the RANGE pin.
In the shutdown mode, all internal circuitry is powered down,
In the standby mode, the internal reference remains powered up to enable a relatively quicker recovery to normal operation mode.
## PAR/SER/BYTE SEL (Input)
The PAR/SER/BYTE SEL pin selects between the parallel, serial, and parallel byte interface modes for reading data from the device.
If this pin is set to logic high, then the serial or parallel byte interface mode is selected depending on the state of the DB15/BYTE SEL pin. If the DB15/BYTE SEL pin is high, the parallel byte interface is selected, and if the DB15/BYTE SEL is low, then the serial mode is selected.
## CONVSTA, CONVSTB (Input)
CONVSTA, and CONVSTB (Input) are conversion control input pins.
CONVSTA can be used to simultaneously sample and initiate the conversion process for the first half count of the input channels (channels 1-4), and CONVSTB can be used to simultaneously sample and initiate the conversion process for the latter half count of the input channels (channels 5-8).
On the rising edge of the CONVSTA, CONVSTB signals, the internal track-and-hold circuits for each analog input channel are placed into the hold mode and the sampled input signal is converted.
The CONVSTA, and CONVSTB signals can be pulled low when the internal conversion is over, as indicated by the BUSY signal. At this point, the front-end circuit for all analog input channels acquires the respective input signals and the internal ADC is not converting.
The output data can be read from the device irrespective of the status of the CONVSTA and CONVSTB pins.
## RESET (Input)
The RESET pin can be used to reset the device at any time in an asynchronous manner. When the RESET pin is set to logic high, the device is in the reset mode and remains in the state until the pin returns low.
The device should be reset after power-up or recovery from the shut down mode when all the supplies and references have settled to the required accuracy.
## RD/SCLK (Input)
RD/SCLK (Input) is a dual-function pin to be used in different interface modes.
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
<table><tr><td colspan="2">Device Operating Condition</td><td>Functionality of RD/SCLK(Input)</td></tr><tr><td>Parallel Interface</td><td>PAR/SER/BYTR SEL = 0DB15/BYTE = 0</td><td rowspan="2">The active-low digital input pin to read the output data from the device.In the parallel or parallel byte interface mode, the output bus is enabled when both the CS and RD inputs are tied to a logic-low input.</td></tr><tr><td>Parallel Byte Interface</td><td>PAR/SER/BYTR SEL = 1DB15/BYTE = 1</td></tr><tr><td>Serial Interface</td><td>PAR/SER/BYTR SEL = 1DB15/BYTE = 0</td><td>The external clock input for the serial data interface. In the serial mode, all synchronous accesses to the device are timed with respect to the rising edge of the SCLK signal.</td></tr></table>
## $\overline{CS}$ (Input)
The $\overline{CS}$ pin is an active-low, chip-select signal.
A rising edge on the $\overline{CS}$ signal outputs all the data lines in tri-state mode.
A falling edge of the $\overline{CS}$ signal marks the beginning of the output data transfer frame in any interface mode of operation for the device.
## OS [2:0]
The OS [2:0] pins are active-high digital input pins used to configure the oversampling ratio for the internal digital filter on the device.
When OS [2:0] = 111, a higher filter bandwidth of $\sim$ 30 kHz is selected.
## Device Modes of Operation
## Power Down Modes
The device supports two power-down modes: standby mode and shutdown mode. The device can enter either power-down mode by pulling the STBY pin to a logic level. Additionally, the selection between these two power-down modes is done by the state of the RANGE pin.
<table><tr><td>Power Down Mode</td><td> $\overline{STBY}$ </td><td>Range</td></tr><tr><td>Standby</td><td>0</td><td>1</td></tr><tr><td>Shutdown</td><td>0</td><td>0</td></tr></table>
## Standby Mode
In the standby mode, only the internal reference of the circuit is powered up, and the analog front-end, signal-conditioning circuit for each channel remains powered down.
## Shutdown Mode
In the shutdown mode, the entire internal circuitry is powered down.
## Conversion Control
The device offers precise control of simultaneously sampling all analog input channels.
## Simultaneous Sampling on All Input Channels
All the analog input channels are to be simultaneously sampled by connecting CONVSTA and CONVSTB signals together, and a single CONVST signal should be used to control the sampling of all analog input channels of the device.
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
## Simultaneous Sampling Two Sets of Input Channels
Two sets of analog input channels can be simultaneously sampled by separating CONVSTA and CONVSTB signals. And the device could not operate in oversampling mode in this state.
## Data read operation
The device updates the internal data registers with the conversion data for all analog channels at the end of every conversion phase (when BUSY goes low).
If the output data are read after BUSY goes low, then the device outputs the conversion results for the current sample.
If the output data are read when BUSY is high, then the device outputs conversion results for the previous sample.
There are three interface modes:
<table><tr><td>Interface mode</td><td> $\overline{PAR}/SER/BYTE SEL$ </td><td>DB15/BYTE SEL</td></tr><tr><td>Parallel Interface</td><td>0</td><td>0</td></tr><tr><td>Parallel Byte Interface</td><td>1</td><td>1</td></tr><tr><td>Serial Interface</td><td>1</td><td>0</td></tr></table>
## Parallel Data Read
The device supports a parallel interface mode for reading the output data of the device using the control inputs ( $\overline{CS}$ and $\overline{RD}$ ), the parallel output bus (DB [15:0]), and the BUSY indicator.
For applications that use only one device in the system and do not share the parallel output bus with any other devices, the CS and RD input signals can be tied together, or the CS signal can be permanently tied low. At the first falling edge of the CS and RD signal, the output data of channel 1 becomes available on the parallel bus to be read by the digital host. At this instant, the FRSTDATA output also goes high, indicating channel 1 data is ready to be read back. The output data for the remaining channels are clocked out on the parallel bus on subsequent falling edges of the CS and RD signal in a sequential manner.
For applications that use multiple devices in the system, the CS and RD input signals must be driven separately.
## Parallel Byte Data Read
The parallel byte interface mode is very similar to the parallel interface mode, except that the output data for each channel is read in two data transfers of 8-bit byte sizes.
In the parallel byte mode, the DB14/HBEN pin decides the order of the most significant byte (MSB byte) and the least significant byte (LSB byte). When the DB14/HBEN pin is tied high, the MSB byte of the conversion results is output first followed by the LSB byte. This order is reversed when DB14/HBEN is tied to logic low.
At the first falling edge of the $\overline{RD}$ signal, the first byte of the channel 1 conversion result becomes available on DB [7:0]. This byte is followed by the second byte of conversion data on the next falling edge of the RD signal.
## Serial Data Read
This interface mode uses a CS control input, a communication clock input (SCLK), BUSY and FRSTDATA output indicators, and serial data output lines DOUTA and DOUTB.
A total of 16 SCLK cycles are required to clock out 16 bits of conversion result for each channel and the same process can be repeated for the remaining channels in an ascending order.
The conversion results from the first set of channels appear first on DOUTA, followed by the second set of channels if only DOUTA is used for reading data. This order is reversed for DOUTB, in which the second set of channels appear first followed by the first set of channels. The use of both data output lines reduces the time needed for data retrieval and a higher throughput can therefore be achieved in this mode.
## Data Read During Conversion
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
The device allows data read when the ADC is converting and the BUSY output is high status. In this case, the ADC outputs conversion results for previous samples.
The data read back during conversion mode allows faster throughput to be achieved from the device.
## Data Read During Conversion
The device can be configured in the oversampling mode by the OS [2:0] pins. The input on the OS pins is latched on the falling edge of the BUSY signal to configure the oversampling rate for the next conversion.
In this mode, the CONVST A and CONVST B signals should be tied or driven together.
The BUSY signal duration varies with the OSR setting because the conversion time increases with the OSR setting.
Oversampling the input signal reduces noise during the conversion process, thus reducing the histogram code spread for a DC input signal to the ADC.
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
## Application and Implementation
Note
Information in the following application sections is not part of the 3PEAK's component specification and 3PEAK does not warrant its accuracy or completeness. 3PEAK's customers are responsible for determining suitability of components for their purposes. Customers should validate and test their design implementation to confirm system functionality.
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
Tape and Reel Information
![](images/4749eae1dd6c621d0dbd7c811bca00b8cf3bd13593146bd28dc8bb4182d566ea.jpg)
<details>
<summary>natural_image</summary>
Technical line drawing of a wheel with four spokes and a central hub, no text or symbols present
</details>
D1:Reel Diameter
![](images/c36041b46def9706b380365e508554455f46e4e3d89ee675b091679e9df03c06.jpg)
<details>
<summary>natural_image</summary>
Pure diagram of a vertical structure with horizontal lines and a central horizontal bar, labeled W1 at the bottom (no text or symbols beyond label)
</details>
![](images/2cdaafaa6a256fbc8cd6edba7b762af379531acb481fc31a71fd939ac81b38d1.jpg)
<details>
<summary>text_image</summary>
Direction of Feed
W0
P0
A0
B0
K0
</details>
<table><tr><td>Order Number</td><td>Package</td><td>D1 (mm)</td><td>W1 (mm)</td><td>A0 (mm)</td><td>B0 (mm)</td><td>K0 (mm)</td><td>P0 (mm)</td><td>W0 (mm)</td><td>Pin1 Quadrant</td></tr><tr><td>TPAFE5160SI08-QP7R</td><td>LQFP10×10-64</td><td>330</td><td>28.4</td><td>12.085</td><td>12.085</td><td>2.1</td><td>16</td><td>24</td><td>Q2</td></tr></table>
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
## Package Outline Dimensions
LQFP10x10-64
Package Outline Dimensions
QP5(LQFP10X10-64-A)
![](images/9ce7a4caaa2788c2c2561d9e7d69c3d74fccea3315ea0ee307ae562847d01c1b.jpg)
<details>
<summary>text_image</summary>
D
D1
64
1
PIN 1
E1
E
</details>
![](images/a1b45902cfbba60871cce6181733e1b136e588a028df9303c8f8c6fd40b237f3.jpg)
<details>
<summary>text_image</summary>
WITH PLATING
b
c
BASE
METAL
</details>
SECTION N-N
![](images/f69b0c5e472b09735358baad95d78c77abc6caffba1dec62b7946792623e25af.jpg)
<details>
<summary>natural_image</summary>
Pure electrical circuit lines without any symbols
</details>
![](images/c42cbf274e4b9daea53dd9192a21043b96bfd4820fc19d1793a23e96be4851ce.jpg)
![](images/8b28c815d6a32e3c1f1c7ced71fb8ccb1eb0e1794ad7a8529b5c410ecb696b53.jpg)
<details>
<summary>text_image</summary>
A
A2
SEATING
PLANE
A1
C
e
b
θ
L
N
</details>
DETAIL Y
## NOTES
1. Do not include mold flash or protrusion.
2. This drawing is subject to change without notice.
<table><tr><td rowspan="2">Symbol</td><td colspan="2">Dimensions In Millimeters</td><td colspan="2">Dimensions In Inches</td></tr><tr><td>MIN</td><td>MAX</td><td>MIN</td><td>MAX</td></tr><tr><td>A</td><td>1.400</td><td>1.600</td><td>0.055</td><td>0.063</td></tr><tr><td>A1</td><td>0.050</td><td>0.150</td><td>0.002</td><td>0.006</td></tr><tr><td>A2</td><td>1.350</td><td>1.450</td><td>0.053</td><td>0.057</td></tr><tr><td>b</td><td>0.170</td><td>0.270</td><td>0.007</td><td>0.011</td></tr><tr><td>c</td><td>0.090</td><td>0.200</td><td>0.004</td><td>0.008</td></tr><tr><td>D</td><td>11.800</td><td>12.200</td><td>0.465</td><td>0.480</td></tr><tr><td>D1</td><td>9.900</td><td>10.100</td><td>0.390</td><td>0.398</td></tr><tr><td>E</td><td>11.800</td><td>12.200</td><td>0.465</td><td>0.480</td></tr><tr><td>E1</td><td>9.900</td><td>10.100</td><td>0.390</td><td>0.398</td></tr><tr><td>e</td><td colspan="2">0.500 BSC</td><td colspan="2">0.020 BSC</td></tr><tr><td>L</td><td>0.450</td><td>0.750</td><td>0.018</td><td>0.030</td></tr><tr><td>θ</td><td>0</td><td>7°</td><td>0</td><td>7°</td></tr></table>
## 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
Order Information
<table><tr><td>Order Number</td><td>Operating Temperature Range</td><td>Package</td><td>Marking Information</td><td>MSL</td><td>Transport Media, Quantity</td><td>Eco Plan</td></tr><tr><td>TPAFE5160SI08-QP7R</td><td>-40 to 125°C</td><td>LQFP10×10-64</td><td>AFE5160</td><td>3</td><td>Tape and Reel, 1000</td><td>Green</td></tr></table>
Green: 3PEAK defines "Green" to mean RoHS compatible and free of halogen substances.
# 16-Bit, 8-Channel, Simultaneous Sampling ADC with Bipolar Inputs
## IMPORTANT NOTICE AND DISCLAIMER
Copyright© 3PEAK 2012-2024. All rights reserved.
Trademarks. Any of the 思瑞浦 or 3PEAK trade names, trademarks, graphic marks, and domain names contained in this document /material are the property of 3PEAK. You may NOT reproduce, modify, publish, transmit or distribute any Trademark without the prior written consent of 3PEAK.
Performance Information. Performance tests or performance range contained in this document/material are either results of design simulation or actual tests conducted under designated testing environment. Any variation in testing environment or simulation environment, including but not limited to testing method, testing process or testing temperature, may affect actual performance of the product.
Disclaimer. 3PEAK provides technical and reliability data (including data sheets), design resources (including reference designs), application or other design recommendations, networking tools, security information and other resources "As Is". 3PEAK makes no warranty as to the absence of defects, and makes no warranties of any kind, express or implied, including without limitation, implied warranties as to merchantability, fitness for a particular purpose or non-infringement of any third-party's intellectual property rights. Unless otherwise specified in writing, products supplied by 3PEAK are not designed to be used in any life-threatening scenarios, including critical medical applications, automotive safety-critical systems, aviation, aerospace, or any situations where failure could result in bodily harm, loss of life, or significant property damage. 3PEAK disclaims all liability for any such unauthorized use.