桌面小屏幕實戰課程:DesktopScreen 11 SPI 水墨屏

飛書文檔https://x509p6c8to.feishu.cn/docx/doxcnlzpIgj3gosCZufBTCZxlMb

SPI說明

SPI是串行外設接口(Serial Peripheral Interface)的縮寫,是一種高速的,全雙工,同步的通信總線,并且在芯片的管腳上占用四根線。

參考源碼位置

/home/kemp/work/esp/esp-idf/examples/peripherals/spi_master

源碼下載方式參考:

源碼下載方式

屏幕接口

SCLK IO25 SPI 串口通信時鐘信號線。

SDI? IO26 SPI 串口通信數據信號線。

CS? IO27 片選,低電平有效。

D/C IO14 數據/命令 讀寫選擇,高電平為數據,低電平為命令。

RES IO12 電子紙復位信號,低電平有效。

BUSY IO13 電子紙刷新時,BUSY 引腳發出忙信號給主 MCU,此時 MCU 無法對電子紙驅動 IC 進行讀寫操作;電子紙刷新完成后,BUSY 引腳發出閑置狀態信號,此時 MCU 可以對 電子紙驅動 IC 進行讀寫操作。GDEW 系列電子紙 BUSY 引腳忙狀態為高電平(GDEH 系列為低電平),BUSY 引腳空閑狀態反之。

墨水屏原理

152*152個像素 19Byte=152Bit 19*152的數組

152*152??? 19BYTE?? 1BYTE=8BIT? 0000 0000? 1111 1111

更多屏幕相關手冊

1.54寸電子紙屏/ 152x152分辨率電子紙/ 四灰階/ 支持局部刷新電子墨水屏 GDEW0154T8D_電子紙屏-大連佳顯電子有限公司

代碼說明

SPI部分

SPI Master Driver - - ? ESP-IDF 編程指南 release-v4.1 文檔

