當前位置:
首頁 > 知識 > STM32F030系列實現仿位帶操作

STM32F030系列實現仿位帶操作


1、位帶操作基本知識

關於真正的位帶操作,網上有不的資料,寫得也很詳細,在這裡我只是簡單說一下我的理解。另,不理解真正的位帶操作,也不影響對本文的理解,因此文跟位帶操作沒有任何關係,只是仿仿罷了,不能當真。如果不想了解一下,此節可直接忽略。

如果不使用位帶操作,我們操作一個次數據時,就要動32位(STM32是32位的),做一個不恰當的比喻,這就相當於我們坐在一輛有32節車廂的火車上,但是輛火車只有一個門,如果我們要查看這火車中乘客的信息,或者是乘客想下車,必須從那一個門進出,如下圖1。

STM32F030系列實現仿位帶操作

圖1 只有1個車門的32節火車

而如果我們有了位帶操作,就相當於,給這輛32節車廂的火車裝上了32個車門,這樣一來,想查看哪個乘客的信息,或都那個乘客要下車,都可以迅速地從指定的車門下車。如下圖2所示。

STM32F030系列實現仿位帶操作

圖2 有32個車門的32節火車

有了32個門後,速度就快多了,但是硬體成本肯定要起來了,這就是為什麼STM32F030系列沒有位帶操作的原因,就是它的成本低。


2、C言語結構體位段操作

在C語言中,對結構體的聲明,有一個位域,它可以控制,此結構體中的成員占幾個位,關於它的使用,有如下代碼:


1 typedef struct _16_Bits_Struct

2 {

3 u16 bit0 : 1;//佔一個位元組

4 u16 bit1 : 1;

5 u16 bit2 : 1;

6 u16 bit3 : 1;

7 u16 bit4 : 1;

8 u16 bit5 : 1;

9 u16 bit6 : 1;

10 u16 bit7 : 1;

11 u16 bit8 : 1;

12 u16 bit9 : 1;

13 u16 bit10 : 1;

14 u16 bit11 : 2;//佔兩個位元組

15 u16 bit12 : 3;//佔三個位元組

16 } _16_Bits_Struct;

上面的_16_Bits_Struct結構體類型共佔用2個位元組,即16位,但它的13個成員變數所佔用的位數不全都一樣,通過「:」後面的數字可決定它占幾位。代碼如下,操作一個此結構體類型的位。


1 _16_Bits_Struct _16_bits;

2 unsigned short _16bits_data;

3 memset(&_16_bits, 0, sizeof(_16_Bits_Struct));//將其內存清0

4

5 _16_bits.bit2 = 1;

6 _16_bits.bit5 = 1;

7 _16_bits.bit8 = 5;

8

9 _16bits_data = *((unsigned short*)(&_16_bits));

10

