Mstar 平台TCA9539 移植

tca959 作为一款纯IIC控制的mcu,上电后即可通过主控IC的I2C 来控制mcu 的管脚,设置这些pin的input / output 模式,以及获取output的高低,另外也可以获取input的状态。通常主控IC 的IO 口不够用时用来扩展IO 口。

TCA9539 I2C地址的确定

查看TCA9539 的datasheet 文档,地址部分,总共有7位,其中Slave address 的bit 位固定,另外最后两个bits 位根据原理图中地址pin 的高低来判断
在这里插入图片描述
查看原理图发现,tca9539 的I2C地址脚IIC_SEL0,IIC_SEL1 接的是下拉电阻,两个PIN都是低电平,故地址应该取0x74.
在这里插入图片描述
结合原理图和datasheet 得到一个7bit 的I2C地址后,需要左移(x2), 末尾补零生成一个8bit 的地址给软件使用。计算后改地址为 0xE8.

IIC地址的配置

找到对应板型的board.h 文件,配置tca9539 IIC 信息。包含在那一组IIC及设备的IIC 地址。其中TCA9539_I2C_ID 只是一个枚举值方便应用调用。
在这里插入图片描述

管脚功能配置

功能配置主要是配置对应pin的输入,输出模式及输出模式的高低状态
在这里插入图片描述根据datasheet 的说明,寄存器0x06 , 0x07 分别配置port 0~ 7 ,
port 10~17对应bit位为1 则为输入 为0 则为输出。 而寄存器0x04, 0x05 分别是设置port 0 ~ 7,port 10 ~ 17 极性的。
例如:设置P3,P4,P5,P7,P10,P11 需要设置为output,其它为input模式

#define  TCA9539_MASK_P0  (1 << 0)
#define  TCA9539_MASK_P1  (1 << 1)
#define  TCA9539_MASK_P2  (1 << 2)
#define  TCA9539_MASK_P3  (1 << 3)
#define  TCA9539_MASK_P4  (1 << 4)
#define  TCA9539_MASK_P5  (1 << 5)
#define  TCA9539_MASK_P6  (1 << 6)
#define  TCA9539_MASK_P7  (1 << 7)

// P3,P4,P5,P7 set to output  0x47
static MAPI_U8 uTca9539_Ports_L_Mode = 0xFF  & \
						(~(TCA9539_MASK_P3)) & \
						(~(TCA9539_MASK_P4)) & \
						(~(TCA9539_MASK_P5)) & \
						(~(TCA9539_MASK_P7));

// P10,P11 set to output  0xFC
static MAPI_U8 uTca9539_Ports_H_Mode = (0xFF  & (~(TCA9539_MASK_P0)) & (~(TCA9539_MASK_P1)));

定义寄存器0x06 需要初始化的值0x47 (0100 0111), 二进制从右到左 bit0~bit7 对应port0 ~ port7;寄存器 0x07,需要初始化的值0xFC (1111 1100) ,二进制从右到左bit0 ~ bit7 对应port10 ~ port17.

	MAPI_U8  uCfgLowPorts    = 0x06;
	MAPI_U8  uCfgHighPorts   = 0x07;
	iptr = mapi_i2c::GetI2C_Dev(TCA9539_I2C_ID);
	if(iptr == NULL)
    {
        printf("[%s][%d] Invalid I2c mcu addr .\n",__FUNCTION__,__LINE__);
        return MAPI_FALSE;
    }

    // config the port mode <input or output>
	if(MAPI_FALSE == iptr->WriteBytes(1,&uCfgLowPorts,1,&uTca9539_Ports_L_Mode))
	{
		printf("[%s][%d] wirte the port 0~7 failed.\n",__FUNCTION__,__LINE__);
		return MAPI_FALSE;
	}
	if(MAPI_FALSE == iptr->WriteBytes(1,&uCfgHighPorts,1,&uTca9539_Ports_H_Mode))
	{
		printf("[%s][%d] wirte the port 10~17 failed.\n",__FUNCTION__,__LINE__);
		return MAPI_FALSE;
	}

这样就完成input , output 模式的配置。

读取输出管脚状态