/* SPI Master exampleThis example code is in the Public Domain (or CC0 licensed, at your option.)Unless required by applicable law or agreed to in writing, thissoftware is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES ORCONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"#include "ds_gpio.h"//#define PIN_NUM_MISO 1? //屏幕只寫不讀,此引腳不用
#define PIN_NUM_MOSI 26
#define PIN_NUM_CLK? 25
#define PIN_NUM_CS?? 27spi_device_handle_t spi;void spi_send_cmd(const uint8_t cmd)
{esp_err_t ret;spi_transaction_t t;//設置發送指令ds_gpio_set_screen_dc(0);//設置片選模塊ds_gpio_set_screen_cs(0);memset(&t, 0, sizeof(t));?????? //Zero out the transaction// t.flags=SPI_TRANS_USE_TXDATA;t.length=8;???????????????????? //Command is 8 bitst.tx_buffer=&cmd;?????????????? //The data is the cmd itselft.user=(void*)0;??????????????? //D/C needs to be set to 0//發送指令ret=spi_device_polling_transmit(spi, &t);? //Transmit!//取消片選模塊ds_gpio_set_screen_cs(1);assert(ret==ESP_OK);??????????? //Should have had no issues.
}void spi_send_data(const uint8_t data)
{esp_err_t ret;spi_transaction_t t;//設置發送數據ds_gpio_set_screen_dc(1);//設置片選模塊ds_gpio_set_screen_cs(0);memset(&t, 0, sizeof(t));?????? //Zero out the transactiont.length=8;???????????????? //Len is in bytes, transaction length is in bits.t.tx_buffer=&data;?????????????? //Datat.user=(void*)1;??????????????? //D/C needs to be set to 1//發送數據ret=spi_device_polling_transmit(spi, &t);? //Transmit!//取消片選模塊ds_gpio_set_screen_cs(1);assert(ret==ESP_OK);??????????? //Should have had no issues.
}//This function is called (in irq context!) just before a transmission starts. It will
//set the D/C line to the value indicated in the user field.
void spi_pre_transfer_callback(spi_transaction_t *t)
{int dc=(int)t->user;printf("dc callback\n");ds_gpio_set_screen_dc(dc);
}void screen_spi_init(void)
{esp_err_t ret;//IO設置spi_bus_config_t buscfg={.miso_io_num = PIN_NUM_MISO,??????????????? // MISO信號線.mosi_io_num = PIN_NUM_MOSI,??????????????? // MOSI信號線.sclk_io_num = PIN_NUM_CLK,???????????????? // SCLK信號線.quadwp_io_num = -1,??????????????????????? // WP信號線,專用于QSPI的D2.quadhd_io_num = -1,??????????????????????? // HD信號線,專用于QSPI的D3.max_transfer_sz = 64*8,??????????????????? // 最大傳輸數據大小};//速率 模式設置spi_device_interface_config_t devcfg={.clock_speed_hz=15*1000*1000,??????????? //Clock out at 26 MHz.mode=0,??????????????????????????????? //SPI mode 0.queue_size=7,????????????????????????? //We want to be able to queue 7 transactions at a time// .pre_cb=spi_pre_transfer_callback,? //Specify pre-transfer callback to handle D/C line};//Initialize the SPI busret=spi_bus_initialize(HSPI_HOST, &buscfg, 0);ESP_ERROR_CHECK(ret);//Attach the LCD to the SPI busret=spi_bus_add_device(HSPI_HOST, &devcfg, &spi);ESP_ERROR_CHECK(ret);}void screen_spi_test(){spi_send_cmd(0x55);vTaskDelay(10 / portTICK_PERIOD_MS);spi_send_data(0x55);
}

屏幕驅動部分

注意:這里的代碼和視頻中不太一樣,因為舊版本屏幕停產,更換了屏幕型號,下方代碼為0154B-D67的屏幕驅動代碼,和最新版本屏幕是一致的。

#include <string.h>
#include <stdio.h>#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "sdkconfig.h"#include "ds_screen.h"
#include "ds_gpio.h"
#include "ds_spi.h"
#include "ds_data_image.h"// Detection busy
static void lcd_chkstatus(void)
{int count = 0;unsigned char busy;while (1){busy = ds_gpio_get_screen_busy();busy = (busy & 0x01);//=1 BUSYif (busy == 0)break;vTaskDelay(10 / portTICK_PERIOD_MS);count++;if (count >= 1000){printf("---------------time out ---\n");break;}}
}static void init_display()
{vTaskDelay(10 / portTICK_PERIOD_MS);ds_gpio_set_screen_rst(0); // Module resetvTaskDelay(10 / portTICK_PERIOD_MS);ds_gpio_set_screen_rst(1);vTaskDelay(100 / portTICK_PERIOD_MS);lcd_chkstatus();spi_send_cmd(0x12); // SWRESETlcd_chkstatus();spi_send_cmd(0x01); // Driver output controlspi_send_data(0xC7);spi_send_data(0x00);spi_send_data(0x01);spi_send_cmd(0x11); // data entry modespi_send_data(0x01);spi_send_cmd(0x44); // set Ram-X address start/end positionspi_send_data(0x00);spi_send_data(0x18); // 0x0C-->(18+1)*8=200spi_send_cmd(0x45);? // set Ram-Y address start/end positionspi_send_data(0xC7); // 0xC7-->(199+1)=200spi_send_data(0x00);spi_send_data(0x00);spi_send_data(0x00);spi_send_cmd(0x3C); // BorderWavefromspi_send_data(0x05);spi_send_cmd(0x18); // Read built-in temperature sensorspi_send_data(0x80);spi_send_cmd(0x4E); // set RAM x address count to 0;spi_send_data(0x00);spi_send_cmd(0x4F); // set RAM y address count to 0X199;spi_send_data(0xC7);spi_send_data(0x00);vTaskDelay(100 / portTICK_PERIOD_MS);lcd_chkstatus();
}/Enter deep sleep mode
void deep_sleep(void) // Enter deep sleep mode
{spi_send_cmd(0x10); // enter deep sleepspi_send_data(0x01);vTaskDelay(100 / portTICK_PERIOD_MS);
}void refresh(void)
{spi_send_cmd(0x22); // Display Update Controlspi_send_data(0xF7);spi_send_cmd(0x20); // Activate Display Update Sequencelcd_chkstatus();
}void refresh_part(void)
{spi_send_cmd(0x22); // Display Update Controlspi_send_data(0xFF);spi_send_cmd(0x20); // Activate Display Update Sequencelcd_chkstatus();
}// 圖片全刷-全白函數
static void ds_screen_display_white(void)
{unsigned int i, k;spi_send_cmd(0x24); // write RAM for black(0)/white (1)for (k = 0; k < 250; k++){for (i = 0; i < 25; i++){spi_send_data(0xff);}}
}// 圖片全刷-數據函數
void ds_screen_full_display_data(const uint8_t *data)
{unsigned int i;spi_send_cmd(0x24); // write RAM for black(0)/white (1)for (i = 0; i < 5000; i++){spi_send_data(*data);data++;}
}// 全刷 不帶數據
void ds_screen_full_display(void pic_display(void))
{init_display();pic_display(); // picturerefresh();???? // EPD_refreshdeep_sleep();
}// 全刷 帶數據
void ds_screen_full_display_bydata(void display_func(const uint8_t *data), const uint8_t *data)
{init_display();display_func(data); // picturerefresh();????????? // EPD_refreshdeep_sleep();
}// 局部刷 不帶數據
void ds_screen_partial_display(unsigned int x_start, unsigned int y_start, void partial_new(void), unsigned int PART_COLUMN, unsigned int PART_LINE)
{unsigned int i;unsigned int x_end, y_start1, y_start2, y_end1, y_end2;x_start = x_start / 8;x_end = x_start + PART_LINE / 8 - 1;y_start1 = 0;y_start2 = 200 - y_start;if (y_start >= 256){y_start1 = y_start2 / 256;y_start2 = y_start2 % 256;}y_end1 = 0;y_end2 = y_start2 + PART_COLUMN - 1;if (y_end2 >= 256){y_end1 = y_end2 / 256;y_end2 = y_end2 % 256;}// Add hardware reset to prevent background color changeds_gpio_set_screen_rst(0); // Module resetvTaskDelay(10 / portTICK_PERIOD_MS);ds_gpio_set_screen_rst(1);vTaskDelay(10 / portTICK_PERIOD_MS);// Lock the border to prevent flashingspi_send_cmd(0x3C); // BorderWavefrom,spi_send_data(0x80);spi_send_cmd(0x44);????? // set RAM x address start/end, in page 35spi_send_data(x_start);? // RAM x address start at 00h;spi_send_data(x_end);??? // RAM x address end at 0fh(15+1)*8->128spi_send_cmd(0x45);????? // set RAM y address start/end, in page 35spi_send_data(y_start2); // RAM y address start at 0127h;spi_send_data(y_start1); // RAM y address start at 0127h;spi_send_data(y_end2);?? // RAM y address end at 00h;spi_send_data(y_end1);?? // ????=0spi_send_cmd(0x4E); // set RAM x address count to 0;spi_send_data(x_start);spi_send_cmd(0x4F); // set RAM y address count to 0X127;spi_send_data(y_start2);spi_send_data(y_start1);spi_send_cmd(0x24); // Write Black and White image to RAMpartial_new();refresh_part();deep_sleep();
}// 局部刷 帶數據
void ds_screen_partial_display_bydata(unsigned int x_start, unsigned int y_start,void partial_new(const uint8_t *data), const uint8_t *new_data,unsigned int PART_COLUMN, unsigned int PART_LINE)
{printf("x_start=%d x_end=%d y_start=%d y_end=%d\n", x_start, y_start, PART_COLUMN, PART_LINE);unsigned int i;unsigned int x_end, y_start1, y_start2, y_end1, y_end2;x_start = x_start / 8;x_end = x_start + PART_LINE / 8 - 1;y_start1 = 0;y_start2 = 200 - y_start;if (y_start >= 256){y_start1 = y_start2 / 256;y_start2 = y_start2 % 256;}y_end1 = 0;y_end2 = y_start2 + PART_COLUMN - 1;if (y_end2 >= 256){y_end1 = y_end2 / 256;y_end2 = y_end2 % 256;}// Add hardware reset to prevent background color changeds_gpio_set_screen_rst(0); // Module resetvTaskDelay(10 / portTICK_PERIOD_MS);ds_gpio_set_screen_rst(1);vTaskDelay(10 / portTICK_PERIOD_MS);// Lock the border to prevent flashingspi_send_cmd(0x3C); // BorderWavefrom,spi_send_data(0x80);spi_send_cmd(0x44);????? // set RAM x address start/end, in page 35spi_send_data(x_start);? // RAM x address start at 00h;spi_send_data(x_end);??? // RAM x address end at 0fh(15+1)*8->128spi_send_cmd(0x45);????? // set RAM y address start/end, in page 35spi_send_data(y_start2); // RAM y address start at 0127h;spi_send_data(y_start1); // RAM y address start at 0127h;spi_send_data(y_end2);?? // RAM y address end at 00h;spi_send_data(y_end1);?? // ????=0spi_send_cmd(0x4E); // set RAM x address count to 0;spi_send_data(x_start);spi_send_cmd(0x4F); // set RAM y address count to 0X127;spi_send_data(y_start2);spi_send_data(y_start1);spi_send_cmd(0x24); // Write Black and White image to RAMpartial_new(new_data);
}uint8_t partial_data[200][25];
uint8_t partial_data_array[5000];void ds_screen_partial_data_init()
{for (int index = 0; index < 200; index++){for (int yindex = 0; yindex < 25; yindex++){partial_data[index][yindex] = 0xff;}}
}void ds_screen_partial_data_add(unsigned int x_start, unsigned int x_end, unsigned int y_start, unsigned int y_end, const uint8_t *data)
{uint8_t x_len = x_end - x_start;// uint8_t y_len = y_end - y_start;uint8_t x_data_location = x_start / 8;uint8_t x_size = x_len / 8;int data_index = 0;// int move = x_start % 8;if (x_start % 8 != 0){x_data_location++;}if (x_len % 8 != 0){x_size++;}for (int x_index = y_start; x_index < y_end; x_index++){for (int y_index = x_data_location; y_index < (x_data_location + x_size); y_index++){partial_data[x_index][y_index] = (~data[data_index]);data_index++;}}
}// 圖片全刷-全白函數
static void ds_screen_display_data(void)
{unsigned int i;spi_send_cmd(0x24);for (i = 0; i < 5000; i++){spi_send_data(partial_data_array[i]);}spi_send_cmd(0x26);for (i = 0; i < 5000; i++){spi_send_data(partial_data_array[i]);}
}// 局刷數據-復制
void ds_screen_partial_data_copy()
{int data_index = 0;for (int index = 0; index < 200; index++){for (int yindex = 0; yindex < 25; yindex++){partial_data_array[data_index] = partial_data[index][yindex];data_index++;}}ds_screen_full_display(ds_screen_display_data);
}// 接口初始化
void init_screen_interface()
{ds_screen_gpio_init();screen_spi_init();
}// 清屏為白色
void ds_screen_clean_white()
{ds_screen_init();vTaskDelay(2000 / portTICK_PERIOD_MS);
}// 初始化
void ds_screen_init()
{ds_screen_full_display(ds_screen_display_white); // EPD_sleep
}

參考:

【科普貼】SPI接口詳解_湉湉家的小虎子的博客-CSDN博客_spi

1.54寸高頻刷新 快刷1.5秒電子墨水屏 分辨率200x200 SPI串口 GDEY0154D67_電子墨水屏幕-大連佳顯電子

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/88636.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/88636.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/88636.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SpringCloud Gateway 組件的使用

作者&#xff1a;小凱 沉淀、分享、成長&#xff0c;讓自己和他人都能有所收獲&#xff01; 我發現了一個很有意思的縮寫單詞 gw、wg&#xff0c;都是網關的意思。因為 gw gateway、wg wangguan&#xff0c;所以在各個系統開發中&#xff0c;既有 gw 也有 wg 的存在。而網關…

隨機地址生成器 - Cloudflare Workers

分享一個完全開源免費部署在 Cloudflare Workers 上的隨機地址生成器&#xff0c;支持全球 24 個國家/地區。 &#x1f517; 工具地址: https://address.chat-tempmail.com ? 特性 &#x1f30d; 支持生成 24 個國家/地區的地址&#x1f4f1; 響應式設計&#xff0c;完美支持…

CNN不是一個模型?

CNN不是一個模型&#xff1f; 結論&#xff1a; CNN 是模型架構而非具體模型&#xff0c;其定位類似深度學習領域的 「設計框架」&#xff0c;而非 LSTM&#xff08;具體單元結構&#xff09;或決策樹&#xff08;具體算法實體&#xff09;。CNN 的 「具體模型」 需要結合網絡…

愛基百客與真邁生物達成戰略合作,共推多組學科研服務升級

近日&#xff0c;武漢愛基百客生物科技有限公司&#xff08;以下簡稱“愛基百客”&#xff09;與真邁生物正式簽署戰略合作協議。此次戰略合作將聚焦表觀組學、單細胞時空組學等前沿科研領域&#xff0c;聯合打造基于自主創新技術的多組學科研服務方案&#xff0c;為科研人員提…

吳恩達:從斯坦福到 Coursera,他的深度學習布道之路

名人說&#xff1a;路漫漫其修遠兮&#xff0c;吾將上下而求索。—— 屈原《離騷》 創作者&#xff1a;Code_流蘇(CSDN)&#xff08;一個喜歡古詩詞和編程的Coder&#x1f60a;&#xff09; 吳恩達&#xff1a;從斯坦福到 Coursera&#xff0c;他的深度學習布道之路 在人工智能…

開疆智能CCLinkIE轉ModbusTCP網關連接測聯無紙記錄儀配置案例

本案例是通過CCLinkIE轉ModbusTCP網關將記錄儀數據傳送到三菱PLC&#xff0c;具體操作過程如下。 &#xff08;1&#xff09; 無紙記錄儀與PT100傳感器連接正確后&#xff0c;將無紙記錄儀和PC通過網線連接&#xff0c;給無紙記錄儀上電&#xff0c;設置無紙記錄儀的IP地址及網…

【軟考高級系統架構論文】# 論軟件設計方法及其應用

論文真題 軟件設計 (Software Design,SD) 根據軟件需求規格說明書設計軟件系統的整體結構、劃分功能模塊、確定每個模塊的實現算法以及程序流程等,形成軟件的具體設計方案。軟件設計把許多事物和問題按不同的層次和角度進行抽象,將問題或事物進行模塊化分解,以便更容易解決…

Spring Boot 3.x 項目搭建 (一)

以下是一個基礎 Spring Boot 項目的創建指南&#xff0c;整合了官方推薦方式和實用配置&#xff0c;幫助您快速搭建可運行的項目骨架。 &#x1f31f; 一、項目創建方式 1. 在線工具 Spring Initializr&#xff08;推薦&#xff09; 步驟&#xff1a; 訪問 Spring Initializr…

《天行數據查詢系統項目介紹》

一、項目概述 天行數據查詢系統是一款功能豐富的 Android 應用程序&#xff0c;旨在為用戶提供便捷的信息查詢服務。該系統集成了多個實用的查詢功能&#xff0c;包括空氣質量查詢、天氣預報查詢、垃圾分類查詢、新聞資訊瀏覽以及身份證信息查詢等&#xff0c;方便用戶一站式獲…

對于服務器企業該如何進行搭建?

企業搭建服務器能夠實現網絡服務、數據存儲和管理等功能&#xff0c;選擇大家服務器不僅能夠實現高效的資源管理和對數據信息進行安全保護&#xff0c;還可以滿足網站運行的需求&#xff0c;下面&#xff0c;小編就主要來為大家介紹一下企業該如何進行服務器搭建&#xff1f; 搭…

重定向攻擊與防御

一、重定向攻擊的主要類型與技術原理 ICMP重定向攻擊 原理&#xff1a;攻擊者偽造網關身份發送虛假ICMP重定向報文&#xff0c;誘導主機修改路由表&#xff0c;將流量導向攻擊者控制的節點。 利用工具&#xff1a;如netwox 86可構造惡意重定向包&#xff0c;源IP偽裝為網關地…

SAP/S4 MM模塊之主數據管理

目錄 一、主要功能 1. 主數據管理 2.采購管理 3. 庫存管理 二、業務價值 三、主數據常見問題 3.1. 物料主數據維護錯誤 3.2. 供應商數據不完整或錯誤 3.3. 數據錄入延遲或遺漏 四、最佳實踐 1. 物料主數據標準化 2. 供應商主數據優化 3.庫存管控精細化 SAP MM&…

Flink Oracle CDC 總結

官方文檔 https://nightlies.apache.org/flink/flink-cdc-docs-release-3.3/zh/docs/connectors/flink-sources/oracle-cdc/ 版本 Flink 1.15.3CDC 2.3.0Oracle 11G 12C &#xff08;官網說支持19&#xff0c;未測試&#xff09; Jar包 https://repo1.maven.org/maven2/co…

django request.data.get 判斷有沒有 某個參數

在 Django 的視圖函數中&#xff0c;當你想要判斷請求&#xff08;request&#xff09;中是否包含某個特定的參數&#xff0c;你可以使用 request.data.get() 方法。這種方法不僅適用于 POST 請求&#xff08;例如&#xff0c;在創建資源時&#xff09;&#xff0c;也適用于任何…

SD-WAN在可擴展性與未來發展靈活性方面的優勢探討

在企業數字化轉型的浪潮中&#xff0c;網絡基礎設施的靈活性和擴展性成為企業關注的核心議題之一。SD-WAN&#xff08;Software-Defined Wide Area Network&#xff09;作為一種新興的網絡技術&#xff0c;因其靈活、智能、高效的特性&#xff0c;逐漸取代傳統WAN&#xff0c;成…

4.9. 環境和分布偏移

目錄 4.9. 環境和分布偏移1&#xff09;分布偏移的類型 4.9. 環境和分布偏移 機器學習應用常被忽視數據來源和模型輸出處理。許多模型在測試集上表現好&#xff0c;但數據分布改變時會部署失敗&#xff0c;甚至模型決策本身可能破壞數據分布&#xff08;如貸款模型基于“穿牛津…

UI前端與數字孿生融合:打造智能工廠的可視化監控平臺

hello寶子們...我們是艾斯視覺擅長ui設計、前端開發、數字孿生、大數據、三維建模、三維動畫10年經驗!希望我的分享能幫助到您!如需幫助可以評論關注私信我們一起探討!致敬感謝感恩! 在工業 4.0 與智能制造的浪潮中&#xff0c;數字孿生技術正從概念走向大規模落地。據麥肯錫報…

【數據集】3D-GloBFP:全球首個三維建筑輪廓數據集

目錄 一、數據集介紹:《3D-GloBFP:全球首個三維建筑輪廓數據集》主要數據來源:模型方法:?? 二、數據下載方式方式1:Figshare方式2:下載亞洲建筑高度數據(完整版)參考?? 數據集概述: 3D-GloBFP 是全球首個在單體建筑層面估算建筑高度的三維建筑輪廓數據集,基于 20…

python基于協同過濾的動漫推薦系統

目錄 技術棧介紹具體實現截圖系統設計研究方法&#xff1a;設計步驟設計流程核心代碼部分展示研究方法詳細視頻演示試驗方案論文大綱源碼獲取/詳細視頻演示 技術棧介紹 Django-SpringBoot-php-Node.js-flask 本課題的研究方法和研究步驟基本合理&#xff0c;難度適中&#xf…

MySQL 中 DATE、DATETIME 和 TIMESTAMP 的區別

MySQL 中 DATE、DATETIME 和 TIMESTAMP 的區別 在 MySQL 中&#xff0c;DATE、DATETIME 和 TIMESTAMP 都是用于存儲日期和時間的數據類型&#xff0c;但它們在格式、范圍、存儲大小、時區處理和功能上存在顯著差異。以下將逐步對比這些區別&#xff0c;幫助您根據實際需求選擇…