📄 i2cint.c
字号:
/****************************************Copyright (c)**************************************************
** Guangzou ZLG-MCU Development Co.,LTD.
** graduate school
** http://www.zlgmcu.com
**
**--------------File Info-------------------------------------------------------------------------------
** File name: I2CINT.c
** Last modified Date: 2004-09-16
** Last Version: 1.0
** Descriptions: The main() function example template
**
**------------------------------------------------------------------------------------------------------
** Created by: Chenmingji
** Created date: 2004-09-16
** Version: 1.0
** Descriptions: The original version
**
**------------------------------------------------------------------------------------------------------
** Modified by: Chenxibing
** Modified date: 2005-01-14
** Version:
** Descriptions: LPC2000硬件I2C中断方式软件包
**
********************************************************************************************************/
#include "config.h"
/*
* 定义用于和I2C中断传递信息的全局变量
*/
volatile uint8 __GuiI2CSla; /* I2C器件从地址 */
volatile uint32 __GuiI2CSuba; /* I2C器件内部子地址 */
volatile uint8 __GuiI2CSubaNum; /* I2C器件子地址字节数 */
volatile uint8 *__GuiI2CBuf; /* 数据缓冲区指针 */
volatile uint32 __GuiI2CNum; /* 要读取/写入的数据个数 */
volatile uint8 __GuiI2CEnd; /* I2C总线结束标志:结束时置1 */
volatile uint32 __GuiI2CSubaEn; /* 子地址控制:
0为已处理或者不需要子地址;
1为读取操作
2为写操作 */
/*********************************************************************************************************
** Function name: ISendByte
** Descriptions: 向无子地址器件发送1字节数据
** input parameters: uiSla 器件地址
** uiDat 要发送的数据
** output parameters: 返回值为0时表示出错,为1时表示操作正确
** Returned value: 无
*********************************************************************************************************/
uint8 ISendByte (uint8 uiSla, uint8 uiDat)
{
/*
* 参数设置
*/
__GuiI2CSla = uiSla; /* 写操作的器件地址 */
__GuiI2CBuf = &uiDat; /* 待发送的数据 */
__GuiI2CNum = 1; /* 待发送的数据个数 */
__GuiI2CSubaEn = 0; /* 无子地址 */
__GuiI2CEnd = 0; /* 总线不结束 */
I2CONCLR = 0x2C;
I2CONSET = 0x60; /* 设置为主机,并启动总线 */
while (0 == __GuiI2CEnd);
if(1 == __GuiI2CEnd)return(1);
else return(0);
}
/*********************************************************************************************************
** Function name: IRcvByte
** Descriptions: 向无子地址器件读取1字节数据
** input parameters: uiSla 器件地址
** uiDat 接收数据的变量指针
** output parameters: 返回值为0时表示操作出错,为1时表示操作正确
** Returned value: 无
*********************************************************************************************************/
uint8 IRcvByte (uint8 uiSla, uint8 *uiDat)
{
/*
* 参数设置
*/
__GuiI2CSla = uiSla + 1; /* 读操作的器件地址 */
__GuiI2CBuf = uiDat;
__GuiI2CNum = 1; /* 待发送的数据个数 */
__GuiI2CSubaEn = 0; /* 无子地址 */
__GuiI2CEnd = 0; /* 总线不结束 */
I2CONCLR = 0x2C;
I2CONSET = 0x60; /* 设置为主机,并启动总线 */
while (0 == __GuiI2CEnd);
if(1 == __GuiI2CEnd)return(1);
else return(0);
}
/*********************************************************************************************************
** Function name: I2CReadNByte
** Descriptions: 从有子地址器件任意地址开始读取N字节数据
** input parameters: uiSla 器件从地址
** uiSubaType 子地址结构 1-单字节地址 2-8+X结构 2-双字节地址
** uiSuba 器件子地址
** *uiS 数据接收缓冲区指针
** uiNum 读取的个数
** output parameters: TRUE 操作成功
** FALSE 操作失败
** Returned value: 无
*********************************************************************************************************/
uint8 I2C_ReadNByte (uint8 uiSla, uint32 uiSubaType, uint32 uiSuba, uint8 *uiS, uint32 uiNum)
{
if(uiNum > 0) /* 判断uiNum个数的合法性 */
{
/*
* 参数设置
*/
if(uiSubaType == 1){ /* 子地址为单字节 */
__GuiI2CSla = uiSla + 1; /* 读操作的器件地址 */
__GuiI2CSuba = uiSuba; /* 器件子地址 */
__GuiI2CSubaNum = 1; /* 器件子地址为1字节 */
}
if(uiSubaType == 2){ /* 子地址为两字节 */
__GuiI2CSla = uiSla + 1; /* 读操作的器件地址 */
__GuiI2CSuba = uiSuba; /* 器件子地址 */
__GuiI2CSubaNum = 2; /* 器件子地址为1字节 */
}
if(uiSubaType == 3){ /* 子地址为8+X结构 */
__GuiI2CSla = uiSla + ((uiSuba >> 7) & 0x0E) + 1; /* 读操作的器件地址 */
__GuiI2CSuba = uiSuba & 0xFF; /* 器件子地址 */
__GuiI2CSubaNum = 1; /* 器件子地址为1字节 */
}
__GuiI2CBuf = uiS; /* 数据接收缓冲区指针 */
__GuiI2CNum = uiNum; /* 要读取的数据个数 */
__GuiI2CSubaEn = 1; /* 有子地址读 */
__GuiI2CEnd = 0;
/*
* 清除STA,SI,AA标志位
*/
I2CONCLR = (1 << 2) | /* 清除AA */
(1 << 3) | /* 清除SI */
(1 << 5) ; /* 清除STA */
/*
* 置位STA,启动I2C总线
*/
I2CONSET = (1 << 5) | /* STA */
(1 << 6) ; /* I2EN */
/*
* 等待I2C操作完成
*/
while (__GuiI2CEnd == 0);
if(__GuiI2CEnd == 1){
return(TRUE);
}
else return(FALSE);
}
return(FALSE);
}
/*********************************************************************************************************
** Function name: I2CWriteNByte
** Descriptions: 向有子地址器件写入N字节数据
** input parameters: uiSla 器件从地址
** uiSubaType 子地址结构 1-单字节地址 3-8+X结构 2-双字节地址
** uiSuba 器件内部物理地址
** *uiS 将要写入的数据的指针
** uiNum 将要写入的数据的个数
** output parameters: TRUE 操作成功
** FALSE 操作失败
** Returned value: 无
*********************************************************************************************************/
uint8 I2C_WriteNByte(uint8 uiSla, uint8 uiSubaType, uint32 uiSuba, uint8 *uiS, uint32 uiNum)
{
if(uiNum > 0){ /* 如果写入的个数为0,返回错误 */
/*
* 参数设置
*/
if(uiSubaType == 1){ /* 子地址为单字节 */
__GuiI2CSla = uiSla; /* 写操作的器件地址 */
__GuiI2CSuba = uiSuba; /* 器件子地址 */
__GuiI2CSubaNum = 1; /* 器件子地址为1字节 */
}
if(uiSubaType == 2){ /* 子地址为单字节 */
__GuiI2CSla = uiSla; /* 写操作的器件地址 */
__GuiI2CSuba = uiSuba; /* 器件子地址 */
__GuiI2CSubaNum = 2; /* 器件子地址为2字节 */
}
if(uiSubaType == 3){ /* 子地址为8+X结构 */
__GuiI2CSla = uiSla + ((uiSuba >> 7) & 0x0E); /* 写操作的器件地址 */
__GuiI2CSuba = uiSuba & 0xFF; /* 器件子地址 */
__GuiI2CSubaNum = 1; /* 器件子地址为1字节 */
}
__GuiI2CBuf = uiS;
__GuiI2CNum = uiNum;
__GuiI2CSubaEn = 2;
__GuiI2CEnd = 0;
/*
* 清除STA,启动I2C总线
*/
I2CONCLR = (1 << 2) | /* 清除AA */
(1 << 3) | /* 清除SI */
(1 << 5) ; /* 清除STA */
/*
* 置位STA,启动I2C总线
*/
I2CONSET = (1 << 5) | /* STA */
(1 << 6) ; /* I2EN */
while (__GuiI2CEnd == 0); /* 等待I2C操作完成 */
if (__GuiI2CEnd == 1){
return (TRUE);
}
else return (FALSE);
}
return (FALSE);
}
/*********************************************************************************************************
** Function name: __irq IRQI2C
** Descriptions: 硬件I2C中断服务程序
** input parameters: 无
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void __irq IRQ_I2C (void)
{
/*
* 读取I2C状态寄存器I2STAT
* 按照全局变量的设置进行操作及设置软件标志
* 清除中断逻辑,中断返回
*/
switch(I2STAT & 0xF8){
/*
* 根据状态码进行相应的处理
*/
case 0x08: /* 已发送起始条件 */
/*
* 装入SLA+W或者SLA+R
*/
if(__GuiI2CSubaEn == 1){ /* 指定子地址读操作 */
I2DAT = __GuiI2CSla & 0xFE; /* 先写入地址 */
}
else
{
I2DAT = __GuiI2CSla; /* 否则直接发送从机地址 */
}
/*
* 清零SI位
*/
I2CONCLR = (1 << 3) | /* 清零SI */
(1 << 5) ; /* 清零STA */
break;
case 0x10: /* 已发送重复起始位 */
I2DAT = __GuiI2CSla; /* 重起总线后,重发从地址 */
I2CONCLR = 0x28; /* 清零SI和STA */
break;
case 0x18:
case 0x28: /* 已发送I2DAT中的数据,
* 已接收ACK */
if (__GuiI2CSubaEn == 0){
if (__GuiI2CNum > 0){ /* 如果还有数据需要写 */
I2DAT = *__GuiI2CBuf++; /* 写数据 */
I2CONCLR = 0x28; /* 清零SI和STA */
__GuiI2CNum--; /* 字节数减一 */
}
else{ /* 没有数据发送了 */
I2CONSET = (1 << 4); /* STO */
I2CONCLR = 0x28; /* 清零SI和STA */
__GuiI2CEnd = 1; /* 总线已经停止 */
}
}
if (__GuiI2CSubaEn == 1){ /* 若是指定地址读,重新启动总线*/
if (__GuiI2CSubaNum == 2){ /* 如果是双字节地址 */
I2DAT = ((__GuiI2CSuba >> 8) & 0xFF); /* 先发送地址高字节 */
I2CONCLR = 0x28; /* 清零SI和STA */
__GuiI2CSubaNum--; /* 字节数减一 */
break;
}
if (__GuiI2CSubaNum == 1){
I2DAT = (__GuiI2CSuba & 0xFF); /* 发送地址低字节 */
I2CONCLR = 0x28; /* 清零SI和STA */
__GuiI2CSubaNum--; /* 字节数减一 */
break;
}
if (__GuiI2CSubaNum == 0){
I2CONSET = 0x20; /* 置位STA,总线重起 */
I2CONCLR = 0x08; /* 清零SI */
__GuiI2CSubaEn = 0; /* 子地址已处理 */
break;
}
}
if (__GuiI2CSubaEn == 2){ /* 指定地址写,发送子地址 */
if (__GuiI2CSubaNum > 0){
if (__GuiI2CSubaNum == 2){ /* 如果是双字节地址 */
I2DAT = ((__GuiI2CSuba >> 8) & 0xFF); /* 先发送地址高字节 */
I2CONCLR = 0x28; /* 清零SI和STA */
__GuiI2CSubaNum--; /* 字节数减一 */
break;
}
if (__GuiI2CSubaNum == 1){
I2DAT = (__GuiI2CSuba & 0xFF); /* 发送地址低字节 */
I2CONCLR = 0x28; /* 清零SI和STA */
__GuiI2CSubaNum--; /* 字节数减一 */
__GuiI2CSubaEn = 0;
break;
}
}
}
break;
case 0x40: /* 已发送SLA+R,已接收ACK */
if (__GuiI2CNum <= 1){ /* 如果是最后一字节 */
I2CONCLR = 1 << 2; /* 下次发送非应答信号 */
}
else{
I2CONSET = 1 << 2; /* 下次发送应答信号 */
}
I2CONCLR = 0x28; /* 清零SI和STA */
break;
case 0x20: /* 已发送SLA+W,已接收非应答 */
case 0x30: /* 已发送I2DAT中的数据,
* 已接收非应答 */
case 0x38: /* SLA+R/W或数据字节中丢失仲裁 */
case 0x48: /* 已发送SLA+R,已接收非应答 */
I2CONCLR = 0x28;
__GuiI2CEnd = 0xFF; /* 总线出错 */
break;
case 0x50: /* 已接收数据字节,已返回ACK */
*__GuiI2CBuf++ = I2DAT;
__GuiI2CNum--;
if(__GuiI2CNum == 1){ /* 接收最后一个字节 */
I2CONCLR = 0x2C; /* STA、SI和AA=0 */
}
else{
I2CONSET = 0x04; /* AA=1 */
I2CONCLR = 0x28;
}
break;
case 0x58: /* 已接收数据字节,已返回非应答*/
*__GuiI2CBuf++ = I2DAT; /* 读取最后一字节数据 */
I2CONSET = 0x10; /* 结束总线 */
I2CONCLR = 0x28;
__GuiI2CEnd = 1;
break;
default:
break;
}
VICVectAddr = 0x00; /* 中断处理结束 */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -