色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

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

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

3天內不再提示

在單片機中引入面向對象的思想

strongerHuang ? 來源:果果小師弟 ? 作者:果果小師弟 ? 2021-11-01 11:36 ? 次閱讀

在看別人單片機程序時,你也許是奔潰的,因為全局變量滿天飛,不知道哪個在哪用了,哪個表示什么,而且編寫極其不規范。自己寫單片機程序時,也許你也是奔潰的。總感覺重新開啟一個項目,之前的寫過相似的代碼也無法使用,得重新敲,代碼重用度不高,編程效率低下,代碼無法積累。而且感覺寫這個代碼沒有思想,沒有靈魂,沒有框架,只是一個一個功能代碼的堆砌,很空泛。

那么這個時候,你也許應該在單片機中引入面向對象的思想了,使代碼更規范。

一、單片機程序框架

1、輪流執行

intmain(void)
{
while(1)
{
sing();
dance();
play();
}
}

函數sing執行的時間比較長的話,函數dance就不能很快的被執行。任何一個函數死掉的話就會影響整個系統。

2、前后臺

在使用 51、AVR、STM32 單片機裸機的時候一般都是在main函數里面用while(1)做一個大循環來完成所有的處理,即應用程序是一個無限的循環,循環中調用相應的函數完成所需的處理。有時候我們也需要中斷中完成一些處理。相對于多任務系統而言,這個就是單任務系統,也稱作前后臺系統,中斷服務函數作為前臺程序,大循環while(1)作為后臺程序。

對應的編程代碼大概是這樣的:

voidEXTI_IRQHandler()
{
flag=1;
}
intmain(void)
{
while(1)
{
if(flag=1)
{
do_something();
flag=0;
}
}
}

有什么問題?

前后臺系統的實時性差,前后臺系統各個任務(應用程序)都是排隊等著輪流執行,不管你這個程序現在有多緊急,沒輪到你就只能等著!相當于所有任務(應用程序)的優先級都是一樣的。但是前后臺系統簡單啊,資源消耗也少啊!在稍微大一點的嵌入式應用中前后臺系統就明顯力不從心了。

3、多任務

voidfirst_task()
{
while(1)
{
if(has_data())
put_data();
}
}
voidsecond_task()
{
while(1)
{
if(get_data())
do_something();
}
}

intmain(void)
{
create_task(first_task);
create_task(second_task);
start_scheduler();
}

多任務系統會把一個大問題“分而治之”,把大任務劃分成很多個小問題,逐步的把小任務解決掉,大任務也就隨之解決了,這些任務是并發處理的。注意,并不是說同一時刻一起執行很多個任務,而是由于每個任務執行的時間很短,導致看起來像是同一時刻執行了很多個任務一樣。

二、執行的程序怎么寫?

以按鍵為例,點亮一個小燈!

1.常規寫法

intmian(void)
{
while(1)
{
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_3)==GPIO_PIN_SET)
{
printf("按鍵按下
");
}
}
}

2.面向對象的寫法

首先我們把每一個按鍵都看成一個對象,既然是對象就肯定有屬性和行為,比如我們定義一個學生,那么這個學生有什么屬性呢?

肯定有姓名、年齡、身高、體重對吧,這些是一些基本的屬性,我們可以用一些單獨的變量來定義它,比如:

typedefstruct
{
uint8_t*name;//姓名(變量)
uint8_tage;//年齡(變量)
uint8_theight;//身高(變量)
uint8_tweight;//體重(變量)
}student_t;

但是一個學生還有很多行為對吧,它會唱歌、跳舞、打籃球、也會關注果果小師弟的公眾號對吧,于是我們就可以這樣定義:

typedefstruct
{
uint8_t*name;//姓名(變量)
uint8_tage;//年齡(變量)
uint8_theight;//身高(變量)
uint8_tweight;//體重(變量)
void(*Sing_song)(void);//會唱歌(函數指針)
void(*Dance_latin)(void);//會跳舞(函數指針)
void(*Wechat_zhiguoxin)(void);//會關注果果的公眾號(函數指針)
}student_t;

好了,這里我們提到了函數指針,所以就來說一說函數指針。

函數指針,顧名思義它就是一個指針,只不過它是一個函數指針,所以指向的是一個函數。類比一般的變量指針,指針變量,實質上是一個變量,只不過這個變量存放的是一個地址,在32位單片機中,任何類型的指針變量都存放的是一個大小為4字節的地址。

重要的話說三遍!牢記在心!!!為什要記住函數指針,因為在單片機面向對象編程中,結構體的成員不是變量就是函數指針這兩種類型。變量就不用說了,函數指針理解就好。

其實函數指針可以類比一般的變量,看下面:

