当前位置:网站首页>采用中微BATG135实现IIC数据/指令交互

采用中微BATG135实现IIC数据/指令交互

2022-07-04 06:19:00 喜欢吃火锅的泪

本例程是一次项目中使用到IIC实现3台中微直接的数据交互,而中微给出的IIC例程偏向简单,实现中遇到很多问题,要真正实现IIC,需要进行改写。

首先需要进行中微作为从机的初始化:

void IICA0_Init(void)
{
    CGC->PER0 |= CGC_PER0_IICA0EN_Msk;              /* enables input clock supply */
    IICA->IICCTL00 = _00_IICA_OPERATION_STOP;       /* stop operation */
    INTC_DisableIRQ(IICA_IRQn);                         /* disable INTIICA interrupt flag */           
    INTC_ClearPendingIRQ(IICA_IRQn);                    /* clear INTIICA interrupt flag */         

#ifdef IICA_STANDARD_MODE /* Max rate: 100Kbps */
    IICA->IICCTL01  = _00_IICA_OPERATE_STANDARD;  /* operates in standard mode */
    IICA->IICWL0    = _4B_IICA_LOW_WIDTH;
    IICA->IICWH0    = _53_IICA_HIGH_WIDTH;
#endif
#ifdef IICA_FAST_MODE /* Max rate: 400Kbps */
    IICA->IICCTL01  = _08_IICA_OPERATE_FAST;  /* operates in fast mode */
    IICA->IICCTL01 |= _04_IICA_FILTER_ON;     /* filter on */
    IICA->IICWL0    = _14_IICA_LOW_WIDTH;
    IICA->IICWH0    = _12_IICA_HIGH_WIDTH;
#endif
    IICA->IICCTL01 |= _01_IICA_FCLK_2_SELECTED;
    IICA->SVA0      = _98_IICA0_SLAVEADDRESS;
    IICA->IICF0    |= _02_IICA_WITHOUT_DETECTION; /* enable generation of a start condition without detecting a stop
condition */
    IICA->IICF0    |= _01_IICA_RESERVATION_DISABLE;       /* disable communication reservation */
    IICA->IICCTL00 |= _08_IICA_INTERRUPT_REQUEST_NINTH; /* interrupt request is generated at the ninth clock's falling edge */
    IICA->IICCTL00 |= _00_IICA_ACKOWNLEDGMENT_DISABLE;   /* enable acknowledgment */
    IICA->IICCTL00 |= _80_IICA_OPERATION_ENABLE;                /* enable operation */
    IICA->IICCTL00 |= _40_IICA_OPERATION_STANDBY;       /* this exits from the current communications and sets standby mode */
    INTC_EnableIRQ(IICA_IRQn);                          /* enable INTIICA interrupt flag */  

    /* Set SCLA0, SDAA0 pin */
    SCLA0_PORT_SETTING();
    SDAA0_PORT_SETTING();
}

 其中:可根据中微的GPIO口进行IIC管脚映射

#define SCLA0_PORT_SETTING() do{ \
        PORT->SCLA0PCFG = 0x13;     /* allocate SCLA0 to P30 */ \
        PORT->P3   &= ~(1 << 0);    /* P30 output low level */ \
        PORT->PM3  &= ~(1 << 0);    /* P30 is N-ch open-drain output mode */ \
        PORT->PMC3 &= ~(1 << 0);     /* P30 digital function */ \
}while(0)

/* ToDo: You can allocate the SDA00 to any desired pins with SDA00PCFG register */
#define SDAA0_PORT_SETTING() do{ \
        PORT->SDAA0PCFG = 0x17;     /* allocate SDAA0 to P50 */ \
        PORT->P5   &= ~(1 << 0);    /* P50 output low level */ \
        PORT->PM5  &= ~(1 << 0);    /* P50 is used as SDAA0 inout */ \
        PORT->PMC5 &= ~(1 << 0);    /* P50 digital function */ \
}while(0)

 接下来是中微作为从机,实现数据的收发:

