Nordic52810入門篇-TWIM串行總線

一、前言

TWI(Two wire Serial Interface):twi接口是對I2C總線接口的繼承和發展,完全兼容I2C總線

Nordic的TWI外設主要分成兩類,TWIM(基於EasyDMA的主設備Master) TWIS(基於EasyDMA的從設備Slave)
ps:如有錯誤,請留言指正,謝謝

二、工作原理

功能特點

  • 兼容I2C總線
  • 可選速率 100kbps/250kbps/400kbps
  • EasyDMA進行RAM數據與寄存器的傳輸
  • 可映射到任意的GPIO引腳

原理框圖
在這裏插入圖片描述

一主多從應用案例
TWI主機可同時掛載多個從機,主機通過從機唯一分配的地址進行尋址訪問,總線需加上拉電阻以保證其驅動能力
在這裏插入圖片描述

數據通信過程

寫數據

  • TWI主機寫數據通過STARTTX任務進行觸發,最終通過STOP結束任務
  • 從機的地址尋址成功後,通過TXD.PTR寄存器指向的RAM地址,調製發送數據
  • 發送時可被SUSPEND任務掛起,掛起期間總線會保持,在生效RESUME任務後可繼續通信
  • 當發送最後一個字節時,TWIM會產生一個LASTTX事件,必須發出STOP任務結束一次通信(不會自動停止總線通信)
  • 僅通信RESUME釋放後才能發送STOP任務

在這裏插入圖片描述

讀數據

  • TWI主機讀數據通過STARTRX 任務觸發,通過STOP借結束任務
  • 讀取到的數據將儲存到RXD.PTR寄存器指向的RAM地址中,數據接收完成後主機產生一個NACK
  • 掛起任務SUSPEND觸發後,將會產生一個SUSPENDED事件,此事件可用於同步軟件
  • 當TWI主機準備接收最後一個字節時,會產生一個LASTRX事件
  • TWI master在被掛起時無法停止,因此必須在TWI master恢復後發出STOP任務

在這裏插入圖片描述