在这里插入图片描述
通过datasheet得到,寄存器0x00,0x01 是用来获取port 的状态。

	MAPI_U8  uLowRegAddr  = 0x00;
	MAPI_U8  uHighRegAddr = 0x01;

	MAPI_U8  uOldData     = 0x00;
	MAPI_U8  uData        = 0x00;
	MAPI_U8  uMask        = 0x00;

	MAPI_U8  uRRegAddr     = (port > TCA9539_P7) ? uHighRegAddr : uLowRegAddr;

	iptr = mapi_i2c::GetI2C_Dev(TCA9539_I2C_ID);
	if(iptr == NULL)
    {
        printf("[%s][%d] Invalid I2c mcu addr .\n",__FUNCTION__,__LINE__);
        return MAPI_FALSE;
    }

    // 获取port 口该组的所有状态
    if(MAPI_FALSE == iptr->ReadBytes(1, &uRRegAddr, 1, &uOldData))
    {
    	printf("[%s][%d] get the port status failed .\n",__FUNCTION__,__LINE__);
    	return MAPI_FALSE;
    }
    // 计算返回对应port 口的状态
    return    (uData >> (port % 10) | 0x01);

设置输出管脚状态

在这里插入图片描述
通过datasheet可知,输出管脚的状态,通过寄存器0x2,0x03 来设置。

MAPI_BOOL device_mcu_tca9539::Set_port_Output(MAPI_U8 port, MAPI_BOOL bOutState)
{
	mapi_i2c *iptr      = NULL;
	// for output status
	MAPI_U8  uLowRegAddr  = 0x00;
	MAPI_U8  uHighRegAddr = 0x01;

	MAPI_U8  uLowWReg     = 0x02;
	MAPI_U8  uHighWReg    = 0x03;

	MAPI_U8  uOldData     = 0x00;
	MAPI_U8  uData        = 0x00;
	MAPI_U8  uMask        = 0x00;

	MAPI_U8  uRRegAddr     = (port > TCA9539_P7) ? uHighRegAddr : uLowRegAddr;
	MAPI_U8  uWRegAddr     = (port > TCA9539_P7) ? uHighWReg : uLowWReg;

	iptr = mapi_i2c::GetI2C_Dev(TCA9539_I2C_ID);
	if(iptr == NULL)
    {
        printf("[%s][%d] Invalid I2c mcu addr .\n",__FUNCTION__,__LINE__);
        return MAPI_FALSE;
    }

    // 通过寄存器0x00(port0 ~ port7)/0x01(port10 ~ port17)读取当前port口的状态
    if(MAPI_FALSE == iptr->ReadBytes(1, &uRRegAddr, 1, &uOldData))
    {
    	printf("[%s][%d] get the port status failed .\n",__FUNCTION__,__LINE__);
    	return MAPI_FALSE;
    }

	// 计算,并设置port 的新状态,其它port 状态不变
    uMask = 1 << (port % 10);
    // set the new status
    if(bOutState){
		uData = (uMask | uOldData);  // set H
    } else {
    	uData = (~uMask) & uOldData;  // set L
    }

	//  对寄存器0x02(port0 ~ port7)/0x03(port10 ~ port17)写输出的高低状态
    if(MAPI_FALSE == iptr->WriteBytes(1, &uWRegAddr, 1, &uData))
    {
		printf("[%s][%d] set the new status failed .\n",__FUNCTION__,__LINE__);
    	return MAPI_FALSE;
    }

	printf("[%s][%d] set the P%02d to  %d.\n",__FUNCTION__,__LINE__,port,bOutState);

	return MAPI_TRUE;
}

头文件源码

#ifndef __DEVIDE_MCU_TCA9539_H__
#define __DEVIDE_MCU_TCA9539_H__

/*@ <Include> @*/
#include "mapi_mcu.h"
#include "MsTypes.h"
#include "MTypes.h"
/*@ </Include> @*/

#define  PORT_INPUT     (1)
#define  PORT_OUTPUT    (0)

#define  OUTPUT_H       (1)
#define  OUTPUT_L       (0)

#define  TCA9539_P0     (0)
#define  TCA9539_P1     (1)
#define  TCA9539_P2     (2)
#define  TCA9539_P3     (3)
#define  TCA9539_P4     (4)
#define  TCA9539_P5     (5)
#define  TCA9539_P6     (6)
#define  TCA9539_P7     (7)

#define  TCA9539_P10     (10)
#define  TCA9539_P11     (11)
#define  TCA9539_P12     (12)
#define  TCA9539_P13     (13)
#define  TCA9539_P14     (14)
#define  TCA9539_P15     (16)
#define  TCA9539_P16     (15)
#define  TCA9539_P17     (17)

#define  TCA9539_MASK_P0  (1 << 0)
#define  TCA9539_MASK_P1  (1 << 1)
#define  TCA9539_MASK_P2  (1 << 2)
#define  TCA9539_MASK_P3  (1 << 3)
#define  TCA9539_MASK_P4  (1 << 4)
#define  TCA9539_MASK_P5  (1 << 5)
#define  TCA9539_MASK_P6  (1 << 6)
#define  TCA9539_MASK_P7  (1 << 7)

