I2C从机 Slave mode

一、stm32f1xx I2C slave

(1)本代码需要Keil编译时,外加HAL库中的两个库文件:

#include "stm32f1xx_ll_i2c.h" 和 stm32f1xx_ll_i2c.c两个文件
typedef struct _s_gt9xx_t {
    i2c_slave_call_t* pcall;
    uint8_t __addr[2];
    uint8_t __status;
    uint8_t __res;

    uint8_t r_status;
    uint8_t startup;
    uint16_t res0;

    uint8_t* reg_addr;
    uint16_t reg_index;
    uint16_t reg_size;
} s_gt9xx_t;

static s_gt9xx_t gt9xx = { 0 };

#define S_ST_W_REQ   	1
#define S_ST_W_ADDR 	2
#define S_ST_W_DATA 	3
#define S_ST_W_DATA_1 	4
#define S_ST_R_DATA	 	5
#define S_ST_STOP 		6
#define S_ST_IDLE 		7

//----------------------- write -------------------------
static int write_reg_continue_start(uint16_t addr)
{
    s_gt9xx_t *pgt = &gt9xx;

	if (pgt->__addr[0] == 0x40) {
		pgt->reg_addr = &reg_40[1];
		pgt->reg_size = TP_DEFAULT_LEN;
	} else if (pgt->__addr[0] == 0x41) {
		pgt->reg_addr = &reg_41[1];
		pgt->reg_size = TP_STD_FRAME_LEN;
	} else if (pgt->__addr[0] == 0x42) {
		pgt->reg_addr = &reg_42[1];
		pgt->reg_size = TP_EXT_FRAME_LEN;
	} else if (pgt->__addr[0] == 0x80) {
        reg_80[0] = pgt->__addr[0];
        reg_80[1] = pgt->__addr[1];
		pgt->reg_addr = &reg_80[2];
		pgt->reg_size = TP_DEFAULT_LEN;   
    } else {
    }

	pgt->reg_index = 0;
	
    return 0;
}

static int write_reg_continue(uint8_t* data, int len)
{
    s_gt9xx_t* pgt = &gt9xx;
	int i = 0;
    if (pgt->reg_addr == NULL) {
        return -1;
    }

    for (i = 0; i < len; i++) {
        if (pgt->reg_index < pgt->reg_size) {
            pgt->reg_addr[pgt->reg_index] = data[i];
            pgt->reg_index++;
        } else {

        }
    }
    return 0;
}

static void write_reg_continue_end(void)
{
    s_gt9xx_t *pgt = &gt9xx;
	pgt->__status = S_ST_IDLE;
    pgt->reg_addr = NULL;
    pgt->reg_index = 0;
    pgt->reg_size = 0;

    if ((reg_80[0] == 0x80) && (reg_80[1] == 0x01)) { // startup done
        pgt->startup = 1;
    }
}

//---------------------------------------
static int i2c_slave_write_requested(void)
{
    s_gt9xx_t* pgt = &gt9xx;
    pgt->reg_index = 0;
    pgt->__status = S_ST_W_REQ;
    return 0;
}

static int i2c_slave_write_received(uint8_t val)
{
    s_gt9xx_t* pgt = &gt9xx;
    switch (pgt->__status) {
        case S_ST_W_REQ: { // 一个byte地址
            pgt->__addr[0] = val;
            pgt->__status  = S_ST_W_DATA;
        } break;
        case S_ST_W_ADDR: { // 两byte地址
            pgt->__addr[1] = val;
            pgt->__status = S_ST_W_DATA;
        } break;
        case S_ST_W_DATA: {
            printf("addr: 0x%x 0x%x \n", pgt->__addr[0], pgt->__addr[1]);
            write_reg_continue_start(pgt->__addr[0]);
            write_reg_continue(&val, 1);
            pgt->__status = S_ST_W_DATA_1;
        } break;
        case S_ST_W_DATA_1: {
            write_reg_continue(&val, 1);
        } break;
		case S_ST_IDLE: {

		} break;
        default:
            break;
    }

    return 0;
}
#include "stm32f1xx_ll_i2c.h"