inta;voidSing_song(void);
int*p;void(*zhiguoxin)(void);
p=&a;zhiguoxin=&Sing_song;
  1. 左邊走義變量a,右邊定義函數Sing_song;
  2. 左邊定義int指針,右邊定義函數指針;
  3. 左邊賦值指針,右邊賦值函數指針;

那么函數指針怎么用呢?我們還是以單片機為例,把按鍵類比為一個對象,這個按鍵有按鍵標志位,有長按或者短按,按鍵還有行為:按鍵初始化、按鍵循環檢測等。

所以我們創建下面這樣一個結構體,當然這個結構體不一定僅僅有這些變量和函數,這完全取決于你自己的定義,你想怎么定義就怎么定義,你甚至可以定義按鍵的顏色都。

typedefstruct
{
uint8_tKEY_Flag;//標志位(變量)
uint8_tClick;//按下(變量)
void(*KEY_Init)(void);//按鍵初始化(函數指針)
void(*KEY_Detect)(void);//按鍵檢測(函數指針)
}KEY_t;

現在已經定義了KEY_t這種類型的結構體,處理器還沒有分配給這個結構體內存,因為我們只是聲明這樣一個類型,而類型是不占用內存的,只有我們定義對應的結構體類型的變量時才會在占用內存空間

那么怎么定義一個結構體類型的變量呢?

KEY_tKEY1;

然后就要初始化結構體的成員變量了。

KEY_tKEY1={0,0,KEY_init,KEY_detect};

這里要注意了現在結構體有四個成員,前兩個普通的變量,我們初始化為0,還有兩個函數指針,我們是不是要把我們想寫得函數的函數名字放在這里啊。

那么聰明的你肯定知道還要定義KEY_init();KEY_detect();這兩個函數。這兩個函數可以這樣寫。

staticvoidKEY_init()
{
GPIO_InitTypeDefGPIO_InitStruct;
GPIO_InitStruct.Pin=GPIO_PIN_3;
GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull=GPIO_NOPULL;
GPIO_InitStruct.Speed=GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);
}
staticvoidKEY_detect()
{
uint8_ti=0;
if(KEY1.KEY_Flag==1)
{
HAL_Delay(100);
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_3)==GPIO_PIN_SET)
{
printf("按鍵按下
");
}
KEY1.KEY_Flag=0;
}
}

好了具體函數中的代碼我就不需要解釋了。這樣一個按鍵的對象我們就定義好了,這個按鍵我們賦予了"他"生命,有屬性(變量)有行為(函數)

這樣我們在主函數就可以這樣的調用,來實現相應的功能了。按鍵使用了中斷,這里并沒有講解。

voidmain(void)
{
KEY1.KEY_Init();//初始化按鍵
while(1)
{
KEY1.KEY_Detect();//按鍵檢測
}
}

如果理解了這些,那么面向對象的精髓你基本已經掌握了,接下來就是不斷地去練習和實踐了。

三、為什么要面向對象?

我們知道,現有的編程范式主要是:面向過程編程、面向對象編程、函數式編程。

對于流程清晰的簡單程序,一般只有一條流程主線,很容易被劃分成順序執行的幾個步驟,面向對象編程和面向過程編程沒有太大差別,并且面向過程編程常常比面向對象編程更加直觀高效。

但當我們面對一個大型的復雜程序,由于其錯綜復雜的流程和交互關系,很難將其簡單地拆分成一條主線串成的簡單步驟,而通常表現為一個網狀關系結構。這個時候,面向過程編程的這種流程化和線性化的思維方式就會顯得比較吃力,而面向對象編程的優勢就比較明顯了。

面向對象編程風格的代碼更容易復用、擴展和維護、更高級、更人性化、更適合大規模復雜程序的開發。在Linux中就是用的面向對象編程,里面有很多的結構體、指針、鏈表等等。如果還沒有接觸到面向對象編程只能說明你做的東西還不夠復雜。

在單片機舉一個例子,一塊開發板可能會適配不同的屏幕:

那么每一塊板子肯定有不同的代碼適配,在程序中我們可以讀出屏幕的ID,然后通過if判斷來執行不同的指令,就行這樣。

如果使用面向對象編程,那么就可以這樣寫代碼。

typedefstructlcd{
uint8_ttype;
void(*LCD_Init)(void)
}lcd_t,*plcd_t;

intRead_id()
{
/*0:LCDA
*1:LCDB
*/
return0;
}

intGet_Lcd_Type(void)
{
returnRead_id();
}

voidLCDA_Init(void)//屏幕A初始化
{
LCD_WR_REG(0xCF);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0xC1);
LCD_WR_DATA(0X30);
}

voidLCDB_Init(void)//屏幕B初始化
{
LCD_WR_REG(0X11);
delay_ms(20);
LCD_WR_REG(0XD0);
LCD_WR_DATA(0X07);
}

