HAL库源码移植与使用之iic驱动PCF8574T

 PCF8574有两个型号,PCF8574T是简称PCF8574,PCF8574A又是另一个版本,一定要分清楚它们的区别,因为不分清后面发地址会很麻烦,他们前三位地址不一样。

我使用的就是PCF8574T

实际上他俩也就地址不同

 

地址字节内容:

PCF8574A地址前四位不是0100而是0111

 

 

 PCF8574时序图

 A是应答信号

  A是应答信号

 

 PCF8574中断引脚的用处:

默认初始引脚是都为1,一旦引脚发生上升沿或下降沿变化,INT引脚就会变低,你可以设置mcu去读取该引脚,若为低就读取判断哪个引脚变化了,再把读取到的引脚状态写入PCF8574里,这就可在不影响现在引脚状态的情况下,完成消除中断的作用,不然他会一直INT拉低

INT引脚检查的上升沿下降沿是针对初始值11111111,但当你写入引脚后就会变为关于写入的引脚状态的边沿检测

 

pcf8574.c 

#include "./BSP/PCF8574/pcf8574.h"
#include "./SYSTEM/delay/delay.h"

/**
 * @brief       初始化PCF8574
 * @param       无
 * @retval      0, 成功;
                1, 失败;
 */
uint8_t pcf8574_init(void)
{
    uint8_t temp = 0;
    GPIO_InitTypeDef gpio_init_struct;
    
    PCF8574_GPIO_CLK_ENABLE();                               /* 使能GPIOB时钟 */

    gpio_init_struct.Pin = PCF8574_GPIO_PIN;                 /* PB12 */
    gpio_init_struct.Mode = GPIO_MODE_INPUT;                 /* 输入 */
    gpio_init_struct.Pull = GPIO_PULLUP;                     /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_HIGH;                /* 高速 */
    HAL_GPIO_Init(PCF8574_GPIO_PORT, &gpio_init_struct);     /* 初始化 */
    
    iic_init();                                              /* IIC初始化 */

    /* 检查PCF8574是否在位 */
    iic_start();
    iic_send_byte(PCF8574_ADDR);                             /* 写地址 */
    temp = iic_wait_ack();                                   /* 等待应答,通过判断是否有ACK应答,来判断PCF8574的状态 */
    iic_stop();                                              /* 产生一个停止条件 */
    
    pcf8574_write_byte (0xFF);
    
    return temp;
}
 



uint8_t pcf8574_read_byte (void)
{ 
    uint8_t temp = 0;
    
    iic_start();                /* 发送起始信号 */
    iic_send_byte(0x41);        /* 发送读操作地址 */
    iic_wait_ack( );            /* 等待pcf8574的应答 */
    temp = iic_read_byte(0);    /* 读取1Byte数据并发nACK信号 */
    iic_stop ();                /* 发送停止信号 */
    return temp;
}



void pcf8574_write_byte (uint8_t data)
{ 
    iic_start();            /* 发送起始信号 */
    iic_send_byte(0x40);    /* 发送写操作地址 */
    iic_wait_ack( );        /* 等待pcf8574的应答 */
    iic_send_byte(data);    /* 发送1Byte数据设置pcf8574的IO状态 */
    iic_wait_ack( );        /* 等待pcf8574的应答 */	
    iic_stop ();            /* 发送停止信号 */
    delay_ms(10);
}


