esp32 esp-idf 移植u8g2驱动oled 硬件spi

u8g2移植前半部分基本一样,都是将u8g2的源码加入所在工程文件,随后删减部分文件和代码。不多赘述,本文主要说明移植需要的接口文件和移植过程中的事项。
可以参考这篇esp32 idf移植u8g2,采用软件spi:[002] [ESP32开发笔记] u8g2移植到esp32-idf
不过需要注意使用component创建u8g2的文件夹,参考这篇文章:
esp32 u8g2 idf移植
不过对于window用idf.py指令,window安装idf后,一般都会自动在桌面创建这两个快捷方式。
在这里插入图片描述双击点开任意一个都行,使用window的命令行跳转至工程所在文件夹,再执行
idf.py create-component -C components/ u8g2
至于Kconfig我没设置,好像没什么影响。
然后再main文件下新建.c、.h文件
在这里插入图片描述

新建esp32_oled.c文件

#include "esp32_oled.h"
#include "stdlib.h"

#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "sys/unistd.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"

static spi_device_handle_t spi;

static spi_bus_config_t buscfg={
		.miso_io_num=-1,//MISO信号线,可复用为QSPI的D0
		.mosi_io_num=PIN_OLED_DIN,//MOSI信号线,可复用为QSPI的D1
		.sclk_io_num=PIN_OLED_CLK,//SCLK信号线
		.quadwp_io_num=-1,//WP信号线,专用于QSPI的D2
		.quadhd_io_num=-1,//HD信号线,专用于QSPI的D3
		.max_transfer_sz=4094,//最大传输数据大小,单位字节,默认为4094
	    //.intr_flags,//中断指示位
};

 void oled_spi_init(void)
 {
  	esp_err_t ret;

  	esp_rom_gpio_pad_select_gpio(PIN_OLED_CS);                // 选择一个GPIO
  	gpio_set_direction(PIN_OLED_CS, GPIO_MODE_OUTPUT);// 把这个GPIO作为输出

  	esp_rom_gpio_pad_select_gpio(PIN_OLED_DC);                // 选择一个GPIO
  	gpio_set_direction(PIN_OLED_DC, GPIO_MODE_OUTPUT);// 把这个GPIO作为输出

  	esp_rom_gpio_pad_select_gpio(PIN_OLED_RES);                // 选择一个GPIO
  	gpio_set_direction(PIN_OLED_RES, GPIO_MODE_OUTPUT);// 把这个GPIO作为输出

  	//对于ESP32 超过26Mhz会报错,C系列、S系列未知
  	spi_device_interface_config_t devcfg={
  	.clock_speed_hz =SPI_MASTER_FREQ_26M,      // Clock out at 26 MHz,
  	.mode = 0,                                  // SPI mode 0
  	.spics_io_num = -1,
    .queue_size = 6,                            // 传输队列大小,决定了等待传输数据的数量
  	 };

  	 //Initialize the SPI bus
  	  ret = spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO);
//  	    ESP_ERROR_CHECK(ret);
  	  ret = spi_bus_add_device(SPI2_HOST, &devcfg, &spi);
//  	    ESP_ERROR_CHECK(ret);
  	}
uint8_t u8x8_byte_hard_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
    /* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */
	spi_transaction_t spi_trans;
	esp_err_t ret;

	printf("msg:%d,arg_int:%d\r\n",msg,arg_int);
    switch(msg){
	 case U8X8_MSG_BYTE_SEND: /*通过SPI发送arg_int个字节数据*/
	 {
		 memset(&spi_trans, 0, sizeof(spi_trans));       //Zero out the transaction
		 spi_trans.length=arg_int*8;                 //Len is in bytes, transaction length is in bits.
		 spi_trans.tx_buffer=arg_ptr;               //Data
		 spi_trans.user=(void*)1;                //D/C needs to be set to 1
		 ret=spi_device_polling_transmit(spi, &spi_trans);  //Transmit!
		 assert(ret==ESP_OK);
	 }
		break;
	case U8X8_MSG_BYTE_INIT: /*初始化函数*/
//    	oled_spi_init();
		break;
	case U8X8_MSG_BYTE_SET_DC:
		arg_int==1?OLED_DC_Set():OLED_DC_Clr();
//		esp_rom_delay_us(1);
		break;
	case U8X8_MSG_BYTE_START_TRANSFER:
		OLED_CS_Clr();
//		esp_rom_delay_us(1);
		break;
	case U8X8_MSG_BYTE_END_TRANSFER:
		OLED_CS_Set();
//		esp_rom_delay_us(1);
		break;
	default:
		return 0;
	}
    return 1;
}



uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
//采用硬件spi,部分分支可以忽略不写
    switch (msg)
    {
    //Initialize SPI peripheral
    case U8X8_MSG_GPIO_AND_DELAY_INIT:
        break;
  	//Function which implements a delay, arg_int contains the amount of ms
  	case U8X8_MSG_DELAY_MILLI:
//  		vTaskDelay(pdMS_TO_TICKS(arg_int));
        break;
  	//Function which delays 10us
      case U8X8_MSG_DELAY_10MICRO:
//    	  esp_rom_delay_us(10);
    	  break;
      // Function to define the logic level of the CS line
  	case U8X8_MSG_GPIO_CS:
//  		arg_int==1?OLED_CS_Set():OLED_CS_Clr();
  	  break;
  	//Function to define the logic level of the Data/ Command line
  	case U8X8_MSG_GPIO_DC:
//  		arg_int==1?OLED_DC_Set():OLED_DC_Clr();
  	  break;
  	//Function to define the logic level of the RESET line
  	case U8X8_MSG_GPIO_RESET:
  	  break;
  	default:
  	  return 0; //A message was received which is not implemented, return 0 to indicate an error
    }
    return 1;
}


