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

📄 iic.cpp

📁 IIC WINCE5.0 流接口驱动程序及测试
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// IIC.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include "IIC.h"
#include "drv.h"
#include <Pkfuncs.h>
#include <nkintr.h>
#include <windev.h>
#include <Pkfuncs.h>

// I2C Registers
#define rIICCON     (pI2C->pI2CReg->IICCON)     // Control Register
#define rIICSTAT    (pI2C->pI2CReg->IICSTAT)    // Status Register
#define rIICADD     (pI2C->pI2CReg->IICADD)     // Address Register
#define rIICDS      (pI2C->pI2CReg->IICDS)      // Data Shift Register

//#define RX_TIMEOUT  3000
//#define TX_TIMEOUT  150000

#define RX_TIMEOUT  0x7FFFFFFFL
#define TX_TIMEOUT  0x7FFFFFFFL

static DWORD I2C_IST(LPVOID Context);

DWORD gIntrIIC 		= SYSINTR_NOP;

VOID InitRegs(PI2C_CONTEXT pI2C)
{
    EnterCriticalSection(&pI2C->RegCS);

    // enable the I2C Clock (PCLK)
    pI2C->pIOPReg->GPECON &= ~(0x0F<<28);
    pI2C->pIOPReg->GPECON |= (0x0A<<28);		// GPE15:IICSDA, GPE14:IICSCL

	// setup GPIO for I2C
    pI2C->pIOPReg->GPEUP |= 0xC000;		// Pull-up-down Disable

    // config controller
    rIICCON  = RESUME_ACK;	// =0xEF clear interrupt pending bit, ACK enabled, div=512, IICCLK=PCLK/512
    rIICSTAT = M_IDLE;		// =0x00 Disable Rx/Tx
    pI2C->State = IDLE;
    pI2C->DataCount = INVALID_DATA_COUNT;	// =-1

    LeaveCriticalSection(&pI2C->RegCS);
}


DWORD HW_Init(PI2C_CONTEXT pI2C)
{
    DWORD dwErr = ERROR_SUCCESS;
	UINT32 Irq;
    
    if ( !pI2C ) 
        return ERROR_INVALID_PARAMETER;
    
    DEBUGMSG(ZONE_TRACE,(TEXT("+I2C_Init: %u, 0x%x, 0x%x \r\n"),pI2C->Mode, pI2C->SlaveAddress));
    InitializeCriticalSection(&pI2C->RegCS);
    
    pI2C->Status    = 0;
    pI2C->pData      = NULL;
    pI2C->DataCount = INVALID_DATA_COUNT;
    pI2C->Flags.DropRxAddr = FALSE;

    pI2C->hProc = (HANDLE)GetCurrentProcessId();
    InitRegs(pI2C);

    // create I/O Done Event
    if ( (pI2C->DoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL)
    {
        dwErr = GetLastError();
        DEBUGMSG(ZONE_ERR,(TEXT("I2C_Init ERROR: Unable to create Done event: %u \r\n"), dwErr));
        goto _init_error;
    }
    // setup Operating Mode
    if ( pI2C->Mode == INTERRUPT ) 
	{
        // create IST event
        if ( (pI2C->ISTEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL)
        {
            dwErr = GetLastError();
            DEBUGMSG(ZONE_ERR,(TEXT("I2C_Init ERROR: Unable to create IST event: %u \r\n"), dwErr));
            goto _init_error;
        }

		// Obtain sysintr values from the OAL for the camera interrupt.
		Irq = IRQ_IIC;
		if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &Irq, sizeof(UINT32), &gIntrIIC, sizeof(UINT32), NULL))
		{
			DEBUGMSG(ZONE_ERR, (TEXT("ERROR: Failed to request the IIC sysintr.\r\n")));
			gIntrIIC = SYSINTR_UNDEFINED;
			return(FALSE);
		}
		// initialize the interrupt
		if( !InterruptInitialize(gIntrIIC, pI2C->ISTEvent, NULL, 0) ) 
		{
			dwErr = GetLastError();
			DEBUGMSG(ZONE_ERR,(TEXT("I2C_Init ERROR: Unable to initialize interrupt: %u\r\n"), dwErr));
			goto _init_error;
		}
		InterruptDone(gIntrIIC);
		
		// create the IST
		if ( (pI2C->IST = CreateThread(NULL, 0, I2C_IST, (LPVOID)pI2C, 0, NULL)) == NULL)
		{
			dwErr = GetLastError();
			DEBUGMSG(ZONE_ERR,(TEXT("I2C_Init ERROR: Unable to create IST: %u\r\n"), dwErr));
			goto _init_error;
		}
		
		// TODO: registry override
		if ( !CeSetThreadPriority(pI2C->IST, THREAD_PRIORITY_ABOVE_NORMAL)) 
		{
			dwErr = GetLastError();
			DEBUGMSG(ZONE_ERR, (TEXT("I2C_Init ERROR: CeSetThreadPriority ERROR:%d\n"), dwErr));
			goto _init_error;
		}
    }
    DEBUGMSG(ZONE_TRACE,(TEXT("-I2C_Init \r\n")));
    return dwErr;

_init_error:
    HW_Deinit(pI2C);
    return dwErr;
}

