Board 层 API 是涂鸦抽象各芯片硬件外设,封装的一层标准接口。您可以调用这些 API 来使用相应外设,快速实现产品功能,也可以根据需要直接调用原厂外设接口。
Board 层功能模块列表如下:
名称 | API 文件 | 功能说明 |
---|
PIN | ty_pin.h | GPIO 外设相关函数的使用说明 | PWM | ty_pwm.h | PWM 外设相关函数的使用说明 | ADC | ty_adc.h | ADC 外设相关函数的使用说明 | I2C | ty_i2c.h | I2C 外设相关函数的使用说明 | FLASH | ty_flash.h | Flash 外设相关函数的使用说明 |
API Demo 获取:tuya_ble_board_api_demo
一. PIN
1.1 文件说明
API 文件
PIN 相关 API 位于 ty_pin.h 文件中,芯片平台关联的驱动代码位于 ty_pin_xxxx.c 文件中。
tuya_ble_sdk_demo
└── board
├── include
| └── ty_pin.h
├── xxxx /* xxxx 为芯片平台,如 TLSR825x */
| └── ty_board_xxxx /* xxxx 为芯片平台,如 ty_board_tlsr825x */
| └── ty_pin_xxxx.c /* xxxx 为芯片平台,如 ty_pin_tlsr825x.c */
└── board.h
Demo 文件
tuya_board_api_demo 的 PIN Demo 文件结构如下:
tuya_ble_sdk_demo
├── app /* API 应用示例 */
| ├── include
| | └── ty_board_demo
| | | ├── demo_config.h /* demo 配置文件 */
| | | └── ty_pin_demo.h /* pin 模块示例代码 */
| | ├── tuya_ble_board_api_demo.h /* board api 示例程序入口 */
| | └── tuya_ble_sdk_demo.h /* tuya_ble_sdk 应用入口 */
| └── src
| ├── ty_board_demo
| | └── ty_pin_demo.c /* pin 模块示例代码 */
| ├── tuya_ble_board_api_demo.c /* board api 示例程序入口 */
| └── tuya_ble_sdk_demo.c /* tuya_ble_sdk 应用入口 */
└── board /* 部分 API 修改示例 */
修改 demo_config.h 文件即可切换到 PIN 模块示例程序:
#define BOARD_API_DEMO BOARD_API_PIN
1.2 API 列表
1.3 API 说明
ty_pin_init
函数名 | ty_pin_init |
---|
函数原型 | uint32_t ty_pin_init(uint8_t pin, ty_pin_mode_t mode); | 功能概述 | 初始化引脚模式 | 参数 | pin [in]:引脚编号 mode [in]:引脚模式,由 ty_pin_mode_t 类型定义 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_pin_set
函数名 | ty_pin_set |
---|
函数原型 | uint32_t ty_pin_set(uint8_t pin, ty_pin_level_t level); | 功能概述 | 设置引脚的电平 | 参数 | pin [in]:引脚编号 level [in]:引脚电平,由 ty_pin_level_t 类型定义 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_pin_get
函数名 | ty_pin_get |
---|
函数原型 | uint32_t ty_pin_get(uint8_t pin, ty_pin_level_t* p_level); | 功能概述 | 读取引脚的电平 | 参数 | pin [in]:引脚编号 p_level [out]:引脚电平,由 ty_pin_level_t 类型定义 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_pin_control
函数名 | ty_pin_control |
---|
函数原型 | uint32_t ty_pin_control(uint8_t pin, uint8_t cmd, void* arg); | 功能概述 | 控制引脚 | 参数 | pin [in]:引脚编号 cmd [in]:控制命令 arg [in]:命令参数 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_pin_uninit
函数名 | ty_pin_uninit |
---|
函数原型 | uint32_t ty_pin_uninit(uint8_t pin, ty_pin_mode_t mode); | 功能概述 | 设置引脚的电平 | 参数 | pin [in]:引脚编号 mode [in]:引脚模式 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值改 |
1.4 数据结构
ty_pin_mode_t
typedef enum {
TY_PIN_MODE_IN_PU,
TY_PIN_MODE_IN_PD,
TY_PIN_MODE_IN_FL,
TY_PIN_MODE_IN_IRQ_RISE,
TY_PIN_MODE_IN_IRQ_FALL,
TY_PIN_MODE_IN_IRQ_RISE_FALL,
TY_PIN_MODE_IN_IRQ_LOW,
TY_PIN_MODE_IN_IRQ_HIGH,
TY_PIN_MODE_OUT_PP_LOW,
TY_PIN_MODE_OUT_PP_HIGH,
TY_PIN_MODE_OUT_PP_PU_LOW,
TY_PIN_MODE_OUT_PP_PU_HIGH,
TY_PIN_MODE_OUT_PP_PD_LOW,
TY_PIN_MODE_OUT_PP_PD_HIGH,
TY_PIN_MODE_OUT_OD_LOW,
TY_PIN_MODE_OUT_OD_HIZ,
TY_PIN_MODE_OUT_OD_PU_LOW,
TY_PIN_MODE_OUT_OD_PU_HIGH,
} ty_pin_mode_t;
ty_pin_level_t
typedef enum {
TY_PIN_LOW = 0,
TY_PIN_HIGH
} ty_pin_level_t;
1.5 API 示例
以 TLSR825x 平台为例,可参考以下代码补充 PIN 模块的 API 函数,或者直接在应用代码中调用芯片原厂提供的 API 来实现相关功能。
ty_pin.h
uint32_t ty_pin_init(uint16_t pin, ty_pin_mode_t mode);
uint32_t ty_pin_set(uint16_t pin, ty_pin_level_t level);
uint32_t ty_pin_get(uint16_t pin, ty_pin_level_t* p_level);
ty_pin_tlsr825x.c
uint32_t ty_pin_init(uint16_t pin, ty_pin_mode_t mode)
{
gpio_set_func(pin, AS_GPIO);
if ((mode & TY_PIN_INOUT_MASK) <= TY_PIN_IN_IRQ) {
gpio_set_input_en(pin, 1);
gpio_set_output_en(pin, 0);
} else {
gpio_set_input_en(pin, 0);
gpio_set_output_en(pin, 1);
}
switch (mode) {
case TY_PIN_MODE_IN_PU:
gpio_setup_up_down_resistor(pin, PM_PIN_PULLUP_10K);
break;
case TY_PIN_MODE_IN_PD:
gpio_setup_up_down_resistor(pin, PM_PIN_PULLDOWN_100K);
break;
case TY_PIN_MODE_IN_FL:
gpio_setup_up_down_resistor(pin, PM_PIN_UP_DOWN_FLOAT);
break;
case TY_PIN_MODE_OUT_PP_LOW:
gpio_write(pin, 0);
break;
case TY_PIN_MODE_OUT_PP_HIGH:
gpio_write(pin, 1);
break;
default:
break;
}
#if(GPIO_WAKEUP_MODULE_POLARITY == 1)
cpu_set_gpio_wakeup (WAKEUP_MODULE_GPIO, Level_High, 1);
GPIO_WAKEUP_MODULE_LOW;
#else
cpu_set_gpio_wakeup (WAKEUP_MODULE_GPIO, Level_Low, 1);
GPIO_WAKEUP_MODULE_HIGH;
#endif
return 0;
}
uint32_t ty_pin_set(uint16_t pin, ty_pin_level_t level)
{
gpio_write(pin, level);
return 0;
}
uint32_t ty_pin_get(uint16_t pin, ty_pin_level_t* p_level)
{
*p_level = gpio_read(pin);
return 0;
}
1.6 应用示例
功能概述
按键按下 (Low),LED 点亮 (High);按键释放 (High),LED 熄灭 (Low)。
代码示例
以 TLSR825x 平台为例:
#include "ty_pin_demo.h"
#include "ty_pin.h"
#include "tuya_ble_log.h"
#include "tuya_ble_port.h"
#define KEY_PIN GPIO_PA0
#define LED_PIN GPIO_PD7
#define KEY_SCAN_TIME_MS 10
static tuya_ble_timer_t sg_pin_timer;
void __pin_timer_cb(void)
{
ty_pin_level_t pin_level = 0;
ty_pin_get(KEY_PIN, &pin_level);
ty_pin_set(LED_PIN, !pin_level);
}
void ty_pin_demo_init(void)
{
uint32_t res;
res = ty_pin_init(KEY_PIN, TY_PIN_MODE_IN_PU);
if (res) {
TUYA_APP_LOG_ERROR("ty_pin_init KEY_PIN failed, error code: %d", res);
return;
}
res = ty_pin_init(LED_PIN, TY_PIN_MODE_OUT_PP_LOW);
if (res) {
TUYA_APP_LOG_ERROR("ty_pin_init KEY_PIN failed, error code: %d", res);
return;
}
tuya_ble_timer_create(&sg_pin_timer, KEY_SCAN_TIME_MS, TUYA_BLE_TIMER_REPEATED, (tuya_ble_timer_handler_t)__pin_timer_cb);
tuya_ble_timer_start(sg_pin_timer);
}
二. PWM
2.1 文件说明
API 文件
PWM 相关 API 位于 ty_pwm.h 文件中,芯片平台关联的驱动代码位于 ty_pwm_xxxx.c 文件中。
tuya_ble_sdk_demo
└── board
├── include
| └── ty_pwm.h
├── xxxx /* xxxx 为芯片平台,如 TLSR825x */
| └── ty_board_xxxx /* xxxx 为芯片平台,如 ty_board_tlsr825x */
| └── ty_pwm_xxxx.c /* xxxx 为芯片平台,如 ty_pwm_tlsr825x.c */
└── board.h
Demo 文件
tuya_board_api_demo 的 PWM Demo 文件结构如下:
tuya_ble_sdk_demo
├── app /* API 应用示例 */
| ├── include
| | └── ty_board_demo
| | | ├── demo_config.h /* demo 配置文件 */
| | | └── ty_pwm_demo.h /* pwm 模块示例代码 */
| | ├── tuya_ble_board_api_demo.h /* board api 示例程序入口 */
| | └── tuya_ble_sdk_demo.h /* tuya_ble_sdk 应用入口 */
| └── src
| ├── ty_board_demo
| | └── ty_pwm_demo.c /* pwm 模块示例代码 */
| ├── tuya_ble_board_api_demo.c /* board api 示例程序入口 */
| └── tuya_ble_sdk_demo.c /* tuya_ble_sdk 应用入口 */
└── board /* 部分 API 修改示例 */
修改 demo_config.h 文件即可切换到 PWM 模块示例程序:
#define BOARD_API_DEMO BOARD_API_PWM
2.2 API 列表
2.3 API 说明
ty_pwm_init
函数名 | ty_pwm_init |
---|
函数原型 | uint32_t ty_pwm_init(ty_pwm_t* p_pwm); | 功能概述 | 初始化 PWM 模块 | 参数 | p_pwm [in]:pwm 参数,由 ty_pwm_t 类型定义 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_pwm_start
函数名 | ty_pwm_start |
---|
函数原型 | uint32_t ty_pwm_start(ty_pwm_t* p_pwm); | 功能概述 | 启动 PWM 输出 | 参数 | p_pwm [in]:pwm 参数,由 ty_pwm_t 类型定义 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_pwm_stop
函数名 | ty_pwm_stop |
---|
函数原型 | uint32_t ty_pwm_stop(ty_pwm_t* p_pwm); | 功能概述 | 停止 PWM 输出 | 参数 | p_pwm [in]:pwm 参数,由 ty_pwm_t 类型定义 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_pwm_control
函数名 | ty_pwm_control |
---|
函数原型 | uint32_t ty_pwm_control(ty_pwm_t* p_pwm, uint8_t cmd, void* arg); | 功能概述 | 控制 PWM 模块 | 参数 | p_pwm [inout]:pwm 参数,由 ty_pwm_t 类型定义 cmd [in]:控制命令,由 ty_pwm_cmd_t 类型定义 arg [in]:命令参数,取决于控制命令 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_pwm_uninit
函数名 | ty_pwm_uninit |
---|
函数原型 | uint32_t ty_pwm_uninit(ty_pwm_t* p_pwm); | 功能概述 | 关闭 PWM 模块 | 参数 | p_pwm [in]:pwm 参数,由 ty_pwm_t 类型定义 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
2.4 数据结构
ty_pwm_t
typedef struct {
GPIO_PinTypeDef pin;
pwm_id id;
uint8_t polarity;
uint32_t freq;
uint8_t duty;
} ty_pwm_t;
ty_pwm_cmd_t
typedef enum {
TY_PWM_CMD_SET_POLARITY = 0,
TY_PWM_CMD_SET_FREQ,
TY_PWM_CMD_SET_DUTY,
} ty_pwm_cmd_t;
ty_pwm_set_polarity_t
typedef struct {
uint8_t polarity;
} ty_pwm_set_polarity_t;
ty_pwm_set_freq_t
typedef struct {
uint32_t freq;
} ty_pwm_set_freq_t;
ty_pwm_set_duty_t
typedef struct {
uint8_t duty;
} ty_pwm_set_duty_t;
2.5 API 示例
以 TLSR825x 平台为例,可参考以下代码补充 PWM 模块的 API 函数,或者直接在应用代码中调用芯片原厂提供的 API 来实现相关功能。
ty_pwm.h
typedef struct {
GPIO_PinTypeDef pin;
GPIO_FuncTypeDef func;
uint8_t polarity;
uint32_t freq;
uint8_t duty;
} ty_pwm_t;
ty_pwm_tlsr825x.c
uint32_t ty_pwm_init(ty_pwm_t* p_pwm)
{
if (p_pwm == NULL) {
return 1;
}
if (p_pwm->duty < 0 || p_pwm->duty > 100) {
return 2;
}
if (p_pwm->func < AS_PWM0 || p_pwm->func > AS_PWM5_N) {
return 3;
}
pwm_set_clk(CLOCK_SYS_CLOCK_HZ, CLOCK_SYS_CLOCK_HZ);
gpio_set_func(p_pwm->pin, p_pwm->func);
pwm_id id = (p_pwm->func < AS_PWM0_N) ? (p_pwm->func - AS_PWM0) : (p_pwm->func - AS_PWM0_N);
pwm_set_mode(id, PWM_NORMAL_MODE);
pwm_polo_enable(id, p_pwm->polarity);
pwm_set_cycle_and_duty(id, (uint16_t)(p_pwm->freq * CLOCK_SYS_CLOCK_1US),
(uint16_t)(p_pwm->freq * CLOCK_SYS_CLOCK_1US * p_pwm->duty / 100));
return 0;
}
uint32_t ty_pwm_start(ty_pwm_t* p_pwm)
{
if (p_pwm == NULL) {
return 1;
}
if (p_pwm->duty < 0 || p_pwm->duty > 100) {
return 2;
}
if (p_pwm->func < AS_PWM0 || p_pwm->func > AS_PWM5_N) {
return 3;
}
pwm_id id = (p_pwm->func < AS_PWM0_N) ? (p_pwm->func - AS_PWM0) : (p_pwm->func - AS_PWM0_N);
pwm_start(id);
return 0;
}
uint32_t ty_pwm_stop(ty_pwm_t* p_pwm)
{
if (p_pwm == NULL) {
return 1;
}
if (p_pwm->func < AS_PWM0 || p_pwm->func > AS_PWM5_N) {
return 3;
}
pwm_id id = (p_pwm->func < AS_PWM0_N) ? (p_pwm->func - AS_PWM0) : (p_pwm->func - AS_PWM0_N);
pwm_stop(id);
return 0;
}
uint32_t ty_pwm_control(ty_pwm_t* p_pwm, uint8_t cmd, void* arg)
{
if ((p_pwm == NULL) || (arg == NULL)) {
return 1;
}
if (p_pwm->func < AS_PWM0 || p_pwm->func > AS_PWM5_N) {
return 3;
}
pwm_id id = (p_pwm->func < AS_PWM0_N) ? (p_pwm->func - AS_PWM0) : (p_pwm->func - AS_PWM0_N);
switch(cmd) {
case TY_PWM_CMD_SET_POLARITY: {
ty_pwm_set_polarity_t* param = arg;
p_pwm->polarity = param->polarity;
pwm_polo_enable(id, p_pwm->polarity);
}
break;
case TY_PWM_CMD_SET_FREQ: {
ty_pwm_set_freq_t* param = arg;
p_pwm->freq = param->freq;
pwm_set_cycle_and_duty(id, (uint16_t)(p_pwm->freq * CLOCK_SYS_CLOCK_1US),
(uint16_t)(p_pwm->freq * CLOCK_SYS_CLOCK_1US * p_pwm->duty / 100));
}
break;
case TY_PWM_CMD_SET_DUTY: {
ty_pwm_set_duty_t* param = arg;
if (p_pwm->duty < 0 || p_pwm->duty > 100) {
return 2;
}
p_pwm->duty = param->duty;
pwm_set_cmp(id, (uint16_t)(p_pwm->freq * CLOCK_SYS_CLOCK_1US * p_pwm->duty / 100));
}
break;
default:
break;
}
return 0;
}
uint32_t ty_pwm_uninit(ty_pwm_t* p_pwm)
{
uint32_t res = ty_pwm_stop(p_pwm);
if (res) {
return res;
}
gpio_set_func(p_pwm->pin, AS_GPIO);
return 0;
}
2.6 应用示例
功能概述
初期输出周期 500us,占空比 50%,极性高电平的 PWM 波形;2s 后,更新占空比为 80%;再 2s 后,更新周期为 800us;再 2s 后,更新极性为低电平;再 2s 后,停止 PWM 输出并关闭 PWM 模块。
代码示例
以 TLSR825x 平台为例:
#include "ty_pwm_demo.h"
#include "ty_pwm.h"
#include "tuya_ble_log.h"
#include "tuya_ble_port.h"
#define PWM_PIN GPIO_PB5
#define PWM_FUNC AS_PWM5
#define PWM_POL 0
#define PWM_POL_UPDATE 1
#define PWM_FREQ 500
#define PWM_FREQ_UPDATE 800
#define PWM_DUTY 50
#define PWM_DUTY_UPDATE 80
#define PWM_UPDATE_TIME_MS 2000
static ty_pwm_t sg_pwm = {
.pin = PWM_PIN,
.func = PWM_FUNC,
.polarity = PWM_POL,
.freq = PWM_FREQ,
.duty = PWM_DUTY
};
static tuya_ble_timer_t sg_pwm_timer;
void __pwm_timer_cb(void)
{
static uint8_t s_step = 0;
switch (s_step) {
case 0: {
ty_pwm_set_duty_t new_duty = {
.duty = PWM_DUTY_UPDATE
};
ty_pwm_control(&sg_pwm, TY_PWM_CMD_SET_DUTY, &new_duty);
}
break;
case 1: {
ty_pwm_set_freq_t new_freq = {
.freq = PWM_FREQ_UPDATE
};
ty_pwm_control(&sg_pwm, TY_PWM_CMD_SET_FREQ, &new_freq);
}
break;
case 2: {
ty_pwm_set_polarity_t new_pol = {
.polarity = PWM_POL_UPDATE
};
ty_pwm_control(&sg_pwm, TY_PWM_CMD_SET_POLARITY, &new_pol);
}
break;
case 3: {
ty_pwm_stop(&sg_pwm);
ty_pwm_uninit(&sg_pwm);
}
break;
default:
break;
}
if (s_step <= 3) {
s_step++;
}
}
void ty_pwm_demo_init(void)
{
uint32_t res;
res = ty_pwm_init(&sg_pwm);
if (res) {
TUYA_APP_LOG_ERROR("ty_pwm_init failed, error code: %d", res);
return;
}
res = ty_pwm_start(&sg_pwm);
if (res) {
TUYA_APP_LOG_ERROR("ty_pwm_start failed, error code: %d", res);
return;
}
tuya_ble_timer_create(&sg_pwm_timer, PWM_UPDATE_TIME_MS, TUYA_BLE_TIMER_REPEATED, (tuya_ble_timer_handler_t)__pwm_timer_cb);
tuya_ble_timer_start(sg_pwm_timer);
}
三. ADC
3.1 文件说明
API 文件
ADC 相关 API 位于 ty_adc.h 文件中,芯片平台关联的驱动代码位于 ty_adc_xxxx.c 文件中。
tuya_ble_sdk_demo
└── board
├── include
| └── ty_adc.h
├── xxxx /* xxxx 为芯片平台,如 TLSR825x */
| └── ty_board_xxxx /* xxxx 为芯片平台,如 ty_board_tlsr825x */
| └── ty_adc_xxxx.c /* xxxx 为芯片平台,如 ty_adc_tlsr825x.c */
└── board.h
Demo 文件
tuya_board_api_demo 的 ADC Demo 文件结构如下:
tuya_ble_sdk_demo
├── app /* API 应用示例 */
| ├── include
| | └── ty_board_demo
| | | ├── demo_config.h /* demo 配置文件 */
| | | └── ty_adc_demo.h /* adc 模块示例代码 */
| | ├── tuya_ble_board_api_demo.h /* board api 示例程序入口 */
| | └── tuya_ble_sdk_demo.h /* tuya_ble_sdk 应用入口 */
| └── src
| ├── ty_board_demo
| | └── ty_adc_demo.c /* adc 模块示例代码 */
| ├── tuya_ble_board_api_demo.c /* board api 示例程序入口 */
| └── tuya_ble_sdk_demo.c /* tuya_ble_sdk 应用入口 */
└── board /* 部分 API 修改示例 */
修改 demo_config.h 文件即可切换到 ADC 模块示例程序:
#define BOARD_API_DEMO BOARD_API_ADC
3.2 API 列表
3.3 API 说明
ty_adc_init
函数名 | ty_adc_init |
---|
函数原型 | uint32_t ty_adc_init(ty_adc_t* p_adc); | 功能概述 | 初始化 ADC 模块 | 参数 | p_adc [in]:adc 参数,由 ty_adc_t 类型定义 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_adc_start
函数名 | ty_adc_start |
---|
函数原型 | uint32_t ty_adc_start(ty_adc_t* p_adc); | 功能概述 | 启动 ADC 采样 | 参数 | p_adc [inout]:adc 参数,由 ty_adc_t 类型定义 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_adc_stop
函数名 | ty_adc_stop |
---|
函数原型 | uint32_t ty_adc_stop(ty_adc_t* p_adc); | 功能概述 | 停止 ADC 采样 | 参数 | p_adc [in]:adc 参数,由 ty_adc_t 类型定义 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_adc_control
函数名 | ty_adc_control |
---|
函数原型 | uint32_t ty_adc_control(ty_adc_t* p_adc, uint8_t cmd, void* arg); | 功能概述 | 控制 ADC 模块 | 参数 | p_adc [in]:adc 参数,由 ty_adc_t 类型定义 cmd [in]:控制命令 arg [in]:命令参数 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_adc_uninit
函数名 | ty_adc_uninit |
---|
函数原型 | uint32_t ty_adc_uninit(ty_adc_t* p_adc); | 功能概述 | 关闭 ADC 模块 | 参数 | p_adc [in]:adc 参数,由 ty_adc_t 类型定义 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
3.4 数据结构
ty_adc_t
typedef struct {
GPIO_PinTypeDef pin;
ADC_InputPchTypeDef channel;
uint32_t value;
} ty_adc_t;
typedef struct {
uint8_t channel;
int16_t value;
} ty_adc_t;
3.5 API 示例
以 TLSR825x 平台为例,可参考以下代码补充 ADC 模块的 API 函数,或者直接在应用代码中调用芯片原厂提供的 API 来实现相关功能。
ty_adc.h
typedef struct {
GPIO_PinTypeDef pin;
uint32_t value;
} ty_adc_t;
ty_adc_tlsr825x.c
uint32_t ty_adc_init(ty_adc_t* p_adc)
{
adc_init();
adc_base_init(p_adc->pin);
adc_power_on_sar_adc(1);
}
uint32_t ty_adc_start(ty_adc_t* p_adc)
{
p_adc.value = adc_sample_and_get_result();
return 0;
}
3.6 应用示例
功能概述
采集 ADC 引脚的电压值,每秒读取 1 次。
代码示例
以 TLSR825x 平台为例:
#include "ty_adc_demo.h"
#include "ty_adc.h"
#include "tuya_ble_log.h"
#include "tuya_ble_port.h"
#define ADC_PIN GPIO_PB6
#define ADC_SAMPLE_TIME_MS 1000
static ty_adc_t sg_adc = {
.pin = ADC_PIN,
.value = 0
};
static tuya_ble_timer_t sg_adc_timer;
void __adc_timer_cb(void)
{
uint32_t res = ty_adc_start(&sg_adc);
if (res) {
TUYA_APP_LOG_ERROR("ty_adc_start failed, error code: %d", res);
} else {
TUYA_APP_LOG_INFO("adc_value is: %d mV", sg_adc.value);
}
}
void ty_adc_demo_init(void)
{
uint32_t res = ty_adc_init(&sg_adc);
if (res) {
TUYA_APP_LOG_ERROR("ty_adc_init failed, error code: %d", res);
return;
}
tuya_ble_timer_create(&sg_adc_timer, ADC_SAMPLE_TIME_MS, TUYA_BLE_TIMER_REPEATED, (tuya_ble_timer_handler_t)__adc_timer_cb);
tuya_ble_timer_start(sg_adc_timer);
}
四. I2C
4.1 文件说明
API 文件
I2C 相关 API 位于 ty_i2c.h 文件中,芯片平台关联的驱动代码位于 ty_i2c_xxxx.c 文件中。
tuya_ble_sdk_demo
└── board
├── include
| └── ty_i2c.h
├── xxxx /* xxxx 为芯片平台,如 TLSR825x */
| └── ty_board_xxxx /* xxxx 为芯片平台,如 ty_board_tlsr825x */
| └── ty_i2c_xxxx.c /* xxxx 为芯片平台,如 ty_i2c_tlsr825x.c */
└── board.h
Demo 文件
tuya_board_api_demo 的 I2C Demo 文件结构如下:
tuya_ble_sdk_demo
├── app /* API 应用示例 */
| ├── include
| | └── ty_board_demo
| | | ├── demo_config.h /* demo 配置文件 */
| | | └── ty_i2c_demo.h /* i2c 模块示例代码 */
| | ├── tuya_ble_board_api_demo.h /* board api 示例程序入口 */
| | └── tuya_ble_sdk_demo.h /* tuya_ble_sdk 应用入口 */
| └── src
| ├── ty_board_demo
| | └── ty_i2c_demo.c /* i2c 模块示例代码 */
| ├── tuya_ble_board_api_demo.c /* board api 示例程序入口 */
| └── tuya_ble_sdk_demo.c /* tuya_ble_sdk 应用入口 */
└── board /* 部分 API 修改示例 */
修改 demo_config.h 文件即可切换到 I2C 模块示例程序:
#define BOARD_API_DEMO BOARD_API_I2C
4.2 API 列表
4.3 API 说明
ty_i2c_init
函数名 | ty_i2c_init |
---|
函数原型 | uint32_t ty_i2c_init(void); | 功能概述 | 初始化 I2C 模块 | 参数 | 无 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_i2c_start
函数名 | ty_i2c_start |
---|
函数原型 | uint32_t ty_i2c_start(void); | 功能概述 | 硬件 I2C:启动 I2C 传输 | 参数 | 无 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_i2c_stop
函数名 | ty_i2c_stop |
---|
函数原型 | uint32_t ty_i2c_stop(void); | 功能概述 | 硬件 I2C:停止 I2C 传输 | 参数 | 无 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_i2c_control
函数名 | ty_i2c_control |
---|
函数原型 | uint32_t ty_i2c_control(uint8_t cmd, void* arg); | 功能概述 | 硬件I2C:控制 I2C 模块 | 参数 | cmd [in]:控制命令 arg [in]:命令参数 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_i2c_uninit
函数名 | ty_i2c_uninit |
---|
函数原型 | uint32_t ty_i2c_uninit(void); | 功能概述 | 硬件 I2C:关闭 I2C 模块 | 参数 | 无 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_i2c_send
函数名 | ty_i2c_send |
---|
函数原型 | uint32_t ty_i2c_send(const uint8_t addr, const uint8_t* buf, uint32_t size); | 功能概述 | 硬件 I2C:发送数据 | 参数 | addr [in]:地址 buf [in]:发送数据 size [in]:数据大小 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
i2c_send_bytes
函数名 | i2c_send_bytes |
---|
函数原型 | void i2c_send_bytes(uint8_t adderss_cmd, uint8_t *buff, uint8_t len); | 功能概述 | 软件 I2C:发送多个字节数据 | 参数 | adderss_cmd [in]:“从机地址+读写命令”字节 buff [in]:发送数据 len [in]:数据长度 | 返回值 | 无 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
i2c_rcv_bytes
函数名 | i2c_rcv_bytes |
---|
函数原型 | void i2c_rcv_bytes(uint8_t adderss_cmd, uint8_t *buff, uint8_t len); | 功能概述 | 软件 I2C:接收多个字节数据 | 参数 | adderss_cmd [in]:“从机地址+读写命令”字节 buff [out]:接收数据 len [in]:数据长度 | 返回值 | 无 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
i2c_soft_cfg
函数名 | i2c_soft_cfg |
---|
函数原型 | void i2c_soft_cfg(uint8_t adderss_cmd, uint8_t reg_addr, uint8_t data); | 功能概述 | 软件 I2C:配置从机寄存器 | 参数 | adderss_cmd [in]:“从机地址+读写命令”字节 reg_addr [in]:寄存器地址 data [in]:寄存器值 | 返回值 | 无 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
i2c_soft_gpio_init
函数名 | i2c_soft_gpio_init |
---|
函数原型 | void i2c_soft_gpio_init(void); | 功能概述 | 软件 I2C:初始 I2C 引脚 | 参数 | 无 | 返回值 | 无 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
i2c_start
函数名 | i2c_start |
---|
函数原型 | void i2c_start(void); | 功能概述 | 软件 I2C:发送起始信号 | 参数 | 无 | 返回值 | 无 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
i2c_stop
函数名 | i2c_stop |
---|
函数原型 | void i2c_stop(void); | 功能概述 | 软件 I2C:发送停止信号 | 参数 | 无 | 返回值 | 无 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
i2c_delay
函数名 | i2c_delay |
---|
函数原型 | void i2c_delay(unsigned long tim_1us); | 功能概述 | 软件 I2C:微秒级延时 | 参数 | tim_1us[in]:微秒值 | 返回值 | 无 | 备注 | 无 |
4.4 数据结构
无。
4.5 API 示例
以 TLSR825x 平台为例,可参考以下代码补充 I2C 模块的 API 函数,或者直接在应用代码中调用芯片原厂提供的 API 来实现相关功能。
ty_i2c.h
#define USE_SOFT_I2C 0
uint32_t ty_i2c_send(const uint32_t addr, const uint8_t addr_len, const uint8_t* buf, uint32_t size);
uint32_t ty_i2c_rcv(const uint32_t addr, const uint8_t addr_len, uint8_t* buf, uint32_t size);
ty_i2c_tlsr825x.c
#define TLSR_I2C_GPIO_GROUP I2C_GPIO_GROUP_C0C1
#define I2C_PIN_SDA GPIO_PC0
#define I2C_PIN_SCL GPIO_PC1
#define SLAVE_ADDR_WRITE (0x44 << 1 | 0x00)
uint32_t ty_i2c_init(void)
{
i2c_gpio_set(TLSR_I2C_GPIO_GROUP);
i2c_master_init(SLAVE_ADDR_WRITE, (unsigned char)(CLOCK_SYS_CLOCK_HZ/(4*200000)));
return 0;
}
uint32_t ty_i2c_send(const uint32_t addr, const uint8_t addr_len, const uint8_t* buf, uint32_t size)
{
i2c_write_series(addr, addr_len, buf, size);
return 0;
}
uint32_t ty_i2c_rcv(const uint32_t addr, const uint8_t addr_len, uint8_t* buf, uint32_t size)
{
i2c_read_series(addr, addr_len, buf, size);
return 0;
}
4.6 应用示例
功能概述
使用硬件 I2C 或 软件 I2C 驱动从机设备,定时采集传感器数据。
代码示例
以 TLSR825x 平台为例。
I2C_API_DEMO_SHT3X - 温湿度传感器 SHT30-DIS 驱动示例
传感资料:
注:SHT3x 的 16 位命令可以作为寄存器地址使用。
#include "ty_i2c_demo.h"
#include "ty_i2c.h"
#include "tuya_ble_log.h"
#include "tuya_ble_port.h"
#define I2C_API_DEMO_S 0x00
#define I2C_API_DEMO_H 0x01
#define I2C_API_DEMO_MODE I2C_API_DEMO_S
#define I2C_SLAVE_ADDR 0x44
#define I2C_DAQ_TIME_MS 1000
#define SHT3X_CMD_MEAS_PERI_1_H 0x2130
#define SHT3X_CMD_FETCH_DATA 0xE000
#define I2C_CMD_BIT_WRITE 0
#define I2C_CMD_BIT_READ 1
#define I2C_ADDR_CMD_W (I2C_SLAVE_ADDR << 1 | I2C_CMD_BIT_WRITE)
#define I2C_ADDR_CMD_R (I2C_SLAVE_ADDR << 1 | I2C_CMD_BIT_READ)
static tuya_ble_timer_t sg_daq_timer;
static uint8_t __check_crc_8(uint8_t* data, uint16_t len, uint8_t crc_val)
{
uint8_t i;
uint8_t crc = 0xFF;
while (len--) {
crc ^= *data;
for (i = 8; i > 0; --i) {
if (crc & 0x80) {
crc = (crc << 1) ^ 0x31;
} else {
crc = (crc << 1);
}
}
data++;
}
if (crc != crc_val){
return 0;
}
return 1;
}
static void __i2c_write_cmd_sht3x(uint16_t cmd, bool stop)
{
#if (I2C_API_DEMO_MODE == I2C_API_DEMO_S)
uint8_t cmd_bytes[2];
cmd_bytes[0] = (uint8_t)(cmd >> 8);
cmd_bytes[1] = (uint8_t)(cmd & 0x00FF);
i2c_start();
i2c_send_bytes(I2C_ADDR_CMD_W, cmd_bytes, 2);
if (stop) {
i2c_stop();
}
#else
ty_i2c_send(cmd, 2, null, 0);
#endif
}
static void __i2c_read_data_sht3x(uint8_t *buf, uint8_t len)
{
#if (I2C_API_DEMO_MODE == I2C_API_DEMO_S)
i2c_start();
i2c_rcv_bytes(I2C_ADDR_CMD_R, buf, len);
i2c_stop();
#else
ty_i2c_rcv(0, 0, buf, len);
#endif
}
static void __daq_timer_handler(void)
{
uint8_t buf[6];
__i2c_write_cmd_sht3x(SHT3X_CMD_FETCH_DATA, 0);
__i2c_read_data_sht3x(buf, 6);
if ((!__check_crc_8(buf, 2, buf[2])) ||
(!__check_crc_8(buf+3, 2, buf[5]))) {
TUYA_APP_LOG_ERROR("__sht3x_check_crc failed.");
return;
}
int32_t temp = ((int16_t)buf[0] << 8 | buf[1]) * 175 / 65535 - 45;
uint32_t humi = ((uint16_t)buf[3] << 8 | buf[4]) * 100 / 65535;
TUYA_APP_LOG_INFO("Temperature: %d, Humidity: %d", temp, humi);
}
void ty_i2c_demo_init(void)
{
#if (I2C_API_DEMO_MODE == I2C_API_DEMO_S)
i2c_soft_gpio_init();
#else
ty_i2c_init();
#endif
__i2c_write_cmd_sht3x(SHT3X_CMD_MEAS_PERI_1_H, 0);
tuya_ble_timer_create(&sg_daq_timer, I2C_DAQ_TIME_MS, TUYA_BLE_TIMER_REPEATED, (tuya_ble_timer_handler_t)__daq_timer_handler);
tuya_ble_timer_start(sg_daq_timer);
}
I2C_API_DEMO_MPU6050 - 运动传感器 MPU6050 驱动示例
传感资料:
#include "ty_i2c_demo.h"
#include "ty_i2c.h"
#include "tuya_ble_log.h"
#include "tuya_ble_port.h"
#define I2C_API_DEMO_S 0x00
#define I2C_API_DEMO_H 0x01
#define I2C_API_DEMO_MODE I2C_API_DEMO_S
#define I2C_SLAVE_ADDR 0x68
#define I2C_DAQ_TIME_MS 5
#define MPU6050_DEV_ID 0x68
#define MPU6050_RA_SMPRT_DIV 0x19
#define MPU6050_RA_CONFIG 0x1A
#define MPU6050_RA_GYRO_CONFIG 0x1B
#define MPU6050_RA_ACCEL_CONFIG 0x1C
#define MPU6050_RA_ACCEL_XOUT_H 0x3B
#define MPU6050_RA_PWR_MGMT_1 0x6B
#define MPU6050_RA_WHO_AM_I 0x75
#define I2C_CMD_BIT_WRITE 0
#define I2C_CMD_BIT_READ 1
#define I2C_ADDR_CMD_W (I2C_SLAVE_ADDR << 1 | I2C_CMD_BIT_WRITE)
#define I2C_ADDR_CMD_R (I2C_SLAVE_ADDR << 1 | I2C_CMD_BIT_READ)
static tuya_ble_timer_t sg_daq_timer;
static void __i2c_write_reg(uint8_t reg_addr, uint8_t reg_val)
{
#if (I2C_API_DEMO_MODE == I2C_API_DEMO_S)
i2c_soft_cfg(I2C_ADDR_CMD_W, reg_addr, reg_val);
#else
ty_i2c_send(reg_addr, 1, ®_val, 1);
#endif
}
static void __i2c_read_reg(uint8_t reg_addr, uint8_t *reg_val, uint8_t len)
{
#if (I2C_API_DEMO_MODE == I2C_API_DEMO_S)
i2c_start();
i2c_send_bytes(I2C_ADDR_CMD_W, ®_addr, 1);
i2c_start();
i2c_rcv_bytes(I2C_ADDR_CMD_R, reg_val, len);
i2c_stop();
#else
ty_i2c_rcv(reg_addr, 1, reg_val, len);
#endif
}
static void __daq_timer_handler(void)
{
uint8_t i;
uint8_t tmp_buf[14];
int16_t accel[3], gyro[3];
__i2c_read_reg(MPU6050_RA_ACCEL_XOUT_H, tmp_buf, 14);
for (i = 0; i < 3; i++) {
accel[i] = ((int16_t)tmp_buf[i*2] << 8) | tmp_buf[i*2+1];
accel[i] /= 2048;
gyro[i] = ((int16_t)tmp_buf[i*2+8] << 8) | tmp_buf[i*2+9];
gyro[i] = gyro[i] * 10 / 164;
}
TUYA_APP_LOG_INFO("ax: %d, ay: %d, az: %d, gx: %d, gy: %d, gz: %d",
accel[0], accel[1], accel[2], gyro[0], gyro[1], gyro[2]);
}
void ty_i2c_demo_init(void)
{
#if (I2C_API_DEMO_MODE == I2C_API_DEMO_S)
i2c_soft_gpio_init();
#else
ty_i2c_init();
#endif
__i2c_write_reg(MPU6050_RA_PWR_MGMT_1, 0x80);
i2c_delay(200*1000);
uint8_t dev_id;
__i2c_read_reg(MPU6050_RA_WHO_AM_I, &dev_id, 1);
if (dev_id != MPU6050_DEV_ID) {
TUYA_APP_LOG_ERROR("MPU6050 is not found.");
return;
}
__i2c_write_reg(MPU6050_RA_PWR_MGMT_1, 0x01);
__i2c_write_reg(MPU6050_RA_GYRO_CONFIG, 0x03);
__i2c_write_reg(MPU6050_RA_ACCEL_CONFIG, 0x03);
__i2c_write_reg(MPU6050_RA_SMPRT_DIV, 0x04);
__i2c_write_reg(MPU6050_RA_CONFIG, 0x02);
tuya_ble_timer_create(&sg_daq_timer, I2C_DAQ_TIME_MS, TUYA_BLE_TIMER_REPEATED, (tuya_ble_timer_handler_t)__daq_timer_handler);
tuya_ble_timer_start(sg_daq_timer);
}
五. FLASH
5.1 文件说明
API 文件
Flash 相关 API 位于 ty_flash.h 文件中,芯片平台关联的驱动代码位于 ty_flash_xxxx.c 文件中。
tuya_ble_sdk_demo
└── board
├── include
| └── ty_flash.h
├── xxxx /* xxxx 为芯片平台,如 TLSR825x */
| └── ty_board_xxxx /* xxxx 为芯片平台,如 ty_board_tlsr825x */
| └── ty_flash_xxxx.c /* xxxx 为芯片平台,如 ty_flash_tlsr825x.c */
└── board.h
Demo 文件
tuya_board_api_demo 的 Flash Demo 文件结构如下:
tuya_ble_sdk_demo
├── app /* API 应用示例 */
| ├── include
| | └── ty_board_demo
| | | ├── demo_config.h /* demo 配置文件 */
| | | └── ty_flash_demo.h /* flash 模块示例代码 */
| | ├── tuya_ble_board_api_demo.h /* board api 示例程序入口 */
| | └── tuya_ble_sdk_demo.h /* tuya_ble_sdk 应用入口 */
| └── src
| ├── ty_board_demo
| | └── ty_flash_demo.c /* flash 模块示例代码 */
| ├── tuya_ble_board_api_demo.c /* board api 示例程序入口 */
| └── tuya_ble_sdk_demo.c /* tuya_ble_sdk 应用入口 */
└── board /* 部分 API 修改示例 */
修改 demo_config.h 文件即可切换到 Flash 模块示例程序:
#define BOARD_API_DEMO BOARD_API_FLASH
5.2 API 列表
5.3 API 说明
ty_flash_init
函数名 | ty_flash_init |
---|
函数原型 | uint32_t ty_flash_init(void); | 功能概述 | 初始化 Flash 模块 | 参数 | 无 | 返回值 | 0 :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_flash_read
函数名 | ty_flash_read |
---|
函数原型 | uint32_t ty_flash_read(uint32_t addr, uint8_t* buf, uint32_t size); | 功能概述 | 读取 Flash | 参数 | addr [in]:起始地址 buf [out]:Flash 数据 size [in]:数据大小 | 返回值 | TUYA_BLE_SUCCESS :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_flash_write
函数名 | ty_flash_write |
---|
函数原型 | uint32_t ty_flash_write(uint32_t addr, const uint8_t* buf, uint32_t size); | 功能概述 | 写入 Flash | 参数 | addr [in]:起始地址 buf [in]:Flash 数据 size [in]:数据大小 | 返回值 | TUYA_BLE_SUCCESS :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_flash_erase
函数名 | ty_flash_erase |
---|
函数原型 | uint32_t ty_flash_erase(uint32_t addr, uint32_t num); | 功能概述 | 擦除 Flash | 参数 | addr [in]:起始地址 num [in]:擦除单位的个数 | 返回值 | TUYA_BLE_SUCCESS :成功;其他:失败 | 备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值,不同芯片平台的擦除单位可能不同 |
5.4 数据结构
无。
5.5 API 示例
无。可直接使用 SDK 中的 API 函数。
5.6 应用示例
功能概述
上电后读取 Flash 并打印,如果已写入过数据,擦除 Flash 后将新数据写入 Flash,擦除和写入操作后读一次数据用来检查操作是否成功。
代码示例
以 TLSR825x 平台为例:(Flash 地址可查看 tuya_ble_sdk_demo\doc 目录下的 flash 分区表)
#include "ty_flash_demo.h"
#include "ty_flash.h"
#include "tuya_ble_log.h"
#define FLASH_ADDR_STA 0x034000
#define FLASH_BUF_SIZE 4
void ty_flash_demo_init(void)
{
uint8_t i;
uint8_t flash_buf[FLASH_BUF_SIZE];
uint8_t flash_buf_tmp[FLASH_BUF_SIZE];
ty_flash_read(FLASH_ADDR_STA, flash_buf, FLASH_BUF_SIZE);
for (i = 0; i < FLASH_BUF_SIZE; i++) {
TUYA_APP_LOG_INFO("The data in %x is %02x", FLASH_ADDR_STA + 8*i, flash_buf[i]);
}
if (flash_buf[0] != 0xFF) {
ty_flash_erase(FLASH_ADDR_STA, 1);
ty_flash_read(FLASH_ADDR_STA, flash_buf_tmp, FLASH_BUF_SIZE);
for (i = 0; i < FLASH_BUF_SIZE; i++) {
TUYA_APP_LOG_INFO("The data in %x is %02x", FLASH_ADDR_STA + 8*i, flash_buf_tmp[i]);
}
}
for (i = 0; i < FLASH_BUF_SIZE; i++) {
flash_buf[i] += (i+1);
}
ty_flash_write(FLASH_ADDR_STA, flash_buf, FLASH_BUF_SIZE);
ty_flash_read(FLASH_ADDR_STA, flash_buf_tmp, FLASH_BUF_SIZE);
for (i = 0; i < FLASH_BUF_SIZE; i++) {
TUYA_APP_LOG_INFO("The data in %x is %02x", FLASH_ADDR_STA + 8*i, flash_buf_tmp[i]);
}
}
上一篇: 第 7 课:SDK API 说明 下一篇: 无
|