硬件准备
原理图
SCL,SDA默认引脚画反了,但是ESP8266的i2c引脚是可以任意的GPIO口。
实物图
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "driver/i2c.h"
#define GPIO_LED_PIN 16
#define GPIO_RLY_PIN 12
#define GPIO_DIR_PIN 5
#define GPIO_OUTPUT_PIN_SEL ((1ULL << GPIO_LED_PIN) | (1ULL << GPIO_RLY_PIN)|(1ULL << GPIO_DIR_PIN))
//i2c
#define I2C_MASTER_SCL_IO 14 /*!< gpio number for I2C master clock */
#define I2C_MASTER_SDA_IO 2 /*!< gpio number for I2C master data */
#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
#define ACK_VAL 0x0 /*!< I2C ack value */
#define NACK_VAL 0x1 /*!< I2C nack value */
#define LAST_NACK_VAL 0x2 /*!< I2C last_nack value */
#define BUF_SIZE (1024)
void LED_TOGGLE(void)
{
static uint8_t sta=0;
sta=sta?0:1;
gpio_set_level(GPIO_LED_PIN,sta);
}
void At24cxxInit(void)
{
int i2c_master_port = I2C_NUM_0;
i2c_config_t conf;
conf.mode = I2C_MODE_MASTER;
conf.sda_io_num = I2C_MASTER_SDA_IO;
conf.sda_pullup_en = 0;
conf.scl_io_num = I2C_MASTER_SCL_IO;
conf.scl_pullup_en = 0;
conf.clk_stretch_tick = 300; // 300 ticks, Clock stretch is about 210us, you can make changes according to the actual situation.
ESP_ERROR_CHECK(i2c_driver_install(i2c_master_port, conf.mode));
ESP_ERROR_CHECK(i2c_param_config(i2c_master_port, &conf));
}
//AT24CXX通用随机写一字节函数
void At24cxxWriteByte(uint16_t addr,uint8_t dat)
{
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, 0xA0, ACK_CHECK_EN);//器件地址+写位
i2c_master_write_byte(cmd, (uint8_t)(addr>>8), ACK_CHECK_EN);//存储地址高字节
i2c_master_write_byte(cmd,(uint8_t)addr,ACK_CHECK_EN);//存储地址低字节
i2c_master_write_byte(cmd,dat,ACK_CHECK_EN);
i2c_master_stop(cmd);
i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
}
//AT24CXX通用随机读一字节函数
int At24cxxRead(uint16_t addr,uint8_t *data,uint8_t len)
{
int ret;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();//创建命令队列
//填充命令……
i2c_master_start(cmd);
i2c_master_write_byte(cmd, 0xa0, ACK_CHECK_EN);
i2c_master_write_byte(cmd, (uint8_t)(addr>>8), ACK_CHECK_EN);
i2c_master_write_byte(cmd, (uint8_t)addr, ACK_CHECK_EN);
//i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS);//发送命令队列
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
return ret;
}
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, 0xa1, ACK_CHECK_EN);
i2c_master_read(cmd, data, len, LAST_NACK_VAL);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
return ret;
}
static void echo_task()
{
gpio_config_t io_conf;
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 0;
gpio_config(&io_conf);
gpio_set_level(GPIO_LED_PIN, 0);//
gpio_set_level(GPIO_RLY_PIN,0);
gpio_set_level(GPIO_DIR_PIN,0);
// Configure parameters of an UART driver,
// communication pins and install the driver
uart_config_t uart_config = {
.baud_rate = 9600,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
uart_param_config(UART_NUM_0, &uart_config);
uart_driver_install(UART_NUM_0, BUF_SIZE * 2, 0, 0, NULL, 0);
// Configure a temporary buffer for the incoming data
uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
//测试代码
At24cxxInit();
At24cxxWriteByte(0x0010,0x33);//写入一个字节
while (1) {
LED_TOGGLE();
vTaskDelay(1000 / portTICK_RATE_MS);
At24cxxRead(0x0010,data,1);//读取上面写入的一字节数据
gpio_set_level(GPIO_DIR_PIN,1);
uart_write_bytes(UART_NUM_0, (const char *) data, 1);
uart_wait_tx_done(UART_NUM_0, portMAX_DELAY);
gpio_set_level(GPIO_DIR_PIN,0);
}
}
void app_main()
{
xTaskCreate(echo_task, "uart_echo_task", 1024, NULL, 10, NULL);
}
程序功能就是向0x0010地址处写入一个字节0x33,然后循环读取并从UART发出来。
编译
下载
运行测试
|
|