• 处理器美之华大170处理器


    最近在学习华大的170处理器。该处理器是一款M0+的低功耗处理器。本着学啥记啥的原则写一下它的相关模块:

    1、IIC模块

    1.1 IIC基本概念

    IIC是通过两根线实现的通讯机制,一根时钟线,一根信号线。通讯时序如图一所示。该部分通讯包括如下几部分:

    1.1.1 起始信号。该信号是在CLK信号高的情况下数据信号由高变低,该信号是不会重复的,为什么呢?因为IIC规定CLK信号在高的时候DAT是不能变化的,当CLK变成低的时候DAT才能变化。

    1.1.2 数据位。一般是8个数据位,当CLK信号在高的时候DAT是不能变化的,当CLK变成低的时候DAT才能变化。

    1.1.3 ACK 。该位算是有一种反馈机制。当接收方接收一个字节后要将总线拉低作为一种反馈。

    1.1.4停止位。该位和起始位刚好相反。当CLK在高的时候DAT由低到高。

                                                       图一  IIC时序图

    1.2华大处理器的IIC

    明白了IIC的基本机制以后第二个问题就来了。华大170是如何实现该功能的。

                        图二 华大170配置寄存器

                              图三 华大处理器状态码 

    图二和图三是华大170处理器要实现该功能主要参考的寄存器。我们先看图二,华大170每步都是可控的。我们来按照图一的时序梳理一遍图二的寄存器。当我们要发送数据的时候首先要发送起始位,对应的程序就要将图二中的BIT5置位,这样IIC模块就会发送一个起始信号到总线上。然后程序要等待终端标准会置1,这时候说明IIC模块执行了一个动作,但是执行了什么动作呢?这个要读取IIC的状态寄存器,返回值代表的意思参考图三,根据图三做后续动作。当状态值表示已经发送了起始位以后要发送从机地址寄存器了。该位是7位值,bit0是读写位(R:1;W:0)。要实现该动作首先要将图二中的起始标志位清零,然后再IIC数据寄存器中写入数据(7位地址,1位读写),然后将,最后最重要的是要将图二中的中断标志位清零,这个动作非常重要,手册也写的很清楚,如果不清零动作无法执行。然后就是其他数据的传送了。只要根据状态寄存器的值进行操作就好了。

    1.3读写代码

     en_result_t I2C_MasterReadData(M0P_I2C_TypeDef* I2CX,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,AHT20_SLAVEADDR|0x01);
                    break;
                case 0x10:                                 ///< 已发送重复起始条件
                    I2C_ClearFunc(I2CX,I2cStart_En);
                    I2C_WriteByte(I2CX,AHT20_SLAVEADDR|0x01);///< 发送SLA+R,开始从从机读取数据
                    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;
    }

    en_result_t I2C_MasterWriteData(M0P_I2C_TypeDef* I2CX,uint8_t *pu8Data,uint32_t u32Len)
    {
        en_result_t enRet = Error;
        uint8_t u8i=0,u8State;
        I2C_SetFunc(I2CX,I2cStart_En);
    //      I2C_ClearIrq(I2CX); 
        while(1)
        {
            while(0 == I2C_GetIrq(I2CX))
            {;}        
            u8State = I2C_GetState(I2CX);
            switch(u8State)
            {
                case 0x08:                               ///< 已发送起始条件
                    I2C_ClearFunc(I2CX,I2cStart_En);
                    I2C_WriteByte(I2CX,AHT20_SLAVEADDR);   ///< 从设备地址发送
                    break;
                case 0x18:                               ///< 已发送SLA+W,并接收到ACK
                    I2C_WriteByte(I2CX,pu8Data[u8i++]);  ///< 继续发送数据
                    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;
    }

    以上是我根据需要在官方给的例程基础上做的修改,大家可以参考一下框架,便于理解它的实现机制。以上就是华大170处理器 IIC模块操作的基本内容,以后用到那个模块会继续做补充。

  • 相关阅读:
    Flask API 如何接入 i18n 实现国际化多语言
    事件链、事件代理、页面的渲染过程、style的操作、防抖与节流【DOM(四)】
    Vue 计算属性
    Powershell脚本自动备份dhcp数据库
    深度学习-Pytorch同时使用Numpy和Tensors各自特效
    [PAT练级笔记] 65 Basic Level 1065 单身狗
    【Git】Git下载安装&环境配置 下载速度慢的解决方案
    【笔试题】【day15】
    【c ++ primer 笔记】第3章 字符串、向量和数组
    安防行业集团采购管理系统:全程数字化采购执行,规范化企业采购业务流程
  • 原文地址:https://blog.csdn.net/guodeqiangde/article/details/126820528