class device_mcu_tca9539 : public mapi_mcu
{
public:
    DLL_PUBLIC device_mcu_tca9539(void);
    DLL_PUBLIC ~device_mcu_tca9539(void);
    DLL_PUBLIC MAPI_BOOL Init(void);
    DLL_PUBLIC MAPI_BOOL Finalize(void);
	DLL_PUBLIC MAPI_BOOL Reset(void);
	DLL_PUBLIC MAPI_BOOL Set_port_mode(MAPI_U8 port, MAPI_BOOL bInput);
	DLL_PUBLIC MAPI_BOOL Get_port_mode(MAPI_U8 port, MAPI_U8 *uMode);
	DLL_PUBLIC MAPI_BOOL Set_port_Output(MAPI_U8 port, MAPI_BOOL bOutState);
	DLL_PUBLIC MAPI_BOOL Get_port_State(MAPI_U8 port, MAPI_BOOL *bMode, MAPI_BOOL *bState);
    DLL_PUBLIC MAPI_BOOL Tca9539Setup(void);
};
#endif // __DEVIDE_LED_DEFAULT_H__

源文件

// Alex.Ke

#include <sys/stat.h>
#include <unistd.h>
#include <cstring>

#include "MsCommon.h"
#include "MsOS.h"
#include <dirent.h>

// #include "mapi_gpio.h"
#include "mapi_i2c.h"
#include "mapi_i2c_devTable.h"
#include "mapi_gpio_devTable.h"
#include "device_mcu_tca9539.h"
#include "MSrv_Control_common.h"

// P3,P4,P5,P7 set to output  0x47
static MAPI_U8 uTca9539_Ports_L_Mode = 0xFF  & \
						(~(TCA9539_MASK_P3)) & \
						(~(TCA9539_MASK_P4)) & \
						(~(TCA9539_MASK_P5)) & \
						(~(TCA9539_MASK_P7));


// P10,P11 set to output  0xFC
static MAPI_U8 uTca9539_Ports_H_Mode = (0xFF  & (~(TCA9539_MASK_P0)) & (~(TCA9539_MASK_P1)));

device_mcu_tca9539::device_mcu_tca9539(void)
{   
}

device_mcu_tca9539::~device_mcu_tca9539(void)
{
}

MAPI_BOOL device_mcu_tca9539::Init(void)
{
    return Reset();
}

MAPI_BOOL device_mcu_tca9539::Finalize(void)
{
	BOOL bRet = FALSE;
    printf("Finalize TCA9539\n");

    bRet = MSrv_Control_common::SetGpioDeviceStatus(MCU_RESET,FALSE);

    return (bRet) ? MAPI_TRUE : MAPI_FALSE;
}

MAPI_BOOL device_mcu_tca9539::Reset(void)
{
	BOOL bRet1 = FALSE;
	BOOL bRet2 = FALSE;
    printf("Reset TCA9539\n");

    bRet1 = MSrv_Control_common::SetGpioDeviceStatus(MCU_RESET,FALSE);
    usleep(100*1000); // 100ms
    bRet2 = MSrv_Control_common::SetGpioDeviceStatus(MCU_RESET,TRUE);

    Tca9539Setup();

    return (bRet1 && bRet2) ? MAPI_TRUE : MAPI_FALSE;
}

MAPI_BOOL device_mcu_tca9539::doHandleOps(void)
{
	MAPI_BOOL    bMode      = FALSE;
	MAPI_BOOL    bPlugState = TRUE;   // plug out: ops H  ; plug in : ops L
    MAPI_BOOL    bState     = TRUE;   // ops status. H: off; L: on
	// OPS Det
	Get_port_State(TCA9539_P6, &bMode, &bPlugState);
	// OPS power
	Get_port_State(TCA9539_P17, &bMode, &bState);
	if((!bPlugState)&&(bState)){
		// // set ops on
		// uData = 0x7F; // P3 = H ,P7 = L
		// if(MAPI_FALSE == iptr->WriteBytes(1,&uLowRegAddr,1,&uData))
		// {
		// 	printf("[%s][%d] wirte the port 10~17 failed.\n",__FUNCTION__,__LINE__);
		// 	return MAPI_FALSE;
		// }

		// usleep(100*1000);

		// uData = 0xFF; // P3 = H ,P7 = H
		// if(MAPI_FALSE == iptr->WriteBytes(1,&uLowRegAddr,1,&uData))
		// {
		// 	printf("[%s][%d] wirte the port 10~17 failed.\n",__FUNCTION__,__LINE__);
		// 	return MAPI_FALSE;
		// }
        Set_port_Output(TCA9539_P7,MAPI_FALSE);  //  to L

        usleep(100*1000);

        Set_port_Output(TCA9539_P7,MAPI_TRUE);   //  to  H 

		printf("[%s][%d] start the ops .\n",__FUNCTION__,__LINE__);

        return TRUE;
	}
	return FALSE;
}