uint8_t pcf8574_read_bit(uint8_t bit)
{
    uint8_t temp = 0;
    
    temp = pcf8574_read_byte ();    /* temp是8个IO口的电平状态 */
    
    if (temp & (1 << bit))
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

void pcf8574_write_bit(uint8_t bit, uint8_t sta)
{
    uint8_t temp = 0;
    
    temp = pcf8574_read_byte ();    /* temp是8个IO口的电平状态 */
    
    if (sta)
    {
        temp |= (1 << bit);
    }
    else
    {
        temp &= ~(1 << bit);
    }
    
    pcf8574_write_byte (temp);
}



pcf8574.h

 

#ifndef __PCF8574_H
#define __PCF8574_H

#include "./SYSTEM/sys/sys.h"
#include "./BSP/IIC/myiic.h"

/******************************************************************************************/
/* 引脚 定义 */
#define PCF8574_GPIO_PORT                  GPIOB
#define PCF8574_GPIO_PIN                   GPIO_PIN_12
#define PCF8574_GPIO_CLK_ENABLE()          do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)             /* PB口时钟使能 */

/******************************************************************************************/

#define PCF8574_INT  HAL_GPIO_ReadPin(PCF8574_GPIO_PORT, PCF8574_GPIO_PIN) /* PCF8574 INT脚 */

#define PCF8574_ADDR  0X40      /* PCF8574地址(左移了一位) */

/* PCF8574各个IO的功能 */
#define BEEP_IO         0       /* 蜂鸣器控制引脚        P0 */
#define AP_INT_IO       1       /* AP3216C中断引脚       P1 */
#define DCMI_PWDN_IO    2       /* DCMI的电源控制引脚    P2 */
#define USB_PWR_IO      3       /* USB电源控制引脚       P3 */
#define EX_IO           4       /* 扩展IO,自定义使用     P4 */
#define MPU_INT_IO      5       /* SH3001中断引脚        P5 */
#define RS485_RE_IO     6       /* RS485_RE引脚          P6 */
#define ETH_RESET_IO    7       /* 以太网复位引脚        P7 */

uint8_t pcf8574_init(void); 
void pcf8574_write_bit(uint8_t bit, uint8_t sta);
uint8_t pcf8574_read_bit(uint8_t bit);
uint8_t pcf8574_read_byte (void);
void pcf8574_write_byte (uint8_t data);

#endif

  • 15
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,我可以给你一些参考代码,帮助你实现这个功能。 首先,你需要在STM32上实现模拟I2C通信。这可以通过软件模拟实现,也可以使用硬件I2C模块。如果你使用的是硬件I2C模块,你需要配置I2C的时钟和数据线,并设置I2C的地址。 接下来,你需要编写代码来控制PCF8574AT驱动LCD1602。PCF8574AT是一个8位I/O扩展器,可以通过I2C接口进行控制。通过设置PCF8574AT的输出端口,可以控制LCD1602的显示内容。 以下是一个示例代码,演示如何使用PCF8574AT驱动LCD1602: ```c #include "stm32f1xx.h" #define SCL_Pin GPIO_PIN_10 #define SDA_Pin GPIO_PIN_11 #define SCL_Port GPIOB #define SDA_Port GPIOB #define I2C_ADDR 0x4E void I2C_Start(void) { GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = SDA_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(SDA_Port, &GPIO_InitStruct); HAL_GPIO_WritePin(SDA_Port, SDA_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(SCL_Port, SCL_Pin, GPIO_PIN_SET); HAL_Delay(1); HAL_GPIO_WritePin(SDA_Port, SDA_Pin, GPIO_PIN_RESET); HAL_Delay(1); HAL_GPIO_WritePin(SCL_Port, SCL_Pin, GPIO_PIN_RESET); } void I2C_Stop(void) { GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = SDA_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(SDA_Port, &GPIO_InitStruct); HAL_GPIO_WritePin(SDA_Port, SDA_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(SCL_Port, SCL_Pin, GPIO_PIN_SET); HAL_Delay(1); HAL_GPIO_WritePin(SDA_Port, SDA_Pin, GPIO_PIN_SET); } void I2C_SendByte(uint8_t data) { GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = SDA_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(SDA_Port, &GPIO_InitStruct); for (int i = 0; i < 8; i++) { if (data & 0x80) HAL_GPIO_WritePin(SDA_Port, SDA_Pin, GPIO_PIN_SET); else HAL_GPIO_WritePin(SDA_Port, SDA_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(SCL_Port, SCL_Pin, GPIO_PIN_SET); HAL_Delay(1); HAL_GPIO_WritePin(SCL_Port, SCL_Pin, GPIO_PIN_RESET); data <<= 1; } } uint8_t I2C_ReadByte(void) { GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = SDA_Pin; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(SDA_Port, &GPIO_InitStruct); uint8_t data = 0; for (int i = 0; i < 8; i++) { data <<= 1; HAL_GPIO_WritePin(SCL_Port, SCL_Pin, GPIO_PIN_SET); HAL_Delay(1); if (HAL_GPIO_ReadPin(SDA_Port, SDA_Pin)) data |= 0x01; HAL_GPIO_WritePin(SCL_Port, SCL_Pin, GPIO_PIN_RESET); } return data; } void LCD_WriteCmd(uint8_t cmd) { I2C_Start(); I2C_SendByte(I2C_ADDR); I2C_SendByte(0x00); I2C_SendByte(cmd); I2C_Stop(); } void LCD_WriteData(uint8_t data) { I2C_Start(); I2C_SendByte(I2C_ADDR); I2C_SendByte(0x40); I2C_SendByte(data); I2C_Stop(); } void LCD_Init(void) { LCD_WriteCmd(0x38); LCD_WriteCmd(0x08); LCD_WriteCmd(0x01); LCD_WriteCmd(0x06); LCD_WriteCmd(0x0C); } int main(void) { HAL_Init(); __HAL_RCC_GPIOB_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = SCL_Pin | SDA_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(SCL_Port, &GPIO_InitStruct); LCD_Init(); LCD_WriteData('H'); LCD_WriteData('e'); LCD_WriteData('l'); LCD_WriteData('l'); LCD_WriteData('o'); while (1) { } } ``` 在上面的代码中,我们首先定义了SCL和SDA的GPIO引脚,以及I2C设备的地址。然后,我们编写了几个I2C通信的基本函数。这些函数用于发送I2C起始信号、停止信号、发送数据和接收数据。 接下来,我们定义了几个LCD控制函数,用于向LCD发送命令和数据。在初始化函数中,我们发送了一些初始化命令,以设置LCD的显示模式。 在main函数中,我们初始化GPIO引脚,并调用LCD_Init函数初始化LCD。然后,我们向LCD发送一些数据,以显示“Hello”这个单词。 需要注意的是,如果你使用的是不同的LCD模块,你需要根据LCD的具体规格来编写相应的初始化命令和数据发送函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

广药门徒

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

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

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

打赏作者

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

抵扣说明:

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

余额充值