1. 程式人生 > 實用技巧 >Vue元件之間通訊的七種方式

Vue元件之間通訊的七種方式

內容來自網路:

一:為什麼要講volatile

因為,很多”面試官”自己找不到能夠測試應聘者的好的方式,所以就google了一下,發現了”嵌入式經典的0x10個面試題”,於是乎就拿來直接問了。我想第一個想到用這個來提問應聘者的人絕對是值得我們仰慕的。

二:Volatile官方說明

Indicates that a variable can be changed by a background routine.

Keyword volatile is an extreme opposite of const. It indicates that a variable may be changed in a way which is absolutely unpredictable by analysing the normal program flow (for example, a variable which may be changed by an interrupt handler). This keyword uses the following syntax:

volatile data-definition;

Every reference to the variable will reload the contents from memory rather than take advantage of situations where a copy can be in a register.

翻譯:

表示一個變數也許會被後臺程式改變.

關鍵字volatile是與const絕然對立的。它指示一個變數也許會被某種方式修改,這種方式按照正常程式流程分析是無法預知的(例如,一個變數也許會被一箇中斷服務程式所修改)。這個關鍵字使用下列語法定義:

volatile data-definition;

變數如果加了volatile修飾,則會從記憶體重新裝載內容,而不是直接從暫存器拷貝內容。

三:例項分析

Volatile應用比較多的場合,在中斷服務程式和cpu相關暫存器的定義。

比如,下面就是lpc2136 相關暫存器定義

 1 /**************************
 2 
 3 /* Vectored Interrupt Controller (VIC) */
 4 
 5 #define VICIRQStatus    (*((volatile unsigned long *) 0xFFFFF000))
 6 
 7 #define VICFIQStatus    (*((volatile unsigned long *) 0xFFFFF004))
 8
9 #define VICRawIntr (*((volatile unsigned long *) 0xFFFFF008)) 10 11 #define VICIntSelect (*((volatile unsigned long *) 0xFFFFF00C)) 12 13 #define VICIntEnable (*((volatile unsigned long *) 0xFFFFF010)) 14 15 #define VICIntEnClr (*((volatile unsigned long *) 0xFFFFF014)) 16 17 #define VICSoftInt (*((volatile unsigned long *) 0xFFFFF018)) 18 19 #define VICSoftIntClear (*((volatile unsigned long *) 0xFFFFF01C)) 20 21 #define VICProtection (*((volatile unsigned long *) 0xFFFFF020)) 22 23 #define VICVectAddr (*((volatile unsigned long *) 0xFFFFF030)) 24 25 #define VICDefVectAddr (*((volatile unsigned long *) 0xFFFFF034)) 26 27 #define VICVectAddr0 (*((volatile unsigned long *) 0xFFFFF100)) 28 29 #define VICVectAddr1 (*((volatile unsigned long *) 0xFFFFF104)) 30 31 #define VICVectAddr2 (*((volatile unsigned long *) 0xFFFFF108)) 32 33 #define VICVectAddr3 (*((volatile unsigned long *) 0xFFFFF10C)) 34 35 #define VICVectAddr4 (*((volatile unsigned long *) 0xFFFFF110)) 36 37 #define VICVectAddr5 (*((volatile unsigned long *) 0xFFFFF114)) 38 39 #define VICVectAddr6 (*((volatile unsigned long *) 0xFFFFF118)) 40 41 #define VICVectAddr7 (*((volatile unsigned long *) 0xFFFFF11C)) 42 43 #define VICVectAddr8 (*((volatile unsigned long *) 0xFFFFF120)) 44 45 #define VICVectAddr9 (*((volatile unsigned long *) 0xFFFFF124)) 46 47 #define VICVectAddr10 (*((volatile unsigned long *) 0xFFFFF128)) 48 49 #define VICVectAddr11 (*((volatile unsigned long *) 0xFFFFF12C))

也許有人看到這裡有帶出了跟本文無關的疑問,#define VICIntEnable (*((volatile unsigned long *) 0xFFFFF010))

是什麼語法。

這裡也一併介紹了:

先總結一句話,#define VICIntEnable (*((volatile unsigned long *) 0xFFFFF010))

其實就是定義一個指標變數。

那什麼是指標變數呢,萬變不離其宗!

我們看C裡面對指標變數的定義:(大家可以去看譚浩強老師C語言第四版指標部分)

Int a;這裡a是一個變數,是一個32位整形變數;

Int *p;同理,p也是一個變數,但他是一個指標變數,他可以存放一個地址,

如:p=&a,(p可以這樣賦值),p存放的地址是變數a的地址&是取地址符。

那麼*p是什麼呢?

*p就是p所指向的內容!!

比如:

1 {
2 Int a;
3 Int *p;
4 a=100;
5 p=&a
6 }

那麼*p就等於100;

但是,這裡還有個問題,p本身的地址。如果想到了這裡,我們就好介紹

#define VICIntEnable (*((volatile unsigned long *) 0xFFFFF010))

我們來做一個例比:

(*((volatile unsigned long *) 0xFFFFF010))=========>*p

那麼這裡 ((volatile unsigned long *) 0xFFFFF010)========>p

這裡0xFFFFF010就對應到p本身的地址。<why?!>

首先,大家應該知道這是一個C語言裡面的巨集定義;然後,0xFFFFF010這個32位數,這個數的來源在lpc2136 datasheet52page/270

所以,這個32位數是一個暫存器地址,要把一個32位數表示成地址怎麼表示呢?

(unsigned long *)0xFFFFF010

就是這樣(也可以表示成(unsigned char *) 0xFFFFF010,

前者表示這個地方可以存放32位資料,

後者表示這個地址只能存放8位資料)[(unsigned long *)表示存放資料長度]

既然是地址,就像我們在超市裡面的寄存包裹箱一樣,是可以存放東西,而且可以取出東西的地方。我們叫可讀寫,當然有些地址是不能寫的,只讀的,比如這裡面的VICIRQStatus..

暫存器地址為什麼要加volatile修飾呢,是因為,這些暫存器裡面的值是隨時變化的。比如,我們這裡的中斷狀態暫存器VICIRQStatus ,當某個中斷髮生的時候,我們無法知道,那麼這個狀態暫存器的內容也是無法預知的。我們讀取的時候,CPU就直接到記憶體裡面取值,而不是到cache裡面取值。

*(volatile uint32 *)0x60001404 = 0x0000;

意思就是初始化0x60001404地址中的值為0x0000,一般在很多微控制器程式中完成暫存器的操作時經常這樣用,它相當於下面兩步

   volatile uint32 * p = (volatile uint32 *)0x60001404;
   * p  = 0x0000;    (peak:把p指向的變數賦值0x0000)

其中(volatile uint32 *)0x60001404,是利用c語言的強制型別轉換把地址值轉換為volatile uint32 * 型別的指標(相當於volatile uint32 * p = (volatile uint32 *)0x60001404),然後將0x0000賦給這個指標指向的地址(相當於 * p = 0x0000),也就使0x60001404地址中的值為0x0000