// I2C 中断事件处理
static void stm32_i2c_slave_event(void* pi2c)
{
    i2c_dev_t* pdev = (i2c_dev_t*)pi2c;
    I2C_TypeDef* i2cx = pdev->i2c_dev;
    uint32_t dir = 0;
    uint8_t val = 0;

    if (LL_I2C_IsActiveFlag_RXNE(i2cx)) {
        val = LL_I2C_ReceiveData8(i2cx);
        if (slave_write_received(pdev, val)) {
            LL_I2C_AcknowledgeNextData(i2cx, LL_I2C_ACK); // LL_I2C_NACK
        }
    } else if (LL_I2C_IsActiveFlag_TXE(i2cx) && LL_I2C_IsActiveFlag_BTF(i2cx)) {
        slave_read_processed(pdev, &val);
        LL_I2C_TransmitData8(i2cx, val);
    } else if (LL_I2C_IsActiveFlag_ADDR(i2cx)) {
        dir = LL_I2C_GetTransferDirection(i2cx);
        if (dir == LL_I2C_DIRECTION_READ) {             // BUS write
            slave_write_requested(pdev);
            LL_I2C_EnableIT_RX(i2cx);
        } else {                                        // BUS read
            slave_read_requested(pdev, &val);
            LL_I2C_TransmitData8(i2cx, val);
            LL_I2C_EnableIT_TX(i2cx);
        }
        // stm32_i2c_enable_transfer_interrupts();
    } else if (LL_I2C_IsActiveFlag_STOP(i2cx)) {
        LL_I2C_ClearFlag_STOP(i2cx);
        /* Prepare to ACK next transmissions address byte */
        LL_I2C_AcknowledgeNextData(i2cx, LL_I2C_ACK);
        slave_stop(pdev);
    }
}

二、stm32f0xx I2C slave

#include "user_inc.h"

typedef struct __gpio_t{
    u32 gpio_pin;
    GPIO_TypeDef *gpio_port;
    u32 alter;
} gpio_t;

typedef struct __i2c_dev_t {
    int i2c_id;
    I2C_TypeDef* i2c_dev;
    gpio_t sda;
    gpio_t scl;
    u32 irqn;
    u32 pre_irq;
    u32 sub_irq;
    u8 is_inited;
    u8 is_first;
    uint16_t res;
    i2c_slave_call_t *pcall;
} i2c_dev_t;

static i2c_dev_t g_i2c_dev[I2C_DEV_CNT] = {
    [I2C_DEV_I2C1] = { 
        .i2c_id = I2C_DEV_I2C1, 
        .i2c_dev = I2C1, 
        .pcall = NULL,
        },
    [I2C_DEV_I2C2] = { 
        .i2c_id = I2C_DEV_I2C2, 
        .i2c_dev = I2C2, 
        .scl = { .gpio_pin = GPIO_PIN_10, .gpio_port = GPIOB, .alter = GPIO_AF1_I2C2 },
        .sda = { .gpio_pin = GPIO_PIN_11, .gpio_port = GPIOB, .alter = GPIO_AF1_I2C2 },
        .irqn = I2C2_IRQn,
        .pre_irq = 1,
        .sub_irq = 0,
        .is_inited = 0,
        .is_first = 0,
        .pcall = NULL,
        },    
};

I2C_HandleTypeDef hi2c;

/*---------------------- I2C clock ------------------------*/
#define I2C_CLK_INIT(dev, val)              \
    if (val) {                              \
        __HAL_RCC_##dev##_CLK_ENABLE();     \
    } else {                                \
        __HAL_RCC_##dev##_CLK_DISABLE();    \
    }                                       \

static void i2c_clk_init(I2C_TypeDef* dev, int enable)
{
    if (dev == I2C1) {
        I2C_CLK_INIT(I2C1, enable);
    } else if (dev == I2C2) {
        I2C_CLK_INIT(I2C2, enable);
    } else {
        _error("No such i2c device\n");
    }
}


