【硬件IIC】stm32單片機利用硬件IIC驅動OLED屏幕

之前操作OLED屏幕都是用GPIO模擬IIC去驅動,最近打算用硬件IIC去驅動,于是寫下這個demo,在這個過程中遇到一點小坑,記錄一下,本文章非小白教程,所以只突出踩到的坑點,文章中涉及到的OLED也是網上資料寫爛的,所以不懂的同學可以萬能的百度。話不多說開始。

目標

使用硬件IIC驅動OLED屏,顯示英文字符串“I am Rio”
在這里插入圖片描述

完整項目工程鏈接: stm32F103C8T6驅動OLED屏顯示字符

同時附上一篇網上找的介紹這個OLED屏的文章
0.96寸OLED(SSD1306)屏幕顯示(一)——基礎功能介紹

硬件

MCU: stm32f103c8t6

屏幕: 0.96寸OLED(SSD1306)

本次使用的是 gpio 的PB6,PB7腳,這兩個腳位可以復用硬件I2C1。

驅動程序

代碼中已加入詳細注釋,放心食用

GPIO和IIC初始化配置

這里遇到第一個坑,就是在配置IO的模式時,一開始設置成推挽輸出GPIO_MODE_OUTPUT_PP,因為想著就接一個IIC設備,推挽輸出或者開漏輸出,都影響不大,結果還說遇到坑了,配置成推挽輸出之后,程序會出現卡死現象,debug之后發現程序卡死在函數HAL_I2C_Init(&hi2c1)里; 然后進入到錯誤HardFault_Handler()中,懷疑是HAL_I2C_Init中的某些設置與設置成推挽輸出GPIO_MODE_OUTPUT_PP出現沖突導致硬件錯誤,具體還未深入研究,歡迎大佬補充。

將GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;后不再出現卡死現象。

I2C_HandleTypeDef hi2c1;
uint16_t slaveAddr = 0x78;	//OLED顯示屏的IIC設備地址,改地址為寫地址
void oled_gpio_init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};__HAL_RCC_GPIOB_CLK_ENABLE();	//使能GPIOB口時鐘/**I2C1 GPIO ConfigurationPB6     ------> I2C1_SCLPB7     ------> I2C1_SDA*/GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;//當時就是這句導致程序卡死,用HAL庫實現硬件IIC時還是乖乖用開漏模式好
//    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;  GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;		//配置為開漏模式GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);/* I2C1 clock enable */__HAL_RCC_I2C1_CLK_ENABLE();hi2c1.Instance = I2C1;hi2c1.Init.ClockSpeed = 100000; // 設置I2C時鐘速度為100kHz(可以根據需要調整)hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; // 占空比(通常不需要修改)hi2c1.Init.OwnAddress1 = 0; // 主設備通常不需要設置自己的地址hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; // 7位地址模式hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; // 雙地址模式禁用hi2c1.Init.OwnAddress2 = 0; // 不使用第二個地址hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; // 通用調用模式禁用hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; // 時鐘延伸模式禁用HAL_I2C_Init(&hi2c1);}
IIC的讀和寫

這里由于沒有理解透HAL庫的函數踩到第二個坑,用的這一款OLED在寫入命令或者數據時,時序是與從機建立IIC通訊開始信號后,就連續寫入control byte + data byte; 比如寫數據為 0x40 + data; 寫命令是0x00 + cmd;

而HAL庫提供的IIC讀寫函數有好幾種,如:

HAL_I2C_Master_Receive(&hi2c1, DevAddress, pData, Size, Timeout);
HAL_I2C_Master_Transmit(&hi2c1, DevAddress, pData, Size, Timeout);

這一組是用來作為主機時,對從機進行讀寫操作,而我一開始在往從機寫數據的時候,使用的就是HAL_I2C_Master_Transmit函數,將control byte + data byte;分開兩次來發送,結果就寫失敗了。原因是分開兩次寫的話,HAL_I2C_Master_Transmit每次寫完一個byte數據之后,就結束該次通訊,這就相當于沒有發送完整的control byte + data byte時序;而是

