⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.c

📁 WINCE5.0下的I2C总线的驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************Copyright (c)**************************************************
**                               gec electronics Co.,LTD.
**                                     
**                                
**
**--------------File Info-------------------------------------------------------------------------------
** File Name: 				I2C.c
** Last modified Date: 		2007-10-25
** Last Version:			V1.0		
** Description: 			S3C2410 I2C主机 驱动
**                          
**------------------------------------------------------------------------------------------------------
** Created By: 				sam 黄利森
** Created date: 			2007-10-25
** Version: 				V1.0
** Descriptions:			The original version
**
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Description:
**
********************************************************************************************************/

#include <windows.h>
#include <types.h>
#include <excpt.h>
#include <tchar.h>
#include <cardserv.h>
#include <cardapi.h>
#include <tuple.h>
#include <devload.h>
#include <diskio.h>
#include <nkintr.h>
#include <windev.h>
#include <Pkfuncs.h>

#include "s2410.h"
#include "I2C.h"

#define PRIVATE			static
#define PUBLIC
#define  S3C2410X_IOPORT_REG              IOPreg
#define    S3C2410X_BASE_REG_PA_IOPORT               IOP_BASE
#define    S3C2410X_IICBUS_REG   IICreg
#define    S3C2410X_BASE_REG_PA_IICBUS                  IIS_BASE

/* 中断事件 */
PRIVATE HANDLE gI2CIntrEvent;

/* 是否退出中断服务线程 */
PRIVATE UINT32 g_bKillIST = FALSE;

/* 读I2C事件*/
PRIVATE HANDLE gI2CEvent;

/* 中断处理线程 */
PRIVATE HANDLE gI2CIntrThread;


/* I2C 的物理中断号及逻辑中断号 */
UINT32 g_I2CIrq = INTSRC_IIC;

UINT32 g_I2CSysIntr = SYSINTR_UNDEFINED;


/* GPIO 寄存器对应的虚拟地址 */
PRIVATE volatile IOPreg * v_pIOPregs;
PRIVATE volatile IICreg * v_pIICPregs;


// I2C总线设置宏定义: 使能 ACK 位, 使能发送/接收中断, IICCLK = PCLK/512 = 132161 
#define	IICCON_DEFAULT			((1 << 7) | (1 << 6) | (1 << 5) | (0 << 0))	

#define	IICCON_DACK(IICCON)		IICCON = IICCON & (~(1 << 4)) | (1 << 7);  	/* 使能 ACK 位 */
#define IICCON_DNACK(IICCON)	IICCON &= ~((1 << 4) | (1 << 7));			/* 禁止 ACK 位 */


#define	IICCON_CLEAR_PENDING(IICCON)	IICCON &= ~(1 << 4);  				/* 使能 ACK 位 */

/* */
#define I2C_READ	0x01
#define I2C_WRITE   0x00

/* 定义 I2C 总线的各种状态, 中断服务线程根据该状态运行 */
#define I2C_STATUS_SETADDR	0x01				/* 设置地址状态 */
#define I2C_STATUS_RECEIVE	0x02				/* 接收状态 */
#define I2C_STATUS_SEND		0x03				/* 发送状态 */


#define I2C_ERROR_NO_ERR	0x0		
#define I2C_ERROR_SETADDR   0x1
#define I2C_ERROR_RECEIVE   0x2
#define I2C_ERROR_SEND      0x3

#define I2C_RW_TIMEOUT		2000


PRIVATE BYTE volatile I2cStatus;
PRIVATE BYTE volatile I2cCurSla;				/* I2C从机,当前地址	*/
PRIVATE BYTE volatile I2cSla = 0xA0;			/* I2C从机地址 */
PRIVATE BYTE IICError = 0;

PRIVATE DWORD g_OpenCount = 0;

/*******************************************************************************************
函数名称: I2C_InitHareware
描    述: 初始化I2C主控器寄存器
输入参数: 无	
输出参数: 无
返    回: 无
********************************************************************************************/
PRIVATE void I2C_InitHareware(void)
{
	// 设置相关引脚为I2C引脚
	v_pIOPregs->rGPECON = (v_pIOPregs->rGPECON & 0x0FFFFFFF) | 0xA0000000;   
	
	// 禁止内部上拉电阻       
	v_pIOPregs->rGPEUP = v_pIOPregs->rGPEUP | 0xC000;					

	// 设置I2C控制寄存器 (使能ACK位时才能接收从机的应答位)
	v_pIICPregs->rIICCON = IICCON_DEFAULT;
     
    // 设置I2C为主机模式
    v_pIICPregs->rIICSTAT = (3 << 6) | (1 << 4);
    
    // 从机地址 (作主机时没有用)
    v_pIICPregs->rIICADD = 0x10;
}

/*******************************************************************************************
函数名称: I2C_ConfigPinDefault
描    述: 配置I2C引脚恢复为输入引脚
输入参数: 无	
输出参数: 无
返    回: 无
********************************************************************************************/
PRIVATE VOID I2C_ConfigPinDefault(VOID)
{
	// Set GPE14, GPE15 is Input
	v_pIOPregs->rGPFCON  &= ~((0x3 << 28) + (0x3 << 30));
}


