处理器美之华大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模块操作的基本内容,以后用到那个模块会继续做补充。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

憨憨的老郭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值