void IIC_Rec_Fuction(void)
{
    static uint8_t times = 0;
    static uint16_t interval = 0;
    uint8_t csc = 0;
    
    if (0 == times)
    {
        times = 1;
        g_iica0_rx_len = 200;
        g_iica0_rx_cnt = 0U;
        g_iica0_rx_end = 0;    
        g_iica0_slave_status_flag  = 0U;
        IICA->IICA0 = SLVADDR_98U; /* slave address */
        interval = gMillisecondTick;
    }
    
    if (1 == times)
    {
        if (((gMillisecondTick - interval) & 0xFFFF) > 10)  //10ms
        {
            if ((g_iica0_rx_end == 1) && (RxBuffer2[0] == 0x55) && (RxBuffer2[1] == 0xAA) &&                         (RxBuffer2[2] != 0x00))
            {
                for(uint16_t i = 0; i < (RxBuffer2[2] + 1);i++ )
                {
                    csc ^= RxBuffer2[i];
                }
                
                if(csc == RxBuffer2[RxBuffer2[2] + 1])
                {
                    Sys_Data.CmdData = (RxBuffer2[4]<<8) + RxBuffer2[5];      /*获取功能指令*/
                    memcpy(Sys_Data.Rec_Data,RxBuffer2,sizeof(RxBuffer2));    /*获取接收数据*/
                    

                   //Sys_Data.Rec_Data为结构体数组:200个字节uint8_t     Rec_Data[200];                             /*接收数组*/,到此处代表接收的数据没有问题可进入

                     /*IIC接收函数处理中*/
                    Rev_Process_Fuction();  

                   

                               
                    Send_Process_Connect_Upload();                   /*IIC发送数据线程*/    
                    
                    g_iica0_rx_len = 200;
                    g_iica0_rx_cnt = 0U;
                    g_iica0_rx_end = 0;    
                    g_iica0_slave_status_flag  = 0U;
                    IICA->IICA0 = SLVADDR_98U; /* slave address */
                }
            }
            
            interval = gMillisecondTick;
        }
    }else
    {
        g_iica0_rx_len = 200;
        g_iica0_rx_cnt = 0U;
        g_iica0_rx_end = 0;    
        g_iica0_slave_status_flag  = 0U;
        IICA->IICA0 = SLVADDR_98U; /* slave address */
    }
}

其中:需要注意的是,要记得修改中微官方给的中断函数:

uint8_t RxBuffer2[200];                      /*接收数组*/
uint16_t RxCounter2 = 0;                     /*接收计数*/