三、寄存器

  • SHORTS:循環模式控制,寫1使能發送/接收最後字節的LASTTX/LASTRX事件後,自動觸發如開啓/掛起/結束任務
  • INTEN:中斷控制寄存器,寫1使能中斷,寫0禁用中斷(按位配置中斷STOPPED/ERROR/SUSPENDED/RXSTARTED/TXSTARTED/LASTRX/LASTTX
  • INTENSET:中斷使能寄存器,寫1有效
  • INTENCLR:中斷禁用寄存器,寫1有效
  • ERRORSRC:錯誤狀態寄存器,寫1清狀態
  • ENABLE:TWIM外設使能寄存器
  • PLSEL.SCL:關聯SCL時鐘引腳,低4位有效
  • PLSEL.SDA:關聯SDA數據引腳,低4位有效
  • FREQUENCY:TWI通信速率選擇 100k 250k 400k
  • RXD.PTR:接收數據寄存器,指向RXD接收緩存
  • RXD.MAXCNT:接收數據緩存區最大長度
  • RXD.AMOUNT:最近一次數據通信的接收傳輸字節長度
  • RXD.LIST:EasyDMA列表類型,寫1使用arraylist接收緩存,觸發START任務時無需更新PTR數據指針寄存器,類似DMA串口中雙緩存循環讀取
  • TXD.PTR:發送數據寄存器,指向TXD發送緩存
  • TXD.MAXCNT:需要發送數據緩存的最大長度
  • TXD.AMOUNT:最近一次數據通信的發送傳輸字節長度
  • TXD.LIST:EasyDMA列表類型,寫1使用arraylist發送緩存,觸發START任務時無需更新PTR數據指針寄存器,類似DMA串口中雙緩存循環發送
  • ADDRESS:TWI總線的尋址地址,最低位爲讀寫位

四、相關接口

SPIM的驅動目錄在modules\nrfx\drivers\src\nrfx_twim.c

  • nrfx_twim_init:初始化twim,形參nrfx_twim_config_t p_config傳入引腳的映射關係與TWI的參數(通信速率、中斷優先級);函數指針nrfx_twim_evt_handler_t handler用於定義事件回調(數據的發送與接收)
nrfx_err_t nrfx_twim_init(nrfx_twim_t const *        p_instance,
                          nrfx_twim_config_t const * p_config,
                          nrfx_twim_evt_handler_t    event_handler,
                          void *                     p_context)
  • nrfx_twim_uninit:禁用twim外設,系統進入低功耗的時候可以調用
void nrfx_twim_uninit(nrfx_twim_t const * p_instance)
  • nrfx_twim_xfer:數據傳輸接口,形參nrfx_twim_xfer_desc_t const * p_xfer_desc定義了發送TX與接收RX的緩存與長度
nrfx_err_t nrfx_twim_xfer(nrfx_twim_t           const * p_instance,
                          nrfx_twim_xfer_desc_t const * p_xfer_desc,
                          uint32_t                      flags)

五、代碼實例

打開工程目錄 examples\peripheral\twi_master_with_twis_slave.eww,選擇pca10040

貼上例程代碼

/*
* 初始化TWI master
*/
static ret_code_t twi_master_init(void)
{
    ret_code_t ret;
    const nrf_drv_twi_config_t config =
    {
       .scl                = TWI_SCL_M,//選擇pin腳
       .sda                = TWI_SDA_M,
       .frequency          = NRF_DRV_TWI_FREQ_400K,//通信速率
       .interrupt_priority = APP_IRQ_PRIORITY_HIGH,//優先級
       .clear_bus_init     = false
    };

    ret = nrf_drv_twi_init(&m_twi_master, &config, NULL, NULL);//調用配置驅動

    if (NRF_SUCCESS == ret)
    {
        nrf_drv_twi_enable(&m_twi_master);//使能總線
    }

    return ret;
}

/*
* main接口,程序主要是通過軟件模擬了從機與主機的通信
*/
int main(void)
{
    ret_code_t err_code;
    bool epprom_error = 0;
    /* Initialization of UART */

    bsp_board_init(BSP_INIT_LEDS);

    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));

    /* Initializing simulated EEPROM */
    err_code = eeprom_simulator_init();//模擬eeprom twis從機總線初始化
    APP_ERROR_CHECK(err_code);

    /* Initializing TWI master interface for EEPROM */
    err_code = twi_master_init();//主機twim總線初始化
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_clock_init();//時鐘初始化
    APP_ERROR_CHECK(err_code);
    nrf_drv_clock_lfclk_request(NULL);

    err_code = app_timer_init();//定時器初始化
    APP_ERROR_CHECK(err_code);

    nrf_drv_uart_config_t uart_config = NRF_DRV_UART_DEFAULT_CONFIG;//串口配置,可以使用串口命令行控制
    uart_config.pseltxd = TX_PIN_NUMBER;
    uart_config.pselrxd = RX_PIN_NUMBER;
    uart_config.hwfc    = NRF_UART_HWFC_DISABLED;
    err_code = nrf_cli_init(&m_cli_uart, &uart_config, true, true, NRF_LOG_SEVERITY_INFO);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_cli_start(&m_cli_uart);//開啓命令行cli控制
    APP_ERROR_CHECK(err_code);

    /* Welcome message */
    NRF_LOG_RAW_INFO(
            "TWIS and TWI usage example started.\r\n"
            "You can access simulated EEPROM memory using <eeprom> command.\r\n"
            "Execute: <eeprom -h> for more information or press the Tab button "
            "to see all available commands.\r\n"
    );

    /* Main loop */
    while (1)
    {
        UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());
        nrf_cli_process(&m_cli_uart);//處理串口命令

        if (epprom_error != eeprom_simulator_error_check())//錯誤狀態查詢
        {
            epprom_error = eeprom_simulator_error_check();
            if (epprom_error != 0)
            {
                NRF_LOG_RAW_INFO(
                        "WARNING: EEPROM transmission error detected.\r\n"
                        "Use 'x' command to read error word.\r\n"
                );
            }
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章