nordic 52832 例程I2C解析

来源:互联网 发布:淘宝第二次申请售后 编辑:程序博客网 时间:2024/06/07 12:41

为了实现两块蓝牙开发板之间的通信,本文着重分析I2C程序。

1、打开twi_master_with_twis_slave文件下的程序,编译运行,下载。

2、在串口工具中,我们看到了如下结果:


3、想要搞清楚p,w,c,x,分别式什么意思,以p为例,从主函数看起,主循环里有个

 case 'p':
            do_print_data();
            break;

4、看do_print_data(),我们在虚拟串口工具(参考上一篇)我们输入p发送数据,看到出现了如下图:


5、为了分析为什么出现Communication error1,我们在do_print_data()里面发现了如下语句:

 if(NRF_SUCCESS != err_code)
        {
            printf("Communication error1\n\r");
            return;
        }

6、很明显的可以看出if语句式成立,也就是说NRF_SUCCESS 和err_code不相等,我们可以查出NRF_SUCCESS =0,那么我们就要证明err_code不等于0.

7、为了看err_code的值,我们右击第二个选项

选择option,打开如下图的c/c++标签,将optimization改为level 0(因为level 3压缩了一些数据),如下图:


8、再次编译下载,按debug,在printf处定定点


在串口工具里发送p,点击运行

可以在call stack+locals或者鼠标放在变量error_code上可以看到当前数值为3,如下图


9、为了找出error_code为什么是3,我们找到如下程序err_code = eeprom_read(addr, buff, IN_LINE_PRINT_CNT)

点eeprom_read进去,发现:

static ret_code_t eeprom_read(size_t addr, uint8_t * pdata, size_t size)
{
    ret_code_t ret;
    if(size > (EEPROM_SIM_SIZE))
    {
        return NRF_ERROR_INVALID_LENGTH;
    }
    do
    {
       uint8_t addr8 = (uint8_t)addr;
       ret = nrf_drv_twi_tx(&m_twi_master, EEPROM_SIM_ADDR, &addr8, 1, true);
       if(NRF_SUCCESS != ret)
       {
           break;
       }
       ret = nrf_drv_twi_rx(&m_twi_master, EEPROM_SIM_ADDR, pdata, size);
    }while(0);
    return ret;
}

可以看出里面有两个return,我们现在就是要找它的返回值。


10、可以找出NRF_ERROR_INVALID_LENGTH的值为9,排除。

那就说明return的是ret,我们可以看出在do while里有两个ret,下面就看break能否执行。

如果bresk执行的话,return的是第一个ret,反之是第二个ret


11、注意:在每次调试或者设置断点时,必须在串口工具重新发送p!!!!!!!!!


12、在break处设置断点,发送p,运行,当它执行到break,单步运行,发现程序跳过第二个ret,所以说明执行的是第一个ret,开始研究第一个ret

  ret = nrf_drv_twi_tx(&m_twi_master, EEPROM_SIM_ADDR, &addr8, 1, true);


13、点进第一个ret的调用函数,看到

ret_code_t nrf_drv_twi_tx(nrf_drv_twi_t const * p_instance,
                          uint8_t               address,
                          uint8_t const *       p_data,
                          uint8_t               length,
                          bool                  no_stop)
{
    nrf_drv_twi_xfer_desc_t xfer = NRF_DRV_TWI_XFER_DESC_TX(address, (uint8_t*)p_data, length);


    return nrf_drv_twi_xfer(p_instance, &xfer, no_stop ? NRF_DRV_TWI_FLAG_TX_NO_STOP : 0);
}


14、发现有一个return的值,继续进入它的调用函数nrf_drv_twi_xfer(p_instance, &xfer, no_stop ? NRF_DRV_TWI_FLAG_TX_NO_STOP : 0)发现,

ret_code_t nrf_drv_twi_xfer(nrf_drv_twi_t           const * p_instance,

                            nrf_drv_twi_xfer_desc_t const * p_xfer_desc,
                            uint32_t                        flags)
{
    ret_code_t ret = NRF_SUCCESS;
    twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];


    // TXRX and TXTX transfers are support only in non-blocking mode.
    ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRF_DRV_TWI_XFER_TXRX)));
    ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRF_DRV_TWI_XFER_TXTX)));


    CODE_FOR_TWIM
    (
        ret = twim_xfer(p_cb, (NRF_TWIM_Type *)p_instance->reg.p_twim, p_xfer_desc, flags);
    )
    CODE_FOR_TWI
    (
        if ( (NRF_DRV_TWI_FLAG_TX_POSTINC | NRF_DRV_TWI_FLAG_RX_POSTINC) & flags)
        {
            return NRF_ERROR_NOT_SUPPORTED;
        }
        ret = twi_xfer(p_cb, (NRF_TWI_Type  *)p_instance->reg.p_twi, p_xfer_desc, flags);
    )
    return ret;
}


15、在debug模式下,程序前面不是灰色的不能设断点,也就是意味着该段程序不执行!!!!!


16、 可以看出代码做参数,相当于执行()里的程序不执行

CODE_FOR_TWIM
    (
        ret = twim_xfer(p_cb, (NRF_TWIM_Type *)p_instance->reg.p_twim, p_xfer_desc, flags);
    )


17、下面就看 

  CODE_FOR_TWI
    (
        if ( (NRF_DRV_TWI_FLAG_TX_POSTINC | NRF_DRV_TWI_FLAG_RX_POSTINC) & flags)
        {
            return NRF_ERROR_NOT_SUPPORTED;
        }
        ret = twi_xfer(p_cb, (NRF_TWI_Type  *)p_instance->reg.p_twi, p_xfer_desc, flags);
    )
    return ret;

