yanglinq 发表于 2024-11-15 16:39

基于华芯微特SWM181CBT6的XL9555的IIC扩展IO驱动源码

本帖最后由 yanglinq 于 2024-11-15 16:48 编辑

/有个项目IO口不够用,又不想换大的CPU,只好用了个QFN24的小芯片通过模拟 IIC来扩展IO口。

/********************************************************************************/
/* @file      xl9555.c                                                                                                                        */
/* @version      V1.00                                                                                                                              */
/* $author:      yuanxihua@21cn.com                                                                                                      */
/* $Date:         2023/09/13 01:54 $                                                                                                         */
/* @brief         SWM181CBT6 Series XL9555 Driver Sample Code                                                      */
/*                                                                                                                                                                */
/* @NOTE                                                                                                                                                */
/* Copyright (C) 2010-2023 PM9GZY Technology Corp. All rights reserved.                        */
/*                                                                                                                                                                */
/********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/*
_________________________________________________
|      SWM181CBT6                                                XL9555                |
|                                                                                                |
|      PB2                SCL               ---->                SCL                        |
|      PB1                SDA               <--->                SDA                        |
|      PE4                INT                        <---               INT                        |
|_______________________________________________|
*/
#include <stdint.h>
/* Private typedef -----------------------------------------------------------*/
#define I2C_Delay                              10                         /* us */
#define I2C_SCL                            GPIOB, PIN2
#define I2C_SDA                            GPIOB, PIN1
#define I2C_INT                            GPIOE, PIN4

/* Private define ------------------------------------------------------------*/
#define XL9555_SLAVEADDR                         0x42                         /* Clock i2c slave address */
/* Private macro -------------------------------------------------------------*/
#define XL9555_INPUT_PORT0                              0x00
#define XL9555_INPUT_PORT1                              0x01
#define XL9555_OUTPUT_PORT0                              0x02
#define XL9555_OUTPUT_PORT1                              0x03
#define XL9555_POLARITY_PORT0                        0x04
#define XL9555_POLARITY_PORT1                        0x05
#define XL9555_CONFIGURATION_PORT0                0x06
#define XL9555_CONFIGURATION_PORT1                0x07
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/

/* Private functions ---------------------------------------------------------*/
void XL9555_Init(void)
{
      GPIO_Init(I2C_INT, 0, 1, 0, 0);                //GPIOE.4 配置为输入引脚,开启上拉 INT
      GPIO_Init(I2C_SDA, 1, 0, 0, 0);                //GPIOB.1 配置为输出引脚,推挽输出 SDA
      GPIO_Init(I2C_SCL, 1, 0, 0, 0);                //GPIOB.2 配置为输出引脚,推挽输出 SCL
      GPIO_SetBit(I2C_SCL);                              //SCL 高
      GPIO_SetBit(I2C_SDA);                              //SDA 高
}
void XL9555_Pluse(void)
{
      GPIO_SetBit(I2C_SCL);                              //SCL 高
      delay_us(I2C_Delay);
      GPIO_ClrBit(I2C_SCL);                              //SCL 低
      delay_us(I2C_Delay);
}
void XL9555_Start(void)
{
      XL9555_Init();
      delay_us(I2C_Delay);
      GPIO_Init(I2C_SDA, 1, 0, 0, 0);                //I2C_SDA 配置为输出引脚,推挽输出 SDA
      GPIO_ClrBit(I2C_SDA);                              //SDA 低
      delay_us(I2C_Delay);
      GPIO_ClrBit(I2C_SCL);                              //SCL 低
      delay_us(I2C_Delay);
}
void XL9555_ACK(uint8_t ack)
{
      GPIO_Init(I2C_SDA, 1, 0, 0, 0);                //I2C_SDA 配置为输出引脚,推挽输出 SDA
      if(ack)      {GPIO_SetBit(I2C_SDA);}                //SDA 高 NAK
      else      {GPIO_ClrBit(I2C_SDA);}                //SDA 低 ACK
      delay_us(I2C_Delay);
      XL9555_Pluse();                                                //发送ACK
      GPIO_SetBit(I2C_SDA);                              //SDA 高         /* CPU释放SDA总线 */
}
uint8_t XL9555_WACK(void)
{
      GPIO_Init(I2C_SDA, 0, 1, 0, 0);                //I2C_SDA 配置为输入引脚,开启上拉 SDA
      delay_us(I2C_Delay);
      uint8_t ack=GPIO_GetBit(I2C_SDA);      //接收ACK
      XL9555_Pluse();                     
      return ack;
}
void XL9555_Stop(void)
{
      GPIO_Init(I2C_SDA, 1, 0, 0, 0);                //I2C_SDA 配置为输出引脚,推挽输出 SDA
      GPIO_ClrBit(I2C_SDA);                              //SDA 低
      delay_us(I2C_Delay);
      GPIO_SetBit(I2C_SCL);                              //SCL 高
      delay_us(I2C_Delay);
      GPIO_SetBit(I2C_SDA);                              //SDA 高
}
void XL9555_Send_Byte(uint8_t data,uint8_t ack)
{
      GPIO_Init(I2C_SDA, 1, 0, 0, 0);                //I2C_SDA 配置为输出引脚,推挽输出 SDA
      for(int i=0;i<8;i++)                              //发送DATA
      {
                if(data&0x80){GPIO_SetBit(I2C_SDA);}
                else{GPIO_ClrBit(I2C_SDA);}
                data<<=1;XL9555_Pluse();
      }
      if(XL9555_WACK()!=ack){XL9555_Stop();}      //等待ACK应答
}
uint16_t XL9555_Read_Byte(uint8_t ack)
{
      uint16_t data=0;
      GPIO_Init(I2C_SDA, 0, 1, 0, 0);                //I2C_SDA 配置为输入引脚,开启上拉 SDA
      for(int i=0;i<8;i++)                              //接收DATA
      {
                data<<=1;
                if(GPIO_GetBit(I2C_SDA)){data+=1;}else{;}
                XL9555_Pluse();
      }
      XL9555_ACK(ack);                //发送ACK或者NAK
      return data;
}

