i2c框架


title: iic框架
tags: ARM
date: 2018-11-05 13:44:58
---

i2c框架

寄存器

mark

mark

mark

/* 配置引脚用于I2C*/
GPECON &= ~((3<<28) | (3<<30));
GPECON |= ((2<<28) | (2<<30));

/* 设置时钟 */
/* [7] : IIC-bus acknowledge enable bit, 1-enable in rx mode
     * [6] : 时钟源, 0: IICCLK = fPCLK /16; 1: IICCLK = fPCLK /512
     * [5] : 1-enable interrupt
     * [4] : 读出为1时表示中断发生了, 写入0来清除并恢复I2C操作
     * [3:0] : Tx clock = IICCLK/(IICCON[3:0]+1).
     * Tx Clock = 100khz = 50Mhz/16/(IICCON[3:0]+1)
     */
IICCON = (1<<7) | (0<<6) | (1<<5) | (30<<0);

中断配置: IIC没有次中断源.直接配置INTMSK即可INTMSK &= ~(1<<27);

主机发送

mark

int do_master_tx(p_i2c_msg msg)
{
    p_cur_msg = msg;
    
    msg->cnt_transferred = -1;
    msg->err = 0;
    
    /* 设置寄存器启动传输 */
    /* 1. 配置为 master tx mode */
    IICCON |= (1<<7); /* TX mode, 在ACK周期释放SDA */
    IICSTAT = (1<<4);
        
    /* 2. 把从设备地址写入IICDS */
    IICDS = msg->addr<<1;
    
    /* 3. IICSTAT = 0xf0 , 数据即被发送出去, 将导致中断产生 */
    IICSTAT = 0xf0;
    

    /* 后续的传输由中断驱动 */

    /* 循环等待中断处理完毕 */
    while (!msg->err && msg->cnt_transferred != msg->len);

    if (msg->err)
        return -1;
    else
        return 0;
}

主机接收

mark

int do_master_rx(p_i2c_msg msg)
{
    p_cur_msg = msg;

    msg->cnt_transferred = -1;
    msg->err = 0;
    
    /* 设置寄存器启动传输 */
    /* 1. 配置为 Master Rx mode */
    IICCON |= (1<<7); /* RX mode, 在ACK周期回应ACK */
    IICSTAT = (1<<4);
        
    /* 2. 把从设备地址写入IICDS */
    IICDS = (msg->addr<<1)|(1<<0);
    
    /* 3. IICSTAT = 0xb0 , 从设备地址即被发送出去, 将导致中断产生 */
    IICSTAT = 0xb0;
    

    /* 后续的传输由中断驱动 */

    /* 循环等待中断处理完毕 */
    while (!msg->err && msg->cnt_transferred != msg->len);

    if (msg->err)
        return -1;
    else
        return 0;
}

中断处理

注意

  1. 连续读的最后一个字节不响应ack,以用来终止读.
  2. 在读写第一个字节的时候,判断是否有ack来判断是否设备存在

mark

if (p_cur_msg->flags == 0)  /* write */
{
    /* 对于第1个中断, 它是发送出设备地址后产生的
         * 需要判断是否有ACK
         * 有ACK : 设备存在
         * 无ACK : 无设备, 出错, 直接结束传输
         */
    if (p_cur_msg->cnt_transferred == 0)  /* 第1次中断 */
    {
        if (iicstat & (1<<0))
        { /* no ack */
            /* 停止传输 */
            IICSTAT = 0xd0;
            IICCON &= ~(1<<4);//挂起标志
            p_cur_msg->err = -1;
            printf("tx err, no ack\n\r");
            delay(1000);
            return;
        }
    }

    if (p_cur_msg->cnt_transferred < p_cur_msg->len)
    {
        /* 对于其他中断, 要继续发送下一个数据
             */
        IICDS = p_cur_msg->buf[p_cur_msg->cnt_transferred];
        IICCON &= ~(1<<4);//挂起标志
    }
    else
    {
        /* 停止传输 */
        IICSTAT = 0xd0;
        IICCON &= ~(1<<4);//挂起标志
        delay(1000);
    }
}

/* 对于第1个中断, 它是发送出设备地址后产生的
 * 需要判断是否有ACK
 * 有ACK : 设备存在, 恢复I2C传输, 这样在下一个中断才可以得到第1个数据
 * 无ACK : 无设备, 出错, 直接结束传输
 */
if (p_cur_msg->cnt_transferred == 0)  /* 第1次中断 */
{
    if (iicstat & (1<<0))
    { /* no ack */
        /* 停止传输 */
        IICSTAT = 0x90;
        IICCON &= ~(1<<4);
        p_cur_msg->err = -1;
        printf("rx err, no ack\n\r");
        delay(1000);
        return;
    }
    else  /* ack */
    {
        /* 如果是最后一个数据, 启动传输时要设置为不回应ACK */
        /* 恢复I2C传输 */
        if (isLastData())
        {
            resume_iic_without_ack();
        }
        else
        {
            resume_iic_with_ack();
        }
        return;
    }
}

/* 非第1个中断, 表示得到了一个新数据
 * 从IICDS读出、保存
 */
if (p_cur_msg->cnt_transferred < p_cur_msg->len)
{
    index = p_cur_msg->cnt_transferred - 1;
    p_cur_msg->buf[index] = IICDS;

    /* 如果是最后一个数据, 启动传输时要设置为不回应ACK */
    /* 恢复I2C传输 */
    if (isLastData())
    {
        resume_iic_without_ack();
    }
    else
    {
        resume_iic_with_ack();
    }
}
else
{
    /* 发出停止信号 */
    IICSTAT = 0x90;
    IICCON &= ~(1<<4);//清标志
    delay(1000);
}

程序框架

mark

img

转载于:https://www.cnblogs.com/zongzi10010/p/10023645.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值