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

  • 相关阅读:
    aspjpeg组件安装、使用常见问题
    调用过程sub时不能使用括号
    asp中,使用js打开别的网址注意点
    让文件夹属性出现“安全”选项卡
    C#正则表达式使用<转载备用>
    .NET编程中常用的路径表示方式<转>
    DIVWEB布局
    winform report<收藏>
    Delphi中MessageBox用法
    DW中常用标签
  • 原文地址:https://www.cnblogs.com/zongzi10010/p/10023645.html
Copyright © 2011-2022 走看看