/***********************************************************************************************************************
* Function Name: iica0_slavehandler
* @brief  This function is IICA0 slave handler.
* @param  None
* @return None
***********************************************************************************************************************/
static void iica0_slavehandler(void)
{
    /* Control for stop condition */
    if (IICA->IICS0 & IICA_IICS0_SPD_Msk)
    {
        /* Get stop condition */
        IICA->IICCTL00 &= ~IICA_IICCTL00_SPIE_Msk; /* SPIE0 = 0: disable */
        if(g_iica0_slave_status_flag & _80_IICA_ADDRESS_COMPLETE)
        {
            if (g_iica0_slave_status_flag & 0x04U)   /* send flag */
            {
                iica0_callback_slave_sendend();
            }
            if (g_iica0_slave_status_flag & 0x02U)   /* receive flag */
            {
                iica0_callback_slave_receiveend();
            }
        }
        g_iica0_slave_status_flag = 1U;
    }
    else
    {
        if ((g_iica0_slave_status_flag & _80_IICA_ADDRESS_COMPLETE) == 0U)
        {
            if (IICA->IICS0 & IICA_IICS0_COI_Msk)
            {
                IICA->IICCTL00 |= IICA_IICCTL00_SPIE_Msk; /* SPIE0 = 1: enable */
                g_iica0_slave_status_flag = _80_IICA_ADDRESS_COMPLETE;

                if (IICA->IICS0 & IICA_IICS0_TRC_Msk)  /* TRC0 == 1 */
                {
                    IICA->IICCTL00 |= IICA_IICCTL00_WTIM_Msk;  /* WTIM0 = 1:  interrupt request is generated at the ninth clock's falling edge */

                    if (g_iica0_tx_cnt > 0U)
                    {
                        IICA->IICA0 = *gp_iica0_tx_address;
                        gp_iica0_tx_address++;
                        g_iica0_tx_cnt--;
                    }
                    else
                    {
                        iica0_callback_slave_sendend();
                        IICA->IICCTL00 |= IICA_IICCTL00_WREL_Msk;  /* WREL0 = 1U: cancel wait */
                    }
                }
                else
                {
                    IICA->IICCTL00 |=  IICA_IICCTL00_ACKE_Msk;   /* ACKE0 = 1U: enable acknowledgment */
                    IICA->IICCTL00 &= ~IICA_IICCTL00_WTIM_Msk;   /* WTIM0 = 0U: interrupt request is generated at the eighth clock's falling edge */
                    IICA->IICCTL00 |=  IICA_IICCTL00_WREL_Msk;   /* WREL0 = 1U: cancel wait */
                }
            }
            else
            {
                iica0_callback_slave_error(MD_ERROR);
            }
        }
        else
        {
            if (IICA->IICS0 & IICA_IICS0_TRC_Msk)  /* TRC0 == 1 */
            {
                g_iica0_slave_status_flag |= 4U;   /* send flag */
                if ((0U == (IICA->IICS0 & IICA_IICS0_ACKD_Msk)) && (g_iica0_tx_cnt != 0U))
                {
                    iica0_callback_slave_error(MD_NACK);
                }
                else
                {
                    if (g_iica0_tx_cnt > 0U)
                    {
                        IICA->IICA0 = *gp_iica0_tx_address;
                        gp_iica0_tx_address++;
                        g_iica0_tx_cnt--;
                    }
                    else
                    {
                        iica0_callback_slave_sendend();
                        IICA->IICCTL00 |= IICA_IICCTL00_WREL_Msk;  /* WREL0 = 1U: cancel wait */
                    }
                }
            }
            else
            {
                g_iica0_slave_status_flag |= 2U;  /* receive flag */
                if (g_iica0_rx_cnt < g_iica0_rx_len)
                {
                    RxBuffer2[g_iica0_rx_cnt] = IICA->IICA0;
                    g_iica0_rx_cnt++;

                    if (g_iica0_rx_cnt == g_iica0_rx_len)
                    {
                        IICA->IICCTL00 |= IICA_IICCTL00_WTIM_Msk;   /* WTIM0 = 1:  interrupt request is generated at the ninth clock's falling edge */
                        IICA->IICCTL00 |= IICA_IICCTL00_WREL_Msk;   /* WREL0 = 1U: cancel wait */
                        iica0_callback_slave_receiveend();
                    }
                    else
                    {
                        IICA->IICCTL00 |=  IICA_IICCTL00_WREL_Msk;   /* WREL0 = 1U: cancel wait */
                    }
                }
                else
                {
                    IICA->IICCTL00 |=  IICA_IICCTL00_WREL_Msk;   /* WREL0 = 1U: cancel wait */
                }
            }
        }
    }
}

/*
*********************************************************************************
* 函 数 名:Send_Process_Connect_Upload
* 功能说明:发送数据给蓝牙MCU
* 形    参:void
* 返 回 值:void
*********************************************************************************
*/
void Send_Process_Connect_Upload(void)
{
    uint16_t value_size = 0;
    //uint16_t i = 0;
    //uint8_t  tmpbuf[10]={0};
    static uint8_t value[200] = {0};
    /* 判断串口发送是否立即执行*/
    if((Sys_Data.Com_Stas & COM_SEND_RDY) !=COM_SEND_RDY)
    {    
        return;
    }
    
    /* 串口组包存值Value*/
  //  value_size = SendPacekData(Sys_Data.SendBuf,Sys_Data.SendLen,value);
    
    IICA0_SlaveSend(SLVADDR_98U,value,value_size);
    while(g_iica0_tx_end == 0);
    
    #if 0
    /*发送数据*/
    printf_log("\r\n send_process :");
    for(i=0;i<(value_size);i++)
    {
        memset(tmpbuf,0,10);
        u8_T_array(value[i],tmpbuf);
        printf_log((const char *)tmpbuf);
        printf_log(" ");
    }
    printf_log("\r\n value_size = %d",value_size);
    #endif
    
    //Sys_Data.Com_Stas = 0;                                   /*指令状态复位*/
   // Sys_Data.CmdData  = 0;                                   /*指令复位*/
  //  Sys_Data.SendLen  = 0;                                   /*数据长度为0*/
  //  memset(Sys_Data.CmdPara,0,sizeof(Sys_Data.CmdPara));      /*命令数据包复位*/

原网站

版权声明
本文为[喜欢吃火锅的泪]所创,转载请带上原文链接,感谢
https://blog.csdn.net/qq_15053863/article/details/125413541