CH423S IO扩展芯片使用记录

CH423S IO扩展芯片使用记录

1.概述

首先看芯片的描述和特点,根据数据手册

1、概述 CH423 是两线串行接口的通用远程 I/O 扩展芯片。CH423 提供 8 个双向输入输出引脚和 16 个通
用输出引脚,支持输入电平变化中断;CH423 内置电流驱动电路,可以静态驱动 24 只 LED 发光管或 者动态驱动 128 只 LED(相当于 16 只数码管);CH423 通过 2 线串行接口与单片机等交换数据。
image-20210818085302007

2、特点
● 通过两线串行接口远程扩展出 8 个通用输入输出引脚 GPIO 和 16 个通用输出引脚 GPO。

● 内置电流驱动级,连续驱动电流不小于 15mA,OC 引脚输出 1/16 脉冲灌电流不小于 120mA。

● 静态显示驱动方式支持 24 只发光管 LED 或者 3 位共阳数码管。

● 分时动态扫描显示驱动方式支持 128 只发光管 LED 或者 16 位共阴数码管,支持亮度控制。

● 双向 I/O 引脚在输入方式下具有输入电平变化时产生中断的功能,中断输出低电平有效。

● 16 个通用输出引脚可以选择推挽输出或者开漏输出。

● 支持 3V~5V 电源电压,支持低功耗睡眠,可以被输入电平变化唤醒。

● 高速 2 线串行接口,时钟速度从 0 到 1MHz,兼容两线 I2C 总线,节约引脚。

● 提供 DIP28S 和 SOP28 两种无铅封装,兼容 RoHS。

目前用的是软件模拟:

// *******************************************************************
//Website:  http://wch.cn
//Email:    tech@wch.cn
//Author:   W.ch 2007.6
// *******************************************************************

// 硬件相关定义, 请根据实际硬件修改本文件
#ifndef	CH423IF_H
#define	CH423IF_H

#include "SWM320.h"


typedef union{
	struct{
		uint16_t OC0:1;
		uint16_t OC1:1;
		uint16_t OC2:1;
		uint16_t OC3:1;
		uint16_t OC4:1;
		uint16_t OC5:1;
		uint16_t OC6:1;
		uint16_t OC7:1;
		uint16_t OC8:1;
		uint16_t OC9:1;
		uint16_t OC10:1;
		uint16_t OC11:1;
		uint16_t OC12:1;
		uint16_t OC13:1;
		uint16_t OC14:1;
		uint16_t OC15:1;
	}state;
	uint16_t v;
}Ch423_Output_Typedef;

typedef union{
	struct{
		uint16_t IO0:1;
		uint16_t IO1:1;
		uint16_t IO2:1;
		uint16_t IO3:1;
		uint16_t IO4:1;
		uint16_t IO5:1;
		uint16_t IO6:1;
		uint16_t IO7:1;
	}state;
	uint8_t v;
}Ch423_Input_Typedef;


/* 2线接口的位操作,与单片机有关 */

#define CH423_SCL_SET       { GPIO_SetBit(GPIOC, PIN4); }
#define CH423_SCL_CLR       { GPIO_ClrBit(GPIOC, PIN4); }
#define CH423_SCL_D_OUT     { GPIO_Init(GPIOC, PIN4, 1, 0, 0); }   // 设置SCL为输出方向,对于双向I/O需切换为输出
#define CH423_SDA_SET       { GPIO_SetBit(GPIOC, PIN5); }
#define CH423_SDA_CLR       { GPIO_ClrBit(GPIOC, PIN5); }
#define CH423_SDA_IN          GPIO_GetBit(GPIOC, PIN5) 
#define CH423_SDA_D_OUT     { GPIO_Init(GPIOC, PIN5, 1, 0, 0); }                // 设置SDA为输出方向,对于双向I/O需切换为输出
#define CH423_SDA_D_IN      { GPIO_Init(GPIOC, PIN5, 0, 1, 0); }    // 设置SDA为输入方向,对于双向I/O需切换为输入

// CH423接口定义
#define     CH423_I2C_ADDR1     0x40         // CH423的地址
#define     CH423_I2C_MASK      0x3E         // CH423的高字节命令掩码

/*  设置系统参数命令 */ 

#define CH423_SYS_CMD     0x4800     // 设置系统参数命令,默认方式
#define BIT_X_INT         0x08       // 使能输入电平变化中断,为0禁止输入电平变化中断;为1并且DEC_H为0允许输出电平变化中断
#define BIT_DEC_H         0x04       // 控制开漏输出引脚高8位的片选译码
#define BIT_DEC_L         0x02       // 控制开漏输出引脚低8位的片选译码
#define BIT_IO_OE         0x01       // 控制双向输入输出引脚的三态输出,为1允许输出

/*  设置低8位开漏输出命令 */

#define CH423_OC_L_CMD    0x4400     // 设置低8位开漏输出命令,默认方式
#define BIT_OC0_L_DAT     0x01       // OC0为0则使引脚输出低电平,为1则引脚不输出
#define BIT_OC1_L_DAT     0x02       // OC1为0则使引脚输出低电平,为1则引脚不输出
#define BIT_OC2_L_DAT     0x04       // OC2为0则使引脚输出低电平,为1则引脚不输出
#define BIT_OC3_L_DAT     0x08       // OC3为0则使引脚输出低电平,为1则引脚不输出
#define BIT_OC4_L_DAT     0x10       // OC4为0则使引脚输出低电平,为1则引脚不输出
#define BIT_OC5_L_DAT     0x20       // OC5为0则使引脚输出低电平,为1则引脚不输出
#define BIT_OC6_L_DAT     0x40       // OC6为0则使引脚输出低电平,为1则引脚不输出
#define BIT_OC7_L_DAT     0x80       // OC7为0则使引脚输出低电平,为1则引脚不输出

/*  设置高8位开漏输出命令 */

#define CH423_OC_H_CMD    0x4600      // 设置低8位开漏输出命令,默认方式
#define BIT_OC8_L_DAT     0x01        // OC8为0则使引脚输出低电平,为1则引脚不输出
#define BIT_OC9_L_DAT     0x02        // OC9为0则使引脚输出低电平,为1则引脚不输出
#define BIT_OC10_L_DAT    0x04        // OC10为0则使引脚输出低电平,为1则引脚不输出
#define BIT_OC11_L_DAT    0x08        // OC11为0则使引脚输出低电平,为1则引脚不输出
#define BIT_OC12_L_DAT    0x10        // OC12为0则使引脚输出低电平,为1则引脚不输出
#define BIT_OC13_L_DAT    0x20        // OC13为0则使引脚输出低电平,为1则引脚不输出
#define BIT_OC14_L_DAT    0x40        // OC14为0则使引脚输出低电平,为1则引脚不输出
#define BIT_OC15_L_DAT    0x80        // OC15为0则使引脚输出低电平,为1则引脚不输出

/* 设置双向输入输出命令 */

#define CH423_SET_IO_CMD   0x6000    // 设置双向输入输出命令,默认方式
#define BIT_IO0_DAT        0x01      // 写入双向输入输出引脚的输出寄存器,当IO_OE=1,IO0为0输出低电平,为1输出高电平
#define BIT_IO1_DAT        0x02      // 写入双向输入输出引脚的输出寄存器,当IO_OE=1,IO1为0输出低电平,为1输出高电平
#define BIT_IO2_DAT        0x04      // 写入双向输入输出引脚的输出寄存器,当IO_OE=1,IO2为0输出低电平,为1输出高电平
#define BIT_IO3_DAT        0x08      // 写入双向输入输出引脚的输出寄存器,当IO_OE=1,IO3为0输出低电平,为1输出高电平
#define BIT_IO4_DAT        0x10      // 写入双向输入输出引脚的输出寄存器,当IO_OE=1,IO4为0输出低电平,为1输出高电平
#define BIT_IO5_DAT        0x20      // 写入双向输入输出引脚的输出寄存器,当IO_OE=1,IO5为0输出低电平,为1输出高电平
#define BIT_IO6_DAT        0x40      // 写入双向输入输出引脚的输出寄存器,当IO_OE=1,IO6为0输出低电平,为1输出高电平
#define BIT_IO7_DAT        0x80      // 写入双向输入输出引脚的输出寄存器,当IO_OE=1,IO7为0输出低电平,为1输出高电平

/* 读取双向输入输出命令 */

#define CH423_RD_IO_CMD		0x4D	// 输入I/O引脚当前状态

// 对外子程序
//extern void CH423_WriteByte( unsigned short cmd );   // 写出数据
//extern unsigned char CH423_ReadByte( void );    // 读取数据
void bsp_CH423_Init(void);	//初始化
void bsp_CH423_Poll(void);	//周期调用
extern Ch423_Output_Typedef Ch423_Output;
extern Ch423_Input_Typedef Ch423_Input;

// 特定用途子程序
//extern void CH423_Write( unsigned short cmd );    // 向CH423发出操作命令,该子程序与CH423_WriteByte不同,区别主要是前者先将命令码高8位移位

// 下述定义仅适用于CH423_Write子程序,这样定义是为了兼容I2C数据,如果不考虑兼容,那么高8位应该先左移1位
#define CH423_DIG0      0x1000              // 数码管位0显示
#define CH423_DIG1      0x1100              // 数码管位1显示 
#define CH423_DIG2      0x1200              // 数码管位2显示
#define CH423_DIG3      0x1300              // 数码管位3显示
#define CH423_DIG4      0x1400              // 数码管位4显示
#define CH423_DIG5      0x1500              // 数码管位5显示 
#define CH423_DIG6      0x1600              // 数码管位6显示 
#define CH423_DIG7      0x1700              // 数码管位7显示
#define CH423_DIG8      0x1800              // 数码管位8显示
#define CH423_DIG9      0x1900              // 数码管位9显示 
#define CH423_DIG10     0x1A00              // 数码管位10显示
#define CH423_DIG11     0x1B00              // 数码管位11显示
#define CH423_DIG12     0x1C00              // 数码管位12显示
#define CH423_DIG13     0x1D00              // 数码管位13显示    
#define CH423_DIG14     0x1E00              // 数码管位14显示    
#define CH423_DIG15     0x1F00              // 数码管位15显示 