第一次發送control byte結束;第二次發送data byte結束;所以兩次沒有一次是完整的組合時序。正確的是應該在一次通訊中發送兩個byte數據才行;

所以我將要發送的時序進行組合,然后一次發送兩個數據即可

uint8_t dataArr[2] = {0x40, data};
I2C_SendData(slaveAddr, dataArr, 2, 1000);

//對HAL_I2C_Master_Transmit函數進行封裝
HAL_StatusTypeDef I2C_SendData(uint16_t DevAddress, uint8_t* pData, uint16_t Size, uint32_t Timeout)
{return HAL_I2C_Master_Transmit(&hi2c1, DevAddress, pData, Size, Timeout);
}//對HAL_I2C_Master_Receive函數進行封裝
HAL_StatusTypeDef I2C_ReceiveData(uint16_t DevAddress, uint8_t* pData, uint16_t Size, uint32_t Timeout)
{return HAL_I2C_Master_Receive(&hi2c1, DevAddress, pData, Size, Timeout);
}//封裝函數,實現對往OLED中寫入一個字節數據
void oled_write_data(uint8_t data)
{    /*錯誤的一次只寫一個數據,時序不完整*/
//    uint8_t dataOptionByte = 0x00;   
//    I2C_SendData(slaveAddr, &dataOptionByte, 1, 1000);
//    I2C_SendData(slaveAddr, &dataData, 1, 1000);/*一次只寫入完整的時序即可*/uint8_t dataArr[2] = {0x40, data};I2C_SendData(slaveAddr, dataArr, 2, 1000);/*使用HAL_I2C_Mem_Write函數,也可實現相同效果*/
//    uint8_t tmpData = data;
//    HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x40, I2C_MEMADD_SIZE_8BIT,
//										&tmpData, 1, 0xff);
}//封裝函數,實現對往OLED中寫入一個字節命令
void oled_write_cmd(uint8_t cmd)
{/*錯誤的一次只寫一個數據,時序不完整*/
//    uint8_t cmdOptionByte = 0x00;
//    I2C_SendData(slaveAddr, &cmdOptionByte, 1, 1000);
//    I2C_SendData(slaveAddr, &dataCmd, 1, 1000);/*一次只寫入完整的時序即可*/uint8_t cmdArr[2] = {0x00, cmd};I2C_SendData(slaveAddr, cmdArr, 2, 1000);/*使用HAL_I2C_Mem_Write函數,也可實現相同效果*/
//    uint8_t tmpCmd = cmd;
//    HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x00, I2C_MEMADD_SIZE_8BIT,
//										&tmpCmd, 1, 0xff);}

完整代碼

oled.c

#include "oled.h"
#include "delay.h"
#include "font.h"I2C_HandleTypeDef hi2c1;
uint16_t slaveAddr = 0x78;
void oled_gpio_init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};__HAL_RCC_GPIOB_CLK_ENABLE();/**I2C1 GPIO ConfigurationPB6     ------> I2C1_SCLPB7     ------> I2C1_SDA*/GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;//    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;  //GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);/* I2C1 clock enable */__HAL_RCC_I2C1_CLK_ENABLE();hi2c1.Instance = I2C1;hi2c1.Init.ClockSpeed = 100000; // 設置I2C時鐘速度為100kHz(可以根據需要調整)hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; // 占空比(通常不需要修改)hi2c1.Init.OwnAddress1 = 0; // 主設備通常不需要設置自己的地址hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; // 7位地址模式hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; // 雙地址模式禁用hi2c1.Init.OwnAddress2 = 0; // 不使用第二個地址hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; // 通用調用模式禁用hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; // 時鐘延伸模式禁用HAL_I2C_Init(&hi2c1);}
/*oled_gpio_init()函數中不配置GPIO口和使能時鐘,在MSP函數中配置也可以,因為
執行HAL_I2C_Init(&hi2c1);時,會執行HAL_I2C_MspInit函數
*/
//void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
//{//  GPIO_InitTypeDef GPIO_InitStruct = {0};
//  if(i2cHandle->Instance==I2C1)
//  {
//  /* USER CODE BEGIN I2C1_MspInit 0 *///  /* USER CODE END I2C1_MspInit 0 *///    __HAL_RCC_GPIOB_CLK_ENABLE();
//    /**I2C1 GPIO Configuration
//    PB6     ------> I2C1_SCL
//    PB7     ------> I2C1_SDA
//    */
//    GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
//    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
//    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
//    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);//    /* I2C1 clock enable */
//    __HAL_RCC_I2C1_CLK_ENABLE();
//  /* USER CODE BEGIN I2C1_MspInit 1 *///  /* USER CODE END I2C1_MspInit 1 */
//  }
//}HAL_StatusTypeDef I2C_SendData(uint16_t DevAddress, uint8_t* pData, uint16_t Size, uint32_t Timeout)
{return HAL_I2C_Master_Transmit(&hi2c1, DevAddress, pData, Size, Timeout);
}HAL_StatusTypeDef I2C_ReceiveData(uint16_t DevAddress, uint8_t* pData, uint16_t Size, uint32_t Timeout)
{return HAL_I2C_Master_Receive(&hi2c1, DevAddress, pData, Size, Timeout);
}void oled_write_data(uint8_t data)
{    
//    uint8_t dataOptionByte = 0x00;   
//    I2C_SendData(slaveAddr, &dataOptionByte, 1, 1000);
//    I2C_SendData(slaveAddr, &dataData, 1, 1000);uint8_t dataArr[2] = {0x40, data};I2C_SendData(slaveAddr, dataArr, 2, 1000);
//    uint8_t tmpData = data;
//    HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x40, I2C_MEMADD_SIZE_8BIT,
//										&tmpData, 1, 0xff);
}void oled_write_cmd(uint8_t cmd)
{
//    uint8_t cmdOptionByte = 0x00;
//    I2C_SendData(slaveAddr, &cmdOptionByte, 1, 1000);
//    I2C_SendData(slaveAddr, &dataCmd, 1, 1000);uint8_t cmdArr[2] = {0x00, cmd};I2C_SendData(slaveAddr, cmdArr, 2, 1000);//    uint8_t tmpCmd = cmd;
//    HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x00, I2C_MEMADD_SIZE_8BIT,
//										&tmpCmd, 1, 0xff);}void oled_init(void)
{oled_gpio_init();delay_ms(100);oled_write_cmd(0xAE);    //設置顯示開啟/關閉,0xAE關閉,0xAF開啟oled_write_cmd(0xD5);    //設置顯示時鐘分頻比/振蕩器頻率oled_write_cmd(0x80);    //0x00~0xFFoled_write_cmd(0xA8);    //設置多路復用率oled_write_cmd(0x3F);    //0x0E~0x3Foled_write_cmd(0xD3);    //設置顯示偏移oled_write_cmd(0x00);    //0x00~0x7Foled_write_cmd(0x40);    //設置顯示開始行,0x40~0x7Foled_write_cmd(0xA1);    //設置左右方向,0xA1正常,0xA0左右反置oled_write_cmd(0xC8);    //設置上下方向,0xC8正常,0xC0上下反置oled_write_cmd(0xDA);    //設置COM引腳硬件配置oled_write_cmd(0x12);oled_write_cmd(0x81);    //設置對比度oled_write_cmd(0xCF);    //0x00~0xFFoled_write_cmd(0xD9);    //設置預充電周期oled_write_cmd(0xF1);oled_write_cmd(0xDB);    //設置VCOMH取消選擇級別oled_write_cmd(0x30);oled_write_cmd(0xA4);    //設置整個顯示打開/關閉oled_write_cmd(0xA6);    //設置正常/反色顯示,0xA6正常,0xA7反色oled_write_cmd(0x8D);    //設置充電泵oled_write_cmd(0x14);oled_write_cmd(0xAF);    //開啟顯示}
// y的值為page,屏幕總共有8個page
void oled_set_cursor(uint8_t x, uint8_t y)
{oled_write_cmd(0xB0 + y);   //確定在哪一個page, 第一個page地址是B0oled_write_cmd((x & 0x0F) | 0x00);  //取字節的低位oled_write_cmd(((x & 0xF0) >> 4) | 0x10);   //取字節的高位,|0x10是因為oled芯片的要求}//清屏函數,每次刷新畫面時,需要清屏,防止上一幀數據殘留
void oled_fill(uint8_t data)
{uint8_t i, j;for( i = 0; i <8 ; i++){oled_set_cursor(0, i);for(j = 0; j < 128; j++){   //page模式,地址每次都自動偏移oled_write_data(data);}}}//輸入字符的坐標、ASCII碼、大小; size一般是寬為高的1/2;
void oled_show_char(uint8_t x, uint8_t y, uint8_t num, uint8_t size)
{uint8_t i, j, page;num = num - ' ';page = size/8;if (size % 8)page++;for(j = 0; j < page; j++ ){oled_set_cursor(x, y + j);for(i = size/2 * j; i < size/2 *(j + 1); i++)   //即每一個page寫size/2寬的數據,{if (size == 12)oled_write_data(ascii_6X12[num][i]);else if (size == 16)oled_write_data(ascii_8X16[num][i]);else if (size == 24)oled_write_data(ascii_12X24[num][i]);}}
}//輸入字符的坐標、字符指針、大小; size一般是寬為高的1/2;
void oled_show_string(uint8_t x, uint8_t y, char *p, uint8_t size)
{while( *p !='\0'){oled_show_char(x, y, *p, size);x += size/2;p++;}
}

oled.h

#ifndef __OLED_H__
#define __OLED_H__#include "sys.h"void oled_gpio_init(void);
void oled_init(void);
void oled_write_cmd(uint8_t cmd);
void oled_write_data(uint8_t data);void oled_set_cursor(uint8_t x, uint8_t y);
void oled_fill(uint8_t data);
void oled_show_char(uint8_t x, uint8_t y, uint8_t num, uint8_t size);
void oled_show_string(uint8_t x, uint8_t y, char *p, uint8_t size);
#endif

main.c

#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "oled.h"int main(void)
{HAL_Init();                         /* 初始化HAL庫 */stm32_clock_init(RCC_PLL_MUL9);     /* 設置時鐘, 72Mhz */led_init();                         /* 初始化LED燈 */uart1_init(115200);printf("hello world!\r\n");oled_init();oled_fill(0x00);oled_set_cursor(0, 0);//劃線
//    oled_write_data(0x80);
//    oled_write_data(0x80);
//    oled_write_data(0x80);
//    oled_write_data(0x80);
//    oled_write_data(0x80);
//    oled_write_data(0x80);//    oled_show_char(0, 0, 'x', 24);oled_show_string(0, 2, "I am Rio", 24);while(1){ led1_on();led2_off();delay_ms(500);led1_off();led2_on();delay_ms(500);}
}

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

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

相關文章

python如何自動加空格

首先&#xff0c;需要進行打開的一個pycharm的軟件&#xff0c;可進行雙擊的打開該軟件。 可以看到的是在當前的打開的文件中&#xff0c;格式相對較亂一下。格式不對會格式錯誤。 然后點擊菜單欄中的“code”。 在彈出的下拉菜單中選擇“reformat code”選項。 可以看到的是在…

【開源免費】基于SpringBoot+Vue.JS網上訂餐系統(JAVA畢業設計)

本文項目編號 T 018 &#xff0c;文末自助獲取源碼 \color{red}{T018&#xff0c;文末自助獲取源碼} T018&#xff0c;文末自助獲取源碼 目錄 一、系統介紹二、演示錄屏三、啟動教程四、功能截圖五、文案資料5.1 選題背景5.2 國內外研究現狀5.3 可行性分析 六、核心代碼6.1 新…

串口通信和SPI通信詳解

0、背景 在現代嵌入式系統中&#xff0c;通信是不同模塊之間交換數據的核心。串口通信和 SPI&#xff08;串行外設接口&#xff09;是兩種常見的通信方式&#xff0c;它們各自有獨特的優勢和適用場景。 1、串口通信 1.1、串口通信概念 串口通信是一種常見的異步串行通信協議…

javase-17、API.數學相關

一、Math類 Math類提供了大量的靜態方法來便于我們實現數學計算&#xff0c;如求絕對值、取最大或最小值等。 https://doc.qzxdp.cn/jdk/17/zh/api/java.base/java/lang/Math.html 所在模塊&#xff1a;java.base所在包&#xff1a; java.lang static double abs(double a)…

答題考試系統v1.6.1高級版源碼分享+uniapp+搭建測試環境

一.系統介紹 一款基于FastAdminThinkPHPUniapp開發的小程序答題考試系統&#xff0c;支持多種試題類型、多種試題難度、練題、考試、補考模式&#xff0c;提供全部前后臺無加密源代碼&#xff0c;支持私有化部署 二.測試環境 系統環境&#xff1a;CentOS、 運行環境&#x…

淺談倉頡語言的優劣

倉頡語言&#xff0c;作為華為自研的新一代編程語言&#xff0c;以其高效、安全、現代化的特點&#xff0c;引起了廣泛的關注。 倉頡語言的優勢 高效并發 倉頡語言的一大亮點是其輕松并發的能力。它實現了輕量化用戶態線程和并發對象庫&#xff0c;使得高效并發變得輕松。倉頡…

Sass系統數據隔離的三種方式

1.完全獨立的數據庫 為每一個租戶單獨部署一個數據庫 優點&#xff1a;達到了真正的按租戶進行隔離&#xff0c;不同租戶之間相互沒有影響&#xff0c;可以針對一些特殊租戶例如大客戶做一些定制化的開發&#xff0c;計費相對簡單&#xff0c;按照資源使用進行計費。 缺點&…

FFmpeg 主要結構體剖析

FFmpeg 探索之旅 FFmpeg 主要結構體剖析 FFmpeg 探索之旅前言1、AVFormatContext2、AVCodecContext3、AVCodec4、AVStream5、AVPacket6、AVFrame7、AVCodecParameters7、SwsContext8、AVIOContext9、AVRational 總結 前言 嘿&#xff0c;各位小伙伴&#xff01;在如今這個多媒…

經典電荷泵/Charge pump——1998.JSSC

電路結構 工作原理 M3 and M4 are the series switches, and M5, M6 switch to the highest voltage. If M5 and M6 are missing, having a large capacitor is of absolute necessity, because must always stay between 2 Vin and 2Vin - Uj to avoid switching on the vert…

Swin transformer 論文閱讀記錄 代碼分析

該篇文章&#xff0c;是我解析 Swin transformer 論文原理&#xff08;結合pytorch版本代碼&#xff09;所記&#xff0c;圖片來源于源paper或其他相應博客。 代碼也非原始代碼&#xff0c;而是從代碼里摘出來的片段&#xff0c;配上簡單數據&#xff0c;以便理解。 當然&…

GPT-Omni 與 Mini-Omni2:創新與性能的結合

近年來&#xff0c;隨著人工智能技術的飛速發展&#xff0c;各種模型和平臺應運而生&#xff0c;以滿足從個人用戶到企業級應用的多樣化需求。在這一領域&#xff0c;GPT-Omni 和 Mini-Omni2 是兩款備受矚目的技術產品&#xff0c;它們憑借獨特的設計和強大的功能&#xff0c;在…

龍迅#LT7911E適用于EDP/DP/TPYE-C轉MIPIDSI應用,支持圖像處理功能,內置I2C,主應用副屏顯示,投屏領域!

1. 描述 LT7911E 是一款高性能 eDP 轉 MIPI D-PHY 轉換器&#xff0c;旨在將 eDP 源連接到 MIPI 顯示面板。 LT7911E 集成了一個符合 eDP1.4 標準的接收器&#xff0c;支持 1.62Gbps 至 5.67Gbps 的輸入數據&#xff0c;以 270Mbps 的遞增步長&#xff0c;以及一個 2 端口 D…

C語言——實現求出最大值

問題描述&#xff1a;利用C語言自定義函數求出一維數組里邊最大的數字 //利用函數找最大數#include<stdio.h>int search(int s[9]) //查找函數 {int i , max s[0] , max_xia 0;for(i0;i<9;i){if(s[i] > max){max_xia i;max s[max_xia];}}return max; } in…

解鎖 draw.io 流程圖制作工具Docker私有化部署(2/2)

一、draw.io 流程圖制作工具簡介 &#xff08;一&#xff09;基礎介紹 draw.io 是一款備受青睞的開源流程圖軟件&#xff0c;它有著諸多優點。首先&#xff0c;其界面十分整潔有序&#xff0c;完全沒有廣告的干擾&#xff0c;并且所有功能都是免費向用戶開放的&#xff0c;這一…

[HNCTF 2022 Week1]baby_rsa

源代碼&#xff1a; from Crypto.Util.number import bytes_to_long, getPrime from gmpy2 import * from secret import flag m bytes_to_long(flag) p getPrime(128) q getPrime(128) n p * q e 65537 c pow(m,e,n) print(n,c) # 62193160459999883112594854240161159…

docker run命令大全

docker run命令大全 基本語法常用選項基礎選項資源限制網絡配置存儲卷和掛載環境變量重啟策略其他高級選項示例總結docker run 命令是 Docker 中最常用和強大的命令之一,用于創建并啟動一個新的容器。該命令支持多種選項和參數,可以滿足各種使用場景的需求。以下是 docker ru…

Java中JDBC過時方法的替代方案以及JDBC為什么過時詳細分析

在Java中&#xff0c;JDBC的一些方法因為安全問題、性能問題或者因為引入了更好的替代方法已經被標記為過時&#xff08;Deprecated&#xff09;。 以下是一些被過時的JDBC方法以及它們的替代方案&#xff1a; 1.DriverManager.getDrivers(): 這個方法用于獲取所有當前注冊的J…

詳細指南:在Ubuntu 20.04 ROS 1環境下設置和使用OpenNI2 SDK

詳細指南&#xff1a;在Ubuntu 20.04 ROS 1環境下設置和使用OpenNI2 SDK 要在Ubuntu 20.04系統上使用ROS 1環境中的OpenNI2 SDK&#xff0c;您需要按照一系列有組織的步驟進行操作&#xff0c;以確保軟件和驅動正確安裝&#xff0c;并配置好相應的開發環境。以下是詳細的步驟說…

RK3568平臺(Kbuild篇)vmlinux 編譯過程

一.vmlinux是什么 vmlinux 是 Linux 操作系統的內核映像文件,它包含了 Linux 內核的所有功能代碼和必要的數據結構。這個文件通常是沒有經過壓縮和符號表去除的原始可執行文件。 具體來說,vmlinux 文件是編譯后的 Linux 內核的最終產物,通常是 ELF(可執行和可鏈接格式)格…

Flink2.0未來趨勢中需要注意的一些問題

手機打字&#xff0c;篇幅不長&#xff0c;主要講一下FFA中關于Flink2.0的未來趨勢&#xff0c;直接看重點。 Flink Forward Asia 2024主會場有一場關于Flink2.0的演講&#xff0c;很精彩&#xff0c;官方也發布了一些關于Flink2.0的展望和要解決的問題。 1.0時代和2.0時代避免…