iarc語言怎么做函數(shù) c語言 argc

關(guān)于IAR函數(shù)指針問題

C語言不允許這樣,keil允許是因?yàn)樗皇菄?yán)格的C語言,IAR不允許說明他嚴(yán)格按照C語言標(biāo)準(zhǔn)。

創(chuàng)新互聯(lián)公司專注于亳州企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè),商城網(wǎng)站建設(shè)。亳州網(wǎng)站建設(shè)公司,為亳州等地區(qū)提供建站服務(wù)。全流程專業(yè)公司,專業(yè)設(shè)計,全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)公司專業(yè)和態(tài)度為您提供的服務(wù)

如果是我我會把函數(shù)指針定義為void (*Pq)(uint8),

然后如果有void f(void)類型的函數(shù)就把他定義為void f(uint8 temp){temp=temp; ........ }

在main之前,IAR都做了啥

首先系統(tǒng)復(fù)位時,Cortex-M3從代碼區(qū)偏移0x0000'0000處獲取棧頂?shù)刂?,用來初始化MSP寄存器的值。

接下來從代碼區(qū)偏移0x0000'0004獲取第一個指令的跳轉(zhuǎn)地址。這些地址,是CM3要求放置中斷向量表的地方。

這里是一個程序的啟動區(qū)的反匯編:

__vector_table:

08004000 2600

08004002 2000

08004004 7E1D

08004006 0800

這個程序是由IAP程序來啟動的,IAP程序獲取0x0800'4000處的MSP值(0x20002600),并設(shè)置為MSP的值,即主堆棧最大

范圍是0x2000'0000~0x2000'25FF。接下來IAP程序獲取0x0800'4004處的Reset_Handler的地址

(0x0800'7E1D),并跳轉(zhuǎn)到Reset_Handler()執(zhí)行。

IAP在這里完全是模仿了Cortex-M3的復(fù)位序列,也就是說,在沒有IAP的系統(tǒng)上,CM3只能從0x0800'0000獲取MSP,從

0x0800'0004獲取第一條指令所處地址。而IAP就存在在0x0800'0000這個地址上,IAP的啟動,已經(jīng)消耗掉了這個復(fù)位序列,所以

IAP要啟動UserApp程序的時候,也是完全模仿Cortex-M3的復(fù)位序列的。

接下來我們看看復(fù)位后第一句指令——Reset_Handler()函數(shù)里有什么。

若我們使用的是ST公司標(biāo)準(zhǔn)外設(shè)庫,那么已經(jīng)有了現(xiàn)成的Reset_Handler,不過他是弱定義——PUBWEAK,可以被我們重寫的同名函數(shù)覆蓋。一般來說,我們使用的都是ST提供的Reset_Handler,在V3.4版本的庫中,可以在startup_stm32f10x_xx.s中找到這個函數(shù):

PUBWEAK Reset_Handler

SECTION .text:CODE:REORDER(2)

Reset_Handler

LDR R0, =SystemInit

BLX R0

LDR R0, =__iar_program_start

BX R0

看來ST沒有做太多的事,他只調(diào)用了自家?guī)焯峁┑腟ystemInit函數(shù)進(jìn)行系統(tǒng)時鐘、Flash讀取的初始化,并把大權(quán)交給了

__iar_program_start這個IAR提供的“內(nèi)部函數(shù)”了,我們就跟緊這個__iar_program_start跳轉(zhuǎn),看看IAR做了什

么,上面一段代碼的反匯編如下:

Reset_Handler:

__iar_section$$root:

08007E1C 4801 LDR R0, [PC, #0x4]; LDR R0, =SystemInit

08007E1E 4780 BLX R0;BLX R0

08007E20 4801 LDR R0, [PC, #0x4];LDR R0, =__iar_program_start

08007E22 4700 BX R0;BX R0

08007E24 6C69

08007E26 0800

08007E28 7D8D

08007E2A 0800

細(xì)心的觀眾會發(fā)現(xiàn)地址是0x0800'7E1C,比我們查到的0x0800'7E1D差了1,這是ARM家族的遺留問題,因?yàn)锳RM處理器的指令至

少是半字對齊的(16位THUMB指令集 or

32位ARM指令集),所以PC指針的LSB是常為0的,為了充分利用寄存器,ARM公司給PC的LSB了一個重要的使命,那就是在執(zhí)行分支跳轉(zhuǎn)時,PC

的LSB=1,表示使用THUMB模式,LSB=0,表示使用ARM模式,但在最新的Cortex-M3內(nèi)核上,只使用了THUMB-2指令集挑大梁,所

以這一位要常保持1,所以我們查到的地址是0x0800'7E1D(C=1100,D=1101),放心,我們的CM3內(nèi)核會忽略掉LSB(除非為0,那

么會引起一個fault),從而正確跳轉(zhuǎn)到0x0800'7E1C。