lcd_topenedv_com_lcds[]={
{0,LCDA_Init},
{1,LCDB_Init},
};

plcd_tget_lcd(void)//獲取到屏幕類型
{
inttype=Get_Lcd_Type();
return&openedv_com_lcds[type];
}

intmain(void)
{
plcd_tlcd;
lcd=get_lcd();//獲取到屏幕類型
lcd->LCD_Init();//初始化對應屏幕
while(1)
{}
}

這里只是偽代碼處理辦法,原理就和上面所講的一樣,在結構體中使用變量和函數。

到這里你應該掌握了面向對象得單片機編程方法,一起來試驗幾個例子:

LED

typedefstruct
{
void(*LED_ON)(uint8_tLED_Num);//打開
void(*LED_OFF)(uint8_tLED_Num);//關閉
void(*LED_Flip)(uint8_tLED_Num);//翻轉
}LED_t;

按鍵KEY

typedefstruct
{
uint8_tKEY_Flag;//標志位(變量)
uint8_tClick;//按下(變量)
void(*KEY_Init)(void);//按鍵初始化(函數指針)
void(*KEY_Detect)(void);//按鍵檢測(函數指針)
}KEY_t;

蜂鳴器BEEP

typedefstruct
{
uint8_tStatus;//狀態
void(*ON)(void);//打開
void(*OFF)(void);//關閉
}BEEP_t;

串口UART

typedefstruct
{
USART_TypeDef*uart;/*STM32內部串口設備指針*/
uint8_t*pTxBuf;/*發送緩沖區*/
uint8_t*pRxBuf;/*接收緩沖區*/

uint16_tusTxBufSize;/*發送緩沖區大小*/
uint16_tusRxBufSize;/*接收緩沖區大小*/

uint16_tusTxWrite;/*發送緩沖區寫指針*/
uint16_tusTxRead;/*發送緩沖區讀指針*/
uint16_tusTxCount;/*等待發送的數據個數*/

uint16_tusRxWrite;/*接收緩沖區寫指針*/
uint16_tusRxRead;/*接收緩沖區讀指針*/
uint16_tusRxCount;/*還未讀取的新數據個數*/

void(*RS485_Set_SendMode)(void);//RS-485接口設置為發送模式
void(*RS485_Set_RecMode)(void);//RS-485接口設置為接收模式
}UART_T;

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

    關注

    6037

    文章

    44563

    瀏覽量

    635876
  • 程序
    +關注

    關注

    117

    文章

    3788

    瀏覽量

    81095
  • 代碼
    +關注

    關注

    30

    文章

    4791

    瀏覽量

    68686

原文標題:分享幾點單片機面向對象思想的案例