DWORD HW_Deinit(PI2C_CONTEXT pI2C)
{
    if ( !pI2C )
        return ERROR_INVALID_PARAMETER;
        
    DEBUGMSG(ZONE_TRACE,(TEXT("I2C_Deinit: %u \r\n"), pI2C->State));
    if ( pI2C->State == IDLE ) 
	{
        pI2C->State = OFF; // also signals the IST to terminate
        rIICSTAT = M_IDLE;

        if (pI2C->DoneEvent && CloseHandle(pI2C->DoneEvent))
            pI2C->DoneEvent = NULL;
        if (pI2C->Mode == INTERRUPT) 
		{
            InterruptDisable(gIntrIIC);
            if (pI2C->ISTEvent && CloseHandle(pI2C->ISTEvent))
                pI2C->ISTEvent = NULL;
            if (pI2C->IST && CloseHandle(pI2C->IST))
                pI2C->IST = NULL;
        }
        pI2C->Mode = POLLING;
        pI2C->pData  = NULL;
        pI2C->DataCount = INVALID_DATA_COUNT;
        pI2C->Flags.DropRxAddr = FALSE;
        DeleteCriticalSection(&pI2C->RegCS);
        return ERROR_SUCCESS;
    }
	else 
	{
        DEBUGMSG(ZONE_ERR,(TEXT("I2C_Deinit ERROR: %u \r\n"), pI2C->State));
        return ERROR_BUSY;
    }
}


DWORD HW_Open(PI2C_CONTEXT pI2C)
{
    return ERROR_SUCCESS;
}


DWORD HW_Close(PI2C_CONTEXT pI2C)
{
    return ERROR_SUCCESS;
}

__inline DWORD SyncIst(PI2C_CONTEXT pI2C,DWORD dwTimeout)
{
    if (pI2C->Mode == INTERRUPT)	//中断方式处理
	{

        DEBUGMSG(ZONE_READ|ZONE_WRITE,(TEXT("SyncIst...\r\n")));
        if(WaitForSingleObject(pI2C->DoneEvent, dwTimeout != WAIT_OBJECT_0 ))
		{
            pI2C->State = IO_ABANDONED;
            if (pI2C->LastError == ERROR_SUCCESS)
                pI2C->LastError = ERROR_TIMEOUT;
            DEBUGMSG(ZONE_WRN|ZONE_READ|ZONE_WRITE,(TEXT("SyncIst: IO_ABANDONED\r\n")));
        }
        DEBUGMSG(ZONE_READ|ZONE_WRITE,(TEXT("...SyncIst: 0x%X\r\n"), pI2C->LastError));
        return pI2C->LastError;
    } 
	else	//查询方式的处理
	{
        while(pI2C->DataCount != INVALID_DATA_COUNT)
		{
            // poll INT pending bit
            if (pI2C->Mode == POLLING && (rIICCON & 0x10))
                I2C_IST(pI2C);
        }
    }
    return ERROR_SUCCESS;
}
//-----------------------------------------------------------------------------------------------------
//RANDOM READ: A random read requires a “dummy” byte write sequence to load in the data
//word address. Once the device address word and data word address are clocked in and
//acknowledged by the EEPROM, the microcontroller must generate another start condition.
//The microcontroller now initiates a current address read by sending a device address with the
//read/write select bit high. The EEPROM acknowledges the device address and serially clocks
//out the data word. 
//-----------------------------------------------------------------------------------------------------
DWORD HW_Read(PI2C_CONTEXT pI2C,
    DWORD  SlaveAddr,   // slave address
    UCHAR  WordAddr,    // starting word address
    PUCHAR pData,       // pdata
    DWORD  Count        // bytes to read
    )
{
    DWORD  dwErr;

    if (!VALID_CONTEXT(pI2C))
        return ERROR_INVALID_PARAMETER;
        
    DEBUGMSG(ZONE_READ|ZONE_TRACE,(TEXT("+I2C_Read[%u]: 0x%X, 0x%X, 0x%X, %u\r\n"), 
        pI2C->State, SlaveAddr, WordAddr, pData, Count));
    
    if ( !pData || !Count || IsBadWritePtr(pData, Count) ) 
	{
        DEBUGMSG(ZONE_ERR,(TEXT("I2C_Read ERROR: invalid parameter \r\n")));
        return ERROR_INVALID_PARAMETER;
    }

    EnterCriticalSection(&pI2C->RegCS);
    
    if ( pI2C->State != IDLE) 
	{
        DEBUGMSG(ZONE_ERR,(TEXT("I2C_Read ERROR: i2cState: %u \r\n"), pI2C->State));
        LeaveCriticalSection(&pI2C->RegCS);
        return ERROR_BUSY;
    }

    pI2C->LastError = ERROR_SUCCESS;
    
    ResetEvent(pI2C->DoneEvent);

	rIICSTAT = M_ACTIVE;	// =0x10 Enable  Rx/Tx
    
    // pre-setup word address
    pI2C->pData = NULL;
    pI2C->State = SET_READ_ADDR;
    pI2C->WordAddr = WordAddr;
    pI2C->Flags.WordAddr = TRUE;
    pI2C->DataCount = 1;
    
    // enable the slave address drop
    pI2C->Flags.DropRxAddr = TRUE;
    
    // write slave address
    rIICDS = (UCHAR)SlaveAddr;
    rIICSTAT = MTX_START;	// =0xF0 Master Tx Start
	Sleep(20);

    // Wait for IST to write the word address
    if (WAIT_OBJECT_0 != SyncIst(pI2C, RX_TIMEOUT)) 
	{
        DEBUGMSG(ZONE_READ|ZONE_ERR,(TEXT("RX_TIMEOUT.1\r\n")));
        goto _done;
    }

    ResetEvent(pI2C->DoneEvent);
 
    // get read data
    pI2C->State = READ_DATA;
    pI2C->pData = pData;
	pI2C->DataCount = Count;
    rIICDS = (UCHAR)SlaveAddr;
    rIICSTAT = MRX_START;	//=0xB0 Master Rx Start
    rIICCON  = RESUME_ACK;  //=0xEF Clear interrupt pending bit, ACK enabled, div=512, IICCLK=PCLK/512
	Sleep(20);

    // Wait for IST to get data
    if (WAIT_OBJECT_0 != SyncIst(pI2C, RX_TIMEOUT)) 
	{
        DEBUGMSG(ZONE_READ|ZONE_ERR,(TEXT("RX_TIMEOUT.2\r\n")));
        goto _done;
    }

_done:    
    rIICSTAT  = M_IDLE;    //=0x00 Disable Rx/Tx
    rIICCON  = RESUME_ACK;  //=0xEF Clear interrupt pending bit, ACK enabled, div=512, IICCLK=PCLK/512
    pI2C->State = IDLE;
    pI2C->pData  = NULL;
    pI2C->DataCount = INVALID_DATA_COUNT;

    //如果接收到地址不是原来发送的地址则出错
    if ( !pI2C->LastError && ((SlaveAddr & ~(0x01)) != (pI2C->RxRetAddr & ~(0x01)) ) ) 
	{
        DEBUGMSG(ZONE_READ|ZONE_ERR,(TEXT("I2C_Read Invalid Return Address: 0x%X != 0x%X \r\n"), 
            pI2C->RxRetAddr, SlaveAddr ));
        pI2C->LastError = ERROR_INCORRECT_ADDRESS;
        TEST_TRAP;
    }
    
    pI2C->RxRetAddr = 0;
    dwErr = pI2C->LastError;
    LeaveCriticalSection(&pI2C->RegCS);
    DEBUGMSG(ZONE_READ|ZONE_TRACE,(TEXT("-I2C_Read:%u \r\n"), dwErr ));

    return dwErr;
}


