在網(wǎng)上查了很長(cháng)時(shí)間關(guān)于頭文件的資料,但是發(fā)現很難找到適合我的。學(xué)單片機的朋友知道,很多程序經(jīng)常要調用相同的函數,如果每寫(xiě)一個(gè)程序都把這些函數重新寫(xiě)一遍或者復制過(guò)來(lái),那是很浪費時(shí)間的,現在我通過(guò)學(xué)習總結以及別人的經(jīng)驗,跟大家分享,歡迎大家轉載學(xué)習。
寫(xiě)程序最好是結構化編程,因為這樣的程序看起來(lái)就不那么長(cháng)了,一目了然,可以很快就知道這個(gè)程序實(shí)現什么功能,而且排錯也非常簡(jiǎn)單。把常用的函數聲明、自定義類(lèi)型、外部變量的聲明等寫(xiě)進(jìn)頭文件,與之配對的擴展名為.c的文件就寫(xiě)常用的函數,main.c最好就寫(xiě)一個(gè)主函數。之前學(xué)的51單片機,現在玩430單片機,就以430單片機為例,其他編程軟件道理與這個(gè)相同。在IAR下新建工程,包含了main.c、mydefine.c和mydefine.h(mydefine.c和mydefine.h是一對)三個(gè)文件(注:可包含多個(gè)配對的頭文件和C文件)。先把程序貼出來(lái),再詳解其中緣由。
main.c內容:
#include "mydefine.h"
void main( void )
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
SegInitial(); //數碼管控制引腳初始化
long m = 0;
while(1)
{
disp(m); //顯示m的值
delay(10);
m++;
if(m == 1000000)
m = 0;
}
}
mydefine.h的內容
#ifndef _MYDEFINE_H
#define _MYDEFINE_H
#include "msp430x14x.h"
typedef unsigned int uint;
typedef unsigned char uchar;
void write_595(uchar dat);
void SegInitial(void);
void disp(long num);
void delays(uint x);
void delay(uint x);
#endif
mydefine.c的內容
#include "mydefine.h"
#include "msp430x14x.h"
/*********************************
流水燈74hc595各引腳定義
*********************************/
#define CLK0 P2OUT &= ~BIT4
#define CLK1 P2OUT |= BIT4
#define STB0 P2OUT &= ~BIT2
#define STB1 P2OUT |= BIT2
#define DS0 P2OUT &= ~BIT5
#define DS1 P2OUT |= BIT5
#define LEDOFF P5OUT = 0x00
uchar dis_num[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //數碼管0~F共陽(yáng)編碼
uchar bitnum[]={0x01,0x02,0x04,0x08,0x10,0x20}; //數碼管位選
uchar dispbuf[6]; //數碼管顯示緩沖區
//以下是延時(shí)函數
void delay(uint x)
{
uint a,b;
for(a=x;a>0;a--)
for(b=10000;b>0;b--);
}
//控制流水燈,使用P2.2(STB),P2.4(CLK),P2.5(DS)
void write_595(uchar dat)
{
uint n;
for(n = 0;n<8;n++)
{
if((dat&0x80) == 0x80)
DS1;
else
DS0;
dat <<= 1;
CLK0;
CLK1;
}
STB1;
STB0;
}
/*****************************************
數碼管顯示初始化函數
*****************************************/
void SegInitial(void)
{
P5DIR = 0XFF;
P4DIR = 0XFF;
P5OUT = 0X00;
P4OUT = 0X00;
}
/****************************************
數碼管防重影延時(shí)函數
*****************************************/
void delays(uint x)
{
for(;x>0;x--);
}
/*****************************************
數碼管顯示函數
位選 P5.0~P5.5
段選 P4
*****************************************/
void disp(long num)
{
uint i;
dispbuf[0] = num%10;
dispbuf[1] = num/10%10;
dispbuf[2] = num/100%10;
dispbuf[3] = num/1000%10;
dispbuf[4] = num/10000%10;
dispbuf[5] = num/100000%10;
for(i=0;i<6;i++)
{
P4OUT = dis_num[dispbuf[i]];
P5OUT = bitnum[i];
delays(400);
P5OUT=0X00;
}
}
首先看main.c里面就寫(xiě)了一個(gè)主函數,它告訴讀者該程序的主要功能。mydefine.h里面包含了一些函數的聲明,如果使用到外部變量(或函數),則需要在該變量(或函數)前寫(xiě)extern加以說(shuō)明其為外部變量(或函數)。寫(xiě)頭文件一定要注意:
#ifndef XXXX
#define XXXX
.
.
.
.
.
.
#endif
其中XXXX習慣大寫(xiě),名稱(chēng)不要與關(guān)鍵字相同,習慣寫(xiě)法請參照上面的程序,#ifndef XXXX #define XXXX ..... #endif的作用是有些頭文件已經(jīng)在其他文件里包含過(guò)了,但是你在這個(gè)文件也包含了,如果沒(méi)有上面那一句,則編譯器會(huì )報錯:重復定義!mydefine.c中用到了mydefine.h中的定義,則需要把mydefine包含進(jìn)來(lái),包含mydefine.h的意思是mydefine.h替換為mydefine.h的內容,即mydefine.c的完整內容為:
#include "msp430x14x.h"
typedef unsigned int uint;
typedef unsigned char uchar;
void write_595(uchar dat);
void SegInitial(void);
void disp(long num);
void delays(uint x);
void delay(uint x);
/*********************************
流水燈74hc595各引腳定義
*********************************/
#define CLK0 P2OUT &= ~BIT4
#define CLK1 P2OUT |= BIT4
#define STB0 P2OUT &= ~BIT2
#define STB1 P2OUT |= BIT2
#define DS0 P2OUT &= ~BIT5
#define DS1 P2OUT |= BIT5
/*********************************
流水燈74hc595各引腳定義
*********************************/
#define LEDOFF P5OUT = 0x00
uchar dis_num[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
uchar bitnum[]={0x01,0x02,0x04,0x08,0x10,0x20};
uchar dispbuf[6];
//以下是延時(shí)函數
void delay(uint x)
{
uint a,b;
for(a=x;a>0;a--)
for(b=10000;b>0;b--);
}
//控制流水燈,使用P2.2(STB),P2.4(CLK),P2.5(DS)
void write_595(uchar dat)
{
uint n;
for(n = 0;n<8;n++)
{
if((dat&0x80) == 0x80)
DS1;
else
DS0;
dat <<= 1;
CLK0;
CLK1;
}
STB1;
STB0;
}
/*****************************************
數碼管顯示初始化函數
*****************************************/
void SegInitial(void)
{
P5DIR = 0XFF;
P4DIR = 0XFF;
P5OUT = 0X00;
P4OUT = 0X00;
}
/****************************************
數碼管延時(shí)函數
*****************************************/
void delays(uint x)
{
for(;x>0;x--);
}
/*****************************************
數碼管顯示函數
位選 P5.0~P5.5
段選 P4
*****************************************/
void disp(long num)
{
uint i;
dispbuf[0] = num%10;
dispbuf[1] = num/10%10;
dispbuf[2] = num/100%10;
dispbuf[3] = num/1000%10;
dispbuf[4] = num/10000%10;
dispbuf[5] = num/100000%10;
for(i=0;i<6;i++)
{
P4OUT = dis_num[dispbuf[i]];
P5OUT = bitnum[i];
delays(400);
P5OUT=0X00;
}
}
下面講一下mydefine.c的功能,一些常用函數都寫(xiě)在里面,一般情況下我們寫(xiě)好頭文件后不必對函數的原型進(jìn)行深究,只需知道函數的功能即可,即頭文件里的函數聲明,多個(gè)C文件編譯鏈接的時(shí)候,相當于主函數放在前面,其他函數放在后面,調用函數的時(shí)候就必須先對這些函數進(jìn)行聲明,否則編譯器不知道你的函數原型是什么,而這些頭文件就起到了函數聲明的作用,所謂頭文件就可以理解為在main函數前面事先要處理的程序(即聲明和定義)。
下面把這個(gè)結構化編程的等效程序貼出來(lái),以方便大家理解:
#include "msp430x14x.h"
typedef unsigned int uint;
typedef unsigned char uchar;
void write_595(uchar dat);
void SegInitial(void);
void disp(long num);
void delays(uint x);
void delay(uint x);
void main( void )
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
SegInitial();
long m = 0;
while(1)
{
disp(m);
delay(10);
m++;
if(m == 1000000)
m = 0;
}
}
/*********************************
流水燈74hc595各引腳定義
*********************************/
#define CLK0 P2OUT &= ~BIT4
#define CLK1 P2OUT |= BIT4
#define STB0 P2OUT &= ~BIT2
#define STB1 P2OUT |= BIT2
#define DS0 P2OUT &= ~BIT5
#define DS1 P2OUT |= BIT5
/*********************************
流水燈74hc595各引腳定義
*********************************/
#define LEDOFF P5OUT = 0x00
uchar dis_num[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
uchar bitnum[]={0x01,0x02,0x04,0x08,0x10,0x20};
uchar dispbuf[6];
//以下是延時(shí)函數
void delay(uint x)
{
uint a,b;
for(a=x;a>0;a--)
for(b=10000;b>0;b--);
}
//控制流水燈,使用P2.2(STB),P2.4(CLK),P2.5(DS)
void write_595(uchar dat)
{
uint n;
for(n = 0;n<8;n++)
{
if((dat&0x80) == 0x80)
DS1;
else
DS0;
dat <<= 1;
CLK0;
CLK1;
}
STB1;
STB0;
}
/*****************************************
數碼管顯示初始化函數
*****************************************/
void SegInitial(void)
{
P5DIR = 0XFF;
P4DIR = 0XFF;
P5OUT = 0X00;
P4OUT = 0X00;
}
/****************************************
數碼管延時(shí)函數
*****************************************/
void delays(uint x)
{
for(;x>0;x--);
}
/*****************************************
數碼管顯示函數
位選 P5.0~P5.5
段選 P4
*****************************************/
void disp(long num)
{
uint i;
dispbuf[0] = num%10;
dispbuf[1] = num/10%10;
dispbuf[2] = num/100%10;
dispbuf[3] = num/1000%10;
dispbuf[4] = num/10000%10;
dispbuf[5] = num/100000%10;
for(i=0;i<6;i++)
{
P4OUT = dis_num[dispbuf[i]];
P5OUT = bitnum[i];
delays(400);
P5OUT=0X00;
}
}
希望這些總結能對大家有所幫助,又不能理解的地方,可以互相交流一下。