11 printf("_16bits_data = %0xH
", _16bits_data);

其輸出結果為:

STM32F030系列實現仿位帶操作

從結果中可以看出,在結構體,從bit0~bit12依次是從低位到高位。在上面代碼的第7行,雖然給bit8寫入了5,但是因為它只佔一位,所以只取了5(D)=0101(B)的最低位,即為1。因此最終結果為124H,它的內存結構如下圖3所示。

STM32F030系列實現仿位帶操作

圖3 結構體內存結構圖


3、STM32F030仿位帶操作

有了上面結構體位段操作的基礎後,離實現仿STM32F030的位帶操作就很近了。我打算做一個最簡單的,實現對GPIO的某一個引腳操作,達到亮滅LED的功能。

從STM32F030的參考手冊中,找到GPIO的輸出寄存器ODR,看到它的基本信息如下圖4所示,這個寄存器是可讀可寫的(RW),因此只要作我們給這個寄存器其中的一個位寫入1,那麼這個引腳就會輸出1,寫0就輸出0(當然前提條件是你把它配置成輸出模式,並且使能了它的時鐘)。

STM32F030系列實現仿位帶操作

圖4 GPIO的ODR寄存器結構圖

我是如何對這個寄存器一次只操作一位的呢,且看下面代碼再來解釋。


1 typedef struct _16_Bits_Struct

2 {

3 u16 bit0 : 1;

4 u16 bit1 : 1;

5 u16 bit2 : 1;

6 u16 bit3 : 1;

7 u16 bit4 : 1;

8 u16 bit5 : 1;

9 u16 bit6 : 1;

10 u16 bit7 : 1;

11 u16 bit8 : 1;

12 u16 bit9 : 1;

13 u16 bit10 : 1;

14 u16 bit11 : 1;

15 u16 bit12 : 1;

16 u16 bit13 : 1;

17 u16 bit14 : 1;

18 u16 bit15 : 1;

19 } Bits_16_TypeDef;

20 #define LED_GPIO_CLK RCC_AHBPeriph_GPIOA

21 #define LED_PORT GPIOA

22 #define LED_PIN GPIO_Pin_4

23 //使用結構體的位段操作, 兼容Cortex-M3的位帶操作.

24 #define LED_PORT_OUT ((Bits_16_TypeDef *)(&(LED_PORT->ODR)))

25 #define LED (LED_PORT_OUT->bit4)

我的硬體連接是:LED接GPIOA的4引腳上。1~19行在前面的結構體知識中已經做出了解釋了,20~22隻是為了代碼更好移植做的一些宏定義,可不要。24行就比較關鍵了:先取出GPIOA->ODR的地址,然後再將它強制轉化為Bits_16_TypeDef *類型(注意,是指針類型)。轉化為此類型後,ODR就有位域的特性了,因此就可以對它進行位操作。25行就是將接在PA.4的LED定義為GPIOA->ODR的第4位。

有了這樣的操作後,想要我們的LED亮滅,就很容易了,代碼如下。


1 LED = 0;//LED亮

2 LED = 1;//LED滅

因硬體的連接不同,效果可能是反的。看到這裡,是不是覺得操作起來很簡單呢。

完整的代碼如下:

led.c


1 /*------------------------------------------------------------------------------

2 風機監測系統(2017年8月12日12:22:38)

3 功能描述:

4 LED的開關功能,主要用於狀態顯示

5

6 使用資源:GPIOA隨板子不用而變化

7

8 文件說明:無

9 作者:Endless 郵箱:endless@139.com 時間:2017年8月10日21:35:38

10 修改:無 時間:

11 ------------------------------------------------------------------------------*/

12 #include "led.h"

13 #include "stm32f0xx.h"

14

15 /*-----------------------------------------------------------------------------

16 函數功能:LED初始化

17 函數參數:無

18 函數返回:無

19 函數說明:調用此函數前,需要在LED.h修改宏定義LED引腳

20 作者:Endless

21 -----------------------------------------------------------------------------*/

22 void LED_Init(void)

23 {

24 GPIO_InitTypeDef GPIO_InitStructure;

25

26 RCC_AHBPeriphClockCmd(LED_GPIO_CLK, ENABLE);

27

28 GPIO_InitStructure.GPIO_Pin = LED_PIN;

29 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

30 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

31 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

32 GPIO_Init(LED_PORT, &GPIO_InitStructure);

33 }

led.h


1 #ifndef __led_H

2 #define __led_H

3

4 #include "stm32f0xx.h"

5 #include "mytype.h"

6

7 #define LED_GPIO_CLK RCC_AHBPeriph_GPIOA

8 #define LED_PORT GPIOA

9 #define LED_PIN GPIO_Pin_4

10

11 //使用結構體的位段操作, 兼容Cortex-M3的位帶操作.

12 #define LED_PORT_OUT ((Bits_16_TypeDef *)(&(LED_PORT->ODR)))

13 #define LED (LED_PORT_OUT->bit4)

14

15 void LED_Init(void);

16

17 #endif

mytype.h


1 #ifndef __MYTYPE_H

2 #define __MYTYPE_H

3 #include "stm32f0xx.h"

4

5 #ifndef BIT

6 #define BIT(x) (1 << (x))

7 #endif

8

9 #ifndef u8

10 #define u8 uint8_t

11 #endif

12

13 #ifndef u16

14 #define u16 uint16_t

15 #endif

16

17 #ifndef u32

18 #define u32 uint32_t

19 #endif

20

21 #ifndef NULL

22 #define NULL 0

23 #endif

24

25 /*------------------------------------------------------------------------------

26 用戶自定變數

27 功能描述:使用結構體的位段操作,可以實現位操作

28 作者:Endless 2017年8月13日18:32:37

29 修改:無 時間:

30 ------------------------------------------------------------------------------*/

31 typedef struct _16_Bits_Struct

32 {

33 u16 bit0 : 1;

34 u16 bit1 : 1;

35 u16 bit2 : 1;

36 u16 bit3 : 1;

37 u16 bit4 : 1;

38 u16 bit5 : 1;

39 u16 bit6 : 1;

40 u16 bit7 : 1;

41 u16 bit8 : 1;

42 u16 bit9 : 1;

43 u16 bit10 : 1;

44 u16 bit11 : 1;

45 u16 bit12 : 1;

46 u16 bit13 : 1;

47 u16 bit14 : 1;

48 u16 bit15 : 1;

49 } Bits_16_TypeDef;

如果你想進行更多的位操作,只需多定義幾次就行了,很容易的。到這裡就差不多結束了,希望能夠幫到大家!



更多優質內容推薦:

2017優就業就業促進計劃:http://www.ujiuye.com/zt/jycj/?wt.bd=zdy35845tt

學IT,用周末給自己加薪!

http://www.ujiuye.com/zt/zmb/?wt.bd=zdy35845tt

IT職業教育:http://xue.ujiuye.com/

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 IT優就業 的精彩文章:

正是因為有你,我才無比優秀
這個七夕你想和誰過?

TAG:IT優就業 |

您可能感興趣

央行開展1560億MLF和801億PSL操作
修復由於主庫NOLOGGING操作引起的備庫ORA-01578和ORA-26040錯誤
GTA5 XBOX360手柄鍵位操作指南
7SR45 操作手冊
GBPUSD 1月30日操作指南
央行昨日開展MLF操作4630億元
DDR4版GT 1030打不過4年前的GT 730顯卡?正常操作而已
Google I/O 2018:50%操作系統、40% AI、10%物聯網和0%隱私
IFA2018第三天,華為專門為EMUI9.0操作系統召開了一場媒體溝通會
新思全球首個USB 3.2操作展示 實測可達1.6 GB/s數據傳輸速率
Windows10 RS5新版17655增強操作中心 Windows10官方簡版系統:16G硬碟就能運行
谷歌Pixel 3發布:單手操作無壓力 5500元起售
2018年1月數據:Windows 10 即將成為全球第一大桌面操作系統
6萬塊買390km續航 江淮IEV6E這波操作很秀
華為P20上手實拍:5.8寸P20 Pro「縮小版」,機身小單手操作方便
EURUSD 3月14日操作指南
OPPO Find X配置拉滿:驍龍845+8GB 頂配只是基本操作
強力騷操作!5.86寸全面屏+64GB僅1399元,全面逆襲
這波操作666!WPS遇上麒麟970,手機照片也能秒變PPT
神操作!70m2老房爆改成北歐婚房【A963第1469期】