/* EEPROM TIMING is calculated in case of the I2C Clock source is the SYSCLK = 48 MHz */
/* Set TIMING to 0x00E0D3FF to reach 100 KHz speed (Rise time = 50ns, Fall time = 10ns) */
//#define EEPROM_TIMING             0x00E0D3FF

/* I2C TIMING Register define when I2C clock source is HSI*/
/* I2C TIMING is calculated in case of the I2C Clock source is the HSI = 8 MHz */
/* This example use TIMING to 0x00201D2C to reach 100Khz speed (Rise time = 50ns, Fall time = 10ns) */
//#define I2C_TIMING                0x00201D2C

/* I2C TIMING Register define when I2C clock source is SYSCLK */
/* I2C TIMING is calculated in case of the I2C Clock source is the SYSCLK = 48 MHz */
/* This example use TIMING to 0x00A51314 to reach 1 MHz speed (Rise time = 100 ns, Fall time = 100 ns) */
#define I2C_TIMING                  0x00A51314

static void i2c_slave_init(int id, uint16_t slave_addr)
{
    i2c_dev_t* pdev = &g_i2c_dev[id];
    GPIO_InitTypeDef GPIO_InitStructure;

    i2c_clk_init(pdev->i2c_dev, ENABLE);
    __HAL_RCC_GPIOB_CLK_ENABLE();

    GPIO_InitStructure.Pin        = pdev->scl.gpio_pin;
    GPIO_InitStructure.Mode       = GPIO_MODE_AF_OD;
    GPIO_InitStructure.Pull       = GPIO_NOPULL; // 如果内部上拉会锁死I2C总线
    GPIO_InitStructure.Speed      = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStructure.Alternate  = pdev->scl.alter;
    HAL_GPIO_Init(pdev->scl.gpio_port, &GPIO_InitStructure);

    GPIO_InitStructure.Pin        = pdev->sda.gpio_pin;
    GPIO_InitStructure.Mode       = GPIO_MODE_AF_OD;
    GPIO_InitStructure.Pull       = GPIO_NOPULL;
    GPIO_InitStructure.Speed      = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStructure.Alternate  = pdev->sda.alter;
    HAL_GPIO_Init(pdev->sda.gpio_port, &GPIO_InitStructure);

    hi2c.Instance = pdev->i2c_dev;
    hi2c.Init.Timing            = I2C_TIMING;
    hi2c.Init.OwnAddress1       = slave_addr;
    hi2c.Init.AddressingMode    = I2C_ADDRESSINGMODE_7BIT;
    hi2c.Init.DualAddressMode   = I2C_DUALADDRESS_DISABLE;
    hi2c.Init.OwnAddress2       = 0;
    hi2c.Init.OwnAddress2Masks  = I2C_OA2_NOMASK;
    hi2c.Init.GeneralCallMode   = I2C_GENERALCALL_ENABLE; 
    hi2c.Init.NoStretchMode     = I2C_NOSTRETCH_DISABLE; //--- 影响i2c最后一个字节数据因为NACK发送不出去

    if (HAL_I2C_Init(&hi2c) != HAL_OK) {
        _error("I2C%d init fail\n", id + 1);
        return;
    }

    LL_I2C_ClearFlag_ADDR(pdev->i2c_dev);
    LL_I2C_ClearFlag_NACK(pdev->i2c_dev);
    LL_I2C_ClearFlag_STOP(pdev->i2c_dev);
    LL_I2C_ClearFlag_TXE(pdev->i2c_dev);
    LL_I2C_ClearFlag_BERR(pdev->i2c_dev);
    LL_I2C_ClearFlag_ARLO(pdev->i2c_dev);
    LL_I2C_ClearFlag_OVR(pdev->i2c_dev);

    pdev->is_inited = 1;
    pdev->is_first  = 1;

    _debug(SYS_INFO, "i2c slave init success ... \n");
}