從0x0800'7E20處的加載指令,我們可以算出__iar_program_start所處的位置,就是當(dāng)前PC指針

(0x0800'7E24),再加上4,即0x0800'7E28處的所指向的地址——0x0800'7D8D(0x0800'7D8C),我們跟緊著跳

轉(zhuǎn),__iar_program_start果然在這里:

__iar_program_start:

08007D8C F000F88C BL __low_level_init

08007D90 2800 CMP R0, #0x0

08007D92 D001 BEQ __iar_init$$done

08007D94 F7FFFFDE BL __iar_data_init2

08007D98 2000 MOVS R0, #0x0

08007D9A F7FDFC49 BL main

我們看到IAR提供了__low_level_init這個函數(shù)進(jìn)行了“底層”的初始化,進(jìn)一步跟蹤,我們可以查到__low_level_init這個函數(shù)做了些什么,不是不是我們想象中的不可告人。

__low_level_init:

08007EA8 2001 MOVS R0, #0x1

08007EAA 4770 BX LR

__low_level_init出乎想象的簡單,只是往R0寄存器寫入了1,就立即執(zhí)行"BX

LR"回到調(diào)用處了,接下來,__iar_program_start檢查了R0是否為0,為0,則執(zhí)行__iar_init$$done,若不是0,就

執(zhí)行__iar_data_init2。__iar_init$$done這個函數(shù)很簡單,只有2句話,第一句是把R0清零,第二句就直接"BL

main",跳轉(zhuǎn)到main()函數(shù)了。不過既然__low_level_init已經(jīng)往R0寫入了1,那么我們還是得走下遠(yuǎn)路——看看

__iar_data_init2做了些什么,雖然距離main只有一步之遙,不過這中間隱藏了編譯器的思想,我們得耐心看下去。

__iar_data_init2:

08007D54 B510 PUSH {R4,LR}