uint8_t XL9555_Write_buf(uint8_t addr,uint8_t reg,uint8_t *buf,uint8_t len)
{
      XL9555_Init();
    XL9555_Start();
    XL9555_Send_Byte(addr|0,0);                                 //发送器件地址+写命令+ACK
    XL9555_Send_Byte(reg,0);                                 //写寄存器地址+ACK
      while(len--){XL9555_Send_Byte(*buf++,0);}      //发送数据+ACK
    XL9555_Stop();
    return 0;
}
uint8_t XL9555_Read_buf(uint8_t addr,uint8_t reg,uint8_t *buf,uint8_t len)
{
      XL9555_Init();
    XL9555_Start();
    XL9555_Send_Byte(addr|0,0);               //发送器件地址+写命令+ACK
    XL9555_Send_Byte(reg,0);               //写寄存器地址+ACK
      XL9555_Start();               
    XL9555_Send_Byte(addr|1,0);               //发送器件地址+读命令+ACK
    while(len--)
    {
      if(len==1)      {*buf++=XL9555_Read_Byte(1);}      //读数据+发送NAK
                else               {*buf++=XL9555_Read_Byte(0);}      //读数据+发送ACK
    }
    XL9555_Stop();                                 //产生一个停止条件
    return 0;      
}
void XL9555_Configuration(uint16_t val)
{
    XL9555_Write_buf(XL9555_SLAVEADDR, XL9555_CONFIGURATION_PORT0,(uint8_t *)&val,2);
}

void XL9555_OutPut(uint16_t val)
{
      XL9555_Configuration(0x0000);
      XL9555_Write_buf(XL9555_SLAVEADDR, XL9555_OUTPUT_PORT0,(uint8_t *)&val,2);
}

uint16_t XL9555_InPut(void)
{
      uint16_t val;
      XL9555_Configuration(0xffff);
      XL9555_Write_buf(XL9555_SLAVEADDR, XL9555_OUTPUT_PORT0,(uint8_t *)&val,2);
      return val;
}
uint16_t XL9555_InOutPut(uint16_t set,uint16_t val)
{
      XL9555_Configuration(set);
      uint8_t *buf=( uint8_t *)&val;
      XL9555_Write_buf(XL9555_SLAVEADDR, XL9555_OUTPUT_PORT0,buf,2);
      delay_us(1000);
      XL9555_Read_buf (XL9555_SLAVEADDR, XL9555_INPUT_PORT0 ,buf,2);
      return val;
}

void XL9555_Test(void)
{
      uint8_t buf;
      XL9555_Read_buf(XL9555_SLAVEADDR,0,buf,sizeof(buf));
      for(int i=0;i<sizeof(buf);i++){printf("0x%02x ",buf);}
}

//代码完毕



页: [1]
查看完整版本: 基于华芯微特SWM181CBT6的XL9555的IIC扩展IO驱动源码