void i2c_open_irq(int id)
{
    i2c_dev_t* pdev = &g_i2c_dev[id];

    LL_I2C_EnableIT_ADDR(pdev->i2c_dev);
    //LL_I2C_EnableIT_RX(pdev->i2c_dev);
    //LL_I2C_EnableIT_TX(pdev->i2c_dev);
    //LL_I2C_EnableIT_NACK(pdev->i2c_dev);
    //LL_I2C_EnableIT_TC(pdev->i2c_dev);
    //LL_I2C_EnableIT_ERR(pdev->i2c_dev);
    //LL_I2C_EnableIT_STOP(pdev->i2c_dev);

    HAL_NVIC_SetPriority((IRQn_Type)pdev->irqn, pdev->pre_irq, pdev->sub_irq);
    HAL_NVIC_EnableIRQ((IRQn_Type)pdev->irqn);
}

/*================================================================*/
void i2c_dev_set_irq_prio(int id, int irq_prio)
{
    i2c_dev_t* pdev = &g_i2c_dev[id];
    HAL_NVIC_SetPriority((IRQn_Type)pdev->irqn, irq_prio, pdev->sub_irq);
    HAL_NVIC_EnableIRQ((IRQn_Type)pdev->irqn);
}

void i2c_slave_uninit(int id)
{
    i2c_dev_t* pdev = &g_i2c_dev[id];
    hi2c.Instance = pdev->i2c_dev;
    HAL_I2C_DeInit(&hi2c);
    HAL_NVIC_DisableIRQ((IRQn_Type)pdev->irqn);
}

void i2c_dev_set_call_back(int id, i2c_slave_call_t *pcall)
{
    i2c_dev_t* pdev = &g_i2c_dev[id];
    pdev->pcall = pcall;
}

/================================================================
typedef struct _s_gt9xx_t {
    i2c_slave_call_t* pcall;
    uint8_t __addr[2];
    uint8_t __status;
    uint8_t __res;

    uint8_t r_status;
    uint8_t startup;
    uint16_t res0;

    uint8_t* reg_addr;
    uint16_t reg_index;
    uint16_t reg_size;
} s_gt9xx_t;

static s_gt9xx_t gt9xx = { 0 };

#define S_ST_W_REQ   	1
#define S_ST_W_ADDR 	2
#define S_ST_W_DATA 	3
#define S_ST_W_DATA_1 	4
#define S_ST_R_DATA	 	5
#define S_ST_STOP 		6
#define S_ST_IDLE 		7

//----------------------- write -------------------------
static int write_reg_continue_start(uint16_t addr)
{
    s_gt9xx_t *pgt = &gt9xx;

	if (pgt->__addr[0] == 0x40) {
		pgt->reg_addr = &reg_40[1];
		pgt->reg_size = TP_DEFAULT_LEN;
	} else if (pgt->__addr[0] == 0x41) {
		pgt->reg_addr = &reg_41[1];
		pgt->reg_size = TP_STD_FRAME_LEN;
	} else if (pgt->__addr[0] == 0x42) {
		pgt->reg_addr = &reg_42[1];
		pgt->reg_size = TP_EXT_FRAME_LEN;
	} else if (pgt->__addr[0] == 0x80) {
        reg_80[0] = pgt->__addr[0];
        reg_80[1] = pgt->__addr[1];
		pgt->reg_addr = &reg_80[2];
		pgt->reg_size = TP_DEFAULT_LEN;   
    } else {
    }

	pgt->reg_index = 0;
	
    return 0;
}

static int write_reg_continue(uint8_t* data, int len)
{
    s_gt9xx_t* pgt = &gt9xx;
	int i = 0;
    if (pgt->reg_addr == NULL) {
        return -1;
    }

    for (i = 0; i < len; i++) {
        if (pgt->reg_index < pgt->reg_size) {
            pgt->reg_addr[pgt->reg_index] = data[i];
            pgt->reg_index++;
        } else {

        }
    }
    return 0;
}

static void write_reg_continue_end(void)
{
    s_gt9xx_t *pgt = &gt9xx;
	pgt->__status = S_ST_IDLE;
    pgt->reg_addr = NULL;
    pgt->reg_index = 0;
    pgt->reg_size = 0;

    if ((reg_80[0] == 0x80) && (reg_80[1] == 0x01)) { // startup done
        pgt->startup = 1;
    }
}

