0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

什么是TVOS?

訊維官方公眾號(hào) ? 來源:訊維官方公眾號(hào) ? 作者:訊維官方公眾號(hào) ? 2022-09-09 14:23 ? 次閱讀

這是我國(guó)自主研發(fā)推出的新一代具有自主知識(shí)產(chǎn)權(quán)、可管可控、安全高效、開放兼容的智能電視操作系統(tǒng)

TVOS 2.0是由國(guó)家新聞出版廣電總局廣科院、華為技術(shù)有限公司、阿里巴巴集團(tuán)、中興通信股份有限公司、國(guó)廣東方網(wǎng)絡(luò)(北京)有限公司、深圳創(chuàng)維一RGB電子有限公司、東方有線網(wǎng)絡(luò)有限公司、江蘇省廣電有線信息網(wǎng)絡(luò)股份有限公司、陜西廣電網(wǎng)絡(luò)傳媒(集團(tuán))股份有限公司、湖南省有線電視網(wǎng)絡(luò)(集團(tuán))股份有限公司等60多家TVOS工作組成員單位在國(guó)家十三五規(guī)劃大力實(shí)施網(wǎng)絡(luò)強(qiáng)國(guó)戰(zhàn)略,互聯(lián)網(wǎng)+行動(dòng)計(jì)劃,發(fā)展積極向上的網(wǎng)絡(luò)文化,促進(jìn)互聯(lián)網(wǎng)和經(jīng)濟(jì)社會(huì)融合發(fā)展的大背景下,以創(chuàng)新的產(chǎn)學(xué)研用聯(lián)合攻關(guān)機(jī)制,在TVOS 1.0與華為MediaOS和阿里巴巴YunOS融合的基礎(chǔ)上,打造的我國(guó)自主創(chuàng)新、安全可靠的新一代智能電視操作系統(tǒng)。

TVOS 2.0將對(duì)行業(yè)產(chǎn)業(yè)化規(guī)模應(yīng)用起到積極的推動(dòng)作用,用戶將足不出戶享受安全、便捷、可靠的智能電視操作所帶來的科技發(fā)展成果,作為牌照運(yùn)營(yíng)方,由國(guó)廣東方運(yùn)營(yíng)的CIBN互聯(lián)網(wǎng)電視平臺(tái)肩負(fù)可管可控、合法合規(guī)的行業(yè)監(jiān)管重任,其旗下自有終端公司環(huán)球智達(dá)科技(北京)有限公司(簡(jiǎn)稱“環(huán)球智達(dá)”)推出了行業(yè)第一家支持 TVOS的互聯(lián)網(wǎng)電視機(jī)頂盒CANbox超能云盒,成為行業(yè)先行標(biāo)桿企業(yè)和品牌。

TVOS是一個(gè)開源系統(tǒng),對(duì)于電視的意義就像Android對(duì)于手機(jī),有了TVOS,人們同樣可以在智能電視終端上開發(fā)基于TVOS的應(yīng)用程序,使觀眾從“看電視”到“用電視”的方向更進(jìn)了一步。

TVOS可實(shí)現(xiàn)諸如智能人機(jī)交互、電子支付、智慧家庭一智能家居、智能人機(jī)交互一無縫體驗(yàn)現(xiàn)有的觸屏游戲、視頻通信和社交應(yīng)用等功能。

審核編輯 :李倩

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 人機(jī)交互
    +關(guān)注

    關(guān)注

    12

    文章

    1217

    瀏覽量

    55499
  • 操作系統(tǒng)
    +關(guān)注

    關(guān)注

    37

    文章

    6889

    瀏覽量

    123653
  • tvOS
    +關(guān)注

    關(guān)注

    0

    文章

    9

    瀏覽量

    3686

原文標(biāo)題:什么是TVOS??

