HC32 IIC/I2C读写

news2025/1/11 21:44:05

IIC状态码

IIC 初始化

void iicInit(uint32_t speed)
{
    stc_gpio_cfg_t stcGpioCfg;
    DDL_ZERO_STRUCT(stcGpioCfg);
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);  //开启GPIO时钟门控
    stcGpioCfg.enDir = GpioDirOut;                           ///< 端口方向配置->输出
    stcGpioCfg.enOD = GpioOdEnable;                          ///< 开漏输出
    stcGpioCfg.enPu = GpioPuEnable;                          ///< 端口上拉配置->使能
    stcGpioCfg.enPd = GpioPdDisable;                         ///< 端口下拉配置->禁止
    Gpio_Init(GpioPortB, GpioPin8, &stcGpioCfg);             ///< 端口初始化
    Gpio_Init(GpioPortB, GpioPin9, &stcGpioCfg);
    Gpio_SetAfMode(GpioPortB, GpioPin8, GpioAf1);            ///< 配置PB08为SCL
    Gpio_SetAfMode(GpioPortB, GpioPin9, GpioAf1);            ///< 配置PB09为SDA
    stc_i2c_cfg_t stcI2cCfg;
    DDL_ZERO_STRUCT(stcI2cCfg);                            ///< 初始化结构体变量的值为0
    Sysctrl_SetPeripheralGate(SysctrlPeripheralI2c0, TRUE); ///< 开启I2C0时钟门控
    stcI2cCfg.u32Pclk = Sysctrl_GetPClkFreq();             ///< 获取PCLK时钟
    stcI2cCfg.u32Baud = speed;                           ///< 1MHz
    stcI2cCfg.enMode = I2cMasterMode;                      ///< 主机模式
    stcI2cCfg.u8SlaveAddr = SLAVE_ADDR;             ///< 从地址,主模式无效
    stcI2cCfg.bGc = FALSE;                                 ///< 广播地址应答使能关闭
    I2C_Init(M0P_I2C0, &stcI2cCfg);                        ///< 模块初始化
}

IIC读写

/**
 ******************************************************************************
 ** 主机接收函数
 ** @param: I2CX
 ** @param: I2C_DEVADDR    从机设备地址
 ** @param:register_addr  读取寄存器addr
 ** @param:pu8Data        读取addr的 data值
 ** @param: u32Len         读取长度
 **
 ******************************************************************************/
en_result_t I2C_MasterReadData(M0P_I2C_TypeDef *I2CX, uint8_t I2C_DEVADDR, uint8_t register_addr, uint8_t *pu8Data, uint32_t u32Len)
{
    en_result_t enRet = Error;
    uint8_t u8i = 0, u8State;

    I2C_SetFunc(I2CX, I2cStart_En);

    while (1)
    {
        while (0 == I2C_GetIrq(I2CX))
        {;}
        u8State = I2C_GetState(I2CX);
        switch (u8State)
        {
        case 0x08:                                    //已发送起始条件,将发送SLA+R
            I2C_ClearFunc(I2CX, I2cStart_En);
            I2C_WriteByte(I2CX, (I2C_DEVADDR));       //发送SLA+W
            break;
        case 0x18:                                    //已发送SLA+W,并接收到ACK
            I2C_WriteByte(I2CX, register_addr);       //发送内存地址
            break;
        case 0x28:                                    //已发送数据,接收到ACK
            I2C_SetFunc(I2CX, I2cStart_En);
            break;
        case 0x10:                                    //已发送重复起始条件
            I2C_ClearFunc(I2CX, I2cStart_En);
            I2C_WriteByte(I2CX, (I2C_DEVADDR) | 0x01); //读命令发送
            break;
        case 0x40:                                    //已发送SLA+R,并接收到ACK
            if (u32Len > 1)
            {
                I2C_SetFunc(I2CX, I2cAck_En);
            }
            break;
        case 0x50:                                    //已接收数据字节,并已返回ACK信号
            pu8Data[u8i++] = I2C_ReadByte(I2CX);
            if (u8i == u32Len - 1)
            {
                I2C_ClearFunc(I2CX, I2cAck_En);       //读数据时,倒数第二个字节ACK关闭
            }
            break;
        case 0x58:                                    //已接收到最后一个数据,NACK已返回
            pu8Data[u8i++] = I2C_ReadByte(I2CX);
            I2C_SetFunc(I2CX, I2cStop_En);            //发送停止条件
            break;
        case 0x38:                                    //在发送地址或数据时,仲裁丢失
            I2C_SetFunc(I2CX, I2cStart_En);           //当总线空闲时发起起始条件
            break;
        case 0x48:                                    //发送SLA+R后,收到一个NACK
            I2C_SetFunc(I2CX, I2cStop_En);
            I2C_SetFunc(I2CX, I2cStart_En);
            break;
        default:                                      //其他错误状态,重新发送起始条件
            I2C_SetFunc(I2CX, I2cStart_En);           //其他错误状态,重新发送起始条件
            break;
        }
        I2C_ClearIrq(I2CX);                               //清除中断状态标志位
        if (u8i == u32Len)                                //数据全部读取完成,跳出while循环
        {
            break;
        }
    }
    enRet = Ok;
    return enRet;
}

