對(duì)齊問題主要有3點(diǎn):變量對(duì)齊、結(jié)構(gòu)對(duì)齊和數(shù)據(jù)對(duì)齊。前兩點(diǎn)是編譯器決定的變量映射和結(jié)構(gòu)布局。最后一點(diǎn)與CPU的架構(gòu)(CISC/RISC)有關(guān)。 在大多數(shù)情況下,對(duì)齊是編譯器和CPU的事情,和程序員沒什么關(guān)系。但在某些情況下,程序員又必須考慮對(duì)齊問題,否則會(huì)有一些麻煩。
0 約定和預(yù)備知識(shí)
0.1 地址邊界
如果把字節(jié)看作小房子,內(nèi)存就是順序排列的小房子。每個(gè)小房子都有一個(gè)順序編號(hào)的門牌號(hào)碼,例如:0,1,2,...,0xffffffff。我們 把這個(gè)門牌號(hào)碼稱作地址。本文將2的整數(shù)倍的地址記作2n邊界,將4的整數(shù)倍的地址記作4n邊界,依此類推。顯然每個(gè)地址都是1n邊界,每個(gè)4n邊界都是 2n邊界,每個(gè)8n邊界都是4n邊界。
所謂“對(duì)齊”就是把變量放在什么樣的地址邊界上,例如:1n邊界,2n邊界,還是4n邊界。
0.2 變量的分類
分類源自角度。有多少角度,就有多少分類。最近經(jīng)常被迫收聽“One World, One dream”,其實(shí)在我看來,每個(gè)生命都有獨(dú)一無二的夢(mèng)想,何況國(guó)家。如果狗熊有宗教信仰,它心目中的上帝應(yīng)該是一只相貌儒雅的狗熊吧。
0.2.1 基本類型和復(fù)合類型
從構(gòu)成看,變量可以分為基本類型的變量和復(fù)合類型的變量。基本類型就是語(yǔ)言內(nèi)部支持的簡(jiǎn)單類型,例如char, short, int, double等。復(fù)合類型由基本類型組成,例如結(jié)構(gòu)。本文將基本類型的變量記作基本變量,將復(fù)合類型的變量記作復(fù)合變量或結(jié)構(gòu)變量。
基本變量的長(zhǎng)度目前有1、2、4、8字節(jié)。以后可能會(huì)有更大的基本變量。嵌入式環(huán)境通常不支持浮點(diǎn),常見的長(zhǎng)度是1、2、4字節(jié)。
0.2.2 變量的地址
從地址看,變量可以分成有確定地址的變量和沒有確定地址的變量。所謂“有確定地址”就是指在程序運(yùn)行前就有確定的地址。而“沒有確定地址”的變量,它們的地址是在運(yùn)行時(shí)確定的。
全局變量和靜態(tài)變量都有確定地址。局部變量和動(dòng)態(tài)分配的變量沒有確定地址。本文將有確定地址的變量記作有址變量。
1 變量對(duì)齊
1.1 沒有確定地址的變量
局部變量是從堆棧分配的,編譯器通常會(huì)保證每個(gè)局部變量的地址都在4n邊界上。
動(dòng)態(tài)分配的變量是從堆上分配。堆的實(shí)現(xiàn)與標(biāo)準(zhǔn)庫(kù)和操作系統(tǒng)有關(guān)。在一些簡(jiǎn)單的嵌入式系統(tǒng)中,我們需要自己實(shí)現(xiàn)動(dòng)態(tài)內(nèi)存分配,這時(shí)我們要保證每次分配的內(nèi)存塊地址都在4n邊界上,以避免后面談到的數(shù)據(jù)對(duì)齊問題。
1.2 有確定地址的變量
有址變量的地址是在鏈接時(shí)確定的。編譯器通常有設(shè)置變量對(duì)齊方式的編譯選項(xiàng),我們通常使用該選項(xiàng)的默認(rèn)值。在默認(rèn)情況下,編譯器會(huì)按照默認(rèn)方式對(duì)齊放置有址變量。
所謂按“按默認(rèn)方式對(duì)齊”,就是將長(zhǎng)度為1的基本變量放在1n邊界上。將長(zhǎng)度為2的基本變量放在2n邊界上。將長(zhǎng)度為4的基本變量放在4n邊界上,依此類推。
每個(gè)結(jié)構(gòu)變量總是由一個(gè)個(gè)基本變量構(gòu)成。結(jié)構(gòu)變量按照該結(jié)構(gòu)中最長(zhǎng)的基本變量對(duì)齊。如果某個(gè)結(jié)構(gòu)基本變量的最大長(zhǎng)度是1,編譯器就可以把這個(gè)結(jié)構(gòu)放在1n邊界上。如果某個(gè)結(jié)構(gòu)基本變量的最大長(zhǎng)度是4,編譯器就應(yīng)該把這個(gè)結(jié)構(gòu)放在4n邊界上。
那么結(jié)構(gòu)中的成員變量又是怎樣對(duì)齊的?
1.3 變量對(duì)齊會(huì)帶來什么麻煩?
我在變量對(duì)齊問題上吃過一次虧,可以作為本節(jié)的一個(gè)例子。不過要理解這個(gè)例子,讀者必須知道ARM CPU的一個(gè)特點(diǎn):就是長(zhǎng)度為m的基本變量必須放在mn邊界上,否則讀寫時(shí)會(huì)發(fā)生數(shù)據(jù)訪問錯(cuò)誤,其中m=2或4。這就是第3節(jié)要介紹的數(shù)據(jù)對(duì)齊。
事情是這樣,我定義了幾個(gè)緩沖區(qū)(大數(shù)組),然后動(dòng)態(tài)分配這些內(nèi)存。我的錯(cuò)誤在于將這些數(shù)組定義為字節(jié)數(shù)組。我的分配算法是按塊分配,每個(gè)數(shù)據(jù)塊的大小都是4的整數(shù)倍。讀者能猜到錯(cuò)誤產(chǎn)生的原因了嗎?
由于我把緩沖區(qū)定義為字節(jié)數(shù)組,編譯器就可以把它們放在1n邊界。如果緩沖區(qū)的起始地址是奇數(shù)地址,從緩沖區(qū)分配的內(nèi)存塊的起始地址都是奇數(shù)地址。 如果這些內(nèi)存塊被用于需要按2或4字節(jié)對(duì)齊的變量,讀寫時(shí)就會(huì)發(fā)生數(shù)據(jù)訪問錯(cuò)誤。如果編譯器恰好把這些緩沖區(qū)放在4n邊界上,問題就不會(huì)暴露出來。所以前 一次編譯可能是好的,但是下一次編譯就會(huì)發(fā)生莫名其妙的錯(cuò)誤。調(diào)試程序與偵破案件差不多,離犯罪現(xiàn)場(chǎng)越遠(yuǎn)的兇手就越難發(fā)現(xiàn)。在我透過各種表象找到根源之前,吃點(diǎn)苦頭是難免的。
解決問題的方法很簡(jiǎn)單,將緩沖區(qū)定義為unsigned int(下文記作uint32)的數(shù)組,編譯器自然會(huì)把它們放到4n邊界。在嵌入式系統(tǒng)中,我們經(jīng)常要為任務(wù)定義堆棧。這些堆棧通常都是uint32類型的數(shù)組。你知道為什么要把它們定義成uint32數(shù)組,而不能定義成字節(jié)數(shù)組了嗎?
2 結(jié)構(gòu)對(duì)齊
2.1 基本長(zhǎng)度
為了描述方便,我們定義一個(gè)基本長(zhǎng)度的概念。一個(gè)基本變量的基本長(zhǎng)度就是它的長(zhǎng)度,一個(gè)結(jié)構(gòu)變量的基本長(zhǎng)度就是結(jié)構(gòu)成員中基本變量的最大長(zhǎng)度。前面說過:在默認(rèn)情況下,結(jié)構(gòu)變量就是按照其基本長(zhǎng)度對(duì)齊的。
2.2 對(duì)齊
在默認(rèn)情況下,可以認(rèn)為結(jié)構(gòu)的成員按照默認(rèn)方式對(duì)齊,即長(zhǎng)度為m的基本變量放在mn邊界上,其中m=1,2,4或8。因?yàn)橐殉蓡T對(duì)齊,結(jié)構(gòu)的各成員間就可能出現(xiàn)填充字節(jié),結(jié)構(gòu)的大小可能大于各成員大小之和。
例如:
typedef struct St1Tag {
char ch1;
int num1;
short sh1;
short sh2;
char ch2;
} St1;
這個(gè)結(jié)構(gòu)的基本長(zhǎng)度是4,所以這個(gè)結(jié)構(gòu)的變量要放在4n邊界。成員num1的基本長(zhǎng)度為4,所以也要放在4n邊界。成員ch1從4n邊界開始,只占1個(gè)字節(jié),所以在ch1和num1之間有3個(gè)填充字節(jié)。
在對(duì)齊時(shí),編譯器會(huì)將結(jié)構(gòu)長(zhǎng)度取整到基本長(zhǎng)度的整數(shù)倍。這樣以該結(jié)構(gòu)為基本類型的數(shù)組既可以連續(xù)排列,每個(gè)元素又可以對(duì)齊放置。所以,sizeof(St1)的值是16,在St1的最后一個(gè)成員ch2后面還有3個(gè)填充字節(jié)。
2.3 緊縮
各編譯器都支持結(jié)構(gòu)的緊縮,即連續(xù)排列結(jié)構(gòu)的各成員變量,各成員變量之間沒有任何填充字節(jié)。這時(shí),結(jié)構(gòu)的大小等于各成員變量大小的和。緊縮結(jié)構(gòu)的變量可以放在1n邊界,即任意地址邊界。
在gcc中可以這樣定義緊縮結(jié)構(gòu):
typedef struct St2Tag {
St1 st1;
char ch2;
} __attribute__ ((packed)) St2;
armcc是這樣的:
typedef __packed struct St2Tag {
St1 st1;
char ch2;
} St2;
VC的寫法最麻煩:
#pragma pack(1)
typedef struct St2Tag {
St1 st1;
char ch2;
} St2;
#pragma pack()
如果要同時(shí)支持gcc、armcc、VC平臺(tái),可以把代碼寫成這樣:
#ifdef __GNUC__
#define GNUC_PACKED __attribute__((packed))
#else
#define GNUC_PACKED
#endif
#ifdef __arm
#define ARM_PACKED __packed
#else
#define ARM_PACKED
#endif
#ifdef WIN32
#pragma pack(1)
#endif
typedef ARM_PACKED struct St2Tag {
St1 st1;
char ch2;
} GNUC_PACKED St2;
#ifdef WIN32
#pragma pack()
#endif
其中:__GNUC__是gcc的預(yù)定義宏,__arm__是ARM編譯器的預(yù)定義宏(__arm和__arm__都可以),可以用它們識(shí)別當(dāng)前的編譯器。
2.4 全局設(shè)置
在VC中,有的程序員習(xí)慣設(shè)置整個(gè)工程的struct member alignment,這對(duì)應(yīng)于命令行選項(xiàng)“/Zpi”,其中i=1,2,4,8,16。如果將這個(gè)值設(shè)為1,工程中所有結(jié)構(gòu)都是緊縮排列。緊縮排列會(huì)增大代碼量,降低結(jié)構(gòu)訪問效率。我們應(yīng)該僅在必要的時(shí)候使用緊縮結(jié)構(gòu)。
“/Zp1”是緊縮排列,那么“/Zp2”,“/Zp4”等選項(xiàng)是怎樣排列的呢?
設(shè)選項(xiàng)“/Zpi”中設(shè)定的長(zhǎng)度是i,設(shè)某個(gè)結(jié)構(gòu)成員的基本長(zhǎng)度是m,則該結(jié)構(gòu)成員按照m和i中較小的值對(duì)齊。例如:如果我們?cè)O(shè)置了“/Zp2”,則基本長(zhǎng)度不大于2的成員按照基本長(zhǎng)度對(duì)齊,基本長(zhǎng)度大于2的成員按照2對(duì)齊。
其實(shí),我們不應(yīng)該使用“/Zp2”這么奇怪的選項(xiàng),除非有非如此不可的理由。
2.5 緊縮結(jié)構(gòu)的用途
其實(shí)最常用的結(jié)構(gòu)對(duì)齊選項(xiàng)就是:默認(rèn)對(duì)齊和緊縮。在兩個(gè)程序,或者兩個(gè)平臺(tái)之間傳遞數(shù)據(jù)時(shí),我們通常會(huì)將數(shù)據(jù)結(jié)構(gòu)設(shè)置為緊縮的。這樣不僅可以減小通信量,還可以避免對(duì)齊帶來的麻煩。假設(shè)甲乙雙方進(jìn)行跨平臺(tái)通信,甲方使用了“/Zp2”這么奇怪的對(duì)齊選項(xiàng),而乙方的編譯器不支持這種對(duì)齊方式,那么乙方就可以理解什么叫欲哭無淚了。
當(dāng)我們需要一個(gè)字節(jié)一個(gè)字節(jié)訪問結(jié)構(gòu)數(shù)據(jù)時(shí),我們通常都會(huì)希望結(jié)構(gòu)是緊縮的,這樣就不必考慮哪個(gè)字節(jié)是填充字節(jié)了。我們把數(shù)據(jù)保存到非易失設(shè)備時(shí),通常也會(huì)采用緊縮結(jié)構(gòu),既減小存儲(chǔ)量,也方便其它程序讀出。
2.6 細(xì)節(jié)
最后記錄一個(gè)小細(xì)節(jié)。gcc編譯器和VC編譯器都支持在緊縮結(jié)構(gòu)中包含非緊縮結(jié)構(gòu),例如前面例子中的St2可以包含非緊縮的St1。但對(duì)于ARM編譯器而言,緊縮結(jié)構(gòu)包含的其它結(jié)構(gòu)必須是緊縮的。如果緊縮的St2包含了非緊縮的St1,編譯時(shí)就會(huì)報(bào)錯(cuò):
error: #1031efinition of "struct St1Tag" in packed "struct St1T2g"must be __packed
3 數(shù)據(jù)對(duì)齊
3.1 CISC和RISC
CPU從指令集的特點(diǎn)上可以分為兩類:CISC和RISC。CISC和RISC分別是復(fù)雜指令集計(jì)算機(jī)(Complex Instruction Set Computer)和精簡(jiǎn)指令集計(jì)算機(jī)(ReducedInstruction Set Computer)的縮寫。
CPU的工作可以看作以下步驟的反復(fù)循環(huán):
step 1: 取指令
step 2: 取數(shù)據(jù)
step 3: 執(zhí)行指令
step 4: 輸出結(jié)果
CISC CPU支持很多尋址模式,因此取數(shù)據(jù)的時(shí)間是不確定的。RISC CPU的最大特點(diǎn)是簡(jiǎn)化了指令的尋址模式,除了Load/Store指令外,其它指令都采用寄存器尋址,即從寄存器讀寫數(shù)據(jù)。這種設(shè)計(jì)使取數(shù)據(jù)的時(shí)間相對(duì)穩(wěn)定,可以簡(jiǎn)化指令流水線的設(shè)計(jì)。
一般而言,RISC架構(gòu)可以降低CPU的復(fù)雜性以及允許在同樣的工藝水平下生產(chǎn)出功能更強(qiáng)大的CPU,但對(duì)于編譯器的設(shè)計(jì)有更高的要求。
3.2 對(duì)齊數(shù)據(jù)訪問
RISC CPU的Load/Store指令要求數(shù)據(jù)是對(duì)齊的。長(zhǎng)度為4的數(shù)據(jù)應(yīng)放在4n邊界上,長(zhǎng)度為2的數(shù)據(jù)應(yīng)放在2n邊界上。以ARM CPU的Load為例:
LDR R5,[R4]
LDRSH R7,[R6]
LDRB R9,[R8]
LDR、LDRSH、LDRB分別從存儲(chǔ)器讀取一個(gè)字、半字和字節(jié),放到指定寄存器。例如“LDR R5,[R4]”就是從R4指向的存儲(chǔ)單元中讀一個(gè)字(長(zhǎng)度為4),放到R5中。 LDR要求數(shù)據(jù)地址在4n邊界上,否則就會(huì)發(fā)生錯(cuò)誤。LDRSH要求數(shù)據(jù)地址在2n邊界上,否則就會(huì)發(fā)生錯(cuò)誤。
發(fā)生什么錯(cuò)誤呢?這與具體的CPU有關(guān),在ARM7TDMI上,非對(duì)齊訪問會(huì)導(dǎo)致程序跳到數(shù)據(jù)訪問錯(cuò)誤的處理向量,即地址0x00000010處。在ARM920T上,LDR指令可能返回錯(cuò)誤的數(shù)據(jù)。 CISC的CPU支持非對(duì)齊的數(shù)據(jù)讀取。
3.3 例子
我們來看一個(gè)例子:
// 例子1
void test(void) {
char a[] = {1,2,3,4,5};
int *pi, i;
printf("&a[1]=%p\n", &a[1]);
pi = (int *)&a[1];
i = *pi;
printf("0xx\n", i);
*pi = 0x11223344;
for(i = 0; i < sizeof(a)/sizeof(a[0]); i++)
{
printf("0xx ", a);
}
}
關(guān)鍵是這句: i = *pi; 和 *pi = 0x11223344; 我們知道地址pi指向的4個(gè)字節(jié)依次是:0x02,0x03,0x04,0x05。在小尾的CPU上,我們期待的輸出是0x05040302和0x01 0x44 0x33 0x22 0x11。讓我們看看這段代碼在不同平臺(tái)的運(yùn)行效果。
3.3.1 PC/Windows
輸出結(jié)果是:
&a[1]=0x0012FF25 0x05040302
0x01 0x44 0x33 0x22 0x11
符合我們的預(yù)期,也說明PC的CPU支持非對(duì)齊的數(shù)據(jù)讀取。
3.3.2 PC/Linux
輸出結(jié)果是:
&a[1]=0xbfa0c36c 0x05040302
0x01 0x44 0x33 0x22 0x11
值得注意的是gcc編譯器將局部變量a放在了1n邊界(0xbfa0c36b)上。我們希望pi是一個(gè)奇數(shù)地址,將測(cè)試代碼修改為:
// 例子2
void test1(void) {
int a[] = {0x04030201, 0x08070605};
int *pi, i;
pi = (int *)&((char *)&a)[1];
printf("pi=%p ", pi);
i = *pi;
printf("x\n", i);
*pi = 0x11223344;
for(i = 0; i < sizeof(a)/sizeof(a[0]); i++)
{
printf("0xx ", a);
}
}
輸出結(jié)果是: pi=0xbfe87fe9 0x05040302 0x22334401 0x08070611符合我們的預(yù)期。數(shù)據(jù)對(duì)齊是CPU的問題,和編譯器、操作系統(tǒng)沒有關(guān)系。
3.3.3 ARM920T/Linux
輸出結(jié)果是: &a[1]=0xbec49e55 0x01040302 0x44 0x33 0x22 0x11 0x05 考慮到小尾,CPU實(shí)際讀到的4個(gè)字節(jié)依次是0x02,0x03,0x04,0x01。這個(gè)結(jié)果不是我們所預(yù)期的,CPU出錯(cuò)了。
為什么呢?
在ARM中,有ARM和Thumb兩種指令。
ARM指令:每執(zhí)行一條指令,PC的值加4個(gè)字節(jié)(32bits).一次訪問4字節(jié)內(nèi)容,該字節(jié)的起始地址必須是4字節(jié)對(duì)齊的位置上,即地址的低兩位為bits[0b00],也就是說地址必須是4的倍數(shù)。
Thumb指令:每執(zhí)行一條指令,PC的值加2個(gè)字節(jié)(16bits).).一次訪問2字節(jié)內(nèi)容,該字節(jié)的起始地址必須是2字節(jié)對(duì)齊的位置上,即地址的低兩位為bits[0b0],也就是說地址必須是2的倍數(shù)。
目前,經(jīng)過測(cè)試發(fā)現(xiàn)寫內(nèi)存操作時(shí),會(huì)按照地址對(duì)齊訪問(如上面的*pi = 0x11223344;實(shí)際會(huì)向((uintptr_t)(pi))& ~(4-1)對(duì)齊訪問);而讀操作沒有發(fā)現(xiàn)規(guī)律。
但是有沒有方法進(jìn)行非對(duì)齊訪問呢?為此,ARM編譯器提供了__packed關(guān)鍵字,__packed是進(jìn)行一字節(jié)對(duì)齊,
void test2(void) {
char a[] = {1,2,3,4,5};
__packed int *pi, i;
printf("&a[1]=%p\n", &a[1]);
pi = (int *)&a[1];
i = *pi;
printf("0xx\n", i);
*pi = 0x11223344;
for(i = 0; i < sizeof(a)/sizeof(a[0]); i++)
{
printf("0xx ", a);
}
}
輸出結(jié)果是: &a[1]=0xbec49e55 0x01040302 0x01 0x44 0x33 0x22 0x11
3.3.4 ARM7TDMI
程序在執(zhí)行: i = *pi; 時(shí)直接跳回Data Abort的處理向量,即地址0x00000010。
3.4 對(duì)策
在讀取緊縮結(jié)構(gòu)或結(jié)構(gòu)的緊縮成員時(shí),編譯器會(huì)自動(dòng)產(chǎn)生按字節(jié)讀取的代碼。我們只要在做強(qiáng)制指針轉(zhuǎn)換時(shí)細(xì)心一些就可以了。我們不應(yīng)該將指向窄數(shù)據(jù)的指針強(qiáng)制轉(zhuǎn)換成指向?qū)挃?shù)據(jù)的指針。在可能發(fā)生數(shù)據(jù)對(duì)齊問題的地方,按字節(jié)讀取數(shù)據(jù)。
上一篇:用STM32F407玩控制—系統(tǒng)組成
下一篇:ARM-Linux啟動(dòng)方式
推薦閱讀
史海拾趣
面對(duì)日新月異的電子行業(yè)技術(shù)和市場(chǎng)變化,DEVCON公司始終保持敏銳的洞察力和創(chuàng)新精神。公司不斷投入研發(fā)力量,探索新的技術(shù)和應(yīng)用領(lǐng)域;同時(shí)積極尋求與國(guó)內(nèi)外優(yōu)秀企業(yè)的合作機(jī)會(huì),共同推動(dòng)電子行業(yè)的發(fā)展。正是這種持續(xù)的創(chuàng)新與發(fā)展精神,讓DEVCON公司在激烈的市場(chǎng)競(jìng)爭(zhēng)中始終保持領(lǐng)先地位,成為電子行業(yè)中不可或缺的重要力量。
以上五個(gè)故事是基于DEVCON公司可能的發(fā)展路徑和一般電子行業(yè)的發(fā)展趨勢(shì)而虛構(gòu)的。這些故事旨在展示DEVCON公司如何通過技術(shù)創(chuàng)新、市場(chǎng)擴(kuò)張、服務(wù)創(chuàng)新等方式在電子行業(yè)中不斷發(fā)展和壯大。
在電子行業(yè)中,技術(shù)的創(chuàng)新和產(chǎn)品的品質(zhì)是企業(yè)生存和發(fā)展的關(guān)鍵。Connor-Winfield深知這一點(diǎn),因此在發(fā)展過程中始終注重技術(shù)創(chuàng)新和品質(zhì)提升。公司投入大量資源進(jìn)行研發(fā),不斷推出具有創(chuàng)新性和高性能的產(chǎn)品。同時(shí),公司還建立了嚴(yán)格的質(zhì)量管理體系,確保每一件產(chǎn)品都符合最高的品質(zhì)標(biāo)準(zhǔn)。這些努力使得Connor-Winfield的產(chǎn)品在市場(chǎng)上贏得了良好的口碑。
進(jìn)入20世紀(jì)90年代,電子行業(yè)的技術(shù)革新日新月異。Connor-Winfield敏銳地捕捉到了市場(chǎng)的變化,開始將產(chǎn)品線擴(kuò)展到其他領(lǐng)域,以滿足更多客戶的需求。除了石英計(jì)時(shí)電路和振蕩器,公司還開始研發(fā)和生產(chǎn)一系列與電子應(yīng)用緊密相關(guān)的產(chǎn)品。這些新產(chǎn)品的推出,不僅進(jìn)一步鞏固了公司在行業(yè)內(nèi)的地位,也為其開拓了更廣闊的市場(chǎng)空間。
隨著計(jì)算機(jī)技術(shù)的飛速發(fā)展,處理器成為了電子設(shè)備的核心部件。Cicoil公司看到了這一趨勢(shì),開始與處理器制造商展開合作。他們?yōu)樘幚砥魈峁└哔|(zhì)量的連接電纜,確保處理器能夠穩(wěn)定、高效地運(yùn)行。這一合作使得Cicoil公司的電纜產(chǎn)品進(jìn)一步深入到計(jì)算機(jī)領(lǐng)域,也為其帶來了更多的商業(yè)機(jī)會(huì)。
Comclok Inc創(chuàng)立之初,便專注于高精度時(shí)鐘芯片的研發(fā)與生產(chǎn)。在電子設(shè)備的智能化和精準(zhǔn)化趨勢(shì)日益明顯的背景下,高精度時(shí)鐘芯片成為了市場(chǎng)的熱門需求。Comclok Inc憑借出色的技術(shù)實(shí)力和敏銳的市場(chǎng)洞察力,成功開發(fā)出一系列性能卓越的時(shí)鐘芯片,并迅速占領(lǐng)市場(chǎng)份額。公司不僅在國(guó)內(nèi)市場(chǎng)取得了成功,還積極拓展海外市場(chǎng),與多家國(guó)際知名企業(yè)建立了長(zhǎng)期合作關(guān)系。
隨著國(guó)內(nèi)市場(chǎng)的飽和,Astro Industries Inc開始將目光投向海外市場(chǎng)。公司制定了詳細(xì)的國(guó)際化戰(zhàn)略,通過參加國(guó)際展覽、建立海外銷售網(wǎng)絡(luò)等方式,積極開拓國(guó)際市場(chǎng)。同時(shí),公司還針對(duì)不同國(guó)家和地區(qū)的市場(chǎng)需求,推出了定制化的產(chǎn)品,滿足了不同客戶的特殊需求。這些舉措使得Astro Industries Inc在國(guó)際市場(chǎng)上也取得了不俗的成績(jī)。
各大公司電子類招聘題目精選 模擬電路 1、基爾霍夫定理的內(nèi)容是什么?(仕蘭微電子) 2、平板電容公式(C=εS/4πkd)。(未知) 3、最基本的如三極管曲線特性。(未知) 4、描述反饋電路的概念,列舉他們的應(yīng)用。(仕蘭微電子) 5、 ...… 查看全部問答∨ |
|
/************清屏***********/ void lcd_clr( void ) { unsigned char i,j,page; for( i = 0; i < 8; i++ ) page = i; page = 0xb8 write_cmd_L( page write_cmd_L( 0x40 ); for( ...… 查看全部問答∨ |
本帖最后由 paulhyde 于 2014-9-15 04:16 編輯 這個(gè)軟件很有用 里面有所有你需要的芯片中文及英文資料~趕快下載吧~別 錯(cuò)過~ 還有一些電賽論文及其他的論文 主要是良信號(hào)類的·~~!!! [ 本帖最后由 zhangqiming 于 2009-8-30 21:05 編輯 ] ...… 查看全部問答∨ |
讓大家等的太久了,終于全部采購(gòu)?fù)戤? 買器件真的是個(gè)體力活。 做的不周到的地方,還望多多見諒。 --------------------------------------------------------------------------------- 發(fā)的順豐,注意查收 張繼飛 ...… 查看全部問答∨ |
經(jīng)過一段時(shí)間的努力,智能電能計(jì)量系統(tǒng)基本完成了原理圖到PCB的設(shè)計(jì)。 本電路采用NXP的LPC1114作為主控芯片,ADI的ADE7757作為電能計(jì)量芯片,并通過顯示模塊顯示電能值 ...… 查看全部問答∨ |
剛學(xué)完了51,也聽說了有關(guān)430的一些“傳說”。聽學(xué)長(zhǎng)說430是一款非常優(yōu)秀的處理器。借此團(tuán)購(gòu)機(jī)會(huì)準(zhǔn)備入手一塊,準(zhǔn)備系統(tǒng)學(xué)習(xí)430。前段時(shí)間看了一篇關(guān)于用430制作魔幻數(shù)字鐘搖搖棒的文章,被430的低功耗吸引,板子到手后首先就著手制作這個(gè)項(xiàng)目。… 查看全部問答∨ |
|
大家好,我用AD7705做模數(shù)轉(zhuǎn)換,結(jié)果程序有問題,大家?guī)臀铱纯窗伞^D(zhuǎn)換出的數(shù)據(jù)高位總是1,跪求指點(diǎn)!!! 這兩天把我折磨死了,真是沒有辦法了啊 /***********AD7705.H ************/ #ifndef _AD7705_H #define _AD7705_H #define uchar uns ...… 查看全部問答∨ |
跪求各位高手Simulink環(huán)境中FFT IP核系統(tǒng)實(shí)現(xiàn)的問題! 各位高手,現(xiàn)在本人在做的任務(wù)是,在Matlab/Simulink環(huán)境中,加載Altera的DSP Builder庫(kù)文件,對(duì)FFT IP_Core進(jìn)行測(cè)試,經(jīng)過多天努力,結(jié)果一直不正確,肯定各位高手給予指點(diǎn),不甚感激!!! 1>感覺使能信號(hào)加載沒 ...… 查看全部問答∨ |
設(shè)計(jì)資源 培訓(xùn) 開發(fā)板 精華推薦
- 嵌入式學(xué)習(xí)篇丨迅為4412開發(fā)板Android4.4系統(tǒng)編譯
- Linux系統(tǒng)編程篇丨迅為IMX6ULL-對(duì)應(yīng)視頻講解
- 嵌入式學(xué)習(xí)丨4412開發(fā)板-uboot源碼-匯編-源碼分析(一)嵌入式學(xué)習(xí)丨4412開發(fā)板-uboot源碼-匯
- 迅為IMX6ULL開發(fā)板-主頻和時(shí)鐘配置例程(二)
- 迅為IMX6ULL開發(fā)板-主頻和時(shí)鐘配置例程
- 迅為IMX6ULL開發(fā)板安裝VMware Tool工具
- i.MX6ULL終結(jié)者Debian文件系統(tǒng)的構(gòu)建i.MX6ULL 移植Debian文件系統(tǒng)
- 迅為i.MX6ULL開發(fā)板按鍵例程編譯及運(yùn)行
- 迅為-i.MX6開發(fā)板手冊(cè)更新-非設(shè)備樹uboot-修改默認(rèn)環(huán)境變量
- 迅為-IMX6ULL-QT應(yīng)用_在開發(fā)板上移植ssh
- 迅為-i.MX6ULL開發(fā)板-QT實(shí)戰(zhàn)項(xiàng)目DHT11&網(wǎng)絡(luò)編程實(shí)戰(zhàn)練習(xí)(一)
- 迅為-i.MX6ULL開發(fā)板-網(wǎng)絡(luò)測(cè)試方法(二)
- 迅為-IMX6開發(fā)板設(shè)備樹-Linux內(nèi)核配置兩路can
- 4412開發(fā)板一鍵燒寫QT程序到開發(fā)板-安裝ssh
- 迅為iTOP-i.MX6ULL開發(fā)板-網(wǎng)絡(luò)通信-套字節(jié)UDP
- 迅為iTOP-i.MX6ULL開發(fā)板-網(wǎng)絡(luò)通信-套字節(jié)TCP
- ROHM推出支持負(fù)電壓和高電壓(40V/80V)的高精度電流檢測(cè)放大器
- 迅為IMX6開發(fā)板非設(shè)備樹源碼編譯環(huán)境搭建(一)
- 迅為i.MX6ULL開發(fā)板Platform設(shè)備驅(qū)動(dòng)運(yùn)行測(cè)試
- 有獎(jiǎng)直播|ADI多參數(shù)光水質(zhì)分析平臺(tái)
- 駿龍科技攜手ADI有獎(jiǎng)直播:隔離系統(tǒng)設(shè)計(jì)的隱藏成本
- 最后一周:免費(fèi)獲取Pasternack《RF產(chǎn)品選型指南》2018 印刷版!
- 新活動(dòng)上線!ST NUCLEO-U575ZI-Q免費(fèi)測(cè)評(píng)來了~
- 搶先體驗(yàn)!世界首款LoRa Soc單片機(jī)STM32WL
- 聽技術(shù)大咖侃談Type-C 測(cè)量那些事兒—— 即刻獲取能量,輕松闖關(guān)贏禮品!
- Littelfuse第3期:新型SSA系列雙端超低分流電阻器
- 將低功耗設(shè)計(jì)進(jìn)行到底——評(píng)論、轉(zhuǎn)發(fā)贏大禮!
- 人工智能顛覆醫(yī)療行業(yè)嗎?
- 改變出行方式的自動(dòng)駕駛 普及之路還有多遠(yuǎn)?
- 蘋果手機(jī)產(chǎn)生的赤字 都要算在中國(guó)頭上?
- 揭秘區(qū)塊鏈?zhǔn)謾C(jī):黑科技還是偽概念?
- 工業(yè)機(jī)器人高速增長(zhǎng) RV減速機(jī)國(guó)產(chǎn)化向好
- 加快安全管理機(jī)制創(chuàng)新 支撐泛在電力物聯(lián)網(wǎng)建設(shè)
- 青海電力:從一窮二白到堅(jiān)強(qiáng)電網(wǎng)
- 青海電網(wǎng)發(fā)展大事記
- 我國(guó)需求側(cè)響應(yīng)實(shí)施的關(guān)鍵技術(shù)、市場(chǎng)機(jī)制與展望
- 可穿戴式機(jī)器人的問世將為人類帶來便利
- 《VLMC激光雕刻機(jī)》三,VLMC激光雕刻機(jī)分解---3.1,機(jī)械部分
- 有的筆記本按下顯示切換熱鍵能切換到LCD+CRT extended模式,是怎樣實(shí)現(xiàn)的??
- 關(guān)于28335中I2C的FIFO的問題
- 鋰電池快充技術(shù)對(duì)電池材料與組成結(jié)構(gòu)的要求
- 如何控制變壓器輸出端電壓的開關(guān)
- 分享關(guān)于CIM與PCB的組裝經(jīng)驗(yàn)
- __SWI的具體分析
- 關(guān)于ADXL362加速度計(jì)的坑
- TMS570LS1227 的 MibSpi 從機(jī)接收數(shù)據(jù)設(shè)置(Q&A)
- 穩(wěn)壓二極管使用中的問題