文章目录
- 一、简介
- 二、特性
- 三、 示例代码
一、简介
4pin控制16ping,IO扩展器件
二、特性
- 16 个等电流输出通道
- 等电流输出值不受输出端负载电压影响等电流范围值,
- 3-30mA@VDp=5V;
- 3-15mA@Vpp=3.3V
- 极为精确的电流输出值,
- 通道间差异值: <±1.5%(一般值);<±2.5%(最大值);
- 芯片间差异值: <±1.5%(一般值);<±3.0% (最大值)。
- 利用一个外接电阻,可设定电流输出值
- 快速的输出电流响应, OE: 45ns (保持输出一致性的条件下)高达 25MHz 时钟频率
- 具 Schmitt trigger 输入
- 装置操作电压: 3.3/5 伏特
- 封装湿度敏感等级:3
三、 示例代码
/********************************************************************************
* @file extend_16ch.c
* @author jianqiang.xue
* @version V1.0.0
* @date 2023-04-07
* @brief 16位恒流驱动芯片 MBI5020 JXI5020GP对于ARM_M平台 @16M
1个NOP:(1/24000000)*1000*1000*1000==41.67ns
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); \
对于n76e003平台 @16M
1个nop 占用87ns
while(1) 占用194ns
函数调用 占用570ns如果没有APP_IO,则需要在外部实现该结构体
static const extend_16ch_gpio_t io = {.clk_pin = {GPIOC, GPIO_PIN_5, GPIO_CLK(GPIOC)},.sdi_pin = {GPIOC, GPIO_PIN_6, GPIO_CLK(GPIOC)},.le_pin = {GPIOC, GPIO_PIN_4, GPIO_CLK(GPIOC)},.oe_pin = {GPIOC, GPIO_PIN_3, GPIO_CLK(GPIOC)},
}
********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>/* Private Includes ----------------------------------------------------------*/
#include "extend_16ch.h"
#include "bsp_gpio.h"#ifdef LISUN_SDK
#include "ls_gpio.h"
#include "ls_syscfg.h"
#endif/* Private Define ------------------------------------------------------------*/
/* Private Typedef -----------------------------------------------------------*/
/* Private Macro -------------------------------------------------------------*/
/* Private Variables ---------------------------------------------------------*/
#ifndef APP_IO
#define GPIO_APBx (0)
#else
#include "app_io.h"
#include "bsp_pwm.h"
#define PWMx g_io.type[io->oe_pin]-IO_TYPE_TIM1_CH1
#endif
/* Private Function Prototypes -----------------------------------------------*/
/* Public Function Prototypes ------------------------------------------------*/
/*** @brief 器件硬件初始化* @param *io: 引脚配置*/
void extend_16ch_init(extend_16ch_gpio_t *io) {
#ifndef APP_IO/* Enable the GPIO Clock */bsp_gpio_set_clk(GPIO_APBx, io->clk_pin.periph, true);/* Configure the GPIO pin */bsp_gpio_init_output(io->clk_pin.port, io->clk_pin.pin, BSP_GPIO_PIN_OUT_PP);/* Reset PIN to switch off the */bsp_gpio_set_pin(io->clk_pin.port, io->clk_pin.pin, BSP_GPIO_PIN_RESET);/* Enable the GPIO Clock */bsp_gpio_set_clk(GPIO_APBx, io->sdi_pin.periph, true);/* Configure the GPIO pin */bsp_gpio_init_output(io->sdi_pin.port, io->sdi_pin.pin, BSP_GPIO_PIN_OUT_PP);/* Reset PIN to switch off the */bsp_gpio_set_pin(io->sdi_pin.port, io->sdi_pin.pin, BSP_GPIO_PIN_RESET);/* Enable the GPIO Clock */bsp_gpio_set_clk(GPIO_APBx, io->le_pin.periph, true);/* Configure the GPIO pin */bsp_gpio_init_output(io->le_pin.port, io->le_pin.pin, BSP_GPIO_PIN_OUT_PP);/* Reset PIN to switch off the */bsp_gpio_set_pin(io->le_pin.port, io->le_pin.pin, BSP_GPIO_PIN_RESET);/* Enable the GPIO Clock */bsp_gpio_set_clk(GPIO_APBx, io->oe_pin.periph, true);/* Configure the GPIO pin */bsp_gpio_init_output(io->oe_pin.port, io->oe_pin.pin, BSP_GPIO_PIN_OUT_PP);/* Reset PIN to switch off the */bsp_gpio_set_pin(io->oe_pin.port, io->oe_pin.pin, BSP_GPIO_PIN_SET);
#else
#endif
}/*** @brief 注销器件引脚* @param *io: 引脚配置*/
void extend_16ch_deinit(extend_16ch_gpio_t *io) {
#ifndef APP_IO/* Turn off */bsp_gpio_set_pin(io->clk_pin.port, io->clk_pin.pin, BSP_GPIO_PIN_RESET);/* DeInit the GPIO pin */bsp_gpio_deinit(io->clk_pin.port, io->clk_pin.pin);/* Turn off */bsp_gpio_set_pin(io->sdi_pin.port, io->sdi_pin.pin, BSP_GPIO_PIN_RESET);/* DeInit the GPIO pin */bsp_gpio_deinit(io->sdi_pin.port, io->sdi_pin.pin);/* Turn off */bsp_gpio_set_pin(io->le_pin.port, io->le_pin.pin, BSP_GPIO_PIN_RESET);/* DeInit the GPIO pin */bsp_gpio_deinit(io->le_pin.port, io->le_pin.pin);/* Turn off */bsp_gpio_set_pin(io->oe_pin.port, io->oe_pin.pin, BSP_GPIO_PIN_SET);/* DeInit the GPIO pin */bsp_gpio_deinit(io->oe_pin.port, io->oe_pin.pin);
#else
#endif
}/*** @brief 写入数据* @param *io: 引脚配置* @param data[]: IO数据,请以倒叙传入。如U5,U4,U3,U2,U1。* @param num: 器件数量*/
void extend_16ch_write(extend_16ch_gpio_t *io, uint16_t data[], uint8_t num) {//extend_16ch_close(io);uint16_t temp = 0;uint8_t bit_val = 0;
#ifndef APP_IO// 先关闭器件bsp_gpio_set_pin(io->clk_pin.port, io->clk_pin.pin, BSP_GPIO_PIN_RESET);bsp_gpio_set_pin(io->sdi_pin.port, io->sdi_pin.pin, BSP_GPIO_PIN_RESET);bsp_gpio_set_pin(io->le_pin.port, io->le_pin.pin, BSP_GPIO_PIN_RESET);for (uint8_t i = 0; i < num; i++) {temp = data[i];for (uint8_t bit = 0; bit < 16; bit++) {bit_val = temp & 0x8000 ? 1 : 0;temp <<= 1;if (bit_val)bsp_gpio_set_pin(io->sdi_pin.port, io->sdi_pin.pin, BSP_GPIO_PIN_SET);elsebsp_gpio_set_pin(io->sdi_pin.port, io->sdi_pin.pin, BSP_GPIO_PIN_RESET);bsp_gpio_set_pin(io->clk_pin.port, io->clk_pin.pin, BSP_GPIO_PIN_SET);__NOP();__NOP();bsp_gpio_set_pin(io->clk_pin.port, io->clk_pin.pin, BSP_GPIO_PIN_RESET);__NOP();__NOP();}}bsp_gpio_set_pin(io->le_pin.port, io->le_pin.pin, BSP_GPIO_PIN_SET);__NOP();bsp_gpio_set_pin(io->le_pin.port, io->le_pin.pin, BSP_GPIO_PIN_RESET);__NOP();__NOP();
#else// 先关闭器件bsp_gpio_set_pin(g_io_cfg[io->clk_pin].port, g_io_cfg[io->clk_pin].pin, BSP_GPIO_PIN_RESET);bsp_gpio_set_pin(g_io_cfg[io->sdi_pin].port, g_io_cfg[io->sdi_pin].pin, BSP_GPIO_PIN_RESET);bsp_gpio_set_pin(g_io_cfg[io->le_pin].port, g_io_cfg[io->le_pin].pin, BSP_GPIO_PIN_RESET);for (uint8_t i = 0; i < num; i++) {temp = data[i];for (uint8_t bit = 0; bit < 16; bit++) {bit_val = temp & 0x8000 ? 1 : 0;temp <<= 1;if (bit_val)bsp_gpio_set_pin(g_io_cfg[io->sdi_pin].port, g_io_cfg[io->sdi_pin].pin, BSP_GPIO_PIN_SET);elsebsp_gpio_set_pin(g_io_cfg[io->sdi_pin].port, g_io_cfg[io->sdi_pin].pin, BSP_GPIO_PIN_RESET);bsp_gpio_set_pin(g_io_cfg[io->clk_pin].port, g_io_cfg[io->clk_pin].pin, BSP_GPIO_PIN_SET);__NOP();__NOP();bsp_gpio_set_pin(g_io_cfg[io->clk_pin].port, g_io_cfg[io->clk_pin].pin, BSP_GPIO_PIN_RESET);__NOP();__NOP();}}bsp_gpio_set_pin(g_io_cfg[io->le_pin].port, g_io_cfg[io->le_pin].pin, BSP_GPIO_PIN_SET);__NOP();bsp_gpio_set_pin(g_io_cfg[io->le_pin].port, g_io_cfg[io->le_pin].pin, BSP_GPIO_PIN_RESET);__NOP();__NOP();
#endif//extend_16ch_open(io);
}/*** @brief 器件使能脚--打开* @param io 引脚配置*/
void extend_16ch_open(extend_16ch_gpio_t *io) {
#ifndef APP_IObsp_gpio_set_pin(io->oe_pin.port, io->oe_pin.pin, BSP_GPIO_PIN_RESET);
#elseif (g_io.type[io->oe_pin] == IO_TYPE_OUT_PP) {if (io->valid_level)bsp_gpio_set_pin(g_io_cfg[io->oe_pin].port, g_io_cfg[io->oe_pin].pin, BSP_GPIO_PIN_SET);elsebsp_gpio_set_pin(g_io_cfg[io->oe_pin].port, g_io_cfg[io->oe_pin].pin, BSP_GPIO_PIN_RESET);} else { // 非输出脚,则为PWM模式if (io->valid_level)bsp_pwm_set_pulse(PWMx, bsp_pwm_pp_to_pulse(PWMx, io->intensity_ctrl));elsebsp_pwm_set_pulse(PWMx, bsp_pwm_pp_to_pulse(PWMx, 100 - io->intensity_ctrl));}
#endif
}/*** @brief 器件使能脚--关闭* @param io 引脚配置*/
void extend_16ch_close(extend_16ch_gpio_t *io) {
#ifndef APP_IObsp_gpio_set_pin(io->oe_pin.port, io->oe_pin.pin, BSP_GPIO_PIN_SET);
#elseif (g_io.type[io->oe_pin] == IO_TYPE_OUT_PP) {if (io->valid_level)bsp_gpio_set_pin(g_io_cfg[io->oe_pin].port, g_io_cfg[io->oe_pin].pin, BSP_GPIO_PIN_RESET);elsebsp_gpio_set_pin(g_io_cfg[io->oe_pin].port, g_io_cfg[io->oe_pin].pin, BSP_GPIO_PIN_SET);} else {if (io->valid_level)bsp_pwm_set_pulse(PWMx, 0);elsebsp_pwm_set_pulse(PWMx, -1);}
#endif
}
/********************************************************************************
* @file extend_16ch.h
* @author jianqiang.xue
* @version V1.0.0
* @date 2023-04-07
* @brief 16位恒流驱动芯片 MBI5020 JXI5020GP如果没有APP_IO则使用下面方式定义引脚:
static const extend_16ch_gpio_t io = {.clk_pin = {GPIOC, GPIO_PIN_5, GPIO_CLK(GPIOC)},.sdi_pin = {GPIOC, GPIO_PIN_6, GPIO_CLK(GPIOC)},.le_pin = {GPIOC, GPIO_PIN_4, GPIO_CLK(GPIOC)},.oe_pin = {GPIOC, GPIO_PIN_3, GPIO_CLK(GPIOC)},
};如果启动了APP_IO则直接用ID号
#define LS_EXIO_CLK_ID (7)
#define LS_EXIO_DIO_ID (8)
#define LS_EXIO_LE_ID (6)
#define LS_EXIO_OE_ID (5)
static const extend_16ch_gpio_t io = {.clk_pin = LS_EXIO_CLK_ID,.sdi_pin = LS_EXIO_DIO_ID,.le_pin = LS_EXIO_LE_ID,.oe_pin = LS_EXIO_OE_ID,
};
********************************************************************************/#ifndef __EXTEND_16CH_H
#define __EXTEND_16CH_H/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include "bsp_gpio.h"
/* Public enum ---------------------------------------------------------------*/
/* Public Struct -------------------------------------------------------------*/
#ifndef APP_IO
typedef struct {bsp_gpio2_t clk_pin; // 时钟脚bsp_gpio2_t sdi_pin; // 数据脚bsp_gpio2_t le_pin; // 锁存 低电平开始准备数据,高电平发送数据bsp_gpio2_t oe_pin; // 使能脚 低电平打开IO0-IO15的输入,高电平关闭
} extend_16ch_gpio_t;
#else
typedef struct { // 填写[g_io_cfg]中索引号uint8_t clk_pin;uint8_t sdi_pin;uint8_t le_pin;uint8_t oe_pin; // 请在syscfg_gui中配置为PWMuint8_t intensity_ctrl; // 亮度控制,通过调整[oe_pin]占空比uint8_t valid_level; // 有效电平
} extend_16ch_gpio_t;
#endif
/* Public Function Prototypes ------------------------------------------------*/void extend_16ch_init(extend_16ch_gpio_t *io);
void extend_16ch_deinit(extend_16ch_gpio_t *io);void extend_16ch_write(extend_16ch_gpio_t *io, uint16_t data[], uint8_t num);
void extend_16ch_open(extend_16ch_gpio_t *io);
void extend_16ch_close(extend_16ch_gpio_t *io);#endif