这里面有两个return,可以看出NRF_ERROR_NOT_SUPPORTED为6,显然不是。

所以执行的是 ret = twi_xfer(p_cb, (NRF_TWI_Type  *)p_instance->reg.p_twi, p_xfer_desc, flags);


18、进入 ret = twi_xfer(p_cb, (NRF_TWI_Type  *)p_instance->reg.p_twi, p_xfer_desc, flags);,看到

__STATIC_INLINE ret_code_t twi_xfer(twi_control_block_t           * p_cb,
                                    NRF_TWI_Type                  * p_twi,
                                    nrf_drv_twi_xfer_desc_t const * p_xfer_desc,
                                    uint32_t                        flags)
{
    ret_code_t ret = NRF_SUCCESS;


   
    nrf_twi_int_disable(p_twi, DISABLE_ALL);


    if (p_cb->busy)
    {
        nrf_twi_int_enable(p_twi, p_cb->int_mask);
        return NRF_ERROR_BUSY;
    }
    else
    {
        p_cb->busy = (NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER & flags) ? false : true;
    }


    if (flags & NRF_DRV_TWI_FLAG_HOLD_XFER)
    {
        return NRF_ERROR_NOT_SUPPORTED;
    }


    p_cb->flags       = flags;
    p_cb->xfer_desc   = *p_xfer_desc;
    p_cb->curr_length = p_xfer_desc->primary_length;
    p_cb->p_curr_buf  = p_xfer_desc->p_primary_buf;
    nrf_twi_address_set(p_twi, p_xfer_desc->address);


    if (p_xfer_desc->type != NRF_DRV_TWI_XFER_RX)
    {
        p_cb->curr_no_stop = ((p_xfer_desc->type == NRF_DRV_TWI_XFER_TX) &&
                             !(flags & NRF_DRV_TWI_FLAG_TX_NO_STOP)) ? false : true;
        ret = twi_tx_start_transfer(p_cb, p_twi, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length, p_cb->curr_no_stop);
    }
    else
    {
        p_cb->curr_no_stop = false;
        ret = twi_rx_start_transfer(p_cb, p_twi, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
    }
    if (p_cb->handler == NULL)
    {
        p_cb->busy = false;
    }
    return ret;
}

可以看出有3个return,其中两个return:NRF_ERROR_BUSY=17,NRF_ERROR_NOT_SUPPORTED=6,可以排除,那么返回的是第3个return,ret


19、可以看出ret有两个

  if (p_xfer_desc->type != NRF_DRV_TWI_XFER_RX)
    {
        p_cb->curr_no_stop = ((p_xfer_desc->type == NRF_DRV_TWI_XFER_TX) &&
                             !(flags & NRF_DRV_TWI_FLAG_TX_NO_STOP)) ? false : true;
        ret = twi_tx_start_transfer(p_cb, p_twi, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length, p_cb->curr_no_stop);
    }
    else
    {
        p_cb->curr_no_stop = false;
        ret = twi_rx_start_transfer(p_cb, p_twi, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
    }
    if (p_cb->handler == NULL)
    {
        p_cb->busy = false;
    }
    return ret;


20、在两个ret前设断点,点击运行,运行到第一个断点后直接跳过了第二个断点,由此我们可以判断,返回的是第一个ret


21、看 ret = twi_tx_start_transfer(p_cb, p_twi, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length, p_cb->curr_no_stop);可以看到

static ret_code_t twi_rx_start_transfer(twi_control_block_t * p_cb,
                                        NRF_TWI_Type *        p_twi,
                                        uint8_t const *       p_data,
                                        uint8_t               length)
{
    ret_code_t ret_code = NRF_SUCCESS;


    nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_STOPPED);
    nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
    nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT);
    nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY);


    p_cb->bytes_transferred = 0;
    p_cb->error             = false;


    if (length == 1)
    {
        nrf_twi_shorts_set(p_twi, NRF_TWI_SHORT_BB_STOP_MASK);
    }
    else
    {
        nrf_twi_shorts_set(p_twi, NRF_TWI_SHORT_BB_SUSPEND_MASK);
    }
    // In case TWI is suspended resume its operation.
    nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_RESUME);
    nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STARTRX);


    if (p_cb->handler)
    {
        p_cb->int_mask = NRF_TWI_INT_STOPPED_MASK   |
                        NRF_TWI_INT_ERROR_MASK     |
                        NRF_TWI_INT_TXDSENT_MASK   |
                        NRF_TWI_INT_RXDREADY_MASK;
        nrf_twi_int_enable(p_twi, p_cb->int_mask);
    }
    else
    {
        while (twi_transfer(p_twi, &p_cb->error, &p_cb->bytes_transferred, (uint8_t*)p_data, length, false))
        {}


        if (p_cb->error)
        {
            ret_code = NRF_ERROR_INTERNAL;
        }
    }
    return ret_code;
}

可以发现返回的是ret_code, 


 22、可以找到

if (p_cb->error)
        {
            ret_code = NRF_ERROR_INTERNAL;
        }

里面的NRF_ERROR_INTERNAL=3,就可以找到为什么出现了最开始的Communication error1


23、后来发现两块蓝牙开发板共地,再发送p,就不会出现最开始的Communication error1,成功的画面如下:

0 0
原创粉丝点击