在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

使用LocalDate和LocalDateTime

Android編程精選 ? 來源:Android編程精選 ? 作者:Android編程精選 ? 2022-07-04 11:34 ? 次閱讀

史蒂夫.喬布斯說,”復雜的終極境界是簡單“,同樣的優雅的代碼一定是精簡明了,可讀性好。

使用LocalDate和LocalDateTime

LocalDate精確到日期,LocalDateTime精確到時分秒。優化前14行代碼


	
  1. try {

  2. SimpleDateFormat sdfDay = new SimpleDateFormat("yyyy-MM-dd");

  3. SimpleDateFormat sdfMins = new SimpleDateFormat("yyyy-MM-dd HHss");

  4. Date now = new Date();

  5. String today = sdfDay.format(now);

  6. String waterStart = today + " 0300";

  7. String waterEnd = today + " 0400";

  8. Date waterStartTime = sdfMins.parse(waterStart);

  9. Date waterEndTime = sdfMins.parse(waterEnd);

  10. } catch (ParseException pe) {

  11. return XX;

  12. }

優化后3行代碼


	
  1. LocalDateTime now = LocalDateTime.now();

  2. LocalDateTime waterStart = LocalDateTime.of(now.getYear(), now.getMonth(),now.getDayOfMonth(),3,0);

  3. LocalDateTime waterEndTime =LocalDateTime.of(now.getYear(), now.getMonth(),now.getDayOfMonth(),4,0);

默認值使用Optional

優化前五行


	
  1. if (null == status) {

  2. param.put("status", new ArrayList<String>());

  3. } else {

  4. param.put("status", status);

  5. }

優化后一行,使用JDK8的Optional


	
  1. Optional.ofNullable(status).orElse(new ArrayList<String>());

如果是字符串可以用


	
  1. StringUtils.defaultIfEmpty(status,"")

字符串累加

字符串只要不在for循環里累加,可以直接用+號,因為編譯成字節碼后會變成StringBuilder,如果在for循環里面用+號會生成多個StringBuilder,所以在for循環里累加最好在循環外創建StringBuilder。優化前五行


	
  1. StringBuffer sblog = new StringBuffer();

  2. sblog.append("waterDriven|sellerId=");

  3. sblog.append(request.getSellerTaobaoId());

  4. sblog.append("|result=");

  5. sblog.append(isSuccess);

優化后一行


	
  1. String sblog="waterDriven|sellerId="+request.getSellerTaobaoId()+"|result="+isSuccess;

以上場景用逗號和等號連接數據,使用GUAVA的Joiner更精簡,可讀性更好


	
  1. String sblog=Joiner.on("|").withKeyValueSeparator("=").join(ImmutableMap.of("sellerId", request.getSellerTaobaoId(), "result", isSuccess))

LIST TO MAP

優化前4行


	
  1. Map<String, String> AssetsMetaIdMap = Maps.newHashMap();

  2. for (AssetsInfoBO assetsInfoBO : request.getAssetsCollectionList()) {

  3. AssetsMetaIdMap.put(assetsInfoBO.getAssetMetadataId(), assetsInfoBO.getAssetMetadataId());

  4. }

優化后1行


	
  1. Map<String, String> AssetsMetaIdMap = request.getAssetsCollectionList().stream().collect(Collectors.toMap(Hosting::getAssetMetadataId, Hosting::getAssetMetadataId));

如果key重復會拋出異常


	
  1. Exception in thread "main" java.lang.IllegalStateException: Duplicate key 80000

減少不需要的判斷

優化前5行


	
  1. String requestId = null;

  2. if (null != request.getExtData()) {

  3. requestId = request.getExtDataValue(REQUEST_ID_KEY);

  4. }

  5. return requestId;

優化后1行


	
  1. return request.getExtDataValue(REQUEST_ID_KEY);

去掉else

優化前5行


	
  1. if (null != result && StringUtils.isNotBlank(no)) {

  2. return no;

  3. } else {

  4. throw new RuntimeException("XX");

  5. }

優化后4行


	
  1. if (null != result && StringUtils.isNotBlank(no)) {

  2. return no;

  3. }

  4. throw new RuntimeException("XX");

不要返回布爾

優化前5行


	
  1. if ("true".equalsIgnoreCase(value.toString())) {

  2. invoke = true;

  3. } else {

  4. invoke = false;

  5. }

優化后一行


	
  1. invoke = "true".equalsIgnoreCase(value.toString());

使用級聯

優化前5行


	
  1. ParamBO paramBO = new ParamBO();

  2. paramBO.setId(1);

  3. paramBO.setName(”ifeve“);

  4. paramBO.setOld(7);

優化后1行


	
  1. new ParamBO().withId(1).withName("ifeve").withOld(7);

-End-

審核編輯 :李倩


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 代碼
    +關注

    關注

    30

    文章

    4823

    瀏覽量

    68954
  • LOCA
    +關注

    關注

    0

    文章

    7

    瀏覽量

    7193

原文標題:幾個代碼瘦身優化的案例