void u8g2Init(u8g2_t *u8g2)
{
	u8g2_Setup_ssd1306_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_hard_spi, u8x8_gpio_and_delay);
	u8g2_InitDisplay(u8g2);
	u8g2_SetPowerSave(u8g2, 0);
	u8g2_ClearBuffer(u8g2);
}

新建esp32_oled.h文件

#ifndef ESP32_OLED_H_
#define ESP32_OLED_H_

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "u8g2.h"
#include "u8x8.h"
#include "stdlib.h"
#include "driver/gpio.h"
#include "driver/spi_master.h"

//              GND
//              VCC  	3.3v
//              D0    	CLK
//              D1    	DIN
//              RES  	RES
//              DC      DC
//              CS      CS

#define PIN_OLED_CLK	23
#define PIN_OLED_DIN	22
#define PIN_OLED_RES	19
#define PIN_OLED_DC		18
#define PIN_OLED_CS		5

#define OLED_CS_Clr()  gpio_set_level(PIN_OLED_CS, 0)//CS
#define OLED_CS_Set()  gpio_set_level(PIN_OLED_CS, 1)

#define OLED_REST_Clr() gpio_set_level(PIN_OLED_RES, 0)//RES
#define OLED_REST_Set() gpio_set_level(PIN_OLED_RES, 1)

#define OLED_DC_Clr() gpio_set_level(PIN_OLED_DC, 0)//DC
#define OLED_DC_Set() gpio_set_level(PIN_OLED_DC, 1)

void u8g2Init(u8g2_t *u8g2);

void oled_spi_init(void);

#endif /* ESP32_OLED_H_ */

此外,在main.c中初始化时,需先初始化spi,在初始u8g2,否则容易出现雪花屏,代码如下

    //需要先初始化spi,否则可能出现会雪花屏
    oled_spi_init();

    //复位OLED
    OLED_REST_Set();
   	vTaskDelay(50 / portTICK_PERIOD_MS);
    OLED_REST_Clr();
   	vTaskDelay(5 / portTICK_PERIOD_MS);
    OLED_REST_Set();
	vTaskDelay(50 / portTICK_PERIOD_MS);
	//初始化u8g2
    u8g2_t u8g2;
    u8g2Init(&u8g2);

这是esp_idf移植u8g2驱动oled的代码,硬件IIC和硬件SPI都有
https://gitee.com/zero-speed-of-light/esp_idf_u8g2_oled.git
在这里插入图片描述
移植的代码,包括硬件spi(4线)和硬件IIC:https://gitee.com/zero-speed-of-light/esp_idf_u8g2_oled.git

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用ESP-IDF框架的ESP32 SPI3通信的示例代码: ```c #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/spi_master.h" #define PIN_CLK 18 #define PIN_MISO 19 #define PIN_MOSI 23 #define PIN_CS 5 void spi_task(void *pvParameters) { spi_device_handle_t spi; spi_bus_config_t bus_config = { .mosi_io_num = PIN_MOSI, .miso_io_num = PIN_MISO, .sclk_io_num = PIN_CLK, .quadwp_io_num = -1, .quadhd_io_num = -1, .max_transfer_sz = 0, }; spi_device_interface_config_t dev_config = { .command_bits = 0, .address_bits = 0, .dummy_bits = 0, .mode = 0, .duty_cycle_pos = 0, .cs_ena_pretrans = 0, .cs_ena_posttrans = 0, .clock_speed_hz = 1000000, // 设置时钟频率为1MHz .input_delay_ns = 0, .spics_io_num = PIN_CS, .flags = 0, .queue_size = 1, .pre_cb = NULL, .post_cb = NULL, }; spi_device_handle_t spi_handle; spi_bus_initialize(VSPI_HOST, &bus_config, 1); spi_bus_add_device(VSPI_HOST, &dev_config, &spi_handle); while (1) { uint8_t send_data = 0x55; uint8_t recv_data; spi_transaction_t trans_desc = { .flags = 0, .cmd = 0, .addr = 0, .length = 8, // 数据位宽为8位 .rxlength = 8, .tx_buffer = &send_data, .rx_buffer = &recv_data, }; spi_device_polling_transmit(spi_handle, &trans_desc); printf("Received data: 0x%02x\n", recv_data); vTaskDelay(1000 / portTICK_PERIOD_MS); } } void app_main() { xTaskCreate(spi_task, "spi_task", 2048, NULL, 10, NULL); } ``` 在这个示例中,我们使用了ESP32的VSPI总线,并且将引脚18、19和23分别连接到SPI3的CLK、MISO和MOSI信号。引脚5用作CS(片选)信号。 我们首先定义了SPI总线和设备的配置参数。然后,通过调用spi_bus_initialize()函数初始化SPI总线,并通过spi_bus_add_device()函数将SPI设备添加到总线上。 在任务函数spi_task()中,我们创建了一个spi_transaction_t结构体来描述传输的参数。然后,我们使用spi_device_polling_transmit()函数来发送和接收数据。 最后,我们在app_main()函数中创建了一个任务来执行SPI通信操作。 请根据你的具体需求进行适当的修改和配置。希望这个例程能帮助你使用ESP-IDF框架进行ESP32 SPI3通信!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值