打印
[文档下载]

教你如何高效编程之头文件书写

[复制链接]
996|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
春风的暖暖|  楼主 | 2015-8-4 21:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在网上查了很长时间关于头文件的资料,但是发现很难找到适合我的。学单片机的朋友知道,很多程序经常要调用相同的函数,如果每写一个程序都把这些函数重新写一遍或者复制过来,那是很浪费时间的,现在我通过学习总结以及别人的经验,跟大家分享,欢迎大家转载学习。        写程序最好是结构化编程,因为这样的程序看起来就不那么长了,一目了然,可以很快就知道这个程序实现什么功能,而且排错也非常简单。把常用的函数声明、自定义类型、外部变量的声明等写进头文件,与之配对的扩展名为.c的文件就写常用的函数,main.c最好就写一个主函数。之前学的51单片机,现在玩430单片机,就以430单片机为例,其他编程软件道理与这个相同。在IAR下新建工程,包含了main.c、mydefine.c和mydefine.h(mydefine.c和mydefine.h是一对)三个文件(注:可包含多个配对的头文件和C文件)。先把程序贴出来,再详解其中缘由。


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共阳编码
uchar bitnum[]={0x01,0x02,0x04,0x08,0x10,0x20};         //数码管位选
uchar dispbuf[6];                                                             //数码管显示缓冲区


//以下是延时函数
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;
}




/****************************************
          数码管防重影延时函数


*****************************************/
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];
      P5OUT = bitnum;
      delays(400);
      P5OUT=0X00;
    }
}


首先看main.c里面就写了一个主函数,它告诉读者该程序的主要功能。mydefine.h里面包含了一些函数的声明,如果使用到外部变量(或函数),则需要在该变量(或函数)前写extern加以说明其为外部变量(或函数)。写头文件一定要注意:

#ifndef XXXX
#define XXXX
        .

        .

        .

        .

        .

        .

#endif

其中XXXX习惯大写,名称不要与关键字相同,习惯写法请参照上面的程序,#ifndef XXXX    #define  XXXX   .....   #endif的作用是有些头文件已经在其他文件里包含过了,但是你在这个文件也包含了,如果没有上面那一句,则编译器会报错:重复定义!mydefine.c中用到了mydefine.h中的定义,则需要把mydefine包含进来,包含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];


//以下是延时函数
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;
}




/****************************************
          数码管延时函数


*****************************************/
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];
      P5OUT = bitnum;
      delays(400);
      P5OUT=0X00;
    }  
}


        下面讲一下mydefine.c的功能,一些常用函数都写在里面,一般情况下我们写好头文件后不必对函数的原型进行深究,只需知道函数的功能即可,即头文件里的函数声明,多个C文件编译链接的时候,相当于主函数放在前面,其他函数放在后面,调用函数的时候就必须先对这些函数进行声明,否则编译器不知道你的函数原型是什么,而这些头文件就起到了函数声明的作用,所谓头文件就可以理解为在main函数前面事先要处理的程序(即声明和定义)。

        下面把这个结构化编程的等效程序贴出来,以方便大家理解:

#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];


//以下是延时函数
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;
}




/****************************************
          数码管延时函数


*****************************************/
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];
      P5OUT = bitnum;
      delays(400);
      P5OUT=0X00;
    }   
}


沙发
芙蓉洞| | 2015-8-5 20:44 | 只看该作者
编写头文件很重要,写好了能提高代码的效率

使用特权

评论回复
板凳
仙女山| | 2015-8-6 09:00 | 只看该作者
头文件质量的好坏对于提高代码的效率有很好的作用

使用特权

评论回复
地板
仙女山| | 2015-8-6 09:00 | 只看该作者
头文件质量的好坏对于提高代码的效率有很好的作用

使用特权

评论回复
5
Luis德华| | 2015-8-6 21:04 | 只看该作者
看到的例子都是#include“.h”文件,不知道#include ".c"有什么区别

使用特权

评论回复
6
大苏牙| | 2015-8-7 11:04 | 只看该作者
为什么要写头文件,不直接写c文件include一下呢?

使用特权

评论回复
7
玛尼玛尼哄| | 2015-8-7 11:51 | 只看该作者
#define CLK0 P2OUT &= ~BIT4
#define CLK1 P2OUT |= BIT4
果然够帅。

使用特权

评论回复
8
春风的暖暖|  楼主 | 2015-8-15 21:52 | 只看该作者
玛尼玛尼哄 发表于 2015-8-7 11:51
#define CLK0 P2OUT &= ~BIT4
#define CLK1 P2OUT |= BIT4
果然够帅。

这样写就很帅啊

使用特权

评论回复
9
734774645| | 2015-8-16 22:07 | 只看该作者
最好参考各个公司的头文件比较好。

使用特权

评论回复
10
玛尼玛尼哄| | 2015-8-16 22:19 | 只看该作者
所有的常用操作都用宏写,那样移植性也增强了。

使用特权

评论回复
11
捉虫天师| | 2015-8-16 22:33 | 只看该作者
常用的,还有关于移植的,都要写到头文件的宏里,这样方便以后修改移植。

使用特权

评论回复
12
捉虫天师| | 2015-8-16 22:33 | 只看该作者
参数性的东西也最好都写在宏里,比如主频了,晶振的频率,使用到的端口。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

37

主题

306

帖子

2

粉丝