MAPI_BOOL device_mcu_tca9539::Tca9539Setup(void)
{
	mapi_i2c *iptr        = NULL;
	MAPI_U8  uCfgLowPorts    = 0x06;
	MAPI_U8  uCfgHighPorts   = 0x07;
	// for output status
	MAPI_U8  uLowRegAddr  = 0x02;
	MAPI_U8  uHighRegAddr = 0x03;
	MAPI_U8  uData        = 0x00;

	printf("[%s][%d] Enter .\n",__FUNCTION__,__LINE__);

	iptr = mapi_i2c::GetI2C_Dev(TCA9539_I2C_ID);
	if(iptr == NULL)
    {
        printf("[%s][%d] Invalid I2c mcu addr .\n",__FUNCTION__,__LINE__);
        return MAPI_FALSE;
    }

    // config the port mode <input or output>
	if(MAPI_FALSE == iptr->WriteBytes(1,&uCfgLowPorts,1,&uTca9539_Ports_L_Mode))
	{
		printf("[%s][%d] wirte the port 0~7 failed.\n",__FUNCTION__,__LINE__);
		return MAPI_FALSE;
	}
	if(MAPI_FALSE == iptr->WriteBytes(1,&uCfgHighPorts,1,&uTca9539_Ports_H_Mode))
	{
		printf("[%s][%d] wirte the port 10~17 failed.\n",__FUNCTION__,__LINE__);
		return MAPI_FALSE;
	}

	// config: set port(output) status
	uData = 0xF7; //  P3 = L  , other bit was seted to H
	if(MAPI_FALSE == iptr->WriteBytes(1,&uLowRegAddr,1,&uData))
	{
		printf("[%s][%d] wirte the port 0~7 failed.\n",__FUNCTION__,__LINE__);
		return MAPI_FALSE;	
	}

	// set touch power
	uData = 0xFC; //  P10, P11 = L  , other bit was seted to H
	if(MAPI_FALSE == iptr->WriteBytes(1,&uHighRegAddr,1,&uData))
	{
		printf("[%s][%d] wirte the port 0~7 failed.\n",__FUNCTION__,__LINE__);
		return MAPI_FALSE;
	}

	doHandleOps();

	#if 0
	// set ops on
	uData = 0x7F; // P3 = H ,P7 = L
	if(MAPI_FALSE == iptr->WriteBytes(1,&uLowRegAddr,1,&uData))
	{
		printf("[%s][%d] wirte the port 10~17 failed.\n",__FUNCTION__,__LINE__);
		return MAPI_FALSE;
	}

	usleep(100*1000);

	uData = 0xFF; // P3 = H ,P7 = H
	if(MAPI_FALSE == iptr->WriteBytes(1,&uLowRegAddr,1,&uData))
	{
		printf("[%s][%d] wirte the port 10~17 failed.\n",__FUNCTION__,__LINE__);
		return MAPI_FALSE;
	}
	#endif

	#if 0
	// config the S_USB_SEL
	// uData = 0xFE; // P10 = L   android source
	uData = 0xFF; // P10 = H   OPS source
	if(MAPI_FALSE == iptr->WriteBytes(1,&uHighRegAddr,1,&uData))
	{
		printf("[%s][%d] wirte the port 10~17 failed.\n",__FUNCTION__,__LINE__);
		return MAPI_FALSE;
	}
	#endif
	printf("[%s][%d] setup success.\n",__FUNCTION__,__LINE__);

	return MAPI_TRUE;
}

// bInput:  TRUE --> input , FALSE  --> output
MAPI_BOOL device_mcu_tca9539::Set_port_mode(MAPI_U8 port, MAPI_BOOL bInput)
{
	printf("[%s][%d] Enter .\n",__FUNCTION__,__LINE__);
	return MAPI_TRUE;
}

// uMode:  1 --> input, 0 --> output
MAPI_BOOL device_mcu_tca9539::Get_port_mode(MAPI_U8 port, MAPI_U8 *uMode)
{
	printf("[%s][%d] Enter .\n",__FUNCTION__,__LINE__);
	return MAPI_TRUE;
}

