zoukankan      html  css  js  c++  java
  • 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
    
    ");
                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
    
    ");
    		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

  • 相关阅读:
    「日常训练」Single-use Stones (CFR476D2D)
    「日常训练」Greedy Arkady (CFR476D2C)
    「Haskell 学习」二 类型和函数(上)
    「学习记录」《数值分析》第二章计算实习题(Python语言)
    「日常训练」Alena And The Heater (CFR466D2D)
    Dubbo 消费者
    Dubbo 暴露服务
    Rpc
    git fail to push some refs....
    Spring Cloud (6)config 客户端配置 与GitHub通信
  • 原文地址:https://www.cnblogs.com/zongzi10010/p/10023645.html
Copyright © 2011-2022 走看看