/*
---------------------------------------------------------------------------------------------------------
*********************************************************************************************************
** 文件名称 : I2CINT.c
** 功能说明 : Luminary硬件I2C中断方式软件包。
** 使用说明 : 主程序要配置好I2C总线接口(I2C引脚功能和I2C中断,并已使能I2C主模式)
*********************************************************************************************************
---------------------------------------------------------------------------------------------------------
*/
#include "hw_ints.h"
#include "hw_memmap.h"
#include "hw_types.h"
#include "hw_i2c.h"
#include "gpio.h"
#include "sysctl.h"
#include "i2c.h"
#include "interrupt.h"
#include "I2CINT.h"
#define uchar unsigned char
#define ulong unsigned long
/*******************************************************************************************
** 中断中的状态
*******************************************************************************************/
#define STATE_IDLE 0 /* 总线空闲状态 */
#define STATE_WRITE_ONE 1 /* 写单个字节状态 */
#define STATE_WRITE_NEXT 2 /* 写下一个字节状态 */
#define STATE_WRITE_FINAL 3 /* 写最后一个字节状态 */
#define STATE_READ_ONE 4 /* 读单个字节状态 */
#define STATE_READ_FIRST 5 /* 读第一个字节状态 */
#define STATE_READ_NEXT 6 /* 读下一个字节状态 */
#define STATE_READ_FINAL 7 /* 读最后一个字节状态 */
#define STATE_READ_WAIT 8 /* 读字节等待状态 */
/*******************************************************************************************
** 全局变量定义
*******************************************************************************************/
static volatile uchar I2C_sla; /* I2C器件从地址 */
static volatile ulong I2C_suba; /* I2C器件内部子地址 */
static volatile uchar I2C_suba_num; /* I2C子地址字节数 */
static volatile uchar *I2C_buf; /* 数据缓冲区指针 */
static volatile ulong I2C_num; /* 要读取/写入的数据个数 */
static volatile uchar I2C_opt; /* I2c读写操作,0为读操作,1为写操作 */
static volatile uchar I2C_state = STATE_IDLE; /* 中断服务程序的当前状态 */
/*
******************************************************************************************
** 函数名称: Delays()
** 函数功能: 延时
** 入口参数: dly
** 出口参数: 无
******************************************************************************************
*/
void Delays (ulong dly)
{
int i,j;
for (; dly>0; dly--)
{
for (i=0; i<150; i++)
for (j=0; j<255; j++);
}
}
/*
*********************************************************************************************************
** 函数名称:I2CInit()
** 函数功能:I2C接口初始化。
** 入口参数:spd 总线速度100K(参数值为100000)或400K(参数值为4000000)
** pri 中断优先级0~7
** 出口参数:返回值为false时表示操作出错,为true时表示操作正确。
** 说明:
*********************************************************************************************************
*/
int I2CInit(ulong spd, uchar pri)
{
if ((spd == 400000) || (spd == 100000))
{
// 使能所使用的外设
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
// 配置相关引脚,以进行I2C操作
GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7);
// 初始化I2C主机,设置主机为低速.
if(spd == 400000)
I2CMasterInit(I2C1_MASTER_BASE, true);
else
I2CMasterInit(I2C1_MASTER_BASE, false);
// 使能处理器中断
IntMasterEnable();
// 使能I2C中断
IntEnable(INT_I2C1);
// 使能I2C主机中断
I2CMasterIntEnable(I2C1_MASTER_BASE);
// 设置I2C中断的优先级
IntPrioritySet(INT_I2C1, (pri << 5));
return(true);
}
else
return(false);
}
/*
*********************************************************************************************************
** 函数名称:ISendByte()
** 函数功能:向无子地址器件发送1字节数据。
** 入口参数:sla 器件地址
** c 要发送的数据
** 出口参数:返回值为false时表示操作出错,为true时表示操作正确。
** 说明: 使用前要初始化好I2C引脚功能和I2C中断,并已使能I2C主模式
*********************************************************************************************************
*/
int ISendByte(uchar sla, uchar c)
{
I2C_sla = sla >> 1;
I2C_buf = &c;
I2C_state = STATE_WRITE_ONE;
I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, I2C_sla, false); // 主机写操作
I2CMasterDataPut(I2C1_MASTER_BASE, *I2C_buf); // 写一个数据
I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_SINGLE_SEND); // 启动单次发送
while(I2C_state != STATE_IDLE);
if(true == I2CMasterBusy(I2C_MASTER_BASE))
return (false);
else
return (true);
}
/*
*********************************************************************************************************
** 函数名称 :ISendStr()
** 函数功能 :向有子地址器件任意地址开始写入N字节数据
** 入口参数 : sla 器件从地址
** suba_type 子地址结构 0-8+X结构 1-单字节地址 2-双字节地址 3-三字节地址
** suba 器件子地址
** s 数据发送缓冲区指针
** no 写入的个数
** 出口参数 : TRUE 操作成功
** FALSE 操作失败
*********************************************************************************************************
*/
int ISendStr(uchar sla, ulong suba, uchar sub_type, uchar *s, ulong no)
{
I2C_sla = sla >> 1;
I2C_buf = s;
I2C_num = no;
I2C_suba = suba;
switch(sub_type)
{
// 子地址为“8+x”类型
case 0:
I2C_sla = I2C_sla | ((suba >> 8) & 0x07);
I2C_suba_num = 1;
break;
// 子地址为1个字节
case 1:
I2C_suba_num = 1;
break;
// 子地址为2个字节
case 2:
I2C_suba_num = 2;
break;
// 子地址为3个字节
case 3:
I2C_suba_num = 3;
break;
default: break;
}
if((no == 1) && (I2C_suba_num == 1))
I2C_state = STATE_WRITE_FINAL; // 单字节地址或8+x结构地址发送1个字节数据
else
I2C_state = STATE_WRITE_NEXT; // 多字节地址或发送多个字节数据
I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, I2C_sla, false); // 主机写操作
I2C_suba_num--;
I2CMasterDataPut(I2C1_MASTER_BASE,
(I2C_suba >> (8 * I2C_suba_num))); // 写子地址高字节
I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START);// 突发写操作启动
while(I2C_state != STATE_IDLE);
if(true == I2CMasterBusy(I2C1_MASTER_BASE))
return (false);
else
return (true);
}
/*
*********************************************************************************************************
** 函数名称:ISendStrExt()
** 函数功能:向无子地址器件发送多字节数据。
** 入口参数:sla 器件地址
** s 要发送的数据
** no 发送的字节个数
** 出口参数:返回值为false时表示操作出错,为true时表示操作正确。
** 说明: 发送数据字节至少2个字节
*********************************************************************************************************
*/
int ISendStrExt(uchar sla, uchar *s, uchar no)
{
I2C_sla = sla >> 1;
I2C_buf = s;
I2C_num = no;
if (no > 1) // 发送的字节参数过滤
{
if(no == 2)
I2C_state = STATE_WRITE_FINAL;
else
I2C_state = STATE_WRITE_NEXT;
I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, I2C_sla, false); // 主机写操作
I2CMasterDataPut(I2C1_MASTER_BASE, *I2C_buf++);
I2C_num--;
I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START);// 突发写操作启动
while(I2C_state != STATE_IDLE);
if(true == I2CMasterBusy(I2C1_MASTER_BASE))
return (false);
else
return (true);
}
else
return(false);
}
/*
*********************************************************************************************************
** 函数名称:IRcvByte()
** 函数功能:向无子地址器件读取1字节数据。
** 入口参数:sla 器件地址
** c 接收数据的变量指针
** 出口参数:返回值为false时表示操作出错,为true时表示操作正确。
** 说明: 使用前要初始化好I2C引脚功能和I2C中断,并已使能I2C主模式
*********************************************************************************************************
*/
int IRcvByte(uchar sla, uchar *c)
{
I2C_sla = sla >> 1;
I2C_buf = c;
I2C_state = STATE_READ_WAIT;
I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, I2C_sla, true); // 主机读操作
I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);// 启动单次读取
while(I2C_state != STATE_IDLE);
if(true == I2CMasterBusy(I2C1_MASTER_BASE))
return (false);
else
return (true);
}
/*
*********************************************************************************************************
** 函数名称 :IRcvStr()
** 函数功能 :向有子地址器件读取N字节数据
** 入口参数 : sla 器件从地址
** suba_type 子地址结构 0-8+X结构 1-单字节地址 2-双字节地址 3-三字节地址
** suba 器件内部物理地址
** *s 将要读取的数据的指针
** no 将要读取的数据的个数
** 出口参数 : TRUE 操作成功
** FALSE 操作失败
*********************************************************************************************************
*/
int IRcvStr(uchar sla, ulong suba, uchar sub_type, uchar *s, uchar no)
{
I2C_sla = sla >> 1;
I2C_buf = s;
I2C_num = no;
I2C_suba = suba;
I2C_opt = 1;
switch(sub_type)
{
// 子地址为“8+x”类型
case 0:
I2C_sla = I2C_sla | ((suba >> 8) & 0x07);
I2C_suba_num = 1;
break;
// 子地址为1个字节
case 1:
I2C_suba_num = 1;
break;
// 子地址为2个字节
case 2:
I2C_suba_num = 2;
break;
// 子地址为3个字节
case 3:
I2C_suba_num = 3;
break;
default: break;
}
if(I2C_suba_num == 1)
{
if(I2C_num == 1)
I2C_state = STATE_READ_ONE;
else
I2C_state = STATE_READ_FIRST;
}
else
I2C_state = STATE_WRITE_NEXT;
I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, I2C_sla, false); // 主机写操作
I2C_suba_num--;
I2CMasterDataPut(I2C1_MASTER_BASE,
(I2C_suba >> (8 * I2C_suba_num))); // 写子地址高字节
I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START);// 突发写操作启动
while(I2C_state != STATE_IDLE);
if(true == I2CMasterBusy(I2C1_MASTER_BASE))
return (false);
else
return (true);
}
/*
此帖出自
小平头技术问答
你怎么解决的,告诉我啊。如果我当时学了,我一定告诉你
一周热门 更多>