MAPI_BOOL device_mcu_tca9539::Set_port_Output(MAPI_U8 port, MAPI_BOOL bOutState)
{
	mapi_i2c *iptr      = NULL;
	// for output status
	MAPI_U8  uLowRegAddr  = 0x00;
	MAPI_U8  uHighRegAddr = 0x01;

	MAPI_U8  uLowWReg     = 0x02;
	MAPI_U8  uHighWReg    = 0x03;

	MAPI_U8  uOldData     = 0x00;
	MAPI_U8  uData        = 0x00;
	MAPI_U8  uMask        = 0x00;

	MAPI_U8  uRRegAddr     = (port > TCA9539_P7) ? uHighRegAddr : uLowRegAddr;
	MAPI_U8  uWRegAddr     = (port > TCA9539_P7) ? uHighWReg : uLowWReg;

	iptr = mapi_i2c::GetI2C_Dev(TCA9539_I2C_ID);
	if(iptr == NULL)
    {
        printf("[%s][%d] Invalid I2c mcu addr .\n",__FUNCTION__,__LINE__);
        return MAPI_FALSE;
    }

    // get the old status 
    if(MAPI_FALSE == iptr->ReadBytes(1, &uRRegAddr, 1, &uOldData))
    {
    	printf("[%s][%d] get the port status failed .\n",__FUNCTION__,__LINE__);
    	return MAPI_FALSE;
    }

    uMask = 1 << (port % 10);
    // set the new status
    if(bOutState){
		uData = (uMask | uOldData);  // set H
    } else {
    	uData = (~uMask) & uOldData;  // set L
    }

    if(MAPI_FALSE == iptr->WriteBytes(1, &uWRegAddr, 1, &uData))
    {
		printf("[%s][%d] set the new status failed .\n",__FUNCTION__,__LINE__);
    	return MAPI_FALSE;
    }

	printf("[%s][%d] set the P%02d to  %d.\n",__FUNCTION__,__LINE__,port,bOutState);

	return MAPI_TRUE;
}

MAPI_BOOL device_mcu_tca9539::Get_port_State(MAPI_U8 port, MAPI_BOOL *bMode, MAPI_BOOL *bState)
{
	mapi_i2c *iptr      = NULL;
	// used for port status
	MAPI_U8  uInLowRegAddr  = 0x00;
	MAPI_U8  uInHighRegAddr = 0x01;
	MAPI_U8  uRegAddr  = (port > TCA9539_P7) ? uInHighRegAddr : uInLowRegAddr;

	// for port mode
	MAPI_U8  uLowPorts    = 0x06;
	MAPI_U8  uHighPorts   = 0x07;
	MAPI_U8  uModeRegAddr = (port > TCA9539_P7) ? uHighPorts : uLowPorts;
	MAPI_U8  uData        = 0x00;
	MAPI_U8  uMode        = 0x00;

	if(NULL == bMode || NULL == bState || (port > TCA9539_P17 || port < TCA9539_P0))
	{
		printf("[%s][%d] param error .\n",__FUNCTION__,__LINE__);	
		return MAPI_FALSE;
	}

	iptr = mapi_i2c::GetI2C_Dev(TCA9539_I2C_ID);
	if(iptr == NULL)
    {
        printf("[%s][%d] Invalid I2c mcu addr .\n",__FUNCTION__,__LINE__);
        return MAPI_FALSE;
    }

    // get the port mode <input/outputO> 
    if(MAPI_FALSE == iptr->ReadBytes(1, &uModeRegAddr, 1, &uData))
    {
    	printf("[%s][%d] get the old status failed .\n",__FUNCTION__,__LINE__);
    	return MAPI_FALSE;
    }

    uMode = (uData >> (port % 10)) & 0x01;
    *bMode = uMode;

    uData = 0x00;
    if(MAPI_FALSE == iptr->ReadBytes(1, &uRegAddr, 1, &uData))
    {
    	printf("[%s][%d] get the port status failed .\n",__FUNCTION__,__LINE__);
    	return MAPI_FALSE;
    }

	printf("[%s][%d] uRegAddr [0x%02x] , uData [0x%02x] \n", __FUNCTION__,__LINE__, uRegAddr, uData);

    *bState = (uData >> (port % 10) & 0x01);

    printf("[%s][%d] P%02d mode <%s> , state [%d] \n", __FUNCTION__,__LINE__, port, (bMode ? "Input":"Output"), *bState);
	return MAPI_TRUE;
}

发布了101 篇原创文章 · 获赞 19 · 访问量 33万+

猜你喜欢

转载自blog.csdn.net/kehyuanyu/article/details/102742726