使用ICCAVR开发AVR单片机的过程中遇到这样的问题:
问题描述:
一个结构体变量在文件file1.h中声明如下:
- #ifndef __FILE1_H
- #define __FILE1_H
- struct PID
- {
- int Reference;
- int FeedBack;
- int Ka;
- int Kb;
- int Kc;
- int ControlValue;
- } speedPID;
- void PIDInit ( struct PID *p ); // PID参数初始化
- #endif
其对应的.c文件:file1.c中如下:
- #include "file1.h"
- void PIDInit ( struct PID *p )
- {
- ....
- }
在file2.c中,加入了#include"file2.h"一句包含,并且相应函数中用到了这个结构体变量,对它的成员变量进行了赋值。也就说该结构体是一个全局变量。
file2.h中内容:
- #ifndef __FILE2_H
- #define __FILE2_H
- extern struct PID speedPID;
- extern void PIDInit( struct PID *speedPID );
- #endif
但是用ICCAVR编译时,提示
- file2.c(102): unknown field `Reference' of `incomplete struct PID defined at C:\DOCUME~1\baifeng\file2.h'
- C:\iccv7avr\bin\imakew.exe: Error code 1
- Done: there are error(s). Exit code: 1
解决方法:
file1.h->
- #ifndef __FILE1_H
- #define __FILE1_H
- extern struct PID speedPID;
- void PIDInit ( struct PID *p ); // PID参数初始化
- void PID_reload ( struct PID *p, int ref, int a, int b, int c );
- #endif
file1.c->
- #include "file1.h"
- struct PID
- {
- int Reference;
- int FeedBack;
- int Ka;
- int Kb;
- int Kc;
- int ControlValue;
- } speedPID;
- void PIDInit ( struct PID *p )
- {
- ......
- }
- // 更新PID参数
- void PID_reload ( struct PID *p, int ref, int a, int b, int c )
- {
- p->Reference = ref;
- p->Ka = a;
- p->Kb = b;
- p->Kc = c;
- }
file2.c等文件中,加入#include "file1.h",然后直接使用PIDInit()和PID_reload()函数就可以了。
评论:
的确是在头文件中定义全局变量不太好,特别是结构体这种变量,虽然加入了#ifndef这样的宏,但是在编译时编译器还是会报重复定义之类的错误。
另外,还查看了ICC的自带头文件,也都是没有声明变量的,仅仅声明了库函数和相关的宏定义。
所以,相关的全局变量放在.c中定义;如果需要在别的文件中修改变量,特别是结构体变量的分量,还是专门编写一个函数的好,结构体的形参使用地址传递。
从这点上,也可以体会出面向对象编程的好处,不会在类的外部随便修改成员变量,而是通过相应的方法(成员函数)达到相同的目的。同时,形参还比面向过程编程少一个。
转载于:https://blog.51cto.com/baifeng/786680