1. nRF52832 TWI特点
本章描述的是
TWIM (带 EasyDMA 的 TWI 主机) ),本章中的 TWI 均指的是 TWIM
即 TWI 主机。
nRF
52832 片内集成的 TWI 两线串行总线 )兼容 I2C 总线, 带有 EasyDMA ,可与连
接到同一总线的多个从 机 设备 通讯,主要特点如下:
兼容 I2C 。
速率: 100 kbps 、 250 kbps 或 400 kbps 。
支持时钟延伸。
带 EasyDMA 。
TWI 的 SCL 和 SDA 信号可以通过配置寄存器连接到任何一个 GPIO 这样可以灵活地
实现器件引脚排列,并有效利用电路板空间和信号路由 。
nRF52832
的 TWI 的原理框图如下图所示, TWI 主机通过触发 STARTTX 或 STARTRX
任务启动 TWI 传输,通过触发 STOP 任务停止 TWI 传输。 TWI 主机 在挂起时无法停止,因
此必须在 TWI 主机 恢复后 触发 STOP 任务 停止 TWI 。 启动 TWI 主机 后,在 TWI 主机 停止
之前,即在 LASTRX LASTTX 或 STOPPED 事件之后,不应再次触发 STARTTX 任务或
STARTRX 任务 。 如果 从机产生 NACK 输入, 那么 TWI 主 机 将产生 ERROR 事件 。
1.1. EasyDMA
TWI主机 通过 EasyDMA 实现 数据传输 因此 TWI 的接收和发送缓存必须位于 数据
RAM 区域, 如果 TXD.PTR 和 RXD.PTR 未指向数据 RAM 区域,则 EasyDMA 传输可能导
致 HardFault 或 RAM 损坏。
.PTR
和 .MAXCNT 寄存器是双缓冲的 ,因此 在收到 RXSTARTED/TXSTARTED 事件后,
可以 立即更新并准备下一个 RX/TX 传输 。 STOPPED 事件表示 EasyDMA 已完成访问 RAM
中的缓冲区 。
1.2. 低功耗
当系统处于低功耗且不需要TWI 外设时, 为了尽可能降低功耗,应先 停止 TWI ,然后
禁用 TWI 外设来实现最低功耗。
如果
TWI 已经停止,则不需要触发 STOP 任务 停止 TWI ,但是如 TWI 正在执行发送,
则 应等待直到收到 STOPPED 事件作为响应,然后再通过 ENABLE 寄存器禁用外设。
1.3. 引脚配置
TWI的 SC L 和 SDA 信号 可以自由映射,通过设置 PSEL.SCL 和 PSEL.SDA 寄存器 可以将它们映射到任意的 物理引脚 。PSEL.SCL和 PSEL.SDA 寄存器及其配置仅在 TWI 使能时使用,并且仅在器件处于 ON模式时保留 。 TWI 禁用 后 ,引脚将作为常规 GPIO 使用 即可以 使用 GPIO 的 OUT 位字段和 PIN_CNF [n] 寄存器中的配置。 PSEL.SCL 和 PSEL.SDA 必须 在 禁用 TWI 后才可以 配置 。为确保SPIM 中的正确行为,在使用 SPIM 前必须要正确配置 SPIM 的引脚, 但是需要注意的是不能同时将多个 SPIM 外设的信号映射到同一个引脚,如不能将 SPIM0 和 SPIM1的 MISO 同时映射到 P0.05 ,否则 可能会导致不可预测的行为 。当系统处于 OFF 模式时以及 TWI 禁用时, 为 确保 TWI 主机使用的引脚上的信号电平正确 ,这些引脚应按照下表所示配置。
TWI 信号 | SPIM 引脚 | 方向 | 输出值 | 驱动能力 |
SCL | 由 PSEL.SCK 寄存器设置 | 输入。 | 不适用 | S0D1 |
SDA | 由 PSEL. SDA 寄存器设置 | 输入。 | 不适用 | S0D1 |
驱动CHT8305C温湿度传感器
/**
* Copyright (c) 2015 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/** @file
* @defgroup tw_sensor_example main.c
* @{
* @ingroup nrf_twi_example
* @brief TWI Sensor Example main file.
*
* This file contains the source code for a sample application using TWI.
*
*/
#include <stdio.h>
#include "boards.h"
#include "app_util_platform.h"
#include "app_error.h"
#include "nrf_drv_twi.h"
#include "nrf_delay.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
/* TWI instance ID. */
#define TWI_INSTANCE_ID 0
#define TWI_SCL_M 8 //I2C SCL
#define TWI_SDA_M 7 //I2C SDA
#define TWI_IIC_POWER_EN 30 //I2C POWER_EN
#define CHT8305C_ADDRESS_LEN (1)
#define CHT8305C_ADDRESS ((0x80) >> 1)
/* Indicates if operation on TWI has ended. */
static volatile bool m_xfer_done = false;
/* TWI instance. */
static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);
/**
* @brief TWI events handler.
*/
void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{
switch (p_event->type)
{
case NRF_DRV_TWI_EVT_DONE:
m_xfer_done = true;
break;
default:
break;
}
}
/**
* @brief UART initialization.
*/
void twi_init (void)
{
ret_code_t err_code;
const nrf_drv_twi_config_t twi_config = {
.scl = TWI_SCL_M,
.sda = TWI_SDA_M,
.frequency = NRF_DRV_TWI_FREQ_400K,
.interrupt_priority = APP_IRQ_PRIORITY_HIGH,
.clear_bus_init = false
};
err_code = nrf_drv_twi_init(&m_twi, &twi_config, twi_handler, NULL);
if (err_code != NRF_SUCCESS)
{
NRF_LOG_INFO("err_code=%d",err_code);
}
nrf_drv_twi_enable(&m_twi);
}
bool cht8305c_register_write(uint8_t register_address, uint8_t value)
{
ret_code_t err_code;
uint8_t tx_buf[CHT8305C_ADDRESS_LEN+1];
tx_buf[0] = register_address;
tx_buf[1] = value;
m_xfer_done = false;
err_code = nrf_drv_twi_tx(&m_twi, CHT8305C_ADDRESS, tx_buf, CHT8305C_ADDRESS_LEN+1, false);
while (m_xfer_done == false);
if (NRF_SUCCESS != err_code)
{
return false;
}
return true;
}
bool cht8305c_register_read(uint8_t register_address, uint8_t * destination, uint8_t number_of_bytes)
{
ret_code_t err_code;
m_xfer_done = false;
err_code = nrf_drv_twi_tx(&m_twi, CHT8305C_ADDRESS,®ister_address, 1, true);
while (m_xfer_done == false);
if (NRF_SUCCESS != err_code)
{
return false;
}
nrf_delay_ms(20);
m_xfer_done = false;
err_code = nrf_drv_twi_rx(&m_twi, CHT8305C_ADDRESS, destination, number_of_bytes);
while (m_xfer_done == false);
if (NRF_SUCCESS != err_code)
{
return false;
}
return true;
}
bool cht8305c_read_temp_humi(void)
{
uint8_t ct8305_temp_h,ct8305_temp_l;
uint8_t ct8305_humi_h,ct8305_humi_l;
uint32_t cht8305_temp,cht8305_humi;
float CHT8305_temp,CHT8305_humi;
uint8_t destination[4];
memset(destination,0,sizeof(destination));
cht8305c_register_read(0x00,destination,4);
ct8305_temp_h = destination[0];
ct8305_temp_l = destination[1];
ct8305_humi_h = destination[2];
ct8305_humi_l = destination[3];
cht8305_temp = (ct8305_temp_h << 8) + ct8305_temp_l;
cht8305_humi = (ct8305_humi_h << 8) + ct8305_humi_l;
CHT8305_temp = (165*cht8305_temp)/65535.0 - 40.0;
CHT8305_humi = cht8305_humi/65535.0;
NRF_LOG_INFO("%f,%f\n",CHT8305_temp,CHT8305_humi);
return true;
}
/**
* @brief Function for main application entry.
*/
int main(void)
{
APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
NRF_LOG_DEFAULT_BACKENDS_INIT();
nrf_gpio_cfg_output(TWI_IIC_POWER_EN);
nrf_gpio_pin_set(TWI_IIC_POWER_EN);
nrf_delay_ms(500);
NRF_LOG_INFO("\r\nTWI sensor example started.");
NRF_LOG_FLUSH();
twi_init();
while (true)
{
cht8305c_read_temp_humi();
NRF_LOG_FLUSH();
nrf_delay_ms(5000);
}
}
/** @} */
要读取的地址波形err_code = nrf_drv_twi_tx(&m_twi, CHT8305C_ADDRESS,®ister_address, 1, true);
要写的地址波形err_code = nrf_drv_twi_rx(&m_twi, CHT8305C_ADDRESS, destination, number_of_bytes);
温度
湿度