图片
图片
#include <stdio.h>
#include "driver/gpio.h"
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_rom_sys.h"
#include "driver/uart.h"
#include "driver/i2c.h"
#include "esp_system.h"
#include "esp_log.h"
//--------------------------------------------------------------------
// I2C 配置参数
#define I2C_EXAMPLE_MASTER_SDA_IO 5 // I2C 数据引脚
#define I2C_EXAMPLE_MASTER_SCL_IO 14 // I2C 时钟引脚
#define I2C_EXAMPLE_MASTER_NUM I2C_NUM_0
#define I2C_EXAMPLE_MASTER_FREQ_HZ 100000
#define I2C_EXAMPLE_MASTER_TX_BUF_DISABLE 0
#define I2C_EXAMPLE_MASTER_RX_BUF_DISABLE 0
#define DS3231_ADDR 0x68 // DS3231 的 I2C 地址
#define WRITE_BIT I2C_MASTER_WRITE
#define READ_BIT I2C_MASTER_READ
//--------------------------------------------------------------------------
#define DATA0_GPIO 2
#define DATA1_GPIO 4
#define DATA2_GPIO 18
#define DATA3_GPIO 19
#define DATA4_GPIO 23
#define DATA5_GPIO 25
#define DATA6_GPIO 26
#define DATA7_GPIO 27
#define RS_GPIO 21 // 数据/命令选择引脚
#define RST_GPIO 15 // 复位引脚
#define EN_GPIO 22 // 使能引脚
#define RW 13
//--------------------------------------------------------------------------
// 初始化 I2C
esp_err_t i2c_master_init() {
esp_err_t ret;
i2c_config_t conf;
conf.mode = I2C_MODE_MASTER;
conf.sda_io_num = I2C_EXAMPLE_MASTER_SDA_IO;
conf.scl_io_num = I2C_EXAMPLE_MASTER_SCL_IO;
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
conf.master.clk_speed = I2C_EXAMPLE_MASTER_FREQ_HZ;
ret = i2c_param_config(I2C_EXAMPLE_MASTER_NUM, &conf);
if (ret != ESP_OK) {
return ret;
}
ret = i2c_driver_install(I2C_EXAMPLE_MASTER_NUM, conf.mode, I2C_EXAMPLE_MASTER_RX_BUF_DISABLE, I2C_EXAMPLE_MASTER_TX_BUF_DISABLE, 0);
return ret;
}
// 读取 DS3231 时间
esp_err_t ds3231_read_time(uint8_t *data, size_t length) {
esp_err_t ret;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (DS3231_ADDR << 1) | WRITE_BIT, true);
i2c_master_write_byte(cmd, 0x00, true); // 从 DS3231 的寄存器 0 开始读取时间
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (DS3231_ADDR << 1) | READ_BIT, true);
i2c_master_read(cmd, data, length, I2C_MASTER_LAST_NACK);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_EXAMPLE_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
return ret;
}
//---------------------------------------------------------------------------------
void pd(){ //判断lcd 忙
gpio_set_level(RW, 1);
gpio_set_level(RS_GPIO, 0);
while(gpio_get_level(27)!=0){
esp_rom_delay_us(10);
}
}
void lcd_write_command(uint8_t cmd) {
pd();
gpio_set_level(RS_GPIO, 0); // 设置为命令模式
gpio_set_level(RW, 0);
gpio_set_level(EN_GPIO, 0);
esp_rom_delay_us(50);
gpio_set_level(EN_GPIO, 1);
gpio_set_level(DATA0_GPIO, cmd & 0x01);
gpio_set_level(DATA1_GPIO, (cmd >> 1) & 0x01);
gpio_set_level(DATA2_GPIO, (cmd >> 2) & 0x01);
gpio_set_level(DATA3_GPIO, (cmd >> 3) & 0x01);
gpio_set_level(DATA4_GPIO, (cmd >> 4) & 0x01);
gpio_set_level(DATA5_GPIO, (cmd >> 5) & 0x01);
gpio_set_level(DATA6_GPIO, (cmd >> 6) & 0x01);
gpio_set_level(DATA7_GPIO, (cmd >> 7) & 0x01);
esp_rom_delay_us(500);
gpio_set_level(EN_GPIO, 0); // 使能低电
esp_rom_delay_us(50);
gpio_set_level(RS_GPIO, 1);
gpio_set_level(RW, 1);
esp_rom_delay_us(20);
}
void lcd_init() {
// 初始化引脚
gpio_set_direction(DATA0_GPIO, GPIO_MODE_OUTPUT);
gpio_set_direction(DATA1_GPIO, GPIO_MODE_OUTPUT);
gpio_set_direction(DATA2_GPIO, GPIO_MODE_OUTPUT);
gpio_set_direction(DATA3_GPIO, GPIO_MODE_OUTPUT);
gpio_set_direction(DATA4_GPIO, GPIO_MODE_OUTPUT);
gpio_set_direction(DATA5_GPIO, GPIO_MODE_OUTPUT);
gpio_set_direction(DATA6_GPIO, GPIO_MODE_OUTPUT);
gpio_set_direction(DATA7_GPIO, GPIO_MODE_OUTPUT);
gpio_set_direction(RS_GPIO, GPIO_MODE_OUTPUT);
gpio_set_direction(RST_GPIO, GPIO_MODE_OUTPUT);
gpio_set_direction(EN_GPIO, GPIO_MODE_OUTPUT);
// 复位 LCD
gpio_set_level(RST_GPIO, 0);
esp_rom_delay_us(500);
gpio_set_level(RST_GPIO, 1);
}
void lcd_write_data(uint8_t data) {
pd();
gpio_set_level(RS_GPIO, 1); // 设置为数据模式
gpio_set_level(RW, 0);
gpio_set_level(EN_GPIO, 0); // 使能低电平
esp_rom_delay_us(50);
gpio_set_level(EN_GPIO, 1);
gpio_set_level(DATA0_GPIO, data & 0x01);
gpio_set_level(DATA1_GPIO, (data >> 1) & 0x01);
gpio_set_level(DATA2_GPIO, (data >> 2) & 0x01);
gpio_set_level(DATA3_GPIO, (data >> 3) & 0x01);
gpio_set_level(DATA4_GPIO, (data >> 4) & 0x01);
gpio_set_level(DATA5_GPIO, (data >> 5) & 0x01);
gpio_set_level(DATA6_GPIO, (data >> 6) & 0x01);
gpio_set_level(DATA7_GPIO, (data >> 7) & 0x01);
esp_rom_delay_us(500);
gpio_set_level(EN_GPIO, 0); // 使能低电平
esp_rom_delay_us(50);
gpio_set_level(RS_GPIO, 0);
gpio_set_level(RW, 1);
esp_rom_delay_us(20);
}
// 应用主函数
void app_main() {
lcd_init();
// 初始化 LCD 控制器(根据 LCD 模型设置命令)
lcd_write_command(0x30); // 8-bit模式,
lcd_write_command(0x30); // 8-bit模式,
lcd_write_command(0x0c); // 开启显示,不显示光标
lcd_write_command(0x01);
lcd_write_command(0x06);
//---------------------------------------------------------------------
esp_err_t ret;
uint8_t data[7]; // DS3231 返回 7 字节数据
// 初始化 I2C
ret = i2c_master_init();
if (ret != ESP_OK) {
ESP_LOGE("I2C", "Failed to initialize I2C");
return;
}
// 读取时间
while(1){
ret = ds3231_read_time(data, sizeof(data));
if (ret == ESP_OK) {
lcd_write_command(0x01);
lcd_write_command(0x06);
lcd_write_command(0x84);
uint8_t o=data[0];
uint8_t oh=(o>>4)&0b00001111;
lcd_write_data(oh+0x30);
uint8_t ol=o&0b00001111;
lcd_write_data(ol+0x30);
lcd_write_command(0x82);
uint8_t fo=data[1];
uint8_t foh=(fo>>4)&0b00001111;
lcd_write_data(foh+0x30);
uint8_t fol=fo&0b00001111;
lcd_write_data(fol+0x30);
lcd_write_command(0x80);
uint8_t so=data[2];
uint8_t soh=(so>>4)&0b00001111;
lcd_write_data(soh+0x30);
uint8_t sol=so&0b00001111;
lcd_write_data(sol+0x30);
} else {
ESP_LOGE("DS3231", "Failed to read time");
}
vTaskDelay(pdMS_TO_TICKS(500));
}
}