08007D56 4804 LDR R0, [PC, #0x10]

08007D58 4C04 LDR R4, [PC, #0x10]

08007D5A E002 B 0x8007D62

08007D5C F8501B04 LDR R1, [R0], #0x4

08007D60 4788 BLX R1

08007D62 42A0 CMP R0, R4

08007D64 D1FA BNE 0x8007D5C

08007D66 BD10 POP {R4,PC}

08007D68 7C78

08007D6A 0800

08007D6C 7C9C

08007D6E 0800

看來IAR遲遲不執(zhí)行main()函數(shù),就是為了執(zhí)行__iar_data_init2,我們來分析分析IAR都干了些什么壞事~

首先壓R4,LR入棧,然后加載0x0800'7C78至R0,0x0800'7C9C至

R4,馬上跳轉(zhuǎn)到0x0800'7D62執(zhí)行R0,R4的比較,結(jié)果若是相等,則彈出R4,PC,然后立即進(jìn)入main()。不過IAR請君入甕是自不會

那么快放我們出來的——結(jié)果不相等,跳轉(zhuǎn)到0x0800'7D5C執(zhí)行,在這里,把R0指向的地址——0x0800'7C78中的值——

0x0800'7D71加載到R1,并且R0中的值自加4,更新為0x0800'7C7C,并跳轉(zhuǎn)到R1指向的地址處執(zhí)行,這里是另一個IAR函

數(shù):__iar_zero_init2:

__iar_zero_init2:

08007D70 2300 MOVS R3, #0x0

08007D72 E005 B 0x8007D80

08007D74 F8501B04 LDR R1, [R0], #0x4

08007D78 F8413B04 STR R3, [R1], #0x4

08007D7C 1F12 SUBS R2, R2, #0x4

08007D7E D1FB BNE 0x8007D78

08007D80 F8502B04 LDR R2, [R0], #0x4

08007D84 2A00 CMP R2, #0x0

08007D86 D1F5 BNE 0x8007D74

08007D88 4770 BX LR

08007D8A 0000 MOVS R0, R0

__iar_data_init2還沒執(zhí)行完畢,就跳轉(zhuǎn)到了這個__iar_zero_inti2,且看我們慢慢分析這個幫兇——__iar_zero_inti2做了什么。

__iar_zero_inti2將R3寄存器清零,立即跳轉(zhuǎn)到0x0800'7D80執(zhí)行'LDR R2, [R0],

#0x4',這句指令與剛才在__iar_data_init2見到的'LDR R1, [R0],

#0x4'很類似,都為“后索引”。這回,將R0指向的地址——0x0800'7C7C中的值——0x0000'02F4加載到R2寄存器,然后R0中的

值自加4,更新為0x0800'7C80。接下來的指令檢查了R2是否為0,顯然這個函數(shù)沒那么簡單想放我我們,R2的值為2F4,我們又被帶到了

0x0800'7D74處,隨后4條指令做了如下的事情:

1、將R0指向的地址——0x0800'7C80中的值——0x2000'27D4加載到R1寄存器,然后R0中的值自加4,更新為0x0800'7C84。

2、將R1指向的地址——0x2000'27D4中的值——改寫為R3寄存器的值——0,然后R1中的值自加4,更新為0x2000'27D8。

3、R2自減4

4、檢查R2是否為0,不為0,跳轉(zhuǎn)到第二條執(zhí)行。不為,則執(zhí)行下一條。

這簡直就是一個循環(huán)!——C語言的循環(huán)for(r2=0x2F4;r2-=4;r!=0){...},我們看看循環(huán)中做了什么。

第一條指令把一個地址加載到了R1——0x2000'27D4

是一個RAM地址,以這個為起點(diǎn),在循環(huán)中,對長度為2F4的RAM空間進(jìn)行了清零的操作。那為什么IAR要做這個事情呢?消除什么記錄么?用Jlink

查看這片內(nèi)存區(qū)域,可以發(fā)現(xiàn)這片區(qū)域是我們定義的全局變量的所在地。也就是說,IAR在每次系統(tǒng)復(fù)位后,都會自動將我們定義的全局變量清零0。

清零完畢后,接下來的指令"LDR R2, [R0],

#0x4"將R0指向的地址——0x0800'7C84中的值——0加載到R2寄存器,然后R0中的值自加4,更新為0x0800'7C88。隨后檢查

R2是否為0,這里R2為0,執(zhí)行'BX

LR'返回到__iar_data_init2函數(shù),若是不為0,我們可以發(fā)現(xiàn)又會跳轉(zhuǎn)至“4指令”處進(jìn)行一個循環(huán)清零的操作。

誰幫我講一下這段IAR的c語言程序,200分重謝!

4-ADC12應(yīng)有例程

//******************************************************************************

//MSP430F149 ADC12模塊+串行通訊的實(shí)驗(yàn)程序

//使用ADC12采集實(shí)驗(yàn),將采集到數(shù)據(jù)送向PC.(單路單次采集)

//P3.4為發(fā)送,P3.5為接收 晶體使32768HZ/8MHZ. 串行波特率B/S

//使用SMCLK作為波特率發(fā)器時,不能使用LPM2,LPM3!

//以下程序已驗(yàn)證通過,初學(xué)者可直接使用.由時間倉促和水平有限,請讀者批評指正.

//編寫:

//******************************************************************************

#include msp430x14x.h

//********************************************

//表區(qū)

unsigned char number_table[]={'0','1','2','3','4','5','6','7','8','9'};

unsigned char display_buffer[]={0x00,0x00,0x00,0x00,0xff};

//*******************波特率***********300 600 1200 2400 4800 9600 19200 38400 76800 115200const

//************************************[0]**[1]**[2]*[3]**[4]**[5]***[6]***[7]****[8]***[9]*

unsigned char BaudrateUBR0[] ={0x6D,0x36,0x1B,0x0D,0x06,0x03, 0xA0, 0xD0, 0x68, 0x45};

unsigned const char BaudrateUBR1[] ={0x00,0x00,0x00,0x00,0x00,0x00, 0x01, 0x00, 0x00, 0x00};

unsigned const char BaudrateUMCTL[]={0x22,0xD5,0x03,0x6B,0x6F,0x4A, 0xC0, 0x40, 0x40, 0x4A};

unsigned char timp;

//變量區(qū)

unsigned int ADC0 ;

//子程序聲明

void init (void); //初始化

void ADC12setup(void); //ADC12初始化

void BaudrateSetup(unsigned char U0); //UART0初始化

void data_converter(unsigned char *p,unsigned int vaule); //數(shù)據(jù)變換

void send_data(unsigned char *p); //串行口發(fā)送數(shù)組

//********************************************

void main(void)

{

init();

//主循環(huán)

for ()

{

LPM0;

ADC12CTL0 |= ADC12SC; //sampling open,AD轉(zhuǎn)換完成后(ADC12BUSY=0),ADC12SC自動復(fù)位;

while((ADC12IFG BIT0) == 0); //等轉(zhuǎn)換結(jié)束

ADC0 = ADC12MEM0; //讀轉(zhuǎn)換數(shù)據(jù)值,同時清ADC12IFG0標(biāo)志

data_converter(display_buffer,ADC0); //數(shù)據(jù)變換

send_data(display_buffer); //發(fā)送數(shù)據(jù)

}

}

//********************************************************************************

void init(void)

{

WDTCTL = WDTPW + WDTHOLD; // 停止WDT

P1DIR=0x01;P1OUT=0x0f; //LED設(shè)置

BaudrateSetup(6);

ADC12setup();

_EINT(); // 全局中斷使能

}

//**********************************************************************************

//串口接收中斷,退出LPM0模式.

#pragma vector=USART0RX_VECTOR

__interrupt void usart0_rx (void)

{

LPM0_EXIT;

}

//**********************************************************************************

//ADC12初始化

void ADC12setup(void)

{

//ADC12設(shè)置**************************

P6SEL |= 0x01; //使用A/D通道 A0

ADC12CTL0 = ADC12ON ; //開ADC12內(nèi)核,設(shè)SHT0=2 (N=4)

ADC12CTL1 = SHP ; //SAMPCON信號選為采樣定時器輸出

//ADC12內(nèi)部參考電壓設(shè)置

ADC12CTL0 |= REF2_5V; //選用內(nèi)部參考電壓為2.5V

ADC12CTL0 |= REFON; //內(nèi)部參考電壓打開

ADC12MCTL0 |= SREF_1; //R+=2.5V R-=VSS

//轉(zhuǎn)換允許

ADC12CTL0 |= ENC ; //轉(zhuǎn)換允許(上升沿)

ADC0=0x00;

}

//**********************************************************************************

//UART0初始化

void BaudrateSetup(unsigned char U0)

{

unsigned int i;

if(U05) //當(dāng)U05時,啟用XT2

{

BCSCTL1 = ~XT2OFF; //啟動XT2,

do

{ IFG1 = ~OFIFG; //清OSCFault標(biāo)志

for(i=0xFF;i0;i--); //延時等待

}

while((IFG1 OFIFG) != 0); //查OSCFault,為0時轉(zhuǎn)換完成

BCSCTL2 |= SELS; //SMCLK為XT2

}

//UART0

P1OUT=0x00;

if(U05){UTCTL0=SSEL1;} // 時鐘源:SMCLK

else{UTCTL0=SSEL0;} // 時鐘源:ACLK

UCTL0 = ~SWRST; // SWRST復(fù)位, USART允許

UCTL0=CHAR; // 8bit

ME1|=UTXE0 + URXE0; // Enable Tx0,Rx0

IE1|=URXIE0; // RX使能

UBR00=BaudrateUBR0[U0]; // 低位分頻器因子

UBR10=BaudrateUBR1[U0]; // 高位分頻器因子

UMCTL0=BaudrateUMCTL[U0]; // 波特率調(diào)整因子

P3SEL |= 0x30; // 將P3.4,5使用外圍模塊 = USART0 TXD/RXD

P3DIR |= 0x10; // 將P3.4設(shè)為輸出(發(fā)),P3.5默認(rèn)為輸入(收)

}

//**********************************************************************************

//數(shù)據(jù)變換

void data_converter(unsigned char *p,unsigned int value)

{

unsigned int m,n,j=0;

p[0]=number_table[value/1000];

m=value%1000;

p[1]=number_table[m/100];

n=m%100;

p[2]=number_table[n/10];

j=n%10;

p[3]=number_table[j/1];

}

//**********************************************************************************

//串行口發(fā)送數(shù)組

void send_data(unsigned char *p)

{unsigned int n;

timp=RXBUF0;

for(n=0;p[n]!=0xff;n++)

{

while ((IFG1 UTXIFG0) == 0); // USART0發(fā)送UTXIFG0=1,表示UTXBUF準(zhǔn)備好發(fā)送一下字符

TXBUF0 = p[n];

}

}

//**********************************************************************************

//ADC12模塊例程(1)結(jié)速

iar中怎么設(shè)置使用printf函數(shù)

添加相應(yīng)的頭文件即可。

IAR中使用printf()函數(shù)和允許位定義的方法

⑴使用printf()函數(shù):

①包含stdio.h頭文件

②編寫putchar函數(shù)

示例:

int putchar(int c)

{

while (!(UCSRA 0x20));

return (UDR=c);

}

③設(shè)置

Option

名稱欄目:iarc語言怎么做函數(shù) c語言 argc
文章地址:http://bm7419.com/article6/ddephog.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供響應(yīng)式網(wǎng)站、微信公眾號、小程序開發(fā)、網(wǎng)站制作、標(biāo)簽優(yōu)化、微信小程序

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司