为什么espidf的spi就是很慢

This commit is contained in:
2026-02-18 04:00:04 +08:00
parent ce0b15e2fa
commit 4adb13d748
10 changed files with 453 additions and 16 deletions
+37 -15
View File
@@ -49,7 +49,8 @@ void spi_init()
.quadwp_io_num = -1, // 不使用 QWP
.quadhd_io_num = -1, // 不使用 QHD
.max_transfer_sz = 4096, // 最大传输大小
.flags = SPICOMMON_BUSFLAG_MASTER,
.flags = 0,
.intr_flags = 0,
};
// 2. 初始化 SPI 总线
@@ -69,6 +70,9 @@ void spi_init()
.spics_io_num = LCD_CS,
.queue_size = 7, // 队列深度
.flags = SPI_DEVICE_NO_DUMMY, // 禁用 dummy 周期
.input_delay_ns = 0,
.pre_cb = NULL,
.post_cb = NULL,
};
@@ -82,15 +86,33 @@ void spi_init()
}
// SPI 写数据
esp_err_t lcd_spi_write8(uint8_t data) {
spi_transaction_t trans = {
.length = 8, // 数据位数
.tx_buffer = &data, // 发送缓冲区
.rx_buffer = NULL, // 不接收
// 高速数据传输函数
esp_err_t spi_transfer_fast(spi_device_handle_t spi, uint8_t *tx_data, uint8_t *rx_data, size_t len)
{
spi_transaction_t t = {
.flags = 0,
.cmd = 0,
.addr = 0,
.length = 8 * len,
.tx_buffer = tx_data,
.rx_buffer = rx_data,
};
return spi_device_transmit(lcd_spi, &trans);
// 使用轮询传输(小数据量更快)
return spi_device_polling_transmit(spi, &t);
}
// SPI 写数据
esp_err_t lcd_spi_write8(uint8_t data) {
// spi_transaction_t trans = {
// .length = 8, // 数据位数
// .tx_buffer = &data, // 发送缓冲区
// .rx_buffer = NULL, // 不接收
// };
// return spi_device_transmit(lcd_spi, &trans);
return spi_transfer_fast(lcd_spi,&data,NULL,1);
}
// SPI 写数据
@@ -100,15 +122,15 @@ esp_err_t lcd_spi_write16(uint16_t data) {
tx_buf[1] = data & 0xFF;
tx_buf[0] = (data >> 8) & 0xFF;
spi_transaction_t trans = {
.length = 16, // 数据位数
.tx_buffer = tx_buf, // 发送缓冲区
.rx_buffer = NULL, // 不接收
};
// spi_transaction_t trans = {
// .length = 16, // 数据位数
// .tx_buffer = tx_buf, // 发送缓冲区
// .rx_buffer = NULL, // 不接收
// };
// return spi_device_transmit(lcd_spi, &trans);
return spi_device_transmit(lcd_spi, &trans);
return spi_transfer_fast(lcd_spi,tx_buf,NULL,2);
}
// SPI 写命令
+5
View File
@@ -0,0 +1,5 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
+10
View File
@@ -0,0 +1,10 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}
+37
View File
@@ -0,0 +1,37 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the convention is to give header files names that end with `.h'.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
+46
View File
@@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into the executable file.
The source code of each library should be placed in a separate directory
("lib/your_library_name/[Code]").
For example, see the structure of the following example libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional. for custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
Example contents of `src/main.c` using Foo and Bar:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
The PlatformIO Library Dependency Finder will find automatically dependent
libraries by scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html
+14
View File
@@ -0,0 +1,14 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:seeed_xiao_esp32c3]
platform = espressif32
board = seeed_xiao_esp32c3
framework = arduino
+241
View File
@@ -0,0 +1,241 @@
#include "lcd.h"
#include <SPI.h>
SPIClass * vspi = NULL;
/******************************************************************************
函数说明:LCD写入命令
入口数据:dat 写入的命令
返回值: 无
******************************************************************************/
void LCD_WR_REG(uint8_t dat)
{
digitalWrite(LCD_DS,0);//写命令
vspi->transfer(dat);
digitalWrite(LCD_DS,1);//写数据
}
/******************************************************************************
函数说明:设置起始和结束地址
入口数据:x1,x2 设置列的起始和结束地址
y1,y2 设置行的起始和结束地址
返回值: 无
******************************************************************************/
void LCD_Address_Set(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2)
{
#if USE_HORIZONTAL==0
LCD_WR_REG(0x2a);//列地址设置
vspi->transfer16(x1);
vspi->transfer16(x2);
LCD_WR_REG(0x2b);//行地址设置
vspi->transfer16(y1);
vspi->transfer16(y2);
LCD_WR_REG(0x2c);//储存器写
#elif USE_HORIZONTAL==1
LCD_WR_REG(0x2a);//列地址设置
vspi->transfer16(x1);
vspi->transfer16(x2);
LCD_WR_REG(0x2b);//行地址设置
vspi->transfer16(y1+80);
vspi->transfer16(y2+80);
LCD_WR_REG(0x2c);//储存器写
#elif USE_HORIZONTAL==2
LCD_WR_REG(0x2a);//列地址设置
vspi->transfer16(x1);
vspi->transfer16(x2);
LCD_WR_REG(0x2b);//行地址设置
vspi->transfer16(y1);
vspi->transfer16(y2);
LCD_WR_REG(0x2c);//储存器写
#elif USE_HORIZONTAL==3
LCD_WR_REG(0x2a);//列地址设置
vspi->transfer16(x1+80);
vspi->transfer16(x2+80);
LCD_WR_REG(0x2b);//行地址设置
vspi->transfer16(y1);
vspi->transfer16(y2);
LCD_WR_REG(0x2c);//储存器写
#endif
}
void LCD_fillRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color)
{
LCD_Address_Set(x,y,width+x-1,height+y-1);
for(uint16_t i=0;i<height;i++)
{
for (uint16_t j=0;j<width;j++)
{
vspi->transfer16(color);
//delay(100);
}
}
}
/******************************************************************************
函数说明:LCD清屏函数
入口数据:无
返回值: 无
******************************************************************************/
void LCD_Clear(uint16_t Color)
{
uint16_t i,j;
LCD_Address_Set(0,0,LCD_W-1,LCD_H-1);
for(i=0;i<LCD_W;i++)
{
for (j=0;j<LCD_H;j++)
{
vspi->transfer16(Color);
}
}
}
void LCD_Clear_Rand()
{
uint16_t i,j;
LCD_Address_Set(0,0,LCD_W-1,LCD_H-1);
for(i=0;i<LCD_W;i++)
{
for (j=0;j<LCD_H;j++)
{
vspi->transfer16(rand());
}
}
}
unsigned int rgb555torgb565(unsigned int c)
{
c=c&0x7fff;
unsigned int r=c>>10;
c=c&0x03ff;
unsigned int g=c>>5;
c=c&0x001f;
unsigned int b=c;
unsigned int output=0;
g=g*2;
output= (r<<11)|(g<<5)|(b);
return output;
}
void lcd_init()
{
pinMode(LCD_SDA, OUTPUT);
pinMode(LCD_SCL, OUTPUT);
pinMode(LCD_CS, OUTPUT);
pinMode(LCD_DS, OUTPUT);
digitalWrite(LCD_SDA,0);
digitalWrite(LCD_SCL,0);
digitalWrite(LCD_CS,0);
digitalWrite(LCD_DS,0);
vspi = new SPIClass(VSPI);
vspi->begin(LCD_SCL, 0, LCD_SDA, LCD_CS);
vspi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
pinMode(vspi->pinSS(), OUTPUT); //HSPI SS
digitalWrite(vspi->pinSS(), LOW); //pull SS slow to prep other end for transfer
//************* Start Initial Sequence **********//
//delay(120);
//LCD_WR_REG(0x01);
//上电后硬件会自己复位
delay(220);
LCD_WR_REG(0x36);
if(USE_HORIZONTAL==0)vspi->transfer(0x00);
else if(USE_HORIZONTAL==1)vspi->transfer(0xC0);
else if(USE_HORIZONTAL==2)vspi->transfer(0x70);
else vspi->transfer(0xA0);
LCD_WR_REG(0x3A);
vspi->transfer(0x05);
LCD_WR_REG(0xB2);
vspi->transfer(0x0C);
vspi->transfer(0x0C);
vspi->transfer(0x00);
vspi->transfer(0x33);
vspi->transfer(0x33);
LCD_WR_REG(0xB7);
vspi->transfer(0x35);
LCD_WR_REG(0xBB);
vspi->transfer(0x19);
LCD_WR_REG(0xC0);
vspi->transfer(0x2C);
LCD_WR_REG(0xC2);
vspi->transfer(0x01);
LCD_WR_REG(0xC3);
vspi->transfer(0x12);
LCD_WR_REG(0xC4);
vspi->transfer(0x20);
LCD_WR_REG(0xC6);
vspi->transfer(0x0F);
LCD_WR_REG(0xD0);
vspi->transfer(0xA4);
vspi->transfer(0xA1);
LCD_WR_REG(0xE0);
vspi->transfer(0xD0);
vspi->transfer(0x04);
vspi->transfer(0x0D);
vspi->transfer(0x11);
vspi->transfer(0x13);
vspi->transfer(0x2B);
vspi->transfer(0x3F);
vspi->transfer(0x54);
vspi->transfer(0x4C);
vspi->transfer(0x18);
vspi->transfer(0x0D);
vspi->transfer(0x0B);
vspi->transfer(0x1F);
vspi->transfer(0x23);
LCD_WR_REG(0xE1);
vspi->transfer(0xD0);
vspi->transfer(0x04);
vspi->transfer(0x0C);
vspi->transfer(0x11);
vspi->transfer(0x13);
vspi->transfer(0x2C);
vspi->transfer(0x3F);
vspi->transfer(0x44);
vspi->transfer(0x51);
vspi->transfer(0x2F);
vspi->transfer(0x1F);
vspi->transfer(0x1F);
vspi->transfer(0x20);
vspi->transfer(0x23);
LCD_WR_REG(0x21);
LCD_WR_REG(0x11);
delay(120);
LCD_WR_REG(0x29);
}
+33
View File
@@ -0,0 +1,33 @@
#ifndef LCD_H
#define LCD_H
#include <arduino.h>
//硬件spi貌似接错线了
#define LCD_SDA 3
#define LCD_SCL 2
#define LCD_CS 7
#define LCD_DS 6
#define USE_HORIZONTAL 2 //设置横屏或者竖屏显示 0或1为竖屏 2或3为横屏
#define LCD_W 320
#define LCD_H 240
#define OLED_CMD 0 //写命令
#define OLED_DATA 1 //写数据
#define VSPI FSPI
static const long spiClk = 80000000; // 80 MHz
void lcd_init();
void LCD_Clear(uint16_t Color);
void LCD_fillRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color);
#endif
+18
View File
@@ -0,0 +1,18 @@
#include <Arduino.h>
#include "lcd.h"
// put function declarations here:
int myFunction(int, int);
void setup()
{
// put your setup code here, to run once:
lcd_init();
LCD_Clear(rand());
}
void loop()
{
// put your main code here, to run repeatedly:
LCD_Clear(rand());
}
+11
View File
@@ -0,0 +1,11 @@
This directory is intended for PlatformIO Test Runner and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PlatformIO Unit Testing:
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html