RCM — ESP32 Room Controller
WT32-ETH01 firmware
Loading...
Searching...
No Matches
pcf8574.c
Go to the documentation of this file.
1
9#include "pcf8574.h"
10
11#include "driver/i2c_master.h"
12#include "esp_check.h"
13#include "esp_log.h"
14#include "freertos/FreeRTOS.h"
15#include "freertos/task.h"
16
17static const char *TAG = "pcf8574";
18
20#define I2C_PORT I2C_NUM_0
21
23#define I2C_SCL_GPIO 14
24#define I2C_SDA_GPIO 15
25
27#define I2C_FREQ_HZ 100000
28
30#define I2C_TIMEOUT_MS 1000
31
33#define PCF8574_I2C_ADDR 0x20
34
36#define LED_CHASE_PIN_COUNT 3
37#define LED_CHASE_PIN_MASK 0x07
38#define LED_CHASE_PORT_IDLE 0xF8
39#define LED_CHASE_STEP_MS 300
40
41static i2c_master_bus_handle_t s_i2c_bus;
42static i2c_master_dev_handle_t s_pcf8574_dev;
43static uint8_t s_port_shadow;
44static bool s_initialized;
45
46static esp_err_t pcf8574_write_raw(uint8_t value)
47{
48 return i2c_master_transmit(s_pcf8574_dev, &value, 1, I2C_TIMEOUT_MS);
49}
50
51static esp_err_t pcf8574_read_raw(uint8_t *value)
52{
53 return i2c_master_receive(s_pcf8574_dev, value, 1, I2C_TIMEOUT_MS);
54}
55
56esp_err_t pcf8574_init(void)
57{
58 if (s_initialized) {
59 return ESP_OK;
60 }
61
62 i2c_master_bus_config_t bus_cfg = {
63 .i2c_port = I2C_PORT,
64 .sda_io_num = I2C_SDA_GPIO,
65 .scl_io_num = I2C_SCL_GPIO,
66 .clk_source = I2C_CLK_SRC_DEFAULT,
67 .glitch_ignore_cnt = 7,
68 .flags.enable_internal_pullup = true,
69 };
70 ESP_RETURN_ON_ERROR(i2c_new_master_bus(&bus_cfg, &s_i2c_bus), TAG, "i2c bus init failed");
71
72 i2c_device_config_t dev_cfg = {
73 .dev_addr_length = I2C_ADDR_BIT_LEN_7,
74 .device_address = PCF8574_I2C_ADDR,
75 .scl_speed_hz = I2C_FREQ_HZ,
76 };
77 ESP_RETURN_ON_ERROR(i2c_master_bus_add_device(s_i2c_bus, &dev_cfg, &s_pcf8574_dev),
78 TAG, "i2c device add failed");
79
80 /* Всее «все»: все пины — вход (1), без активных выходов в 0 */
81 s_port_shadow = 0xFF; // все пины входы (1)
82 ESP_RETURN_ON_ERROR(pcf8574_write_raw(s_port_shadow), TAG, "initial write failed");
83
84 uint8_t readback = 0;
85 ESP_RETURN_ON_ERROR(pcf8574_read_raw(&readback), TAG, "initial read failed");
86
87 s_initialized = true;
88 ESP_LOGI(TAG, "PCF8574 at 0x%02X, I2C SCL=GPIO%d SDA=GPIO%d, port=0x%02X",
90 return ESP_OK;
91}
92
93esp_err_t pcf8574_write(uint8_t value)
94{
95 ESP_RETURN_ON_FALSE(s_initialized, ESP_ERR_INVALID_STATE, TAG, "not initialized");
96
97 esp_err_t err = pcf8574_write_raw(value);
98 ESP_RETURN_ON_ERROR(err, TAG, "write failed");
99
100 s_port_shadow = value;
101 return ESP_OK;
102}
103
104esp_err_t pcf8574_read(uint8_t *value)
105{
106 ESP_RETURN_ON_FALSE(s_initialized, ESP_ERR_INVALID_STATE, TAG, "not initialized");
107 ESP_RETURN_ON_FALSE(value, ESP_ERR_INVALID_ARG, TAG, "null value");
108
109 return pcf8574_read_raw(value);
110}
111
112esp_err_t pcf8574_set_pin(uint8_t pin, bool level)
113{
114 ESP_RETURN_ON_FALSE(pin < 8, ESP_ERR_INVALID_ARG, TAG, "pin out of range");
115
116 uint8_t mask = (uint8_t)(1U << pin);
117 uint8_t next = s_port_shadow;
118
119 if (level) {
120 next |= mask;
121 } else {
122 next &= (uint8_t)~mask;
123 }
124
125 return pcf8574_write(next);
126}
127
128esp_err_t pcf8574_get_pin(uint8_t pin, bool *level)
129{
130 ESP_RETURN_ON_FALSE(pin < 8, ESP_ERR_INVALID_ARG, TAG, "pin out of range");
131 ESP_RETURN_ON_FALSE(level, ESP_ERR_INVALID_ARG, TAG, "null level");
132
133 uint8_t value = 0;
134 ESP_RETURN_ON_ERROR(pcf8574_read(&value), TAG, "read failed");
135
136 *level = (value & (1U << pin)) != 0;
137 return ESP_OK;
138}
139
143static void led_chase_task(void *arg)
144{
145 uint8_t pin = 0;
146
147 while (true) {
148 uint8_t port = LED_CHASE_PORT_IDLE | (uint8_t)(1U << pin);
149 if (pcf8574_write(port) == ESP_OK) {
150 ESP_LOGD(TAG, "Chase: P%d on (port=0x%02X)", pin, port);
151 }
152
153 pin = (uint8_t)((pin + 1) % LED_CHASE_PIN_COUNT);
154 vTaskDelay(pdMS_TO_TICKS(LED_CHASE_STEP_MS));
155 }
156}
157
159{
160 static bool started = false;
161
162 ESP_RETURN_ON_FALSE(s_initialized, ESP_ERR_INVALID_STATE, TAG, "not initialized");
163
164 if (started) {
165 return ESP_OK;
166 }
167
168 BaseType_t created = xTaskCreate(led_chase_task, "led_chase", 2048, NULL, 5, NULL);
169 ESP_RETURN_ON_FALSE(created == pdPASS, ESP_ERR_NO_MEM, TAG, "chase task create failed");
170
171 started = true;
172 ESP_LOGI(TAG, "LED chase started on P0..P%d", LED_CHASE_PIN_COUNT - 1);
173 return ESP_OK;
174}
#define I2C_FREQ_HZ
Частота I2C, Гц
Definition pcf8574.c:27
#define LED_CHASE_STEP_MS
Definition pcf8574.c:39
esp_err_t pcf8574_read(uint8_t *value)
Читает текущее состояние порта P0..P7.
Definition pcf8574.c:104
esp_err_t pcf8574_init(void)
Инициализирует шину I2C и устройство PCF8574T.
Definition pcf8574.c:56
static i2c_master_bus_handle_t s_i2c_bus
Definition pcf8574.c:41
#define I2C_SDA_GPIO
Definition pcf8574.c:24
static const char * TAG
Definition pcf8574.c:17
static uint8_t s_port_shadow
Definition pcf8574.c:43
#define I2C_SCL_GPIO
GPIO шины I2C.
Definition pcf8574.c:23
static bool s_initialized
Definition pcf8574.c:44
esp_err_t pcf8574_get_pin(uint8_t pin, bool *level)
Читает уровень одного пина (0..7).
Definition pcf8574.c:128
static esp_err_t pcf8574_read_raw(uint8_t *value)
Definition pcf8574.c:51
esp_err_t pcf8574_led_chase_start(void)
Запускает задачу «бегущий огонь» на светодиодах P0..P2.
Definition pcf8574.c:158
#define PCF8574_I2C_ADDR
7-битный адрес PCF8574 на шине (A0=A1=A2=0 → 0x20)
Definition pcf8574.c:33
static void led_chase_task(void *arg)
Циклически включает по одному светодиоду на P0, P1, P2.
Definition pcf8574.c:143
static i2c_master_dev_handle_t s_pcf8574_dev
Definition pcf8574.c:42
static esp_err_t pcf8574_write_raw(uint8_t value)
Definition pcf8574.c:46
#define I2C_TIMEOUT_MS
Таймаут транзакции, мс
Definition pcf8574.c:30
#define LED_CHASE_PIN_COUNT
Светодиоды на P0..P2 (остальные пины не трогаем)
Definition pcf8574.c:36
#define I2C_PORT
Порт I2C.
Definition pcf8574.c:20
esp_err_t pcf8574_write(uint8_t value)
Записывает байт в порт расширителя (состояние P0..P7).
Definition pcf8574.c:93
#define LED_CHASE_PORT_IDLE
Definition pcf8574.c:38
esp_err_t pcf8574_set_pin(uint8_t pin, bool level)
Устанавливает уровень одного пина (0..7).
Definition pcf8574.c:112
Драйвер I2C-расширителя портов PCF8574T.