文章出處:【微信號:AndroidPush,微信公眾號:Android編程精選】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    【瑞薩RA2L1入門學習】05、待機模式按鍵外部中斷喚醒 低功耗測試

    1 前言 本次實驗的目標是設置低功耗模式,并配置按鍵中斷喚醒。為之后整個項目核心——低功耗做前期準備工作。 2 硬件部分 2.1 外部中斷 ICU ICU是中斷控制單元Interrupt Controller Unit。 中斷控制器單元(ICU)控制著一些事件發出的信號,從而鏈接到嵌套矢量中斷控制器(NVIC)、DMA控制器(DMAC)和數據傳輸控制器(DTC)模塊。ICU還控制著不可屏蔽的中斷。 所以可以說圍繞著 ICU 的有四個部分:NVIC、DMAC、DTC和NMI。 當中斷來臨的時候會最先經過IRQ寄存器,IRQ寄存器檢測到中斷的時候,會向中央處理嵌套向量中斷控制器NVIC發送中斷信號, 當NVIC檢測到中斷請求的時候,會將相應的中斷服務函數進行掛起。之后將運行的八個寄存器進行壓棧,壓棧完成之后將中斷服務程序進行激活。 之后將原先壓棧的寄存器取出,繼續運行之前的程序。 2.2 電源管理——低功耗模式 在很多應用場合中都對電子設備的功耗要求非常苛刻,如某些傳感器信息采集設備,僅靠小型的電池提供電源,要求工作長達數年之久, 且期間不需要任何維護;由于智慧穿戴設備的小型化要求,電池體積不能太大導致容量也比較小,所以也很有必要從控制功耗入手, 提高設備的續行時間。 因此,RA芯片有專門管理設備的運行模式,確保系統正常運行,并盡量降低器件的功耗。 RA2L1支持3種低功耗模式:睡眠模式(Sleep Mode)、軟件待機模式(Software Standby Mode)、貪睡模式(Snooze Mode) 2.2.1 睡眠模式 上電時,默認的低功耗模式即睡眠模式。睡眠模式是最方便的低功耗模式,它不需要任何額外的配置,只需要配置好用于喚醒的中斷源。 在睡眠模式下,SRAM、處理寄存器和外設狀態都會被保留,片上外設可以繼續工作,進入睡眠模式以及從睡眠模式喚醒所消耗的時間都是極少的。 任何中斷或者復位都會將MCU從睡眠模式下喚醒,并開始處理中斷,這也包括Systick系統計時器,因此讀者如果用到了RTOS, 進入睡眠模式前需要暫停Systick。 2.2.2 軟件待機模式 在軟件待機模式下,CPU以及大部分片上外設功能和所有內部晶振都停止工作。但是會保留CPU內部寄存器和SRAM數據的內容, 片上外設以及IO口的狀態。軟件待機模式可以顯著降低功耗,因為大多數振蕩器在這種模式下停止。 與睡眠模式一樣,待機模式需要配置一個中斷,并使用它來喚醒MCU。退出軟件待機模式時,所有內部晶振都會被啟動, 待所有晶振穩定后,MCU返回正常模式。 2.2.3 貪睡模式 貪睡模式與軟件待機模式相似,但是在貪睡模式下,可以運行很多核心外設和所有時鐘,可以執行一些比較簡單的任務,與軟件待機模式相比, 貪睡模式可以實現更加靈活的低功耗配置。 3 軟件部分 將先前03_RTC工程復制一份,重命名為05_Low-Power-Mode-Btn-Wakeup。 3.1 配置按鍵外部中斷 從開發板的原理圖可以得知,用戶按鍵接在P015引腳上,而其對應的中斷請求(IRQ)通道為IRQ7 序號 操作 1 點擊界面下方標簽欄中的Pins標簽,進入引腳配置界面。 2 在Pin Selection區域,展開Input:ICU選項,選擇ICU0。 3 在Pin Configuration區域,將Operation Mode設置為Enabled,勾選IRQ07對應的P015引腳。 序號 操作 1 點擊界面下方標簽欄中的Stacks標簽,進入堆棧配置頁面。 2 在HAL/Common Stacks區域,點擊New Stack按鈕。 3 在彈出菜單中,選擇Input選項下的External IRQ (r_icu)。 序號 操作 1 在下方Settings設置區域的Module g_external_irq7 External IRQ (r_icu)部分,設置Name為g_external_irq7,Channel為7。 2 Module g_external_irq7 External IRQ (r_icu)部分,設置Callback為key_irq_callback,Pin Interrupt Priority為Priority 2。 3.2 配置低功耗模式 序號 操作 1 點擊界面下方標簽欄中的Stacks標簽,進入堆棧配置頁面。 2 在HAL/Common Stacks區域,點擊New Stack按鈕。 3 在Power子菜單中,選擇Low Power Modes (r_lpm)。 序號 操作 1 在下方Settings設置區域的Module g_lpm0 Low Power Modes (r_lpm)部分,設置Name為g_lpm0。 2 在Settings設置區域的Module g_lpm0 Low Power Modes (r_lpm)部分,將Low Power Mode設置為Software Standby mode。 3 Module g_lpm0 Low Power Modes (r_lpm) - Wake Sources部分,勾選IRQ7。 3.3 編寫代碼 3.3.1 按鍵中斷 新建irq.h ::: details 查看代碼 #ifndef IRQ_H_ #define IRQ_H_ #include \"hal_data.h\" void IRQ_Init(); extern volatile bool key_pressed; #endif ::: 新建irq.c ::: details 查看代碼 #include \"irq.h\" #include \"hal_data.h\" volatile bool key_pressed = false; void key_irq_callback(external_irq_callback_args_t *p_args) { key_pressed = true; } void IRQ_Init() { g_external_irq7.p_api->open(&g_external_irq7_ctrl, &g_external_irq7_cfg); g_external_irq7.p_api->enable(&g_external_irq7_ctrl); } ::: 在irq.c文件中定義了初始化函數IRQ_Init,并實現按鍵中斷回調函數key_irq_callback。 3.3.2 低功耗模式 新建lpm.h ::: details 查看代碼 #ifndef LPM_H_ #define LMP_H_ #include \"hal_data.h\" extern volatile bool in_LPM; void LPM_Init(); void EnterLowPowerMode(); #endif ::: 新建lpm.c ::: details 查看代碼 #include \"lpm.h\" #include \"hal_data.h\" volatile bool in_LPM = true;// 在低功耗模式的標志位 防止用按鍵喚醒了又立即進待機 void LPM_Init() { g_lpm0.p_api->open(&g_lpm0_ctrl, &g_lpm0_cfg); } void EnterLowPowerMode() { if(!in_LPM){ printf(\"進入低功耗模式\\\\n\"); in_LPM = true; g_lpm0.p_api->lowPowerModeEnter(&g_lpm0_ctrl); } } :::EnterLowPowerMode是進入低功耗模式的函數,LPM_Init是初始化低功耗模式的。 3.3.3 修改hal_entry.c hal_entry函數之前 ::: details 查看代碼 #include \"hal_data.h\" #include \"debug_bsp_uart.h\" #include \"rtc.h\" #include \"irq.h\" #include \"lpm.h\" rtc_time_t get_time; ::: 在hal_entry函數內添加 ::: details 查看代碼 Debug_UART9_Init(); // SCI9 UART 調試串口初始化 RTC_Init(); IRQ_Init(); LPM_Init(); while (1) { if (key_pressed) { key_pressed = false; if(!in_LPM){ EnterLowPowerMode(); printf(\"退出待機模式\\\\n\"); } else{ in_LPM = false; } } if (rtc_flag) { g_rtc0.p_api->calendarTimeGet(&g_rtc0_ctrl, &get_time); // 獲取 RTC 計數時間 rtc_flag = 0; printf(\"%d年%d月%d日 %d:%d:%d\\\\n\", get_time.tm_year + 1900, get_time.tm_mon + 1, get_time.tm_mday, get_time.tm_hour, get_time.tm_min, get_time.tm_sec); } if (uart_rx_complete_flag) { char *time; uart_rx_complete_flag = 0; // 解析設置時間的命令 e.g: time:20250126080910 // warning: 未添加錯誤糾正算法,請輸入正確的時間,否則工作異常! if (strncmp(rx_data, \"time:\", 5) == 0) { time = rx_data + 5; set_time.tm_year = ((time[0] - \'0\') * 1000) + ((time[1] - \'0\') * 100) + ((time[2] - \'0\') * 10) + (time[3] - \'0\') - 1900; set_time.tm_mon = ((time[4] - \'0\') * 10) + (time[5] - \'0\') - 1; set_time.tm_mday = ((time[6] - \'0\') * 10) + (time[7] - \'0\'); set_time.tm_hour = ((time[8] - \'0\') * 10) + (time[9] - \'0\'); set_time.tm_min = ((time[10] - \'0\') * 10) + (time[11] - \'0\'); set_time.tm_sec = ((time[12] - \'0\') * 10) + (time[13] - \'0\'); g_rtc0.p_api->calendarTimeSet(&g_rtc0_ctrl, &set_time); } } } ::: ::: tip 主程序設計為按鍵按下即進入待機模式,這里只是為了快速實現效果,而采用的按鍵觸發方式,可以是串口發消息觸發、程序邏輯調用等等方法進入待機模式。 ::: 4 下載測試 把編譯好的程序下載到開發板并復位,打開PC端的串口助手,能查看到串口打印的時間。點按一下開發板上的用戶按鍵,進入待機模式,再按一下則恢復正常工作模式。待機模式下RTC實時時鐘正常計數,可以通過這個方法來實現低功耗日歷的設計。 最后關心一下功耗到底如何,因為RA2L1開發板最重要的特性就是低功耗。在不接任何外設,輸入電壓3.3V的情況下,測試得到正常運行的電流約6mA,待機模式下的電流約14uA。 工程附件 *附件:05_Low-Power-Mode-Btn-Wakeup.zip
    發表于 01-29 23:08

    【瑞薩RA2L1入門學習】1. 點亮LED

    首次使用瑞薩單片機,先說一下使用感受。 本次學習使用的是RA-Eco-RA2L1-48PIN-V1.0開發板+e2studio(官方的集成開發環境)+RAFP(官方的程序燒錄工具)。 整個流程都是參考“RA2L1入門教學實驗.pdf”進行的,之前使用過STM32CubeIDE和STM32CubeMX軟件,瑞薩與之相對應的是e2studio和RASC軟件,整體用起來還是挺方便的。RASC(圖形化配置軟件)方便快捷,我之前也用過國內的一些單片機,但是都沒有各自廠商的圖形化配置軟件。RAFP(程序燒錄工具)與常用的串口燒錄軟件些許不同,操作起來稍顯麻煩。 1.編寫代碼: 2.連接設備 硬件連接:串口設備--> 開發板 3.3V--> VCC RX --> P109 TX --> P110 GND --> GND 如果連接過程中出現錯誤,請按一下RESET按鈕!3.下載程序 如下載過程中出現錯誤,請按一下RESET按鈕!4.實驗結果 經過這次實驗,搭建了開發環境,使用了FSP庫,對于該庫還處于初識階段,希望通過后面的幾個實驗能夠進一步認識學習該庫。
    發表于 01-29 22:17

    關于用Labview編寫壓機軟件

    我想請教一下,我如果想實現如下圖這樣,在xy圖上有力判定點該如何做到呢
    發表于 01-29 19:12

    要:李想STM32開發板的軟件(包括燒寫、相關支持)

    我要:李想STM32開發板(LX-1ATFT)的軟件(包括燒寫、相關支持等軟件,不要視頻)。我曾經買過他硬件,當時沒空,現在想學,又沒有資料及網站了。先謝謝!
    發表于 01-29 17:12

    【瑞薩RA2L1入門學習】04、I2C驅動OLED屏幕 BME280傳感器

    1.前言 本次實驗的目標是把I2C相關的搞定,再嘗試驅動SSD1306 0.96寸OLED屏幕以及BME280傳感器,最后將傳感器讀到的數據和實時時間顯示在屏幕上。 2,硬件部分 2.1 I2C協議簡介 I2C 通訊協議(Inter-Integrated Circuit)是由Philips公司開發的,由于它引腳少,硬件實現簡單,可擴展性強, 不需要USART、CAN等通訊協議的外部收發設備,現在被廣泛地使用在系統內多個集成電路(IC)間的通訊。 在計算機科學里,大部分復雜的問題都可以通過分層來簡化。如芯片被分為內核層和片上外設; 瑞薩的FPS庫則是在寄存器與用戶代碼之間的軟件層。對于通訊協議,我們也以分層的方式來理解, 最基本的是把它分為物理層和協議層。物理層規定通訊系統中具有機械、電子功能部分的特性,確保原始數據在物理媒體的傳輸。 協議層主要規定通訊邏輯,統一收發雙方的數據打包、解包標準。簡單來說物理層規定我們用嘴巴還是用肢體來交流, 協議層則規定我們用中文還是英文來交流。 具體的I2C協議入門可以看TI的A Basic Guide to I2C - Texas Instruments 2.2 OLED屏幕 本次使用的屏幕是0.96寸 4針 I2C協議 OLED屏幕,其驅動IC為SSD1306,屏幕分辨率為128x64。 編程時參考的數據手冊,以及基于商家給的STM32驅動庫修改,具體的修改參考軟件部分。 2.3 BME280溫濕度氣壓傳感器 BME280是一款由Bosch Sensortec開發的多功能環境傳感器,可同時精確測量溫度、濕度和氣壓,具有低功耗和小尺寸的特點,廣泛應用于氣象監測、室內導航、健康監測及物聯網等領域。 3.軟件部分 將先前03_RTC工程復制一份,重命名為04_OLED_BME280-I2C。 3.1 配置I2C 首先在e2s內配置I2C 序號 操作 1 點擊界面下方標簽欄中的Pins標簽,進入引腳配置界面。 2 在Pin Selection區域,展開Connectivity:I2C選項,選擇I2C0。 3 在Pin Configuration區域,將Pin Group Selection設置為_A only,Operation Mode設置為Enabled。 4 勾選SDA0對應的P401引腳和SCL0對應的P400引腳。 序號 操作 1 在Pin Selection區域,分別選擇P400和P401引腳。 2 將Output type設置為n-ch open drain,把P400和P401配置成開漏輸出。 序號 操作 1 點擊界面下方標簽欄中的Stacks標簽,進入堆棧配置頁面。 2 在HAL/Common Stacks區域,點擊New Stack按鈕。 3 在彈出菜單中,選擇Connectivity選項。 4 在Connectivity子菜單中,選擇I2C Master (r_iic_master)。 序號 操作 1 在HAL/Common Stacks區域,點擊選中g_i2c_master0 I2C Master (r_iic_master)。 2 在下方Settings設置區域的Module g_i2c_master0 I2C Master (r_iic_master)部分,將Rate設置為Fast-mode。 3 Module g_i2c_master0 I2C Master (r_iic_master)部分,設置Slave Address為0x3c。 4 Module g_i2c_master0 I2C Master (r_iic_master)部分,設置Callback為iic_callback,Interrupt Priority Level為Priority 2。 這里說明一下,在移植商家給的STM32 OLED驅動庫時看到屏幕地址為0x78,即 01111000,是包含讀寫位的(最低位)。而瑞薩這里是7位地址,不含讀寫位,因此要將0x78右移1位,即0x3C (0111100)。 確認上面設置沒問題后,生成項目代碼。 2 編寫代碼 2.1 I2C通信相關 新建i2c.c和i2c.h文件。 i2c.h: ::: details 查看代碼 #ifndef I2C_H_ #define I2C_H_ extern volatile bool i2c_rx_complete; extern volatile bool i2c_tx_complete; void i2c_wait_rx(); void i2c_wait_tx(); #endif ::: i2c.c: ::: details 查看代碼 #include \"hal_data.h\" #include \"i2c.h\" volatile bool i2c_rx_complete = false; volatile bool i2c_tx_complete = false; uint16_t timeout = 0; void iic_callback(i2c_master_callback_args_t *p_args) { if (p_args->event == I2C_MASTER_EVENT_RX_COMPLETE) { i2c_rx_complete = true; } else if (p_args->event == I2C_MASTER_EVENT_TX_COMPLETE) { i2c_tx_complete = true; } } void i2c_wait_tx() { timeout = 1000; while (!i2c_tx_complete && timeout > 0) { timeout--; } i2c_tx_complete = false; } void i2c_wait_rx() { timeout = 1000; while (!i2c_rx_complete && timeout > 0) { timeout--; } i2c_rx_complete = false; } ::: 由于瑞薩FSP庫的高集成度,我只需要編寫代碼實現回調函數iic_callback、等待發送函數i2c_wait_tx、等待接收i2c_wait_rx函數改變標志位即可。 3.2.2 BME280操作相關 bme280.h: ::: details 查看代碼 #ifndef BME280_H_ #define BME280_H_ #include \"hal_data.h\" #define BME280_ID 0x60 typedef struct { double humi, temp, press; bool initialized; } BME_Struct; void BME280_Get_Data(BME_Struct *bme); void BME280_Init(BME_Struct *bme); void BME280_Write_then_Read(uint8_t *src, uint8_t write_bytes, uint8_t *data_dest, uint8_t read_bytes); void BME280_Trimming_Values(); double BME280_compensate_T_double(int32_t adc_T); double BME280_compensate_P_double(int32_t adc_P); double bme280_compensate_H_double(int32_t adc_H); #endif /* BME280_H_ */ ::: bme280.c: ::: details 查看代碼 #include \"bme280.h\" #include \"hal_data.h\" #include \"i2c.h\" uint16_t dig_T1; int16_t dig_T2; int16_t dig_T3; uint16_t dig_P1; int16_t dig_P2; int16_t dig_P3; int16_t dig_P4; int16_t dig_P5; int16_t dig_P6; int16_t dig_P7; int16_t dig_P8; int16_t dig_P9; int8_t dig_H1; int16_t dig_H2; int8_t dig_H3; int16_t dig_H4; int16_t dig_H5; int8_t dig_H6; void BME280_Write_then_Read(uint8_t *src, uint8_t write_bytes, uint8_t *data_dest, uint8_t read_bytes) { //臨時設置I2C從機地址為0x76 g_i2c_master0.p_api->slaveAddressSet(&g_i2c_master0_ctrl, 0x76, I2C_MASTER_ADDR_MODE_7BIT); g_i2c_master0.p_api->write(&g_i2c_master0_ctrl, src, write_bytes, true); i2c_wait_tx(); g_i2c_master0.p_api->read(&g_i2c_master0_ctrl, data_dest, read_bytes, false); i2c_wait_rx(); g_i2c_master0.p_api->slaveAddressSet(&g_i2c_master0_ctrl, 0x3C, I2C_MASTER_ADDR_MODE_7BIT); } void BME280_Init(BME_Struct *bme) { uint8_t reg = 0xD0; uint8_t write_settings[7] = {0x00}; uint8_t read_data; BME280_Write_then_Read(&reg, 1, &read_data, 1); if (read_data != BME280_ID) { printf(\"Init BME280 Failed!\\\\n\"); bme->initialized = false; return; } else { bme->initialized = true; } write_settings[0] = 0xF2; // 設置濕度采集的寄存器 0xF2 write_settings[1] = 0x05; // 00000 101 濕度 oversampling x16 write_settings[2] = 0xF4; // 設置溫度采集、氣壓采集、工作模式的寄存器 0xF4 write_settings[3] = 0x93; // 100 100 11 溫度和氣壓 oversampling x8,模式為normal write_settings[4] = 0xF5; // 配置config寄存器 write_settings[5] = 0x10; // 000 100 0 0 ,配置濾波器系數為16 g_i2c_master0.p_api->slaveAddressSet(&g_i2c_master0_ctrl, 0x76, I2C_MASTER_ADDR_MODE_7BIT); g_i2c_master0.p_api->write(&g_i2c_master0_ctrl, &write_settings[0], 6, false); i2c_wait_tx(); g_i2c_master0.p_api->slaveAddressSet(&g_i2c_master0_ctrl, 0x3C, I2C_MASTER_ADDR_MODE_7BIT); R_BSP_SoftwareDelay(2, BSP_DELAY_UNITS_MILLISECONDS); // 校準數據 BME280_Trimming_Values(); } void BME280_Trimming_Values() { uint8_t data[33] = { 0, }; uint8_t reg = 0x88; BME280_Write_then_Read(&reg, 1, &data[0], 24); R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS); // 適當加延遲否則數據錯誤 reg = 0xA1; BME280_Write_then_Read(&reg, 1, &data[24], 1); R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS); // 適當加延遲否則數據錯誤 reg = 0xE1; BME280_Write_then_Read(&reg, 1, &data[25], 7); R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS); // 適當加延遲否則數據錯誤 dig_T1 = (data[1] << 8) | data[0]; dig_T2 = (data[3] << 8) | data[2]; dig_T3 = (data[5] << 8) | data[4]; dig_P1 = (data[7] << 8) | data[6]; dig_P2 = (data[9] << 8) | data[8]; dig_P3 = (data[11] << 8) | data[10]; dig_P4 = (data[13] << 8) | data[12]; dig_P5 = (data[15] << 8) | data[14]; dig_P6 = (data[17] << 8) | data[16]; dig_P7 = (data[19] << 8) | data[18]; dig_P8 = (data[21] << 8) | data[20]; dig_P9 = (data[23] << 8) | data[22]; dig_H1 = data[24]; dig_H2 = (data[26] << 8) | data[25]; dig_H3 = data[27]; dig_H4 = (data[28] << 4) | (data[29] & 0x0F); dig_H5 = (data[30] << 4) | ((data[29] >> 4)); dig_H6 = data[31]; } // Returns temperature in DegC, double precision. Output value of “51.23” equals 51.23 DegC. // t_fine carries fine temperature as global value volatile long signed int t_fine; double BME280_compensate_T_double(long signed int adc_T) { double var1, var2, T; var1 = (((double)adc_T) / 16384.0 - ((double)dig_T1) / 1024.0) * ((double)dig_T2); var2 = ((((double)adc_T) / 131072.0 - ((double)dig_T1) / 8192.0) * (((double)adc_T) / 131072.0 - ((double)dig_T1) / 8192.0)) * ((double)dig_T3); t_fine = (long signed int)(var1 + var2); T = (var1 + var2) / 5120.0; return T; } // Returns pressure in Pa as double. Output value of “96386.2” equals 96386.2 Pa = 963.862 hPa double BME280_compensate_P_double(long signed int adc_P) { double var1, var2, p; var1 = ((double)t_fine / 2.0) - 64000.0; var2 = var1 * var1 * ((double)dig_P6) / 32768.0; var2 = var2 + var1 * ((double)dig_P5) * 2.0; var2 = (var2 / 4.0) + (((double)dig_P4) * 65536.0); var1 = (((double)dig_P3) * var1 * var1 / 524288.0 + ((double)dig_P2) * var1) / 524288.0; var1 = (1.0 + var1 / 32768.0) * ((double)dig_P1); if (var1 == 0.0) { return 0; // avoid exception caused by division by zero } p = 1048576.0 - (double)adc_P; p = (p - (var2 / 4096.0)) * 6250.0 / var1; var1 = ((double)dig_P9) * p * p / 2147483648.0; var2 = p * ((double)dig_P8) / 32768.0; p = p + (var1 + var2 + ((double)dig_P7)) / 16.0; return p; } // Returns humidity in %rH as as double. Output value of “46.332” represents 46.332 % rH double bme280_compensate_H_double(long signed int adc_H) { double var_H; var_H = (((double)t_fine) - 76800.0); var_H = (adc_H - (((double)dig_H4) * 64.0 + ((double)dig_H5) / 16384.0 * var_H)) * (((double)dig_H2) / 65536.0 * (1.0 + ((double)dig_H6) / 67108864.0 * var_H * (1.0 + ((double)dig_H3) / 67108864.0 * var_H))); var_H = var_H * (1.0 - ((double)dig_H1) * var_H / 524288.0); if (var_H > 100.0) var_H = 100.0; else if (var_H < 0.0) var_H = 0.0; return var_H; } void BME280_Get_Data(BME_Struct *bme) { uint8_t dat[8] = {0}; uint32_t press_t, temp_t, hum_t = 0; uint8_t reg = 0xF7; BME280_Write_then_Read(&reg, 1, &dat[0], 8); R_BSP_SoftwareDelay(2, BSP_DELAY_UNITS_MILLISECONDS); press_t = ((((uint32_t)dat[0] << 12) | ((uint32_t)dat[1] << 4)) | ((uint32_t)dat[2] >> 4)); temp_t = ((((uint32_t)dat[3] << 12) | ((uint32_t)dat[4] << 4)) | ((uint32_t)dat[5] >> 4)); hum_t = (((uint32_t)dat[6] << 8) | (uint32_t)dat[7]); bme->temp = BME280_compensate_T_double(temp_t); bme->press = BME280_compensate_P_double(press_t) / 100.0; bme->humi = bme280_compensate_H_double(hum_t); // printf(\"temp: %.2lf, humid: %.2lf, pressure: %.2lf\\\\n\", bme->temp, bme->humi, bme->press); } :::BME280_compensate_T_double、bme280_compensate_H_double、bme280_compensate_P_double這三個函數分別為溫度、濕度、氣壓的補償算法函數,借鑒了BME280官方數據手冊內給出的參考代碼。 bme280工作流程為 步驟 內容 1 上電初始化 2 寫入0xF2、0xF4、0xF5寄存器以設定過采樣率等參數 3 獲取校準數據 4 調用BME280_Get_Data函數,讀取0xF7~0xFE寄存器的數據 5 調用補償算法函數得到人類可讀的數值 :::warning 注意 在寫入+讀取函數后記得跟1~5ms的延時,再進行下一步操作,否則會因為bme280側的數據未準備好,有極大概率讀取到錯誤數據或讀不到數據。 ::: 3.2.3 OLED屏幕操作相關 oled.h: ::: details 查看代碼 #ifndef OLED_H_ #define OLED_H_ #include \"hal_data.h\" #define OLED_CMD 0// 寫命令 #define OLED_DATA 1 // 寫數據 void OLED_ClearPoint(uint8_t x, uint8_t y); void OLED_ColorTurn(uint8_t i); void OLED_DisplayTurn(uint8_t i); void OLED_WR_Byte(uint8_t dat, uint8_t mode); void OLED_DisPlay_On(void); void OLED_DisPlay_Off(void); void OLED_Refresh(void); void OLED_Clear(void); void OLED_DrawPoint(uint8_t x, uint8_t y, uint8_t t); void OLED_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t mode); void OLED_DrawCircle(uint8_t x, uint8_t y, uint8_t r); void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t size1); void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *chr, uint8_t size1); void OLED_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size1); void OLED_ShowChinese(uint8_t x, uint8_t y, uint8_t num, uint8_t size1); void OLED_ScrollDisplay(uint8_t num, uint8_t space); void OLED_ShowPicture(uint8_t x, uint8_t y, uint8_t sizex, uint8_t sizey, uint8_t BMP[], uint8_t mode); void OLED_Init(void); #endif oled.c: ::: details 查看代碼 #include \"oled.h\" #include \"oled_font.h\" #include \"i2c.h\" volatile uint8_t OLED_GRAM[144][8]; // 反顯函數 void OLED_ColorTurn(uint8_t i) { if (i == 0) { OLED_WR_Byte(0xA6, OLED_CMD); // 正常顯示 } if (i == 1) { OLED_WR_Byte(0xA7, OLED_CMD); // 反色顯示 } } // 屏幕旋轉180度 void OLED_DisplayTurn(uint8_t i) { if (i == 0) { OLED_WR_Byte(0xC8, OLED_CMD); // 正常顯示 OLED_WR_Byte(0xA1, OLED_CMD); } if (i == 1) { OLED_WR_Byte(0xC0, OLED_CMD); // 反轉顯示 OLED_WR_Byte(0xA0, OLED_CMD); } } // 發送一個字節 // mode:數據/命令標志 0,表示命令;1,表示數據; void OLED_WR_Byte(uint8_t dat, uint8_t mode) { uint8_t data[2]; if (mode) { data[0] = 0x40; } else { data[0] = 0x00; } data[1] = dat; R_IIC_MASTER_Write(&g_i2c_master0_ctrl, data, 2, false); i2c_wait_tx(); } // 開啟OLED顯示 void OLED_DisPlay_On(void) { OLED_WR_Byte(0x8D, OLED_CMD); // 電荷泵使能 OLED_WR_Byte(0x14, OLED_CMD); // 開啟電荷泵 OLED_WR_Byte(0xAF, OLED_CMD); // 點亮屏幕 } // 關閉OLED顯示 void OLED_DisPlay_Off(void) { OLED_WR_Byte(0x8D, OLED_CMD); // 電荷泵使能 OLED_WR_Byte(0x10, OLED_CMD); // 關閉電荷泵 OLED_WR_Byte(0xAE, OLED_CMD); // 關閉屏幕 } // 更新顯存到OLED void OLED_Refresh(void) { uint8_t i, n; for (i = 0; i < 8; i++) { OLED_WR_Byte(0xb0 + i, OLED_CMD); // 設置行起始地址 OLED_WR_Byte(0x00, OLED_CMD);// 設置低列起始地址 OLED_WR_Byte(0x10, OLED_CMD);// 設置高列起始地址 for (n = 0; n < 128; n++) { OLED_WR_Byte(OLED_GRAM[n][i], OLED_DATA); } } } // 清屏函數 void OLED_Clear(void) { uint8_t i, n; for (i = 0; i < 8; i++) { for (n = 0; n < 128; n++) { OLED_GRAM[n][i] = 0; // 清除所有數據 } } OLED_Refresh(); // 更新顯示 } // 畫點 // x:0~127 // y:0~63 // t:1 填充 0,清空 void OLED_DrawPoint(uint8_t x, uint8_t y, uint8_t t) { uint8_t i, m, n; i = y / 8; m = y % 8; n = 1 << m; if (t) { OLED_GRAM[x][i] |= n; } else { OLED_GRAM[x][i] = ~OLED_GRAM[x][i]; OLED_GRAM[x][i] |= n; OLED_GRAM[x][i] = ~OLED_GRAM[x][i]; } } // 畫線 // x1,y1:起點坐標 // x2,y2:結束坐標 void OLED_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t mode) { uint16_t t; int xerr = 0, yerr = 0, delta_x, delta_y, distance; int incx, incy, uRow, uCol; delta_x = x2 - x1; // 計算坐標增量 delta_y = y2 - y1; uRow = x1; // 畫線起點坐標 uCol = y1; if (delta_x > 0) incx = 1; // 設置單步方向 else if (delta_x == 0) incx = 0; // 垂直線 else { incx = -1; delta_x = -delta_x; } if (delta_y > 0) incy = 1; else if (delta_y == 0) incy = 0; // 水平線 else { incy = -1; delta_y = -delta_x; } if (delta_x > delta_y) distance = delta_x; // 選取基本增量坐標軸 else distance = delta_y; for (t = 0; t < distance + 1; t++) { OLED_DrawPoint(uRow, uCol, mode); // 畫點 xerr += delta_x; yerr += delta_y; if (xerr > distance) { xerr -= distance; uRow += incx; } if (yerr > distance) { yerr -= distance; uCol += incy; } } //OLED_Refresh(); } // x,y:圓心坐標 // r:圓的半徑 void OLED_DrawCircle(uint8_t x, uint8_t y, uint8_t r) { int a, b, num; a = 0; b = r; while (2 * b * b >= r * r) { OLED_DrawPoint(x + a, y - b, 1); OLED_DrawPoint(x - a, y - b, 1); OLED_DrawPoint(x - a, y + b, 1); OLED_DrawPoint(x + a, y + b, 1); OLED_DrawPoint(x + b, y + a, 1); OLED_DrawPoint(x + b, y - a, 1); OLED_DrawPoint(x - b, y - a, 1); OLED_DrawPoint(x - b, y + a, 1); a++; num = (a * a + b * b) - r * r; // 計算畫的點離圓心的距離 if (num > 0) { b--; a--; } } //OLED_Refresh(); } // 顯示字符 不建議直接使用,若要使用需要加上OLED_Refresh();更新到顯存 void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t size1) { uint8_t i, m, temp, size2, chr1; uint8_t x0 = x, y0 = y; // 計算字符的字節數 if (size1 == 8) size2 = 6; else size2 = (size1 / 8 + ((size1 % 8) ? 1 : 0)) * (size1 / 2); // 字體占用的字節數 chr1 = chr - \' \'; // 偏移字符值,轉換為數組索引 for (i = 0; i < size2; i++) { // 根據字體大小選擇相應的字模 if (size1 == 8) { temp = asc2_0806[chr1][i]; } else if (size1 == 12) { temp = asc2_1206[chr1][i]; } else if (size1 == 16) { temp = asc2_1608[chr1][i]; } else if (size1 == 24) { temp = asc2_2412[chr1][i]; } else { return; // 字體不支持 } for (m = 0; m < 8; m++) { if (temp & 0x01) OLED_GRAM[x][y / 8] |= (1 << (y % 8)); // 設置顯存中的點 else OLED_GRAM[x][y / 8] &= ~(1 << (y % 8)); // 清除顯存中的點 temp >>= 1; y++; } x++; if ((size1 != 8) && ((x - x0) == size1 / 2)) { x = x0; y0 = y0 + 8; } y = y0; } } // 顯示字符串 // x,y:起點坐標 // size1:字體大小 //*chr:字符串起始地址 void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *chr, uint8_t size1) { while ((*chr >= \' \') && (*chr <= \'~\')) // 判斷是不是非法字符! { OLED_ShowChar(x, y, *chr, size1); if (size1 == 8) x += 6; else x += size1 / 2; chr++; } OLED_Refresh(); } // m^n uint32_t OLED_Pow(uint8_t m, uint8_t n) { uint32_t result = 1; while (n--) { result *= m; } return result; } // 顯示數字 // x,y :起點坐標 // num :要顯示的數字 // len :數字的位數 // size:字體大小 void OLED_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size1) { uint8_t t, temp, m = 0; if (size1 == 8) m = 2; for (t = 0; t < len; t++) { temp = (num / OLED_Pow(10, len - t - 1)) % 10; if (temp == 0) { OLED_ShowChar(x + (size1 / 2 + m) * t, y, \'0\', size1); } else { OLED_ShowChar(x + (size1 / 2 + m) * t, y, temp + \'0\', size1); } } OLED_Refresh(); } void OLED_ShowChinese(uint8_t x, uint8_t y, uint8_t num, uint8_t size1) { uint8_t m, temp; uint8_t x0 = x, y0 = y; uint16_t i, size3 = (size1 / 8 + ((size1 % 8) ? 1 : 0)) * size1; // 計算一個字符對應的字節數 uint8_t mask; // 用來構造顯示的掩碼 for (i = 0; i < size3; i++) { if (size1 == 16) { temp = Hzk1[num][i]; // 獲取字形數據 } else { return; // 只處理 16x16 字體 } for (m = 0; m < 8; m++) { mask = (1 << (y % 8)); // 根據當前 y 坐標計算掩碼 if (temp & 0x01) // 當前位為 1 { OLED_GRAM[x][y / 8] |= mask; // 設置該位 } else // 當前位為 0 { OLED_GRAM[x][y / 8] &= ~mask; // 清除該位 } temp >>= 1; // 右移,處理下一個像素 y++;// 縱向位置移動 } x++; // 橫向位置移動 // 判斷是否換行 if ((x - x0) == size1) { x = x0; y0 = y0 + 8; // 換行時,y 坐標增加 8 } y = y0; // 恢復 y 坐標 } // 最后刷新整個顯示屏 OLED_Refresh(); } // num 顯示漢字的個數 // space 每一遍顯示的間隔 void OLED_ScrollDisplay(uint8_t num, uint8_t space) { uint8_t i, n, t = 0, m = 0, r; while (1) { if (m == 0) { OLED_ShowChinese(128, 24, t, 16); // 寫入一個漢字保存在OLED_GRAM[][]數組中 t++; } if (t == num) { for (r = 0; r < 16 * space; r++) // 顯示間隔 { for (i = 1; i < 144; i++) { for (n = 0; n < 8; n++) { OLED_GRAM[i - 1][n] = OLED_GRAM[i][n]; } } OLED_Refresh(); } t = 0; } m++; if (m == 16) { m = 0; } for (i = 1; i < 144; i++) // 實現左移 { for (n = 0; n < 8; n++) { OLED_GRAM[i - 1][n] = OLED_GRAM[i][n]; } } OLED_Refresh(); } } // x,y:起點坐標 // sizex,sizey,圖片長寬 // BMP[]:要寫入的圖片數組 // mode:0,反色顯示;1,正常顯示 void OLED_ShowPicture(uint8_t x, uint8_t y, uint8_t sizex, uint8_t sizey, uint8_t BMP[], uint8_t mode) { uint16_t j = 0; uint8_t i, n, temp, m; uint8_t x0 = x, y0 = y; sizey = sizey / 8 + ((sizey % 8) ? 1 : 0); for (n = 0; n < sizey; n++) { for (i = 0; i < sizex; i++) { temp = BMP[j]; j++; for (m = 0; m < 8; m++) { if (temp & 0x01) OLED_DrawPoint(x, y, mode); else OLED_DrawPoint(x, y, !mode); temp >>= 1; y++; } x++; if ((x - x0) == sizex) { x = x0; y0 = y0 + 8; } y = y0; } } OLED_Refresh(); } // OLED的初始化 void OLED_Init(void) { OLED_WR_Byte(0xAE, OLED_CMD); //--turn off oled panel 關閉顯示 OLED_WR_Byte(0x00, OLED_CMD); //---set low column address OLED_WR_Byte(0x10, OLED_CMD); //---set high column address OLED_WR_Byte(0x40, OLED_CMD); //--set start line addressSet Mapping RAM Display Start Line (0x00~0x3F) OLED_WR_Byte(0x81, OLED_CMD); //--set contrast control register OLED_WR_Byte(0xCF, OLED_CMD); // Set SEG Output Current Brightness OLED_WR_Byte(0xA1, OLED_CMD); //--Set SEG/Column Mapping0xa0左右反置 0xa1正常 OLED_WR_Byte(0xC8, OLED_CMD); // Set COM/Row Scan Direction0xc0上下反置 0xc8正常 OLED_WR_Byte(0xA6, OLED_CMD); //--set normal display OLED_WR_Byte(0xA8, OLED_CMD); //--set multiplex ratio(1 to 64) 設置驅動路數 OLED_WR_Byte(0x3f, OLED_CMD); //--1/64 duty OLED_WR_Byte(0xD3, OLED_CMD); //-set display offsetShift Mapping RAM Counter (0x00~0x3F) OLED_WR_Byte(0x00, OLED_CMD); //-not offset OLED_WR_Byte(0xd5, OLED_CMD); //--set display clock divide ratio/oscillator frequency OLED_WR_Byte(0x80, OLED_CMD); //--set divide ratio, Set Clock as 100 Frames/Sec OLED_WR_Byte(0xD9, OLED_CMD); //--set pre-charge period OLED_WR_Byte(0xF1, OLED_CMD); // Set Pre-Charge as 15 Clocks & Discharge as 1 Clock OLED_WR_Byte(0xDA, OLED_CMD); //--set com pins hardware configuration OLED_WR_Byte(0x12, OLED_CMD); OLED_WR_Byte(0xDB, OLED_CMD); //--set vcomh OLED_WR_Byte(0x30, OLED_CMD); // Set VCOM Deselect Level OLED_WR_Byte(0x20, OLED_CMD); //-Set Page Addressing Mode (0x00/0x01/0x02) OLED_WR_Byte(0x02, OLED_CMD); // OLED_WR_Byte(0x8D, OLED_CMD); //--set Charge Pump enable/disable OLED_WR_Byte(0x14, OLED_CMD); //--set(0x10) disable OLED_Clear(); OLED_WR_Byte(0xAF, OLED_CMD); } :::tip 最開始OLED屏幕上顯示字的速度非常慢,幾乎是一個字一個字地往外蹦。 解決方法是開一個顯存數組OLED_GRAM ,將內容先緩存到顯存數組,再調用OLED_Refresh一次性地寫給OLED屏幕控制器 ::: 3.2.4 修改hal_entry.c 在hal_entry.c開頭加入 ::: details 查看代碼 #include \"hal_data.h\" #include \"debug_bsp_uart.h\" #include \"oled.h\" #include \"bme280.h\" #include \"rtc.h\" #include <stdio.h> BME_Struct bme = {0, 0, 0, false}; rtc_time_t get_time; ::: 在hal_entry函數中加入 ::: details 查看代碼 Debug_UART9_Init(); // SCI9 UART 調試串口初始化 g_i2c_master0.p_api->open(&g_i2c_master0_ctrl, &g_i2c_master0_cfg); BME280_Init(&bme); OLED_Init(); RTC_Init(); printf(\"I2C OLED屏幕+BME280獲取溫濕度實驗\\\\n\"); printf(\"若要通過串口設置時間,請輸入類似time:20250126080910的字符串\\\\n\"); while (1) { uint8_t t1[50] = {0}, t2[50] = {0}, t3[50] = {0}, t4[50] = {0}; if (rtc_flag) { g_rtc0.p_api->calendarTimeGet(&g_rtc0_ctrl, &get_time); // 獲取 RTC 計數時間 rtc_flag = 0; //printf(\"%d年%d月%d日 %d:%d:%d\\\\n\", // get_time.tm_year + 1900, get_time.tm_mon + 1, get_time.tm_mday, // get_time.tm_hour, get_time.tm_min, get_time.tm_sec); sprintf((char *)t1, \"%4d.%02d.%02d\", get_time.tm_year + 1900, get_time.tm_mon + 1, get_time.tm_mday); sprintf((char *)t2, \"%02d:%02d:%02d\", get_time.tm_hour, get_time.tm_min, get_time.tm_sec); if (bme.initialized) { BME280_Get_Data(&bme); sprintf((char *)t3, \"%.1fC %.1f%%RH\", bme.temp, bme.humi); sprintf((char *)t4, \"%.1fhPa\", bme.press); OLED_ShowString(12, 32, t3, 16); // 顯示溫度濕度 OLED_ShowString(24, 48, t4, 16); // 顯示氣壓 } OLED_ShowString(24, 0, t1, 16);// 顯示年月日 OLED_ShowString(32, 16, t2, 16); // 顯示時分秒 } if (uart_rx_complete_flag) { char *time; uart_rx_complete_flag = 0; // 解析設置時間的命令 e.g: time:20250126080910 // warning: 未添加錯誤糾正算法,請輸入正確的時間,否則工作異常! if (strncmp(rx_data, \"time:\", 5) == 0) { time = rx_data + 5; set_time.tm_year = ((time[0] - \'0\') * 1000) + ((time[1] - \'0\') * 100) + ((time[2] - \'0\') * 10) + (time[3] - \'0\') - 1900; set_time.tm_mon = ((time[4] - \'0\') * 10) + (time[5] - \'0\') - 1; set_time.tm_mday = ((time[6] - \'0\') * 10) + (time[7] - \'0\'); set_time.tm_hour = ((time[8] - \'0\') * 10) + (time[9] - \'0\'); set_time.tm_min = ((time[10] - \'0\') * 10) + (time[11] - \'0\'); set_time.tm_sec = ((time[12] - \'0\') * 10) + (time[13] - \'0\'); g_rtc0.p_api->calendarTimeSet(&g_rtc0_ctrl, &set_time); } else{ printf(\"若要通過串口設置時間,請輸入類似time:20250126080910的字符串\\\\n\"); } } } ::: 這段程序實現了每1秒刷新一次OLED屏幕上的時間和溫濕度氣壓數據,同時能從串口接收格式化的數據以設定時間。 4.下載測試 把編譯好的程序下載到開發板并復位。觀察到OLED屏幕上正確顯示了預設的時間和獲取到的溫濕度氣壓值。 可以打開串口助手,在發送框輸入 time:20250128235958 工程附件 把代碼全貼上來的話超字數限制了,請下載附件查看完整代碼 *附件:04_OLED_BME280-I2C.zip
    發表于 01-29 17:09

    閃速存儲器屬于RAM還是ROM,閃速存儲器一般用來做什么的

    在數字存儲技術的快速發展中,閃速存儲器(Flash Memory)以其獨特的性能和廣泛的應用領域,成為了連接隨機存取存儲器(RAM)與只讀存儲器(ROM)之間的重要橋梁。本文將深入探討閃速存儲器的技術特性、分類及其在現代電子設備中的應用。
    的頭像 發表于 01-29 16:53 ?80次閱讀

    串行接口的工作方式有幾種,串行接口的RXD1和TXD1是什么端口

    在數字通信領域,串行接口作為一種高效的數據傳輸方式,廣泛應用于各種電子設備之間的數據交換。串行接口不僅具有結構簡單、傳輸距離遠、抗干擾能力強等優點,而且能夠支持多種工作方式,以適應不同應用場景的需求。本文將深入探討串行接口的工作方式,并解析RXD1和TXD1端口的含義及其在串行通信中的作用。
    的頭像 發表于 01-29 16:51 ?57次閱讀

    信號線電壓不穩定原因分析

    在電子設備和通信系統中,信號線作為數據傳輸的關鍵通道,其電壓穩定性直接關系到系統的性能和穩定性。當信號線電壓出現不穩定現象時,可能會導致數據傳輸錯誤、設備故障甚至系統癱瘓。因此,深入分析信號線電壓不穩定的原因,對于確保系統的正常運行和優化性能具有重要意義。本文將從多個角度探討信號線電壓不穩定的常見原因。
    的頭像 發表于 01-29 16:47 ?119次閱讀

    信號線電壓高怎么回事,如何解決

    在電子設備和通信系統中,信號線作為信息傳輸的關鍵通道,其電壓狀態直接影響到系統的穩定性和性能。當信號線電壓異常升高時,可能會導致信號失真、設備損壞甚至系統癱瘓。因此,了解信號線電壓高的原因并采取相應的解決方法至關重要。本文將深入探討信號線電壓高的常見原因、檢測方法及解決策略。
    的頭像 發表于 01-29 16:43 ?75次閱讀

    信號線電壓一般是多少,信號線電壓怎么測量

    在電子和通信系統中,信號線作為信息傳輸的媒介,其電壓特性對于系統的性能和穩定性至關重要。了解信號線電壓的一般范圍以及正確的測量方法,對于確保系統的正常運行和優化性能具有重要意義。本文將深入探討信號線電壓的一般范圍、測量方法以及測量過程中需要注意的事項,旨在為相關領域的工程師和技術人員提供有價值的參考。
    的頭像 發表于 01-29 16:40 ?48次閱讀

    功放變壓器換成功率大的可以嗎怎么換

    在音頻系統中,功放變壓器作為電源供應的核心部件,其性能直接影響功放的輸出功率和音質。隨著音頻設備需求的不斷提升,許多音樂愛好者和專業音響師開始考慮將功放機的變壓器更換為功率更大的型號,以期獲得更高的功率輸出和更優的音質表現。本文將深入探討功放變壓器換成功率更大的可行性、具體更換步驟以及需要注意的事項,旨在為相關領域的工程師和愛好者提供有價值的參考。
    的頭像 發表于 01-29 16:37 ?51次閱讀

    磁性元件飽和會有什么影響

    在電子和電力電子系統中,磁性元件(如電感器、變壓器等)扮演著至關重要的角色。然而,當這些磁性元件達到飽和狀態時,其性能將受到顯著影響,進而影響整個系統的穩定性和可靠性。本文將深入探討磁性元件飽和的影響及其應對策略。
    的頭像 發表于 01-29 16:35 ?85次閱讀

    漏電繼電器多長時間檢查一次,漏電斷路器壞了怎么判斷

    在電氣系統中,漏電繼電器與漏電斷路器作為關鍵的安全裝置,承擔著監測電路中的漏電情況并在檢測到異常時及時切斷電源的重要職責,以防止電擊事故和火災等安全隱患。為了確保這些設備的正常運行和電氣系統的整體安全,定期的檢查與維護是必不可少的。本文將深入探討漏電繼電器的檢查周期以及漏電斷路器的故障判斷方法。
    的頭像 發表于 01-29 16:34 ?80次閱讀

    信道編碼的作用,信道編碼有哪幾種

    在數字通信系統中,信道編碼作為一種重要的技術手段,扮演著提升傳輸可靠性和抗干擾性的關鍵角色。本文將深入探討信道編碼的作用及其主要類型。
    的頭像 發表于 01-29 16:32 ?92次閱讀

    死區損耗包括哪些損耗

    在電力電子領域,同步整流DC-DC變換器因其高效能和低損耗而得到廣泛應用。然而,在實際應用中,死區損耗成為影響變換器性能的重要因素。本文將深入探討死區損耗的概念、分類及其影響。
    的頭像 發表于 01-29 16:31 ?77次閱讀
    主站蜘蛛池模板: 精品国产_亚洲人成在线高清 | 3344a毛片在线看| 四虎在线成人免费网站 | www.天天射.com | 天天精品在线 | 欧美综合天天夜夜久久 | 国产精品欧美一区二区 | 在线精品小视频 | 午夜精品久久久久久99热 | 国产看午夜精品理论片 | 欧美黄色大全 | 久久综合影视 | 亚洲精品在线视频观看 | 特黄大片aaaaa毛片 | 久久久久久国产精品免费免 | 视频在线高清完整免费观看 | 全部免费特黄特色大片农村 | 男人视频网| 色噜噜狠狠成人网 | 福利三区 | 欧美日韩色片 | 视频免费1区二区三区 | 一级毛片在线不卡直接观看 | 亚洲精品系列 | 久久免费精品国产72精品剧情 | 欧美黑人性受xxxx喷水 | 日本一区二区免费在线观看 | 乱码精品一区二区三区 | 亚洲精品午夜久久aaa级久久久 | 天堂中文www在线 | 天天做天天玩天天爽天天 | 午夜三级福利 | 欧美12一13高清视频 | 精品xxxxxbbbb欧美中文 | 日本免费看黄 | 中文字幕一区二区三区免费看 | 亚洲国产高清人在线 | 国产亚洲视频在线 | 午夜影皖普通区 | 国产精品久久久久久久成人午夜 | 特黄色毛片 |