文章出處:【微信號(hào):xunwei201508,微信公眾號(hào):訊維官方公眾號(hào)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    【瑞薩RA2L1入門學(xué)習(xí)】05、待機(jī)模式按鍵外部中斷喚醒 低功耗測(cè)試

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

    【瑞薩RA2L1入門學(xué)習(xí)】1. 點(diǎn)亮LED

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

    關(guān)于用Labview編寫壓機(jī)軟件

    我想請(qǐng)教一下,我如果想實(shí)現(xiàn)如下圖這樣,在xy圖上有力判定點(diǎn)該如何做到呢
    發(fā)表于 01-29 19:12

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

    我要:李想STM32開發(fā)板(LX-1ATFT)的軟件(包括燒寫、相關(guān)支持等軟件,不要視頻)。我曾經(jīng)買過他硬件,當(dāng)時(shí)沒空,現(xiàn)在想學(xué),又沒有資料及網(wǎng)站了。先謝謝!
    發(fā)表于 01-29 17:12

    【瑞薩RA2L1入門學(xué)習(xí)】04、I2C驅(qū)動(dòng)OLED屏幕 BME280傳感器

    1.前言 本次實(shí)驗(yàn)的目標(biāo)是把I2C相關(guān)的搞定,再嘗試驅(qū)動(dòng)SSD1306 0.96寸OLED屏幕以及BME280傳感器,最后將傳感器讀到的數(shù)據(jù)和實(shí)時(shí)時(shí)間顯示在屏幕上。 2,硬件部分 2.1 I2C協(xié)議簡(jiǎn)介 I2C 通訊協(xié)議(Inter-Integrated Circuit)是由Philips公司開發(fā)的,由于它引腳少,硬件實(shí)現(xiàn)簡(jiǎn)單,可擴(kuò)展性強(qiáng), 不需要USART、CAN等通訊協(xié)議的外部收發(fā)設(shè)備,現(xiàn)在被廣泛地使用在系統(tǒng)內(nèi)多個(gè)集成電路(IC)間的通訊。 在計(jì)算機(jī)科學(xué)里,大部分復(fù)雜的問題都可以通過分層來簡(jiǎn)化。如芯片被分為內(nèi)核層和片上外設(shè); 瑞薩的FPS庫(kù)則是在寄存器與用戶代碼之間的軟件層。對(duì)于通訊協(xié)議,我們也以分層的方式來理解, 最基本的是把它分為物理層和協(xié)議層。物理層規(guī)定通訊系統(tǒng)中具有機(jī)械、電子功能部分的特性,確保原始數(shù)據(jù)在物理媒體的傳輸。 協(xié)議層主要規(guī)定通訊邏輯,統(tǒng)一收發(fā)雙方的數(shù)據(jù)打包、解包標(biāo)準(zhǔn)。簡(jiǎn)單來說物理層規(guī)定我們用嘴巴還是用肢體來交流, 協(xié)議層則規(guī)定我們用中文還是英文來交流。 具體的I2C協(xié)議入門可以看TI的A Basic Guide to I2C - Texas Instruments 2.2 OLED屏幕 本次使用的屏幕是0.96寸 4針 I2C協(xié)議 OLED屏幕,其驅(qū)動(dòng)IC為SSD1306,屏幕分辨率為128x64。 編程時(shí)參考的數(shù)據(jù)手冊(cè),以及基于商家給的STM32驅(qū)動(dòng)庫(kù)修改,具體的修改參考軟件部分。 2.3 BME280溫濕度氣壓傳感器 BME280是一款由Bosch Sensortec開發(fā)的多功能環(huán)境傳感器,可同時(shí)精確測(cè)量溫度、濕度和氣壓,具有低功耗和小尺寸的特點(diǎn),廣泛應(yīng)用于氣象監(jiān)測(cè)、室內(nèi)導(dǎo)航、健康監(jiān)測(cè)及物聯(lián)網(wǎng)等領(lǐng)域。 3.軟件部分 將先前03_RTC工程復(fù)制一份,重命名為04_OLED_BME280-I2C。 3.1 配置I2C 首先在e2s內(nèi)配置I2C 序號(hào) 操作 1 點(diǎn)擊界面下方標(biāo)簽欄中的Pins標(biāo)簽,進(jìn)入引腳配置界面。 2 在Pin Selection區(qū)域,展開Connectivity:I2C選項(xiàng),選擇I2C0。 3 在Pin Configuration區(qū)域,將Pin Group Selection設(shè)置為_A only,Operation Mode設(shè)置為Enabled。 4 勾選SDA0對(duì)應(yīng)的P401引腳和SCL0對(duì)應(yīng)的P400引腳。 序號(hào) 操作 1 在Pin Selection區(qū)域,分別選擇P400和P401引腳。 2 將Output type設(shè)置為n-ch open drain,把P400和P401配置成開漏輸出。 序號(hào) 操作 1 點(diǎn)擊界面下方標(biāo)簽欄中的Stacks標(biāo)簽,進(jìn)入堆棧配置頁(yè)面。 2 在HAL/Common Stacks區(qū)域,點(diǎn)擊New Stack按鈕。 3 在彈出菜單中,選擇Connectivity選項(xiàng)。 4 在Connectivity子菜單中,選擇I2C Master (r_iic_master)。 序號(hào) 操作 1 在HAL/Common Stacks區(qū)域,點(diǎn)擊選中g(shù)_i2c_master0 I2C Master (r_iic_master)。 2 在下方Settings設(shè)置區(qū)域的Module g_i2c_master0 I2C Master (r_iic_master)部分,將Rate設(shè)置為Fast-mode。 3 Module g_i2c_master0 I2C Master (r_iic_master)部分,設(shè)置Slave Address為0x3c。 4 Module g_i2c_master0 I2C Master (r_iic_master)部分,設(shè)置Callback為iic_callback,Interrupt Priority Level為Priority 2。 這里說明一下,在移植商家給的STM32 OLED驅(qū)動(dòng)庫(kù)時(shí)看到屏幕地址為0x78,即 01111000,是包含讀寫位的(最低位)。而瑞薩這里是7位地址,不含讀寫位,因此要將0x78右移1位,即0x3C (0111100)。 確認(rèn)上面設(shè)置沒問題后,生成項(xiàng)目代碼。 2 編寫代碼 2.1 I2C通信相關(guān) 新建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庫(kù)的高集成度,我只需要編寫代碼實(shí)現(xiàn)回調(diào)函數(shù)iic_callback、等待發(fā)送函數(shù)i2c_wait_tx、等待接收i2c_wait_rx函數(shù)改變標(biāo)志位即可。 3.2.2 BME280操作相關(guān) 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) { //臨時(shí)設(shè)置I2C從機(jī)地址為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; // 設(shè)置濕度采集的寄存器 0xF2 write_settings[1] = 0x05; // 00000 101 濕度 oversampling x16 write_settings[2] = 0xF4; // 設(shè)置溫度采集、氣壓采集、工作模式的寄存器 0xF4 write_settings[3] = 0x93; // 100 100 11 溫度和氣壓 oversampling x8,模式為normal write_settings[4] = 0xF5; // 配置config寄存器 write_settings[5] = 0x10; // 000 100 0 0 ,配置濾波器系數(shù)為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); // 校準(zhǔn)數(shù)據(jù) 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); // 適當(dāng)加延遲否則數(shù)據(jù)錯(cuò)誤 reg = 0xA1; BME280_Write_then_Read(&reg, 1, &data[24], 1); R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS); // 適當(dāng)加延遲否則數(shù)據(jù)錯(cuò)誤 reg = 0xE1; BME280_Write_then_Read(&reg, 1, &data[25], 7); R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS); // 適當(dāng)加延遲否則數(shù)據(jù)錯(cuò)誤 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這三個(gè)函數(shù)分別為溫度、濕度、氣壓的補(bǔ)償算法函數(shù),借鑒了BME280官方數(shù)據(jù)手冊(cè)內(nèi)給出的參考代碼。 bme280工作流程為 步驟 內(nèi)容 1 上電初始化 2 寫入0xF2、0xF4、0xF5寄存器以設(shè)定過采樣率等參數(shù) 3 獲取校準(zhǔn)數(shù)據(jù) 4 調(diào)用BME280_Get_Data函數(shù),讀取0xF7~0xFE寄存器的數(shù)據(jù) 5 調(diào)用補(bǔ)償算法函數(shù)得到人類可讀的數(shù)值 :::warning 注意 在寫入+讀取函數(shù)后記得跟1~5ms的延時(shí),再進(jìn)行下一步操作,否則會(huì)因?yàn)閎me280側(cè)的數(shù)據(jù)未準(zhǔn)備好,有極大概率讀取到錯(cuò)誤數(shù)據(jù)或讀不到數(shù)據(jù)。 ::: 3.2.3 OLED屏幕操作相關(guān) oled.h: ::: details 查看代碼 #ifndef OLED_H_ #define OLED_H_ #include \"hal_data.h\" #define OLED_CMD 0// 寫命令 #define OLED_DATA 1 // 寫數(shù)據(jù) 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]; // 反顯函數(shù) void OLED_ColorTurn(uint8_t i) { if (i == 0) { OLED_WR_Byte(0xA6, OLED_CMD); // 正常顯示 } if (i == 1) { OLED_WR_Byte(0xA7, OLED_CMD); // 反色顯示 } } // 屏幕旋轉(zhuǎn)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); // 反轉(zhuǎn)顯示 OLED_WR_Byte(0xA0, OLED_CMD); } } // 發(fā)送一個(gè)字節(jié) // mode:數(shù)據(jù)/命令標(biāo)志 0,表示命令;1,表示數(shù)據(jù); 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); // 點(diǎn)亮屏幕 } // 關(guān)閉OLED顯示 void OLED_DisPlay_Off(void) { OLED_WR_Byte(0x8D, OLED_CMD); // 電荷泵使能 OLED_WR_Byte(0x10, OLED_CMD); // 關(guān)閉電荷泵 OLED_WR_Byte(0xAE, OLED_CMD); // 關(guān)閉屏幕 } // 更新顯存到OLED void OLED_Refresh(void) { uint8_t i, n; for (i = 0; i < 8; i++) { OLED_WR_Byte(0xb0 + i, OLED_CMD); // 設(shè)置行起始地址 OLED_WR_Byte(0x00, OLED_CMD);// 設(shè)置低列起始地址 OLED_WR_Byte(0x10, OLED_CMD);// 設(shè)置高列起始地址 for (n = 0; n < 128; n++) { OLED_WR_Byte(OLED_GRAM[n][i], OLED_DATA); } } } // 清屏函數(shù) 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; // 清除所有數(shù)據(jù) } } OLED_Refresh(); // 更新顯示 } // 畫點(diǎn) // 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:起點(diǎn)坐標(biāo) // x2,y2:結(jié)束坐標(biāo) 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; // 計(jì)算坐標(biāo)增量 delta_y = y2 - y1; uRow = x1; // 畫線起點(diǎn)坐標(biāo) uCol = y1; if (delta_x > 0) incx = 1; // 設(shè)置單步方向 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; // 選取基本增量坐標(biāo)軸 else distance = delta_y; for (t = 0; t < distance + 1; t++) { OLED_DrawPoint(uRow, uCol, mode); // 畫點(diǎn) xerr += delta_x; yerr += delta_y; if (xerr > distance) { xerr -= distance; uRow += incx; } if (yerr > distance) { yerr -= distance; uCol += incy; } } //OLED_Refresh(); } // x,y:圓心坐標(biāo) // 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; // 計(jì)算畫的點(diǎn)離圓心的距離 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; // 計(jì)算字符的字節(jié)數(shù) if (size1 == 8) size2 = 6; else size2 = (size1 / 8 + ((size1 % 8) ? 1 : 0)) * (size1 / 2); // 字體占用的字節(jié)數(shù) chr1 = chr - \' \'; // 偏移字符值,轉(zhuǎn)換為數(shù)組索引 for (i = 0; i < size2; i++) { // 根據(jù)字體大小選擇相應(yīng)的字模 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)); // 設(shè)置顯存中的點(diǎn) else OLED_GRAM[x][y / 8] &= ~(1 << (y % 8)); // 清除顯存中的點(diǎn) temp >>= 1; y++; } x++; if ((size1 != 8) && ((x - x0) == size1 / 2)) { x = x0; y0 = y0 + 8; } y = y0; } } // 顯示字符串 // x,y:起點(diǎn)坐標(biāo) // 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; } // 顯示數(shù)字 // x,y :起點(diǎn)坐標(biāo) // num :要顯示的數(shù)字 // len :數(shù)字的位數(shù) // 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; // 計(jì)算一個(gè)字符對(duì)應(yīng)的字節(jié)數(shù) uint8_t mask; // 用來構(gòu)造顯示的掩碼 for (i = 0; i < size3; i++) { if (size1 == 16) { temp = Hzk1[num][i]; // 獲取字形數(shù)據(jù) } else { return; // 只處理 16x16 字體 } for (m = 0; m < 8; m++) { mask = (1 << (y % 8)); // 根據(jù)當(dāng)前 y 坐標(biāo)計(jì)算掩碼 if (temp & 0x01) // 當(dāng)前位為 1 { OLED_GRAM[x][y / 8] |= mask; // 設(shè)置該位 } else // 當(dāng)前位為 0 { OLED_GRAM[x][y / 8] &= ~mask; // 清除該位 } temp >>= 1; // 右移,處理下一個(gè)像素 y++;// 縱向位置移動(dòng) } x++; // 橫向位置移動(dòng) // 判斷是否換行 if ((x - x0) == size1) { x = x0; y0 = y0 + 8; // 換行時(shí),y 坐標(biāo)增加 8 } y = y0; // 恢復(fù) y 坐標(biāo) } // 最后刷新整個(gè)顯示屏 OLED_Refresh(); } // num 顯示漢字的個(gè)數(shù) // 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); // 寫入一個(gè)漢字保存在OLED_GRAM[][]數(shù)組中 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++) // 實(shí)現(xiàn)左移 { for (n = 0; n < 8; n++) { OLED_GRAM[i - 1][n] = OLED_GRAM[i][n]; } } OLED_Refresh(); } } // x,y:起點(diǎn)坐標(biāo) // sizex,sizey,圖片長(zhǎng)寬 // BMP[]:要寫入的圖片數(shù)組 // 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 關(guān)閉顯示 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) 設(shè)置驅(qū)動(dòng)路數(shù) 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屏幕上顯示字的速度非常慢,幾乎是一個(gè)字一個(gè)字地往外蹦。 解決方法是開一個(gè)顯存數(shù)組OLED_GRAM ,將內(nèi)容先緩存到顯存數(shù)組,再調(diào)用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函數(shù)中加入 ::: details 查看代碼 Debug_UART9_Init(); // SCI9 UART 調(diào)試串口初始化 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獲取溫濕度實(shí)驗(yàn)\\\\n\"); printf(\"若要通過串口設(shè)置時(shí)間,請(qǐng)輸入類似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 計(jì)數(shù)時(shí)間 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); // 顯示時(shí)分秒 } if (uart_rx_complete_flag) { char *time; uart_rx_complete_flag = 0; // 解析設(shè)置時(shí)間的命令 e.g: time:20250126080910 // warning: 未添加錯(cuò)誤糾正算法,請(qǐng)輸入正確的時(shí)間,否則工作異常! 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(\"若要通過串口設(shè)置時(shí)間,請(qǐng)輸入類似time:20250126080910的字符串\\\\n\"); } } } ::: 這段程序?qū)崿F(xiàn)了每1秒刷新一次OLED屏幕上的時(shí)間和溫濕度氣壓數(shù)據(jù),同時(shí)能從串口接收格式化的數(shù)據(jù)以設(shè)定時(shí)間。 4.下載測(cè)試 把編譯好的程序下載到開發(fā)板并復(fù)位。觀察到OLED屏幕上正確顯示了預(yù)設(shè)的時(shí)間和獲取到的溫濕度氣壓值。 可以打開串口助手,在發(fā)送框輸入 time:20250128235958 工程附件 把代碼全貼上來的話超字?jǐn)?shù)限制了,請(qǐng)下載附件查看完整代碼 *附件:04_OLED_BME280-I2C.zip
    發(fā)表于 01-29 17:09

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

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

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

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

    信號(hào)線電壓不穩(wěn)定原因分析

    在電子設(shè)備和通信系統(tǒng)中,信號(hào)線作為數(shù)據(jù)傳輸?shù)年P(guān)鍵通道,其電壓穩(wěn)定性直接關(guān)系到系統(tǒng)的性能和穩(wěn)定性。當(dāng)信號(hào)線電壓出現(xiàn)不穩(wěn)定現(xiàn)象時(shí),可能會(huì)導(dǎo)致數(shù)據(jù)傳輸錯(cuò)誤、設(shè)備故障甚至系統(tǒng)癱瘓。因此,深入分析信號(hào)線電壓不穩(wěn)定的原因,對(duì)于確保系統(tǒng)的正常運(yùn)行和優(yōu)化性能具有重要意義。本文將從多個(gè)角度探討信號(hào)線電壓不穩(wěn)定的常見原因。
    的頭像 發(fā)表于 01-29 16:47 ?116次閱讀

    蘋果推出tvOS與HomePod 18.2更新

    蘋果推出了 iOS 18.2、iPad OS 18.2、macOS 15.2 Sequoia 等一系列系統(tǒng)更新,同時(shí)還對(duì) tvOS 18.2 和 HomePod 18.2 進(jìn)行了相應(yīng)的升級(jí)。此次
    的頭像 發(fā)表于 12-12 15:24 ?347次閱讀

    蘋果發(fā)布iOS 18、iPadOS 18、macOS Sequoia、watchOS 11和tvOS 18的公開測(cè)試版

    測(cè)試版將為各種蘋果設(shè)備帶不來足夠大的驚喜但依然有用的功能。 iOS 18公開測(cè)試版將帶來iPhone軟件工作方式的關(guān)鍵更新,包括對(duì)RCS消息的支持和新的自定義選項(xiàng),讓用戶可以將應(yīng)用程序放在主屏幕上的任何位置,或者為圖標(biāo)和小部件應(yīng)用顏色。它還帶來了全新的照片應(yīng)用布局、經(jīng)過重新設(shè)計(jì)的、更可定制的控制中心,以及深色模式圖標(biāo)。
    的頭像 發(fā)表于 07-16 09:06 ?462次閱讀
    蘋果發(fā)布iOS 18、iPadOS 18、macOS Sequoia、watchOS 11和<b class='flag-5'>tvOS</b> 18的公開測(cè)試版

    RetroArch iOS模擬器現(xiàn)已發(fā)布,可暢玩多平臺(tái)游戲

    作為第一款公開獲得tvOS認(rèn)證的模擬器,RetroArch讓iPhone、iPad及Apple TV用戶能夠暢玩多種系統(tǒng)的游戲。同時(shí),該模擬器支持MFi手柄,方便用戶在大屏設(shè)備上進(jìn)行游戲體驗(yàn)。
    的頭像 發(fā)表于 05-16 11:08 ?1282次閱讀

    蘋果發(fā)布tvOS 17.5系統(tǒng)更新,注重穩(wěn)定性和性能提升

    據(jù)悉,AppleTV今日正式推出tvOS17.5系統(tǒng)升級(jí),為2021年9月面世的tvOS17操作系統(tǒng)的第五次迭代更新,相較于前一個(gè)版本tvOS17.4的發(fā)布時(shí)間間隔兩個(gè)月。
    的頭像 發(fā)表于 05-14 11:07 ?1283次閱讀

    蘋果Apple TV或?qū)⒋钶d攝像頭,實(shí)現(xiàn)手勢(shì)交互控制

    近期發(fā)布的tvOS 17版本中,蘋果為Apple TV增加了FaceTime應(yīng)用,用戶只需將兼容設(shè)備與之相連,即可利用其后置攝像頭進(jìn)行視頻通話。
    的頭像 發(fā)表于 04-08 11:16 ?476次閱讀

    Apple TV設(shè)備升級(jí)至tvOS 17.4后,遙控器出現(xiàn)兼容問題

    眾多用戶反映,此次受影響的遙控器品牌涵蓋索尼、三星及松下等主流廠商,tvOS 17.4更新似乎與之不適配。經(jīng)IT之家在Reddit社區(qū)及 X評(píng)分網(wǎng)站的調(diào)查發(fā)現(xiàn),這一問題并非孤立存在,但具體受害群體及受影響范圍尚不明確。
    的頭像 發(fā)表于 03-26 10:05 ?859次閱讀

    蘋果HomePod和tvOS更新:默認(rèn)應(yīng)用變更,無法手動(dòng)選擇

    據(jù)蘋果解釋,使用Siri播放音樂時(shí),設(shè)備會(huì)根據(jù)用戶習(xí)慣自動(dòng)選擇默認(rèn)媒體應(yīng)用程序,此外,該更新還有性能和穩(wěn)定性提升。
    的頭像 發(fā)表于 03-05 10:20 ?1011次閱讀