一文讀懂c語言結構體在單片機中的應用
Struck
看到單片機中有很多struck 的應用,但是呢我當初學C語言的時候又沒有很認真的去學習,今天復習下,寫一篇小小的交流,希望能夠給大傢帶來幫助。
1.struck的定義
/***********方式一**********/ struct Book { char title[128]; char aurhor[40]; float price; unsigned int date; char pubilsher[40]; }; /*定義瞭Book這個模板*/ struct Book book1,book2,book3;//使用struct Book這個模板建立瞭一個book1變量 /***********方式二**********/ struct Book { char title[128]; char aurhor[40]; float price; unsigned int date; char pubilsher[40]; }book1,book2,book3; //和方式1的結果相同
2.struck調用
scanf(“%s”,book.title)//使用的.(點)運算符,表示book變量裡的title屬性 scanf(“%s”,&book.price)//數組不需要加取地址符,整型需要
3.struck的初始化
/********方式一*******/ struct Book book1 { “小甲魚帶你學習帶你飛”, “小甲魚”, 48.8, 2017111111, “清華大學出版社”, }; /********方法二*******/ struct Book book1{.price=48.8 };//可以以這種方式定義多種數值
4.struck在單片機中的應用
好的,進入正題。復習瞭struck結構體的基本用法。也就是大傢在課堂上學習的知識之後。我們在單片機的學習以及編譯過程中是如何使用的呢。
void LED_Init(void) { GPIO_InitTypeDef GPIO_Initure; __HAL_RCC_GPIOB_CLK_ENABLE(); //開啟GPIOB時鐘 __HAL_RCC_GPIOE_CLK_ENABLE(); //開啟GPIOE時鐘 GPIO_Initure.Pin=GPIO_PIN_5; //PB5 GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽輸出 GPIO_Initure.Pull=GPIO_PULLUP; //上拉 GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH; //高速 HAL_GPIO_Init(GPIOB,&GPIO_Initure); GPIO_Initure.Pin=GPIO_PIN_5; //PE5 HAL_GPIO_Init(GPIOE,&GPIO_Initure); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET); //PB5置1,默認初始化後燈滅 HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET); //PE5置1,默認初始化後燈滅 }
這是一段led燈的初始化代碼
(進入方式如下,選中LED_Init,右鍵,Go to Defintion of xxxxxx)
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,參考自己的吧]
我們來逐行分析這些代碼
void LED_Init(void) //空函數空返回值,定義瞭一個函數,函數的名字是LED_Init,空形參,空返回值 /***c語言函數部分**/
第一行很簡單沒什麼問題,下一行GPIO_InitTypeDef GPIO_Initure;遇到問題瞭。看不懂
首先打開百度翻譯翻譯下這句話
外鏈圖片轉存失敗,先不給大傢展示圖片。
大概就是GPIO初始化的意思。我們再次右鍵看下,第一個可能是個函數,將後面的這部分定義瞭。
typedef struct { uint32_t Pin; /*!< Specifies the GPIO pins to be configured. This parameter can be any value of @ref GPIO_pins_define */ uint32_t Mode; /*!< Specifies the operating mode for the selected pins. This parameter can be a value of @ref GPIO_mode_define */ uint32_t Pull; /*!< Specifies the Pull-up or Pull-Down activation for the selected pins. This parameter can be a value of @ref GPIO_pull_define */ uint32_t Speed; /*!< Specifies the speed for the selected pins. This parameter can be a value of @ref GPIO_speed_define */ } GPIO_InitTypeDef;
還是和剛剛一樣右鍵然後Go to Defintion of xxxxxx。我們來到瞭這裡,但是全是英文。所以又要借助我們的老朋友瞭,百度翻譯。
/************翻譯之後的**************/ typedef struct { uint32_t Pin; /*指定要配置的GPIO引腳,此參數可以是@ref GPIO_pins_define中的值*/ uint32_t Mode; /*指定所選管腳的工作模式。此參數可以是@ref GPIO\u mode\u define的值*/ uint32_t Pull; /*指定選定接點的上拉或下拉激活。此參數可以是@ref GPIO\u pull\u define的值*/ uint32_t Speed; /*指定選定接點的速度。此參數可以是@ref GPIO\u speed\u define的值*/ } GPIO_InitTypeDef;
我們可以看到這裡的用法與我們c語言中的struck有些類似,但是又有些許的不同。結果是一樣的。
現說結論,他這裡建立瞭一個 GPIO_InitTypeDef的模板。與下列的代碼相似。或者說是結果相同
struct GPIO_InitTypeDef { uint32_t Pin; //uint32_t是定義瞭一個32位的變量,右鍵go to也能找到對應的位置 uint32_t Mode; uint32_t Pull; uint32_t Speed; }; /******************************/ /*******go to之後得到的內容*****/ //typedef unsigned char uint8_t; -->將unsigned char改名為uint8_t //typedef unsigned short int uint16_t; -->將unsigned short int改名為uint16_t //typedef unsigned int uint32_t; -->將unsigned int改名為uint16_t //typedef unsigned __INT64 uint64_t; -->將unsigned __INT64改名為uint64_t /***進行變化之後更方便我們使用時候選取適合字節數的變量名來定義****/
但是他這裡用瞭一個typedef,相當於把這部分重命名瞭方便瞭我們以後的使用。對比下
/******使用純粹的C語言編程*******/ struct GPIO_InitTypeDef { uint32_t Pin; uint32_t Mode; uint32_t Pull; uint32_t Speed; }GPIO_Initure; //或者如下 struct GPIO_InitTypeDef { uint32_t Pin; uint32_t Mode; uint32_t Pull; uint32_t Speed; }; struct GPIO_InitTypeDef GPIO_Initure; /********使用改進後的代碼進行編程******/ typedef struct { uint32_t Pin; /*指定要配置的GPIO引腳,此參數可以是@ref GPIO_pins_define中的值*/ uint32_t Mode; /*指定所選管腳的工作模式。此參數可以是@ref GPIO\u mode\u define的值*/ uint32_t Pull; /*指定選定引腳的上拉或下拉激活。此參數可以是@ref GPIO\u pull\u define的值*/ uint32_t Speed; /*指定選定引腳的速度。此參數可以是@ref GPIO\u speed\u define的值*/ } GPIO_InitTypeDef; //這段代碼放在底層文件中,官方配置的。我們直接調用即可。 GPIO_InitTypeDef GPIO_Initure;//我們自己書寫的函數時使用的 //總的來說是提高瞭代碼的可移植性以及可讀性。
總的來說就是定義瞭一個結構體,方式與我們正常的C語言編程不同而已。結果是一樣的。我們繼續往下看
void LED_Init(void) /***c語言函數部分**/ //空函數空返回值,定義瞭一個函數,函數的名字是LED_Init,空形參,空返回值 { GPIO_InitTypeDef GPIO_Initure; //定義瞭一個名字為GPIO_Initure的結構體,裡面有pin(引腳),mode(工作方式),pull(輸出方式) //speed(輸出速度)幾個屬性的一個結構體 __HAL_RCC_GPIOB_CLK_ENABLE(); //開啟GPIOB時鐘 __HAL_RCC_GPIOE_CLK_ENABLE(); //開啟GPIOE時鐘 //兩個函數,功能如註釋所示 GPIO_Initure.Pin=GPIO_PIN_5; //PB5 GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽輸出 GPIO_Initure.Pull=GPIO_PULLUP; //上拉 GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH; //高速 //使用struck的初始化方式對struck結構體進行瞭初始化 HAL_GPIO_Init(GPIOB,&GPIO_Initure); //這裡又出現瞭一個新的函數HAL_GPIO_Init,我們繼續go to去看下 GPIO_Initure.Pin=GPIO_PIN_5; //PE5 HAL_GPIO_Init(GPIOE,&GPIO_Initure); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET); //PB5置1,默認初始化後燈滅 HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET); //PE5置1,默認初始化後燈滅 }
HAL_GPIO_Init的go to結果(快速翻過即可)
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init) { uint32_t position = 0x00u; uint32_t ioposition; uint32_t iocurrent; uint32_t temp; uint32_t config = 0x00u; __IO uint32_t *configregister; /* Store the address of CRL or CRH register based on pin number */ uint32_t registeroffset; /* offset used during computation of CNF and MODE bits placement inside CRL or CRH register */ /* Check the parameters */ assert_param(IS_GPIO_ALL_INSTANCE(GPIOx)); assert_param(IS_GPIO_PIN(GPIO_Init->Pin)); assert_param(IS_GPIO_MODE(GPIO_Init->Mode)); /* Configure the port pins */ while (((GPIO_Init->Pin) >> position) != 0x00u) { /* Get the IO position */ ioposition = (0x01uL << position); /* Get the current IO position */ iocurrent = (uint32_t)(GPIO_Init->Pin) & ioposition; if (iocurrent == ioposition) { /* Check the Alternate function parameters */ assert_param(IS_GPIO_AF_INSTANCE(GPIOx)); /* Based on the required mode, filling config variable with MODEy[1:0] and CNFy[3:2] corresponding bits */ switch (GPIO_Init->Mode) { /* If we are configuring the pin in OUTPUT push-pull mode */ case GPIO_MODE_OUTPUT_PP: /* Check the GPIO speed parameter */ assert_param(IS_GPIO_SPEED(GPIO_Init->Speed)); config = GPIO_Init->Speed + GPIO_CR_CNF_GP_OUTPUT_PP; break; /* If we are configuring the pin in OUTPUT open-drain mode */ case GPIO_MODE_OUTPUT_OD: /* Check the GPIO speed parameter */ assert_param(IS_GPIO_SPEED(GPIO_Init->Speed)); config = GPIO_Init->Speed + GPIO_CR_CNF_GP_OUTPUT_OD; break; /* If we are configuring the pin in ALTERNATE FUNCTION push-pull mode */ case GPIO_MODE_AF_PP: /* Check the GPIO speed parameter */ assert_param(IS_GPIO_SPEED(GPIO_Init->Speed)); config = GPIO_Init->Speed + GPIO_CR_CNF_AF_OUTPUT_PP; break; /* If we are configuring the pin in ALTERNATE FUNCTION open-drain mode */ case GPIO_MODE_AF_OD: /* Check the GPIO speed parameter */ assert_param(IS_GPIO_SPEED(GPIO_Init->Speed)); config = GPIO_Init->Speed + GPIO_CR_CNF_AF_OUTPUT_OD; break; /* If we are configuring the pin in INPUT (also applicable to EVENT and IT mode) */ case GPIO_MODE_INPUT: case GPIO_MODE_IT_RISING: case GPIO_MODE_IT_FALLING: case GPIO_MODE_IT_RISING_FALLING: case GPIO_MODE_EVT_RISING: case GPIO_MODE_EVT_FALLING: case GPIO_MODE_EVT_RISING_FALLING: /* Check the GPIO pull parameter */ assert_param(IS_GPIO_PULL(GPIO_Init->Pull)); if (GPIO_Init->Pull == GPIO_NOPULL) { config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_FLOATING; } else if (GPIO_Init->Pull == GPIO_PULLUP) { config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_PU_PD; /* Set the corresponding ODR bit */ GPIOx->BSRR = ioposition; } else /* GPIO_PULLDOWN */ { config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_PU_PD; /* Reset the corresponding ODR bit */ GPIOx->BRR = ioposition; } break; /* If we are configuring the pin in INPUT analog mode */ case GPIO_MODE_ANALOG: config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_ANALOG; break; /* Parameters are checked with assert_param */ default: break; } /* Check if the current bit belongs to first half or last half of the pin count number in order to address CRH or CRL register*/ configregister = (iocurrent < GPIO_PIN_8) ? &GPIOx->CRL : &GPIOx->CRH; registeroffset = (iocurrent < GPIO_PIN_8) ? (position << 2u) : ((position - 8u) << 2u); /* Apply the new configuration of the pin to the register */ MODIFY_REG((*configregister), ((GPIO_CRL_MODE0 | GPIO_CRL_CNF0) << registeroffset), (config << registeroffset)); /*--------------------- EXTI Mode Configuration ------------------------*/ /* Configure the External Interrupt or event for the current IO */ if ((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE) { /* Enable AFIO Clock */ __HAL_RCC_AFIO_CLK_ENABLE(); temp = AFIO->EXTICR[position >> 2u]; CLEAR_BIT(temp, (0x0Fu) << (4u * (position & 0x03u))); SET_BIT(temp, (GPIO_GET_INDEX(GPIOx)) << (4u * (position & 0x03u))); AFIO->EXTICR[position >> 2u] = temp; /* Configure the interrupt mask */ if ((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT) { SET_BIT(EXTI->IMR, iocurrent); } else { CLEAR_BIT(EXTI->IMR, iocurrent); } /* Configure the event mask */ if ((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT) { SET_BIT(EXTI->EMR, iocurrent); } else { CLEAR_BIT(EXTI->EMR, iocurrent); } /* Enable or disable the rising trigger */ if ((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE) { SET_BIT(EXTI->RTSR, iocurrent); } else { CLEAR_BIT(EXTI->RTSR, iocurrent); } /* Enable or disable the falling trigger */ if ((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE) { SET_BIT(EXTI->FTSR, iocurrent); } else { CLEAR_BIT(EXTI->FTSR, iocurrent); } } } position++; } }
……………………………………
??????????
什麼玩意……………………
好吧,抱歉拉下瞭一行
/** * @brief Initializes the GPIOx peripheral according to the specified parameters in the GPIO_Init. * @param GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral * @param GPIO_Init: pointer to a GPIO_InitTypeDef structure that contains * the configuration information for the specified GPIO peripheral. * @retval None */
很顯然我們進入的是官方的配置文件瞭,也就是官方的庫。所謂的標準庫以及hal庫是不同的。當然我們也可以自己寫庫(這就是學習51單片機的同學最應該掌握的部分以及學習的部分)。但是對於學習32的同學來說我們隻需要去看懂相應的函數用法即可。也就是說我們上面的長串代碼不需要讀懂,隻需要看懂這段代碼前面的官方註釋即可。也提醒我們同學,在自己寫庫以及寫代碼的時候一定要加上註釋加上簡介,方便後續的使用。
/** *@簡介 根據GPIO_Init中指定的參數初始化GPIOx外圍設備。 *@參數 GPIOx:其中x可以是(A~G,取決於使用的設備)來選擇GPIO外圍設備 *@參數 GPIO_Init:指向包含指定GPIO外圍設備的配置信息的GPIO_InitTypeDef結構的指針。 *@返回值 無 */ void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init) 大致意思就是將我們定義的那個結構體放到GPIO_x中去 HAL_GPIO_Init(GPIOB,&GPIO_Initure); //所以這行代碼是說,將我們定義的結構體放到GPIOB中得到的結果就是 // GPIOB_pin_5的配置如下 // GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽輸出 // GPIO_Initure.Pull=GPIO_PULLUP; //上拉 // GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH; //高速
這段分析之後我們再回到源代碼中
void LED_Init(void) /***c語言函數部分**/ //空函數空返回值,定義瞭一個函數,函數的名字是LED_Init,空形參,空返回值 { GPIO_InitTypeDef GPIO_Initure; //定義瞭一個名字為GPIO_Initure的結構體,裡面有pin(引腳),mode(工作方式),pull(輸出方式) //speed(輸出速度)幾個屬性的一個結構體 __HAL_RCC_GPIOB_CLK_ENABLE(); //開啟GPIOB時鐘 __HAL_RCC_GPIOE_CLK_ENABLE(); //開啟GPIOE時鐘 //兩個函數,功能如註釋所示 GPIO_Initure.Pin=GPIO_PIN_5; //PB5 GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽輸出 GPIO_Initure.Pull=GPIO_PULLUP; //上拉 GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH; //高速 //使用struck的初始化方式對struck結構體進行瞭初始化 HAL_GPIO_Init(GPIOB,&GPIO_Initure); // GPIOB_pin_5的配置如下 // GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽輸出 // GPIO_Initure.Pull=GPIO_PULLUP; //上拉 // GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH; //高速 GPIO_Initure.Pin=GPIO_PIN_5; //PE5 //這裡應該對代碼沒有改變,應該隻是為瞭加個註釋 HAL_GPIO_Init(GPIOE,&GPIO_Initure); // GPIOE_pin_5的配置如下 // GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽輸出 // GPIO_Initure.Pull=GPIO_PULLUP; //上拉 // GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH; //高速 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET); //PB5置1,默認初始化後燈滅 HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET); //PE5置1,默認初始化後燈滅 } //The end
5.總結
我們可以看到,單片機的編程依舊是以C語言為基礎的。同時今天講解的這個struck結構體的方式不僅教授瞭大傢struck在單片機中的應用。也教會瞭大傢一些在keil中的常用檢索方式,以及如何應對keil中的未知代碼以及函數。當然還有一個最重要的最重要的!!找一個好的翻譯軟件。
以上就是c語言結構體在單片機中的應用的詳細內容,更多關於c語言結構體單片機的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- OpenCV物體跟蹤樹莓派視覺小車實現過程學習
- 使用C語言操作樹莓派GPIO的詳細步驟
- 超詳細OpenMV與STM32單片機通信 附完整源碼
- C語言 module_init函數與initcall案例詳解
- C語言如何寫類實現教程示例