/*******************************************************************************************
函数名称: I2C_InitializeAddresses
描    述: 取得I2C主控器相关寄存器的虚拟地址
输入参数: 无	
输出参数: 无
返    回: > 0 分配到的虚拟地址;  FALSE: 失败  
********************************************************************************************/
PRIVATE BOOL I2C_InitializeAddresses(void)
{
	BOOL	RetValue = TRUE;

	RETAILMSG(1, (TEXT(">>> IIC_initalization address..set..\r\n")));
     v_pIOPregs = (IOPreg *)IOP_BASE;

    
      v_pIICPregs= (IICreg *)IIC_BASE;
	//	IO Register Allocation
	/*
	v_pIOPregs = (volatile S3C2410X_IOPORT_REG *)VirtualAlloc(0, sizeof(S3C2410X_IOPORT_REG), MEM_RESERVE, PAGE_NOACCESS);
	if (v_pIOPregs == NULL) 
	{
		ERRORMSG(1,(TEXT("For IOPregs : VirtualAlloc failed!\r\n")));
		RetValue = FALSE;
	}
	else 
	{
		if (!VirtualCopy((PVOID)v_pIOPregs, (PVOID)(S3C2410X_BASE_REG_PA_IOPORT), sizeof(S3C2410X_IOPORT_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE)) 
		{
			ERRORMSG(1,(TEXT("For IOPregs: VirtualCopy failed!\r\n")));
			RetValue = FALSE;
		}
	}
	
	if (!RetValue) 
	{
		RETAILMSG (1, (TEXT("::: I2C_InitializeAddresses - Fail!!\r\n") ));

		if (v_pIOPregs) 
			VirtualFree((PVOID) v_pIOPregs, 0, MEM_RELEASE);

		v_pIOPregs = NULL;

		RetValue = FALSE;
		return RetValue;
	}

	//	IIC Register Allocation
	v_pIICPregs = (volatile S3C2410X_IICBUS_REG *)VirtualAlloc(0, sizeof(S3C2410X_IICBUS_REG), MEM_RESERVE, PAGE_NOACCESS);
	if (v_pIICPregs == NULL) 
	{
		ERRORMSG(1,(TEXT("For IICPregs : VirtualAlloc failed!\r\n")));
		RetValue = FALSE;
	}
	else 
	{
		if (!VirtualCopy((PVOID)v_pIICPregs, (PVOID)(S3C2410X_BASE_REG_PA_IICBUS), sizeof(S3C2410X_IICBUS_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE)) 
		{
			ERRORMSG(1,(TEXT("For IICPregs: VirtualCopy failed!\r\n")));
			RetValue = FALSE;
		}
	}
	
	if (!RetValue) 
	{
		RETAILMSG (1, (TEXT("::: I2C_InitializeAddresses - Fail!!\r\n") ));

		if (v_pIICPregs) 
			VirtualFree((PVOID) v_pIICPregs, 0, MEM_RELEASE);

		v_pIICPregs = NULL;
	}
	*/
 RETAILMSG(1,(TEXT("return(RetValue);\r\n")));
	return(RetValue);

}


#define DEFAULT_S3C2410X_PCLK (203000000 / 4)

/*******************************************************************************************
函数名称: I2C_GetSpeed
描    述: 取得 I2C 的传输速度
输入参数: 无	
输出参数: 无
返    回: I2C 总线的传输速度, 单位为 Hz  
********************************************************************************************/
PRIVATE DWORD I2C_GetSpeed(void)
{
	PROCESSOR_INFO procInfo;
	DWORD dwBytesReturned;
	DWORD pclk, i2cspeed;
	
    /* get the information of the device */
    if (!KernelIoControl(IOCTL_PROCESSOR_INFORMATION, NULL, 0, &procInfo, sizeof(PROCESSOR_INFO), &dwBytesReturned))
    {
        pclk = DEFAULT_S3C2410X_PCLK;
        RETAILMSG(TRUE, (TEXT("WARNING: I2C_GetSpeed:: failed to obtain processor frequency - using default value (%d).\r\n"), pclk)); 
    }
    else
    {
        pclk = procInfo.dwClockSpeed;
    }
    
    /* calculate the clock of IIC transmit speed */
    i2cspeed = pclk / 512 / ((v_pIICPregs->rIICCON & 0x0F) + 1);

    return i2cspeed;
}


/*******************************************************************************************
函数名称: StartI2C
描    述: 启动总线,发送从机地址,并发送从机地址
输入参数: BYTE sla: 从机地址	
输出参数: 无
返    回: 无
********************************************************************************************/
void  StartI2C(BYTE sla)
{	
	v_pIICPregs->rIICDS = sla;									// 设置从机地址				
	
	if(sla & 0x01)
	{	
	    v_pIICPregs->rIICSTAT = (2 << 6) | (1 << 5) | (1 << 4);	// 主接收模式,发送使能,启动总线
		IICCON_DACK(v_pIICPregs->rIICCON);						// 若是重启总线, 则需要有此操作
    }
    else
    {	
        v_pIICPregs->rIICSTAT = (3 << 6) | (1 << 5) | (1 << 4);	// 主发送模式,发送使能,启动总线 
    }
   
}		    
	

