chen
2024-12-11 8e0cbe0992619a36bf34a660cfdd75f083f19730
keil/include/drivers/PCA9555.c
@@ -1,14 +1,17 @@
#include "PCA9555.h"
uint8_t gps_led_output_state,tts_enbale_output_state,wake_up_output_state,air780e_enable_output_state,sos_enable_output_state,gps_backup_output_state,gps_power_output_state,main_ri_output_state;//1组output IO口从左到右1.0~1.7
uint8_t mcu_a_output_state,chg_g_output_state,lora_irq_output_state,lora_nrst_output_state,adc_minius_output_state,input_5v_output_state,pwr_on_output_state,pwr_enable_output_state;//2组output IO口从左到右0.0~0.7
uint8_t pca9555writedata_config[10];//暂存寄存器所有配置的数组
uint8_t pca9555writedata_output[10];
uint8_t pca9555writedata_output[10];//暂存输出高低电平配置的数组
uint8_t pca9555writedata_input[10];//暂存输入寄存器所有配置的数组
uint8_t pca9555writedata_polarity[10];//暂存输入极性反转寄存器所有配置的数组
void IIC_gpio_pca_init(void)
{
    io_pin_mux_set(SDA_PIN, IO_FUNC0);
    io_pin_mux_set(SCL_PIN, IO_FUNC0);
    gpio_pin_set_dir(SDA_PIN , GPIO_DIR_OUT, 1);
//      io_open_drain_set(SDA_PIN, 1);
      //io_open_drain_set(SDA_PIN, 1);
    io_pull_set(SDA_PIN , IO_PULL_UP, IO_PULL_UP_LEVEL2);//输出高阻态
    gpio_pin_set_dir(SCL_PIN , GPIO_DIR_OUT, 1);
@@ -18,13 +21,22 @@
void IIC2_pca_Start(void)
{
//      IIC2_SDA_OUT();     //sda线输出
////      IIC2_SDA_OUT();     //sda线输出
//    SDA_1;
//      delay_us(10);
//    SCL_1;
//      delay_us(10);
//    SDA_0;//START:when CLK is high,DATA change form high to low
//    delay_us(10);
   //      IIC2_SDA_OUT();     //sda线输出
    SDA_1;
      delay_us(10);
//      delay_us(10);
    SCL_1;
      delay_us(10);
//      delay_us(10);
    SDA_0;//START:when CLK is high,DATA change form high to low
    delay_us(10);
    SCL_0;//钳住I2C总线,准备发送或接收数据
}
void IIC_pca_Ready(void)
{
@@ -38,13 +50,21 @@
void IIC2_pca_Stop(void)
{
    SDA_0;//STOP:when CLK is high DATA change form low to high
//    SDA_0;//STOP:when CLK is high DATA change form low to high
//
//    delay_us(10);
//    SCL_1;
//      delay_us(10);
//    SDA_1;//发送I2C总线结束信号
//    delay_us(10);
   
    delay_us(10);
    SCL_1;
      delay_us(10);
    SDA_1;//发送I2C总线结束信号
    delay_us(10);
         SCL_0;
         SDA_0;//sToP:when ClK is high DATA change form low to high
         delay_us(10);
         SCL_1;
         //delay_us(10);
         SDA_1;//7发送I2C总线结束信号
         delay_us(10);
}
//等待应答信号到来
//返回值:1,接收应答失败
@@ -52,12 +72,16 @@
uint8_t IIC2_Wait_pca_Ack(void)
{
    uint8_t ucErrTime=0;
//  IIC2_SDA_IN();
   gpio_pin_set_dir(SDA_PIN , GPIO_DIR_IN, 1); //SDA设置为输入等待接收端的应答信号
    SDA_1;
    delay_us(6);
    SCL_1;
    delay_us(6);
//  IIC2_SDA_IN();
   gpio_pin_set_dir(SDA_PIN,GPIO_DIR_IN,1); //SDA设置为输入等待接收端的应答信号
    SDA_1;
   delay_us(6);
   SCL_1;
  delay_us(6);
//    SDA_1;
//    delay_us(6);
    while(IIC2_READ_SDA)
    {
@@ -65,10 +89,11 @@
        if(ucErrTime>250)
        {
            IIC2_pca_Stop();
                  gpio_pin_set_dir(SDA_PIN , GPIO_DIR_OUT, 1);
            return 1;
        }
    }
    gpio_pin_set_dir(SDA_PIN , GPIO_DIR_OUT, 1);
    gpio_pin_set_dir(SDA_PIN , GPIO_DIR_OUT, 0);
    SCL_0;//时钟输出0
    return 0;
      
@@ -76,30 +101,34 @@
//产生ACK应答
void IIC2_pca_send_Ack(void)
{
    SDA_0;
    delay_us(10);
    SCL_1;//读取SDA电平为低则有应答
    delay_us(10);
    SCL_0;
    SDA_0;//读取SDA电平为低则有应答
    delay_us(10);
    SCL_1;
      delay_us(10);
      SCL_0;
}
//不产生ACK应答
void IIC2_pca_send_NAck(void)
{
    SDA_1;
    delay_us(10);
    SCL_1;//读取SDA电平为高则无应答信号
    delay_us(10);
    SCL_0;
    SDA_1;//读取SDA电平为高则无应答信号
    delay_us(10);
    SCL_1;
      delay_us(10);
      SCL_0;
}
//IIC发送一个字节,WRITE
//返回从机有无应答
//1,有应答
//0,无应答
uint8_t statistic_num;
void IIC2_Send_pca_Byte(uint8_t txd)
{
    uint8_t t;
//      IIC2_SDA_OUT();
    SCL_0;//拉低时钟开始数据传输
//      delay_us(10);
    for(t=0; t<8; t++)
    {
        if((txd&0x80)>>7)
@@ -117,28 +146,38 @@
        SCL_0;
        delay_us(10);
    }
      SDA_1;//新增sda拉高
      delay_us(10);
//      statistic_num=txd;
//      SDA_1;//新增sda拉高
//      delay_us(10);
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK,不是一样的
uint8_t IIC2_Read_pca_Byte(unsigned char ack)
{
    unsigned char i,receive=0;
//   IIC2_SDA_IN();//SDA设置为输入
      gpio_pin_set_dir(SDA_PIN,GPIO_DIR_IN,0); //设置为输入读取电平
//      io_pull_set(SDA_PIN , IO_HIGH_Z, IO_PULL_UP_NONE);
    for(i=0; i<8; i++ )
    {
        SCL_0;
        delay_us(10);
        delay_us(6);//修改时间
        SCL_1;
        receive<<=1;
        if(IIC2_READ_SDA)receive++;
        delay_us(5);
    }
    if (!ack)
        IIC2_pca_send_NAck();//发送nACK
    else
        IIC2_pca_send_Ack(); //发送ACK
      SCL_0;
      if(ack==2){
      gpio_pin_set_dir(SDA_PIN,GPIO_DIR_OUT,0); //设置为输出恢复ACK
      }else{
      gpio_pin_set_dir(SDA_PIN,GPIO_DIR_OUT,1); //设置为输出恢复ACK
      }
//      io_pull_set(SDA_PIN , IO_PULL_UP, IO_PULL_UP_LEVEL2);//输出高阻态
//    if (!ack)
//        IIC2_pca_send_NAck();//发送nACK
//    else
//        IIC2_pca_send_Ack(); //发送ACK
    return receive;
}
@@ -150,46 +189,95 @@
  high_byte  写入芯片的前后位数据
*********************************************************/
//写pca9555第一层,最底层驱动
int temp_ack3,temp_ack4,temp_ack5,temp_ack6;
void IIC_Write_Pca9555(unsigned char addr,unsigned char reg_addr,unsigned char low_byte,unsigned char high_byte)
{
     IIC2_pca_Start();
     IIC2_Send_pca_Byte(addr & 0xfe);
     IIC2_Wait_pca_Ack();
     temp_ack3=IIC2_Wait_pca_Ack();
     IIC2_Send_pca_Byte(reg_addr);
     IIC2_Wait_pca_Ack();
     temp_ack4=IIC2_Wait_pca_Ack();
     IIC2_Send_pca_Byte(low_byte);
     IIC2_Wait_pca_Ack();
     temp_ack5=IIC2_Wait_pca_Ack();
     IIC2_Send_pca_Byte(high_byte);
     IIC2_Wait_pca_Ack();
     temp_ack6=IIC2_Wait_pca_Ack();
     IIC2_pca_Stop();
}
//       IIC2_Start();
//    IIC2_Send_Byte(addr & 0xfe);       //发送写命令
//    temp_ack3=IIC2_Wait_pca_Ack();
//    IIC2_Send_Byte(reg_addr);               //发送地址
//    temp_ack4=IIC2_Wait_pca_Ack();
//    IIC2_Send_Byte(low_byte);     //发送字节
//    temp_ack5=IIC2_Wait_pca_Ack();
//      IIC2_Send_Byte(high_byte);     //发送字节
//      temp_ack6=IIC2_Wait_pca_Ack();
//    IIC2_Stop();//产生一个停止条件
}
/*
  //     IIC2_Start();
//    IIC2_Send_Byte(addr & 0xfe);       //发送写命令
//    temp_ack3=IIC2_Wait_Ack();
//    IIC2_Send_Byte(reg_addr);               //发送地址
//    temp_ack4=IIC2_Wait_Ack();
//    IIC2_Send_Byte(low_byte);     //发送字节
//    temp_ack5=IIC2_Wait_Ack();
//      IIC2_Send_Byte(high_byte);     //发送字节
//      temp_ack6=IIC2_Wait_Ack();
//    IIC2_Stop();//产生一个停止条件
*/
int temp_ack,temp_ack1,temp_ack2;
 uint8_t temp=0;
void IIC_Read_Pca9555(uint8_t addr,uint8_t reg_addr,uint8_t* pBuffer,uint16_t num)
{
     IIC2_pca_Start();
     IIC2_Send_pca_Byte(addr & 0xfe);
     IIC2_Wait_pca_Ack();
     temp_ack=IIC2_Wait_pca_Ack();
     IIC2_Send_pca_Byte(reg_addr);
     IIC2_Wait_pca_Ack();
     temp_ack1=IIC2_Wait_pca_Ack();
     IIC2_pca_Start();
     IIC2_Send_pca_Byte(addr | 0x01);
     IIC2_Wait_pca_Ack();
     temp_ack2=IIC2_Wait_pca_Ack();
//      if(num==2){
//      pBuffer[0]=IIC2_Read_Byte(1);
//      pBuffer[1]=IIC2_Read_Byte(0);
//      }else{
//      pBuffer[0]=IIC2_Read_Byte(0);
//      }
     while (num)
     {
          *pBuffer = IIC2_Read_pca_Byte(1);
          *pBuffer = IIC2_Read_pca_Byte(num);
         if (num == 1)
         {
            IIC2_pca_send_NAck();
            //IIC2_NAck();
         }
         else
         { 
            IIC2_pca_send_Ack();
            //IIC2_Ack();
         }   
          pBuffer++;
         num--;
     }
     IIC2_pca_Stop();
//    IIC2_Start();
//    IIC2_Send_Byte(addr & 0xfe);        //发送写命令
//    IIC2_Wait_pca_Ack();
//    IIC2_Send_Byte(reg_addr);   //发送读地址
//    IIC2_Wait_pca_Ack();
//    IIC2_Start();
//    IIC2_Send_Byte(0x41);       //发送读命令,进入接收模式
//    IIC2_Wait_pca_Ack();
//    temp=IIC2_Read_Byte(0);
//    IIC2_Stop();                        //产生一个停止条件
}
/*写pca9555第二层驱动,可辅助逻辑不破坏最底层驱动,该函数默认配置输出寄存器
@@ -201,7 +289,7 @@
{                        
      IIC_Write_Pca9555(addr,PCA9555_REG_OUT0,data_L,data_H);//   PCA9555_REG_OUT0 输出寄存器0地址
      pca9555writedata_output[0]=   data_L;//保存该次设置数据
      pca9555writedata_output[0]=   data_H;
      pca9555writedata_output[1]=   data_H;
}
/*写pca9555第二层驱动,可辅助逻辑不破坏最底层驱动,该函数默认配置输出寄存器
@@ -213,16 +301,51 @@
{                        
      IIC_Write_Pca9555(addr,PCA9555_REG_CFG0,data_L,data_H);//   PCA9555_REG_OUT0 输出寄存器0地址 
      pca9555writedata_config[0]=   data_L;//保存该次设置数据
      pca9555writedata_config[0]=   data_H;
      pca9555writedata_config[1]=   data_H;
}
/*写pca9555第二层驱动,可辅助逻辑不破坏最底层驱动,该函数默认配置输入极性翻转寄存器 1翻转 2不变
  addr    芯片地址,0x40表示第一个芯片地址
  data_L  写入芯片的前八位数据
  data_H  写入芯片的前后位数据
*/
void PCA9555_write_polarity_port_data(unsigned char addr,unsigned char data_L,unsigned char data_H)
{
      IIC_Write_Pca9555(addr,PCA9555_REG_POL0,data_L,data_H);//   PCA9555_REG_OUT0 输出寄存器0地址
      pca9555writedata_polarity[0]=   data_L;//保存该次设置数据
      pca9555writedata_polarity[1]=   data_H;
}
/*读pca9555第二层驱动,可辅助逻辑不破坏最底层驱动
  addr     芯片地址,0x40表示第一个芯片地址
  pBuffer  读出芯片的数据 2个寄存器的gpio电平
  pBuffer  读出芯片的数据 2个输入寄存器的值仅限输入模式使用
*/
void PCA9555_readdata(unsigned char addr,unsigned char* pBuffer)
{
      IIC_Read_Pca9555(addr,PCA9555_REG_IN0,pBuffer,2);//2为读出芯片数据组数,9555为2组,全部读出   
}
/*读pca9555第二层驱动,可辅助逻辑不破坏最底层驱动
  addr     芯片地址,0x40表示第一个芯片地址
  pBuffer  读出芯片的数据 2个寄存器的值仅限输出模式,此模式下仅回复输入输出的控制模式的值,而非电平值
*/
void PCA9555_readdata_from_output_register(unsigned char addr,unsigned char* pBuffer)
{
      IIC_Read_Pca9555(addr,PCA9555_REG_OUT0,pBuffer,2);//2为读出芯片数据组数,9555为2组,全部读出
}
/*读pca9555第二层驱动,可辅助逻辑不破坏最底层驱动
  addr     芯片地址,0x40表示第一个芯片地址
  pBuffer  读出芯片的数据 2个寄存器的值仅限输出模式,此模式下仅回复输入输出的控制模式的值,而非电平值
*/
void PCA9555_readdata_from_polarity_register(unsigned char addr,unsigned char* pBuffer)
{
      IIC_Read_Pca9555(addr,PCA9555_REG_POL0,pBuffer,2);//2为读出芯片数据组数,9555为2组,全部读出
}
/*读pca9555第二层驱动,可辅助逻辑不破坏最底层驱动
  addr     芯片地址,0x40表示第一个芯片地址
  pBuffer  读出芯片的数据 配置2个寄存器的数值
*/
void PCA9555_readdata_from_config_register(unsigned char addr,unsigned char* pBuffer)
{
      IIC_Read_Pca9555(addr,PCA9555_REG_CFG0,pBuffer,2);//2为读出芯片数据组数,9555为2组,全部读出
}
///*配置芯片的对应管脚输入输出功能
//  addr    芯片地址,0x40表示第一个芯片地址
@@ -289,7 +412,7 @@
}
/*设置第一个芯片某一通道IO输入或输出
  num    控制的IO序号 1~17
  value  控制的IO输出状态 0:低电平 1:高电平
  value  控制的IO输出状态 0:输出 1:输入
*/
void PCA9555_Set_One_Value_Config(unsigned char num,unsigned char value) 
{
@@ -310,9 +433,27 @@
}
void PCA9555_init()
{
IIC_gpio_pca_init();//配置IIC管脚
PCA9555_write_config_port_data(PCA9555_DEVICE_ADDR,0x00,0x00);//全配置为输出
//IIC_gpio_pca_init();//配置IIC管脚
   PCA9555_write_config_port_data(PCA9555_DEVICE_ADDR,PCA_OUTPUT_CONFIG_MASK,PCA_OUTPUT_CONFIG_MASK);//全配置为输出
   //PCA9555_write_config_port_data(PCA9555_DEVICE_ADDR,PCA_INPUT_CONFIG_MASK,PCA_INPUT_CONFIG_MASK);//全配置为输入
   //PCA9555_write_polarity_port_data(PCA9555_DEVICE_ADDR,0x00,0x00);//翻转
   PCA9555_Set_One_Value_Config(WAKE_UP,1);
   //PCA9555_Set_All_Output(1);
   //PCA9555_readdata_from_output_register(PCA9555_DEVICE_ADDR,pca9555writedata_input);
   //PCA9555_Set_One_Value_Output(AIR780E_ENBALE,0);
   //PCA9555_Set_One_Value_Output(PWR_ON,0);
//   PCA9555_Set_All_Output(0);
   //PCA9555_readdata_from_polarity_register(PCA9555_DEVICE_ADDR,pca9555writedata_input);
   PCA9555_readdata(PCA9555_DEVICE_ADDR,pca9555writedata_input);//读输入寄存器的值
   PCA9555_readdata_from_config_register(PCA9555_DEVICE_ADDR,pca9555writedata_config);
//   PCA9555_Set_All_Output(0);//全部拉低
   //测试
PCA9555_Set_All_Output(1);//全部拉高
//PCA9555_Set_All_Output(1);//全部拉高
//PCA9555_Set_All_Output(0);//全部拉低
}