//---------------------------------------
static int i2c_slave_write_requested(void)
{
    s_gt9xx_t* pgt = &gt9xx;
    pgt->reg_index = 0;
    pgt->__status = S_ST_W_REQ;
    return 0;
}

static int i2c_slave_write_received(uint8_t val)
{
    s_gt9xx_t* pgt = &gt9xx;
    switch (pgt->__status) {
        case S_ST_W_REQ: { // 一个byte地址
            pgt->__addr[0] = val;
            pgt->__status  = S_ST_W_ADDR;
        } break;
        case S_ST_W_ADDR: { // 两byte地址
            pgt->__addr[1] = val;
            pgt->__status = S_ST_W_DATA;
        } break;
        case S_ST_W_DATA: {
            printf("addr: 0x%x 0x%x \n", pgt->__addr[0], pgt->__addr[1]);
            write_reg_continue_start(pgt->__addr[0]);
            write_reg_continue(&val, 1);
            pgt->__status = S_ST_W_DATA_1;
        } break;
        case S_ST_W_DATA_1: {
            write_reg_continue(&val, 1);
        } break;
		case S_ST_IDLE: {

		} break;
        default:
            break;
    }

    return 0;
}

//----------------------- read -------------------------
//static uint8_t default_tmp[TP_DEFAULT_LEN] = { 0 };     // default临时缓冲区
static uint8_t std_tmp[TP_STD_FRAME_LEN]   = { 0 };     // STD临时缓冲区
static uint8_t ext_tmp[TP_EXT_FRAME_LEN]   = { 0 };     // EXT临时缓冲区

#define I2C_READ_VERSION        0
#define I2C_READ_STARTUP        1
#define I2C_READ_COOR           2
#define I2C_UPDATE_ACK          3   //--- reg_f0[TP_DEFAULT_LEN]

#define TOUCH_POINT_1_2         0
#define TOUCH_POINT_3_5         1

static int read_reg_continue_start(void)
{
    s_gt9xx_t* pgt = &gt9xx;
    static int touch_status = TOUCH_POINT_1_2;
    uint8_t is_idle = reg_44[0];
    uint8_t touch_num = reg_41[1];

    pgt->reg_index = 0; // 清除每次取数据时的计数索引

    if (pgt->startup == 1) { // startup done
        pgt->r_status = I2C_READ_COOR;
    } else {
        if ((is_idle == 0) && (touch_status == TOUCH_POINT_1_2)) {
            pgt->r_status = I2C_READ_STARTUP;
        } else {
            pgt->r_status = I2C_READ_COOR;
        }
    }

    switch (pgt->r_status) 
    {
        case I2C_READ_VERSION: {
            pgt->__addr[0] = 0x4b;
            pgt->reg_addr = &reg_4b[0];
            pgt->reg_size = TP_DEFAULT_LEN;
        }
        break;
        case I2C_READ_STARTUP: {
            pgt->__addr[0] = 0x40;
            pgt->reg_addr = &reg_40[0];
            pgt->reg_size = TP_DEFAULT_LEN;
        }
        break;
        case I2C_READ_COOR: {
            if (touch_status == TOUCH_POINT_1_2) {

                memcpy(std_tmp, reg_41, TP_STD_FRAME_LEN);
                pgt->__addr[0] = 0x41;
                pgt->reg_addr = &std_tmp[0];
                pgt->reg_size = TP_STD_FRAME_LEN;
                
                if (touch_num > 2) { // 超过2点触摸时,先使用0x41上报,随后再使用reg:0x42上报
                    touch_status = TOUCH_POINT_3_5;
                    //memcpy(ext_tmp, reg_42, TP_EXT_FRAME_LEN); ///--- 考虑多点触摸要不要同步数据
                } else {
                    reg_44[0] = 0;
                }
            } else {
                memcpy(ext_tmp, reg_42, TP_EXT_FRAME_LEN);
                pgt->__addr[0] = 0x42;
                pgt->reg_addr = &ext_tmp[0];
                pgt->reg_size = TP_EXT_FRAME_LEN;

                reg_44[0] = 0; // idle
                touch_status = TOUCH_POINT_1_2; // clear touch
            }
        }
        break;
        default: {
        }
        break;
    }

    // debug_printf("reg_0x40", reg_40, TP_DEFAULT_LEN);
    // debug_printf("reg_0x41", reg_41, TP_STD_FRAME_LEN);
    // debug_printf("reg_0x42", reg_42, TP_EXT_FRAME_LEN);

    return 0;
}