/*******************************************************************************************
函数名称: StopI2C
描    述: 结束总线
输入参数: BYTE send: I2C当前模模式.主发送模式时为1,否则为0(主接收模式)
输出参数: 无
返    回: 无
********************************************************************************************/
void  StopI2C(BYTE send)
{	
 	if(send)
	{	
	    v_pIICPregs->rIICSTAT = (3 << 6) | (0 << 5) | (1 << 4);   // 发送结束信号
	}
	else
	{	
	    v_pIICPregs->rIICSTAT = (2 << 6) | (0 << 5) | (1 << 4);   // 发送结束信号
	}

	IICCON_DACK(v_pIICPregs->rIICCON);

	Sleep(1);		// 等待结束信号产生完毕
}


/*******************************************************************************************
函数名称: SendByteI2C
描    述: 发送一个字节的数据
输入参数: BYTE data: 要发送的字节
输出参数: 无
返    回: 无
********************************************************************************************/
void IIC_SendByte(BYTE data)
{
	// 将数据写入I2C数据寄存器
	v_pIICPregs->rIICDS = data;	
	
	// 清除中断标志,允许发送数据操作							
	IICCON_DACK(v_pIICPregs->rIICCON);					
}


/*******************************************************************************************
函数名称: IIC_StartRecByteA
描    述: 开始接收 IIC 总线上的数据, 接收该数据时需要发送一个应答
输入参数: 无
输出参数: 无
返    回: 无
********************************************************************************************/
void IIC_StartRecByteA(void)
{
	IICCON_DACK(v_pIICPregs->rIICCON);
}


/*******************************************************************************************
函数名称: IIC_StartRecByteNA
描    述: 开始接收 IIC 总线上的数据, 接收该数据时,不需要发送一个应答
输入参数: 无	
输出参数: 无
返    回: 无 
********************************************************************************************/
void IIC_StartRecByteNA(void)
{
	IICCON_DNACK(v_pIICPregs->rIICCON);
}


/*******************************************************************************************
函数名称: IIC_RecByte
描    述: 从 IIC 总线上接收一个字节
输入参数: 无	
输出参数: 无
返    回: 无 
********************************************************************************************/
BYTE IIC_RecByte(void)
{
	return (v_pIICPregs->rIICDS);
}


/*******************************************************************************************
函数名称: I2C_IntrThread
描	  述: I2C 中断服务线程
输入参数: PVOID pArg:  	线程输入参数	
输出参数: 无
返    回: 1 或 0
********************************************************************************************/
DWORD I2C_IntrThread(PVOID pArg)
{
	DWORD ret;

	// 创建I2C中断中断事件
	gI2CIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

	// 初始化 I2C 中断: 注册中断事件, 允许 I2C 中断
	if (!(InterruptInitialize(g_I2CSysIntr, gI2CIntrEvent, 0, 0))) 
	{
		CloseHandle(gI2CIntrEvent);
		RETAILMSG(1, (TEXT("ERROR: I2C Bus: Interrupt initialize failed.\r\n")));
		return 0;
	}

	// IIC 中断线程开始运行
	while (1) 
	{
		ret = WaitForSingleObject(gI2CIntrEvent, INFINITE);
		if ((ret != WAIT_OBJECT_0) || (g_bKillIST == TRUE))					/* 驱动卸载或错误发生 */
		{		
			CloseHandle(gI2CIntrEvent);
			RETAILMSG(1, (TEXT("INFO: I2C Bus Driver DeInit or Error Occur. \r\n")));
			return 0;														/* 线程退出 */
		}

		switch(I2cStatus)
		{	
    		// Start IIC Status 
    		case I2C_STATUS_SETADDR:						
				if((v_pIICPregs->rIICSTAT & 0x09) == 0)						// 发送地址成功
				{
					SetEvent(gI2CEvent);		
					IICError = I2C_ERROR_NO_ERR;
				}
				else
				{
					if (I2cCurSla & I2C_READ)
						v_pIICPregs->rIICSTAT = (2 << 6) | (0<<5) | (1<<4);	// 读终止
					else		
						v_pIICPregs->rIICSTAT = (3 << 6) | (0<<5) | (1<<4);	// 写终止
					
					IICCON_DACK(v_pIICPregs->rIICCON);
					Sleep(1);												// 等待结束信号产生完毕	
					
					SetEvent(gI2CEvent);
					IICError = I2C_ERROR_SETADDR;
				}
			break;
    
    		// Send Bytes Status
    		case I2C_STATUS_SEND:	
    			if((v_pIICPregs->rIICSTAT & 0x09) == 0)						// 数据成功发送

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -