導航:首頁 > 操作系統 > 單片機結構體的應用

單片機結構體的應用

發布時間:2022-09-18 17:43:52

1. ARM單片機的頭文件如何用結構體定義地

下面我們以ARM Cortex-M0內核單片機LPC1114的頭文件lpc11xx.h文件進行說明。

1.先說兩句

lpc11xx.h文件是lpc11xx系列單片機包含的頭文件。這個文件的作用和51單片機中的reg51.h頭文件是一個性質,都是用來定義寄存器在單片機中的地址的。

你現在就可以打開reg51.h文件和lpc11xx.h文件看看,對比後你會發現兩個主要的區別,首先是lpc11xx.h文件的寄存器定義是用結構體的形式,而reg51.h文件中,寄存器的定義都是一條一條的很直接的地址定義。然後是reg51.h文件中有sfr這樣的「偽c語言」,而lpc11xx.h中用的是標準的c語言。C語言的最大用武之地就是單片機,要想學c,就在單片機上學,要想學單片機,就先入門c語言。兩者相輔相成的學,效果最好。學以致用,才是學習的最終目標。

2.lpc11xx.h文件中如何定義寄存器地址?

在文件中,定義寄存器地址用到了一下幾方面的c語言基礎知識:

結構體;

結構體指針;

宏定義#define

關鍵字typedef

關鍵字volatile

關鍵字const

lpc11xx.h文件中,把每個模塊都定義了一個結構體,這些模塊有SYSCON、IOCON、UART、GPIO、SSP、I2C、WDT、ADC等。

例如,下面是ADC模塊的結構體定義:

typedef struct
{
__IO uint32_t CR;
__IO uint32_t GDR;
uint32_t RESERVED0;
__IO uint32_t INTEN;
__IO uint32_t DR[8];
__I uint32_t STAT;
} LPC_ADC_TypeDef;

結構體的定義有三種形式,我們這里使用的是「直接說明變數」的形式。

lpc11xx.h文件的第566~584行,給每個模塊的結構體變數定義了結構體指針,並加了宏定義#define,為的是以後寫程序時書寫方便。

把滑鼠放到uint32_t上面,單擊滑鼠右鍵,在彈出的菜單中選擇「Go To Definition Of 『uint32_t』」,如下圖所示:

選擇後,就會跳到它的定義之處,如下圖所示:

typedef是類型重定義關鍵字,所以實際上,CR寄存器的定義是這樣的:

__IO unsigned int CR;

按照同樣的方法,可以找到__IO的定義為:

所以,CR寄存器定義實際上是:

volatile unsigned int CR;

volatile關鍵字的作用是為了讓編譯器不要優化這個變數。

unsigned int關鍵字,用來定義無符號的整形變數。

這時候,有人會問,為什麼不直接寫成這樣呢?答:為了閱讀方便。

__IO uint32_t CR;

看到這條語句,我們就會知道,CR寄存器是一個「32位的可讀可寫寄存器」。

volatile unsigned int CR;

同樣的這句話,我們對它的了解就不是那麼一目瞭然了。

3.如何查看每個寄存器的地址?

上面講到,寄存器的地址是由結構體和結構體指針定義的。現在我們來驗證一下它的正確性。

我們隨便找個寄存器,比如ADC模塊的INTEN寄存器(ADC中斷允許寄存器),打開LPC1114的用戶手冊,找到第25章ADC模塊部分,如下圖所示:

從上面圖中,可以看到INTEN的寄存器的地址是0x4001C00C,接下來,我們打開lpc11xx.c文件來驗證一下吧。

打開lpc11xx.c文件,找到ADC模塊的結構體,如下圖所示:

然後再找到LPC_ADC_TypeDef的結構體指針,如下所示:

結構體指針就是用來指向一個地址的,我們來看看上面語句中的LPC_ADC_BASE是什麼:

再看看上條語句中的LPC_APB0_BASE是什麼:

現在終於挖到底了,原來LPC_ADC_TypeDef指針指向的地址為:

0x40000000+0x1C000=0x4001C000

c語言基礎知識:結構體的第一個變數的地址=結構體指針的地址。

所以結構體的第一個變數地址就是0x4001C000,INTEN前面有3個4位元組的變數,所以INTEN的地址就是0x4001C00C。

驗證完畢。

4.程序中,如何操作寄存器?

C語言基礎知識:用結構體變數指針訪問結構體中的變數,形式有兩種:

*結構體指針變數.變數名

結構體指針變數->變數名

還是拿INTEN寄存器為例,假設我們要給這個寄存器寫0x837,可以這樣寫:

*LPC_ADC.INTEN=0x837;

LPC_ADC->INTEN=0X837;

以上兩種形式,在寫程序的時候,都可以用。人們習慣用第二種形式。

2. C51單片機語言枚舉和結構體在單片機裡面究竟用來處理什麼功能

枚舉和結構體的應用都差不多.
通常都是定義一個結構體或枚舉,然後再用其定義成一個數組,
舉例,有人做字型檔時有結構體,
裡麵包括一個unsigned int用於存漢字代碼,
一個unsigned char[32]用於存點陣.
然後用該結構定義一個數組,
然後查詢數組里unsigned int是否對應漢字,如果對應,則unsigned char[32]為該漢字的點陣,
這通常應用於LCD漢字顯示.

總的一句話,就是方便數據歸類,
如果學過C++,其實就有點類似C++的類,
當然,這比類要弱很多很多.

3. C語言結構體的應用疑問

定義一個函數,名字為Dma_GetDescriptor,它的形式參數是(unsigned int iChan,boolean bAlternate),它的函數原型是{。。。},它的返回值類型是DmaDesc * ,也就是上文定義的一個
結構體類型的指針。

4. 單片機通信是,定義的結構體要怎麼傳輸。

需要明白一個道理,串口協議有規定位數,不管定義什麼類型,都需要按照串口協議才能傳輸出去。如:常用的8位USART,傳輸的數據如是十進制600,需要按照串口協議拆開傳輸。這就要自己做協議了

5. 51單片機在Keil環境下,用C語言編程,關於片外存儲區xdata中存放結構體類型的數據的問題,替朋友問的。

Keil本身對STC單片機缺乏支持,對外部xram沒有資料庫描述。在器件庫中選個帶xram的單片機就可以了,比如sst89x516rd.

6. c語言中如何定義一個結構體

結構體的定義如下所示,struct為結構體關鍵字,tag為結構體的標志,member-list為結構體成員列表,其必須列出其所有成員;variable-list為此結構體聲明的變數。在一般情況下,tag、member-list、variable-list這3部分至少要出現2個。

結構體的成員可以包含其他結構體,也可以包含指向自己結構體類型的指針,而通常這種指針的應用是為了實現一些更高級的數據結構如鏈表和樹等。如果兩個結構體互相包含,則需要對其中一個結構體進行不完整聲明。

(6)單片機結構體的應用擴展閱讀:

一、結構體作用:

結構體和其他類型基礎數據類型一樣,例如int類型,char類型,只不過結構體可以做成你想要的數據類型,以方便日後的使用。

在實際項目中,結構體是大量存在的,研發人員常使用結構體來封裝一些屬性來組成新的類型。由於C語言內部程序比較簡單,研發人員通常使用結構體創造新的「屬性」,其目的是簡化運算。

結構體在函數中的作用不是簡便,其最主要的作用就是封裝。封裝的好處就是可以再次利用。讓使用者不必關心這個是什麼,只要根據定義使用就可以了。

二、結構體的大小與內存對齊:

結構體的大小不是結構體元素單純相加就行的,因為我們主流的計算機使用的都是32bit字長的CPU,對這類型的CPU取4個位元組的數要比取一個位元組要高效,也更方便。

所以在結構體中每個成員的首地址都是4的整數倍的話,取數據元素時就會相對更高效,這就是內存對齊的由來。每個特定平台上的編譯器都有自己的默認「對齊系數」(也叫對齊模數)。

程序員可以通過預編譯命令#pragma pack(n),n=1,2,4,8,16來改變這一系數,其中的n就是你要指定的「對齊系數」。

三、結構體的規則:

1、數據成員對齊規則:結構(struct)(或聯合(union))的數據成員,第一個數據成員放在offset為0的地方,以後每個數據成員的對齊按照#pragma pack指定的數值和這個數據成員自身長度中,比較小的那個進行。

2、結構(或聯合)的整體對齊規則:在數據成員完成各自對齊之後,結構(或聯合)本身也要進行對齊,對齊將按照#pragma pack指定的數值和結構(或聯合)最大數據成員長度中,比較小的那個進行。

3、結合1、2可推斷:當#pragma pack的n值等於或超過所有數據成員長度的時候,這個n值的大小將不產生任何效果。

7. 單片機的位域是什麼意思如何使用

標准C提供了一種基於結構體的數據結構--位域(BitField),位域就是把一個
存儲單元
中的
二進制
劃分為幾個不同的區域。並說明每個區域的
位數。每一個域有一個
域名
,允許在
程序
中按域名進行操作,位域的定義格式如下:
struct
位域結構名{
位域列表
};
位域列表格式為:類型說明符
位域名:位域長度如:
struct
k{
unsigned
int
a:1
unsigned
int
:2
unsigned
int
b:3
unsigned
int
:0

//空域
}k1;
說明:
1)各位依次從低位到高位排列,排滿一個存儲單元,按地址接著排下一單元;
2)位域可以無域名,但不能被引用,如
第二域
,這時其只用來填充或調整位置;
3)第四行稱空域,目的是將目前存儲單元的剩餘部分分為一個域,且填充0。
位域的引用很簡單,如:
k1.a=1;
//置k1的b0位為1
k1.b=7;
//將k1的b3-5位置111
通過位域定義位
變數
,是實現單
個位
位操作的重要途徑和方法,採用位域定義位變數,產生的
代碼
緊湊、高效。這種位域應用於
單片機
開發比較普遍。

8. 在keil C51中使用結構體的問題

樓主沒有搞清楚 51的 結構.
樓上說的雖然大多是廢話,,對你的項目可以沒多少幫助
但是至少有一點是對的..設置成xdata可以解決你的問題.
雖然不是什麼好辦法.

51的 ram 分外三種.
內部直接定址你的128byte 內部間接的128byte
還有就是外部 ram

你的51單片機有512byte
那麼肯定是 內部 直接 間接各128
外加外部256位元組

你把那些大一點的數據全部改成 xdata 聲明就可以了.
當然如果你會控制ram大小的話..用idata 聲明效率更好一點
例如 unsigned char yy;
寫個成 unsigned char xdata yy;

(你看你自己的編譯結果顯示 data=137, xdata=0, code=4856
就應該猜測一下 xdata 干嗎用的了

最後 建議樓主. 最好不用在keil c51裡面使用printf函數(浪費啊)
回去.仔細看一遍51的結構..然後看看keil c51的區別於ansi c的東西
會對你有幫助

如果對您有幫助,請記得採納為滿意答案,謝謝!祝您生活愉快!

9. 學什麼單片機好學單片機怎麼樣能賺錢嗎有前途嗎

先學51單片機,可以看看學習視頻,對於每個人來說,多學習一種技能 可以拓寬 就業渠道,

單片機學習可以先學習一些模擬示例,如

#include<reg51.h>

#define uchar unsigned char

uchar temp;

int key1,key,disbuf;// 此表為 LED 的字模 0 1 2 3 4 5 6 7 8 9 a b c d e f

unsigned char code LED7Code[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};

unsigned char ledx[8];

uchar t,j,i;

bit s0,s1;

void scan() //要是按鍵了,掃描鍵盤編碼值

{

P1=0xF0;

for(j=0;j<250;j++);

temp=P1;

switch(temp)

{

case 0xe0: key1=0; //

break;

case 0xd0: key1=1; //

break;

case 0xb0: key1=2; //

break;

case 0x70: key1=3; //

break;

}

P1=0x0f;

for(j=0;j<250;j++)

temp=P1;

switch(temp)

{

case 0x0E: key=key1+0;

break;

case 0x0D: key=key1+4;

break;

case 0x0B: key=key1+8;

break;

case 0x07: key=key1+12;

break;

default : key=-1;

}

if((key1+1)&&(key+1)) disbuf=key;

}

void ejjc() //判斷是否按鍵

{

P1=0xF0;

if(P1!=0xF0) { scan();s0=1;}

else { s0=0; s1=1;}

}

void main()

{

TMOD=0x51; // T1 外部計數

TH0=(65535-2000)/256;

TL0=(65535-2000)%256;

EA=1;

ET0=1; //開定時器0中斷

ET1=1; //開定時器1中斷

TR0=1; //啟動定時器0

TR1=1; //啟動定時器1

while(1)

{

ejjc();

if(s0==1 && s1==1)

{

s0=0;s1=0;

for(i=0;i<8;i++)

{ ledx[i]=ledx[i+1]; ledx[8]=disbuf; }

}

}

}

void timer0() interrupt 1

{

TH0=(65535-2000)/256;

TL0=(65535-2000)%256;

P0=0xff;

switch(t)

{

case 0: P2=LED7Code[ledx[0]]; P0=0xfe;break;

case 1: P2=LED7Code[ledx[1]]; P0=0xfd;break;

case 2: P2=LED7Code[ledx[2]]; P0=0xfb;break;

case 3: P2=LED7Code[ledx[3]]; P0=0xf7;break;

case 4: P2=LED7Code[ledx[4]]; P0=0xef;break;

case 5: P2=LED7Code[ledx[5]]; P0=0xdf;break;

case 6: P2=LED7Code[ledx[6]]; P0=0xbf;break;

case 7: P2=LED7Code[ledx[7]]; P0=0x7f;break;

}

t++;

if(t==8) t=0;

}

10. 單片機的位域是什麼意思如何使用

標准C提供了一種基於結構體的數據結構--位域(BitField),位域就是把一個存儲單元中的二進制劃分為幾個不同的區域。並說明每個區域的
位數。每一個域有一個域名,允許在程序中按域名進行操作,位域的定義格式如下:
struct
位域結構名{
位域列表
};
位域列表格式為:類型說明符
位域名:位域長度如:
struct
k{
unsigned
int
a:1
unsigned
int
:2
unsigned
int
b:3
unsigned
int
:0

//空域
}k1;
說明:
1)各位依次從低位到高位排列,排滿一個存儲單元,按地址接著排下一單元;
2)位域可以無域名,但不能被引用,如第二域,這時其只用來填充或調整位置;
3)第四行稱空域,目的是將目前存儲單元的剩餘部分分為一個域,且填充0。
位域的引用很簡單,如:
k1.a=1;
//置k1的b0位為1
k1.b=7;
//將k1的b3-5位置111
通過位域定義位變數,是實現單個位位操作的重要途徑和方法,採用位域定義位變數,產生的代碼緊湊、高效。這種位域應用於單片機開發比較普遍。

閱讀全文

與單片機結構體的應用相關的資料

熱點內容
單片機的功能模塊 瀏覽:769
安卓手機如何錄制視頻長時間 瀏覽:283
安全問題app哪個好 瀏覽:445
壓縮水會變冰嗎 瀏覽:526
小說配音app哪個靠譜 瀏覽:820
編譯iso 瀏覽:944
照片生成pdf格式 瀏覽:194
病歷轉pdf 瀏覽:835
雲伺服器配硬體 瀏覽:978
伺服器10k什麼意思 瀏覽:21
pdfeditor漢化 瀏覽:884
新科學pdf 瀏覽:746
現在還有c語言編譯嗎 瀏覽:675
哪裡買到單片機 瀏覽:480
linux文件打開數量 瀏覽:510
編譯原理中什麼是l屬性文法 瀏覽:372
硬碟加密時出現的問題 瀏覽:61
如何退域命令 瀏覽:108
看書的app哪裡看 瀏覽:291
伺服器怎麼調大 瀏覽:4