#endif

#include "dev_ch423s.h"    // 修改该文件以适应硬件环境/单片机型号等

static void delay1us()
{
	uint32_t i;
	for(i = 0; i < 100; i++);
}
#define DELAY_0_1US    delay1us()       // MCS51>10MHz


static void CH423_I2c_Start( void )    // 操作起始
{
    CH423_SDA_SET;    // 发送起始条件的数据信号
    CH423_SDA_D_OUT;    // 设置SDA为输出方向 
    CH423_SCL_SET;
    CH423_SCL_D_OUT;    // 设置SCL为输出方向 
    DELAY_0_1US;
    CH423_SDA_CLR;    //发送起始信号
    DELAY_0_1US;      
    CH423_SCL_CLR;    //钳住I2C总线,准备发送或接收数据 
}

static void CH423_I2c_Stop( void )    // 操作结束
{
    CH423_SDA_CLR;
    DELAY_0_1US;
    CH423_SCL_SET;
    DELAY_0_1US;
    CH423_SDA_SET;    // 发送I2C总线结束信号
    DELAY_0_1US;
}

static void CH423_I2c_WrByte( uint8_t dat )    // 写一个字节数据
{
    uint8_t i;
    for( i = 0; i != 8; i++ )    // 输出8位数据
    {
        if( dat&0x80 ) { CH423_SDA_SET; }
        else { CH423_SDA_CLR; }
        DELAY_0_1US;
        CH423_SCL_SET;
        dat<<=1;
        DELAY_0_1US;    // 可选延时
        CH423_SCL_CLR;
    }
    CH423_SDA_SET;
    DELAY_0_1US;
    CH423_SCL_SET;    // 接收应答
    DELAY_0_1US;
    CH423_SCL_CLR;
}

static uint8_t CH423_I2c_RdByte( void )    // 读一个字节数据
{
    uint8_t dat,i;
    CH423_SDA_SET;
    CH423_SDA_D_IN;    // 设置SDA为输入方向 
    dat=0;
    for( i = 0; i != 8; i++ )    // 输入8位数据
    {
        DELAY_0_1US;    // 可选延时
        CH423_SCL_SET;
        DELAY_0_1US;    // 可选延时
        dat<<=1;
        if(CH423_SDA_IN) dat++;    // 输入1位
        CH423_SCL_CLR;
    }
    CH423_SDA_SET;
    DELAY_0_1US;
    CH423_SCL_SET;    // 发出无效应答
    DELAY_0_1US;
    CH423_SCL_CLR;
    return(dat);
}

static void CH423_Write( uint16_t cmd )    // 写命令
{
    CH423_I2c_Start();    // 启动总线
    CH423_I2c_WrByte( ( ( uint8_t )( cmd>>7 ) & CH423_I2C_MASK ) | CH423_I2C_ADDR1 );
    CH423_I2c_WrByte( ( uint8_t ) cmd );    // 发送数据
    CH423_I2c_Stop();    // 结束总线 
}

static void CH423_WriteByte( uint16_t cmd )    // 写出数据
{
    CH423_I2c_Start();    // 启动总线
    CH423_I2c_WrByte( ( uint8_t )( cmd>>8 ) );
    CH423_I2c_WrByte( ( uint8_t ) cmd );    // 发送数据
    CH423_I2c_Stop();    // 结束总线  
}

static uint8_t CH423_ReadByte()    // 读取数据
{
    uint8_t din;
    CH423_I2c_Start();    // 启动总线
    CH423_I2c_WrByte( CH423_RD_IO_CMD );    // 此值为0x4D
    din=CH423_I2c_RdByte();    // 读取数据
    CH423_I2c_Stop();    // 结束总线
    return( din );
}
//读IO0-7的值
static uint8_t bsp_CH423_ReadIO(void)
{
	return CH423_ReadByte();
}
//写OC0-15的值
static void bsp_CH423_WriteIO(uint16_t value)
{
	CH423_Write(CH423_OC_L_CMD | (uint8_t)  value );//OC0-7输出
	CH423_Write(CH423_OC_H_CMD | (uint8_t)( value >> 8) );//OC8-15输出
}




//CH423输出输入状态寄存器
Ch423_Input_Typedef Ch423_Input;
Ch423_Output_Typedef Ch423_Output;

/* 对外接口 */
//CH423初始化
void bsp_CH423_Init(void)
{
	Ch423_Input.v = 0;
	Ch423_Output.v = 0;
	GPIO_Init(GPIOC, PIN4, 1, 0, 0);
	GPIO_Init(GPIOC, PIN5, 1, 0, 0);
	CH423_Write(CH423_SYS_CMD);
}
//周期调用CH423
void bsp_CH423_Poll(void)
{
	Ch423_Input.v = bsp_CH423_ReadIO();//读
	bsp_CH423_WriteIO(Ch423_Output.v);//写
}

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

炒饭多加个蛋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值