static int read_reg_continue(uint8_t* data, int len)
{
    s_gt9xx_t* pgt = &gt9xx;
    int i;
    
    for (i = 0; i < len; i++) {
        if (pgt->reg_index < pgt->reg_size) {
            data[i] = pgt->reg_addr[pgt->reg_index];
            pgt->reg_index++;
        } else {
            data[i] = 0xff;
        }
    }

    //printf("=== reg_index: %d,reg_size:%d, data = 0x%x \n", pgt->reg_index, pgt->reg_size, data[0]);

    return 0;
}

static void read_reg_continue_end(void)
{ 
    s_gt9xx_t *pgt = &gt9xx;
    pgt->__status = S_ST_IDLE;
    pgt->reg_addr = NULL;
    pgt->reg_index = 0;
    pgt->reg_size = 0;
}

//-------------------- read ---------------------
static int i2c_slave_read_requested(uint8_t* val)
{
    int ret;
    s_gt9xx_t *pgt = &gt9xx;
    pgt->__status = S_ST_R_DATA;

    ret = read_reg_continue_start();
    if (ret == 0) {
        ret = read_reg_continue(val, 1);
        if (ret < 0) {
            *val = 0xff;
        }
    } else {
        *val = 0xff;
    }

    return 0;
}

static int i2c_slave_read_processed(uint8_t *val)
{
    int ret;
    s_gt9xx_t *pgt = &gt9xx;
	
    if(pgt->__status == S_ST_R_DATA) {
        ret = read_reg_continue(val,1);
        if(ret < 0){
            *val = 0xff;
        }
    }

	return 0;
}

static int i2c_slave_stop(void)
{
    s_gt9xx_t* pgt = &gt9xx;
    pgt->__addr[0] = 0;
    pgt->__addr[1] = 0;

    if (pgt->__status == S_ST_R_DATA) {
        read_reg_continue_end();
    } else if (pgt->__status == S_ST_W_DATA_1) {
        write_reg_continue_end();
    } else {
    }
    return 0;
}

i2c_slave_call_t gi2c_slave_call = {
    .write_requested = i2c_slave_write_requested,
    .write_received  = i2c_slave_write_received,
    .read_requested  = i2c_slave_read_requested,
    .read_processed  = i2c_slave_read_processed,
    .stop            = i2c_slave_stop,
};


static int slave_write_requested(void *pi2c)
{
    int ret = 0; 
    i2c_dev_t *pdev = (i2c_dev_t *)pi2c;
    i2c_slave_call_t *pcall = pdev->pcall;
    if(pcall){
       ret = pcall->write_requested();
    }       
	return ret;
}

static int slave_write_received(void *pi2c,uint8_t val)
{
    int ret = 0; 
    i2c_dev_t *pdev = (i2c_dev_t *)pi2c;

    i2c_slave_call_t *pcall = pdev->pcall;
    if(pcall){
      ret = pcall->write_received(val);
    }       
	return ret;
}


static int slave_read_requested(void *pi2c, uint8_t *val)
{
    int ret = 0; 
    i2c_dev_t *pdev = (i2c_dev_t *)pi2c;
	/* Increment will be done in the read_processed callback */
     i2c_slave_call_t *pcall = pdev->pcall;
    if(pcall){
       ret = pcall->read_requested(val);
    }
	return ret;
}