/**
 ******************************************************************************
 ** 主机发送函数
 ** @param: I2CX
 ** @param: I2C_DEVADDR    从机设备地址
 ** @param:register_addr  写入寄存器addr
 ** @param:pu8Data        写入addr的 data值
 ** @param: u32Len         写入长度
 **
 ******************************************************************************/
en_result_t I2C_MasterWriteData(M0P_I2C_TypeDef *I2CX, uint8_t I2C_DEVADDR, uint8_t register_addr, uint8_t *pu8Data, uint32_t u32Len)
{
    en_result_t enRet = Error;
    uint8_t u8i = 0, u8State;
    I2C_SetFunc(I2CX, I2cStart_En);
    while (1)
    {
        while (0 == I2C_GetIrq(I2CX))
        {;}
        u8State = I2C_GetState(I2CX);
        switch (u8State)
        {
        case 0x08:                                 ///已发送起始条件
            I2C_ClearFunc(I2CX, I2cStart_En);
            I2C_WriteByte(I2CX, (I2C_DEVADDR));    ///从设备地址发送
            break;
        case 0x18:                                 ///已发送SLA+W,并接收到ACK
            I2C_WriteByte(I2CX, register_addr);
            break;
        case 0x28:                                 ///上一次发送数据后接收到ACK
            I2C_WriteByte(I2CX, pu8Data[u8i++]);
            break;
        case 0x20:                                 ///上一次发送SLA+W后,收到NACK
        case 0x38:                                 ///上一次在SLA+读或写时丢失仲裁
            I2C_SetFunc(I2CX, I2cStart_En);        ///当I2C总线空闲时发送起始条件
            break;
        case 0x30:                                 ///已发送I2Cx_DATA中的数据,收到NACK,将传输一个STOP条件
            I2C_SetFunc(I2CX, I2cStop_En);         ///发送停止条件
            break;
        default:
            break;
        }
        if (u8i > u32Len)
        {
            I2C_SetFunc(I2CX, I2cStop_En);             ///此顺序不能调换,出停止条件
            I2C_ClearIrq(I2CX);
            break;
        }
        I2C_ClearIrq(I2CX);                            ///清除中断状态标志位
    }
    enRet = Ok;
    return enRet;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1048344.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kubernetes 上的数据已跨越鸿沟:在 GKE 上运行有状态应用程序的案例

Kubernetes 是当今云原生开发的事实上的标准。长期以来&#xff0c;Kubernetes 主要与无状态应用程序相关&#xff0c;例如 Web 和批处理应用程序。然而&#xff0c;与大多数事物一样&#xff0c;Kubernetes 也在不断发展。如今&#xff0c;我们看到 Kubernetes 上有状态应用程…

MySQL学习笔记19

MySQL日志文件&#xff1a;MySQL中我们需要了解哪些日志&#xff1f; 常见日志文件&#xff1a; 我们需要掌握错误日志、二进制日志、中继日志、慢查询日志。 错误日志&#xff1a; 作用&#xff1a;存放数据库的启动、停止和运行时的错误信息。 场景&#xff1a;用于数据库的…

ubuntu apt工具软件操作

apt工具 -----> 网关 国内网络(仓库源) 美国网络(仓库源)/etc/apt/sources.list https://mirrors.tuna.tsinghua.edu.cn/help/ubuntu/sudo apt-get update sudo apt install sl 安装包 sudo apt-cache show sl 查看包信…

Jquery 复选框全选和反选失灵的问题

页面上有这么一张表格&#xff0c;点击All时将列表中的复选框全部勾选&#xff0c;反之亦然。 表头&#xff1a; <th><input type"checkbox" id"chkAll" onclick"CheckAll(this)" />All </th> 表格数据源绑定&#xff1a; …

TouchGFX界面开发 | 项目代码结构分析

项目代码结构分析 本文介绍TouchGFX项目中TouchGFX Designer自动生成的代码&#xff0c;以及需要用户编写的扩展代码。 一、生成的代码和用户代码 TouchGFX Designer生成的代码将与用户编写的代码完全分离。 事实上&#xff0c;自动生成的代码位于generated/gui_generated文…

【DTEmpower案例操作教程】智能模型预警

DTEmpower是由天洑软件自主研发的一款通用的智能数据建模软件&#xff0c;致力于帮助工程师及工科专业学生&#xff0c;利用工业领域中的仿真、试验、测量等各类数据进行挖掘分析&#xff0c;建立高质量的数据模型&#xff0c;实现快速设计评估、实时仿真预测、系统参数预警、设…

全面解析‘’vcomp140.dll,无法继续执行代码怎么修复,解决方法分享

在我最近的一次的打开电脑软件过程中&#xff0c;我遇到了一个棘手的问题&#xff1a;我的计算机无法启动&#xff0c;系统提示找不到vcomp140.dll文件。这个文件是Windows操作系统的一个重要组件&#xff0c;如果丢失或损坏&#xff0c;可能会导致系统无法正常运行。我决定挑战…

详解 TCP 原理

TCP 一、TCP 报文协议段二、TCP 原理1、确认应答机制2、超时重传机制3、连接管理机制4、滑动窗口5、流量控制6、拥塞控制7、延时应答8、捎带应答9、面向字节流&#xff08;粘包问题&#xff09;10、异常情况&#xff08;机器掉电/网线断开&#xff1a;心跳包&#xff09; 一、T…

TouchGFX界面开发 | 按钮控件应用示例

按钮控件应用示例 按钮是最常见的部件之一&#xff0c;有了按钮就可以点击&#xff0c;从而响应事件&#xff0c;达到人机交互的目的。TouchGFX Designer内置了七种按钮部件&#xff1a; 下压按钮&#xff1a;能够在被释放时发送回调&#xff0c;按下和释放状态都关联了图像标…

AI算法+视频技术助力构建智慧城管解决方案,实现城市管理精细化

一、背景分析 物联网、大数据、移动互联网等技术的日新月异&#xff0c;城市管理对信息资源需求的日益提升&#xff0c;广大市民对政府服务新的诉求&#xff0c; 智慧城管正面临千载难逢的发展机遇。 发展历程&#xff1a; 1&#xff09;数字城管&#xff1a;城市管理机制的…

RecycleView刷新功能

RecycleView刷新某一个Item&#xff0c;或这某一个Item中某一个View。 这样的需求&#xff0c;在实际的开发中是很普遍的。 在数据变化后需要刷新列表。 刷新列表有三种方式&#xff1a; 前两种大家应该很熟&#xff0c;第三中会有点陌生。 那么这三种方式&#xff0c;有什…

google的日志glog安装及使用

1.glog glog是google出的一个轻量级的c日志库 2.下载及编译 下载或克隆库&#xff0c;我选择的是V0.6.0版本&#xff1a; github.com/goolge/glog/releases/tag/v0.6.0 我用cmake编译&#xff08;参考&#xff1a;github.com/google/glog#cmake&#xff09; 按照说明步骤进…

【运维知识高级篇】超详细的Jenkins教程4(参数化构建+脚本传参+代码秒级发布+秒级回滚)

之前我们介绍的大多是测试环境的推送&#xff0c;在生产环境中&#xff0c;我们不会用到那么多次的构建测试&#xff0c;但是会涉及稳定版本的发布和回滚&#xff0c;我们也通过jenkins配合gitlab去实现&#xff0c;通过远程仓库的tag传递参数&#xff0c;我们把这种方式称为参…

企业会议新闻稿怎么写?会议类新闻稿如何撰写?

企业会议新闻稿是企业对外传递信息的重要途径之一&#xff0c;它能够将企业的决策、动态以及成果展示给公众。本文伯乐网络传媒将详细解析企业会议新闻稿的写作要点和技巧&#xff0c;以及常见问题及解决方法&#xff0c;帮助大家更好地完成企业会议新闻稿的撰写工作。 一、企业…

Spring Mvc的相关知识

一、初识MVC 1.Spring Mvc 是控制层的Spring框架&#xff0c;替换Servlet&#xff0c;除了它以外&#xff0c;还有 struct1和 struct2 区别&#xff1a; 1.struct1被struct2 取代 2.struct2&#xff1a;采用 prototype多例模式&#xff0c;内存消耗快&#xff0c;经常会出现内存…

RocketMQ Promethus Exporter

介绍​ Rocketmq-exporter 是用于监控 RocketMQ broker 端和客户端所有相关指标的系统&#xff0c;通过 mqAdmin 从 broker 端获取指标值后封装成 87 个 cache。 警告 过去版本曾是 87 个 concurrentHashMap&#xff0c;由于 Map 不会删除过期指标&#xff0c;所以一旦有 la…

python实现遗传算法,并绘制训练过程以及参数对比

前言: 本实验使用遗传算法寻找3维函数的最大/最小值&#xff0c;并对基因位数&#xff0c;种群初始大小&#xff0c;每次死亡个数&#xff0c;适应度计算方式这些参数进行修改&#xff0c;对比结果。 初始代码如下&#xff1a; import numpy as np import matplotlib.pyplot …

【atcoder】abc312~abc321题解

UNIQUE VISION Programming Contest 2023 Summer(AtCoder Beginner Contest 312) A 把信息存进去然后找就行。 B 枚举右上角&#xff0c;然后模拟判断即可。 C 二分这个 X X X &#xff0c;然后判断即可。 D 典型的括号类的 d p dp dp 。 d p i , j dp_{i, j} dpi,j​…

Python大数据之Python进阶(二)多任务编程-进程

文章目录 多任务编程-进程本章节学习目标本章节常用单词 多任务的介绍1. 提问2. 多任务的概念多任务3. 多任务的执行方式4. 小结 进程1. 进程的介绍2. 进程的概念3. 进程的作用4. 小结 多任务编程-进程 本章节学习目标 能够知道多任务的执行方式能够知道进程的作用能够使用多…