文章出處:【微信號:strongerHuang,微信公眾號:strongerHuang】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    單片機Debug工具性能對比 單片機調試常用命令

    單片機(Microcontroller Unit, MCU)調試是嵌入式開發的一個重要環節,它幫助開發者發現和修復代碼的錯誤,優化程序性能。不同的單片機和開發環境可能使用不同的調試
    的頭像 發表于 12-19 09:56 ?279次閱讀

    51單片機為什么很少出現printf的身影

    51單片機為什么很少出現 printf 的身影?是用不了嗎? 不是的,51單片機可以用 printf,只是不建議使用。 平時我們操作系統上寫C語言代碼,使用 printf 可以把數
    的頭像 發表于 12-03 10:46 ?350次閱讀
    51<b class='flag-5'>單片機</b><b class='flag-5'>中</b>為什么很少出現printf的身影

    基于狀態面向對象思想設計按鍵檢測模塊

    嵌入式入門學習的教程里面,按鍵原理普遍被認為是“很簡單”的知識點之一,按鍵輸入檢測的原理,無非就是通過CPU不斷掃描按鍵引腳的電平狀態,或者采用單片機引腳外部中斷方式,然后死循環或者中斷服務程序里面處理按鍵被按下
    的頭像 發表于 11-14 11:44 ?258次閱讀
    基于狀態<b class='flag-5'>機</b>和<b class='flag-5'>面向</b><b class='flag-5'>對象</b>的<b class='flag-5'>思想</b>設計按鍵檢測模塊

    單片機物聯網的作用

    隨著技術的飛速發展,物聯網已經成為連接物理世界與數字世界的橋梁。物聯網設備通過互聯網相互連接,實現數據的收集、處理和傳輸,從而提高效率、降低成本并增強用戶體驗。在這一過程單片機作為物聯網設備
    的頭像 發表于 11-01 14:27 ?608次閱讀

    如何優化單片機項目的功耗

    現代電子設計,功耗優化已成為一個不可忽視的重要議題。對于單片機(MCU)項目而言,功耗不僅關系到產品的能效比,還直接影響到電池壽命和熱管理。 硬件層面的功耗優化 1. 選擇合適的單片機
    的頭像 發表于 11-01 14:16 ?374次閱讀

    單片機工業自動化的應用

    用電器、汽車電子和工業控制系統。工業自動化單片機因其可靠性、靈活性和成本效益而受到青睞。 2. 單片機的特點 低成本 :單片機的價格相
    的頭像 發表于 11-01 14:15 ?331次閱讀

    單片機怎么寫入程序

    單片機(Microcontroller Unit,MCU)是一種集成電路芯片,它將計算機的CPU、存儲器、輸入/輸出接口等功能集成一個芯片上。單片機廣泛應用于嵌入式系統和物聯網設備
    的頭像 發表于 10-21 11:21 ?504次閱讀

    單片機的中斷機制

    單片機的中斷機制是一種重要的處理方式,它允許單片機執行主程序的過程,能夠暫停當前任務,轉而處理外部或內部緊急事件。這種機制極大地提高了系統的響應速度和處理能力,使得
    的頭像 發表于 10-17 18:03 ?761次閱讀

    單片機異常復位的原因

    單片機異常復位是指單片機正常工作過程,非預期地返回到初始狀態或重啟。這種異常復位現象可能由多種因素引起,以下是對單片機異常復位原因的詳細
    的頭像 發表于 10-17 17:56 ?1004次閱讀

    單片機STM32可以用Python寫嗎?可以的開發板有哪些?

    近年來,隨著嵌入式技術的發展,Python語言逐漸被引入單片機開發,尤其是一些高性能的單片機上。這一趨勢給開發者帶來了極大的便利,尤其是
    的頭像 發表于 09-05 08:00 ?3608次閱讀
    <b class='flag-5'>單片機</b>STM32可以用Python寫嗎?可以的開發板有哪些?

    單片機燒錄程序的基本步驟是什么

    單片機燒錄程序是單片機開發過程中非常重要的一步,它涉及到將編寫好的程序代碼通過一定的方式傳輸到單片機內部的存儲器,使單片機能夠按照預定的邏
    的頭像 發表于 09-02 09:47 ?1113次閱讀

    單片機復位電路的電容是什么電容?

    單片機復位電路的電容是一種特殊類型的電容,通常被稱為“去耦電容”或“旁路電容”。這種電容的主要作用是單片機的電源線路中提供一個低阻抗的路徑,以便在電源電壓發生瞬變時,能夠迅速地吸收
    的頭像 發表于 08-06 10:31 ?812次閱讀

    fpga和單片機的區別

    FPGA和單片機多個方面存在顯著的差異:
    的頭像 發表于 03-14 16:30 ?5154次閱讀

    PIC單片機振蕩電路如何選擇晶體?

    PIC單片機振蕩電路如何選擇晶體? PIC單片機振蕩電路中選擇晶體是一個重要的步驟,它直接影響到系統的穩定性和性能。本文將詳細介紹如何
    的頭像 發表于 01-31 09:28 ?638次閱讀

    單片機中斷功能及其應用

    事件的響應和處理。它具有實時性好、可靠性高、效率高等優點,廣泛應用于各種電子設備和系統。 一、單片機中斷的基本概念 單片機中斷是一種可以程序執行的任何地方改變程序的正常執行的功能。
    的頭像 發表于 01-30 14:45 ?5525次閱讀
    主站蜘蛛池模板: 一本色道久久综合一区| 国产国拍亚洲精品永久软件| 回复术士勇者免费观看全集| 亚洲综合日韩中文字幕v在线| 花蝴蝶高清影视视频在线播放| 一个人色导航| 欧美乱妇15p图| 国产黄A片在线观看永久免费麻豆| 亚洲AV蜜桃永久无码精品红樱桃| 久久777国产线看观看精品卜| 999久久狠狠免费精品| 神马午夜不卡片| 久久免费看少妇高潮A片JA | 我要搞av| 久久精品嫩草影院免费看| 87.6在线收听| 色戒在线完整观看在线播放版| 黄色毛片a| 成人国产在线不卡视频| 亚洲无码小格式| 日本大片免a费观看视频| 精品午夜国产福利观看| 冰山高冷受被c到哭np双性| 亚洲偷自拍精品视频在线观看| 人妻夜夜爽99麻豆AV| 久久99国产精品无码AV| 高hnp全肉| 99热这里精品| 一本之道高清www在线观看| 日韩精品熟女一区二区三区中文| 花蝴蝶高清影视视频在线播放| 成人国产在线看不卡| 1区2区3区4区产品不卡码网站| 香蕉尹人综合精品| 全黄h全肉细节文在线观看| 久久综合丁香激情久久| 国产午夜福利100集发布| 大肥女ass樱桃| 2021国产精品一卡2卡三卡4卡| 亚洲国产综合另类视频| 色偷偷在线视频|