static int slave_read_processed(void *pi2c,uint8_t *val)
{
    int ret = 0; 
    i2c_dev_t *pdev = (i2c_dev_t *)pi2c;
	/* Increment will be done in the next read_processed callback
	 * In case of STOP, the byte won't be taken in account
	 */
    i2c_slave_call_t *pcall = pdev->pcall;
    if(pcall){
      ret =  pcall->read_processed(val);
    }
	return ret;
}

static int slave_stop(void *pi2c)
{
    int ret = 0; 
    i2c_dev_t *pdev = (i2c_dev_t *)pi2c;
    i2c_slave_call_t *pcall = pdev->pcall;
    if(pcall){
        ret = pcall->stop();
    }
	return ret;
}

static void slave_irq_proc(void* pi2c)
{
    i2c_dev_t* pdev = (i2c_dev_t*)pi2c;
    I2C_TypeDef* i2cx = pdev->i2c_dev;

    if (!pdev->is_inited) {
        return;
    }

    if (LL_I2C_IsActiveFlag_TXE(i2cx)) {
        uint8_t val = 0xff;
        slave_read_processed(pdev, &val);
        LL_I2C_TransmitData8(i2cx, val);
        return;
    }

    if (LL_I2C_IsActiveFlag_RXNE(i2cx)) {
        uint8_t r_val = LL_I2C_ReceiveData8(i2cx);
        if (slave_write_received(pdev, r_val)) {
            LL_I2C_AcknowledgeNextData(i2cx, LL_I2C_NACK);
        }
        return;
    }

    ///<--- 异常判断
    if (LL_I2C_IsActiveFlag_BERR(i2cx)) { // Bus error
        LL_I2C_ClearFlag_BERR(i2cx);
    }
    if (LL_I2C_IsActiveFlag_ARLO(i2cx)) { // Arbitration los
        LL_I2C_ClearFlag_ARLO(i2cx);
    }
    if (LL_I2C_IsActiveFlag_OVR(i2cx)) {  // Overrun / Underrun
        LL_I2C_ClearFlag_OVR(i2cx);
    }
    if (LL_I2C_IsActiveFlag_STOP(i2cx)) { // Stop sign
        slave_stop(pdev);

        /* Prepare to ACK next transmissions address byte */
        LL_I2C_AcknowledgeNextData(i2cx, LL_I2C_ACK); // LL_I2C_ACK  LL_I2C_NACK
        LL_I2C_DisableIT_STOP(i2cx);
        LL_I2C_ClearFlag_STOP(i2cx);
        return;
    }

    if (LL_I2C_IsActiveFlag_ADDR(i2cx)) {
        uint32_t dir = LL_I2C_GetTransferDirection(i2cx);
        if (dir == LL_I2C_DIRECTION_READ) {
            uint8_t val = 0xff;
            i2cx->ISR |= I2C_ISR_TXE; // flush transmit data register
            slave_read_requested(pdev, &val);
            LL_I2C_TransmitData8(i2cx, val);
            LL_I2C_EnableIT_TX(i2cx);
        } else {
            slave_write_requested(pdev);
            LL_I2C_EnableIT_RX(i2cx);
        }
        LL_I2C_EnableIT_STOP(i2cx);
        LL_I2C_ClearFlag_ADDR(i2cx);
    }

    return;
}

void I2C1_IRQHandler(void)
{
    i2c_dev_t* pi2c = &g_i2c_dev[I2C_DEV_I2C1];
    slave_irq_proc(pi2c);
}

void I2C2_IRQHandler(void)
{
    i2c_dev_t* pi2c = &g_i2c_dev[I2C_DEV_I2C2];
    slave_irq_proc(pi2c);
}

void s_gt911_init(void)
{
    i2c_slave_init(TP_I2C_DEV, SLAVE_OWN_ADDRESS);
    i2c_dev_set_call_back(TP_I2C_DEV, &gi2c_slave_call);
    gt9xx.pcall = &gi2c_slave_call;
    i2c_open_irq(TP_I2C_DEV);
}

void s_gt911_uninit(void)
{
    i2c_slave_uninit(TP_I2C_DEV);
    gt9xx.pcall = NULL;
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值