s3c2440裸机-I2c编程-3.i2c中断服务程序

2023-07-21  

Start信号之后,发出设备地址,在第9个时钟就会产生一个中断,我们根据i2c的流程图来编写中断程序。


每传输完一个数据将产生一个中断,I2C操作的主体在中断服务程序,它可以分为两部分:写操作,读操作。


完整code如下:


static p_i2c_msg p_cur_msg;

 

int isLastData(void)

{

        if (p_cur_msg->cnt_transferred == p_cur_msg->len - 1)

                return 1;  /* 正要开始传输最后一个数据 */

        else 

                return 0;

}

 

void resume_iic_with_ack(void)

{

        unsigned int iiccon = IICCON;

        iiccon |= (1<<7); /* 回应ACK */

        iiccon &= ~(1<<4); /* 恢复IIC操作 */

        IICCON =  iiccon;

}

 

void resume_iic_without_ack(void)

{

        unsigned int iiccon = IICCON;

        iiccon &= ~((1<<7) | (1<<4)); /* 不回应ACK, 恢复IIC操作 */

        IICCON =  iiccon;

}

 

void i2c_interrupt_func(int irq)

{

        int index;

        unsigned int iicstat = IICSTAT;

        unsigned int iiccon;

 

        //printf("i2c_interrupt_func! flags = %dnr", p_cur_msg->flags);

 

        p_cur_msg->cnt_transferred++;

        

        /* 每传输完一个数据将产生一个中断 */

 

        /* 对于每次传输, 第1个中断是"已经发出了设备地址" */

 

        if (p_cur_msg->flags == 0)        /* write */

        {

                /* 对于第1个中断, 它是发送出设备地址后产生的

                 * 需要判断是否有ACK

                 * 有ACK : 设备存在

                 * 无ACK : 无设备, 出错, 直接结束传输

                 */

                if (p_cur_msg->cnt_transferred == 0)  /* 第1次中断 */

                {

                        if (iicstat & (1<<0)) /*iicstat [0] == 1表示no ack*/

                        { /* no ack */

                                /* 停止传输 */

                                IICSTAT = 0xd0;

                                IICCON &= ~(1<<4); //clear pending bit

                                p_cur_msg->err = -1;

                                printf("tx err, no acknr");

                                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);//clear pending bit

        }

        else

        {

                /* 停止传输 */

                IICSTAT = 0xd0;

                IICCON &= ~(1<<4);

                delay(1000);

        }

        }

        else /* read */

        {

                /* 对于第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); //clear pending bit

                                p_cur_msg->err = -1;

                                printf("rx err, no acknr");

                                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);

        }

}


写操作:


        if (p_cur_msg->flags == 0)        /* write */

        {

                /* 对于第1个中断, 它是发送出设备地址后产生的

                 * 需要判断是否有ACK

                 * 有ACK : 设备存在

                 * 无ACK : 无设备, 出错, 直接结束传输

                 */

                if (p_cur_msg->cnt_transferred == 0)  /* 第1次中断 */

                {

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。