DWORD HW_Write(
    PI2C_CONTEXT pI2C,
    DWORD  SlaveAddr,   // slave address
    UCHAR  WordAddr,    // starting slave word address
    PUCHAR pData,       // pdata
    DWORD  Count        // bytes to write
    )    
{
    DWORD dwErr;

    if ( !VALID_CONTEXT(pI2C) )
        return ERROR_INVALID_PARAMETER;
        
    DEBUGMSG(ZONE_WRITE|ZONE_TRACE,(TEXT("+I2C_Write[%u]: 0x%X, 0x%X, 0x%X, %u \r\n"), pI2C->State, SlaveAddr, WordAddr, *pData, Count));
    
    if ( !pData || !Count || IsBadReadPtr(pData, Count) ) 
	{
        DEBUGMSG(ZONE_ERR,(TEXT("I2C_Write ERROR: invalid parameter \r\n")));
        return ERROR_INVALID_PARAMETER;
    }

    EnterCriticalSection(&pI2C->RegCS);
    
    if ( pI2C->State != IDLE) 
	{
        DEBUGMSG(ZONE_ERR,(TEXT("I2C_Write ERROR: i2cState: %u \r\n"), pI2C->State));
        LeaveCriticalSection(&pI2C->RegCS);
        return ERROR_BUSY;
    }
    pI2C->LastError = ERROR_SUCCESS;
    ResetEvent(pI2C->DoneEvent);

    rIICSTAT = M_ACTIVE;

    // pre-setup write data
    pI2C->State     = WRITE_DATA;
    pI2C->DataCount = 1 + Count; // slave word address + data 
    pI2C->WordAddr  = WordAddr;
    pI2C->Flags.WordAddr = TRUE;    
    pI2C->pData      = pData;

    // write slave address
    rIICDS   = (UCHAR)SlaveAddr;
    rIICSTAT = MTX_START;
	Sleep(20);

    // IST writes the slave word address & data

⌨️ 快捷键说明

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