打印
[LOOK]

请教C++文件结构问题——把类封装在一个文件中

[复制链接]
2374|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 gdmgb520 于 2011-9-29 05:47 编辑

目的:把tft类从led.cpp中分离。
问题:建立tft.cpp和tft.h,在led.cpp中创建tft对象,调用构造函数出现问题。编译报错。


tft.h
//#if LOOK_H == 0
//#include "NUC1xx.h"
//#include "NUC1xxM051Seriescfg.h"
//#else
//#define __HAVE_GPIO
//#include <nuc120re3an.h>
//using namespace nuvoton;
//#endif
#ifndef TFT_H
#define TFT_H

#include "look_config.h"
#include <look.h>

#define __HAVE_GPIO
#include <nuc120re3an.h>
using namespace nuvoton;

#include "asc.H"

#define RS        14          //
#define CS        15          //

#define WR        6          //
#define RD        7          //

extern unsigned int color[];
extern unsigned int POINT_COLOR;//默认红色   


// 任务类 task_tft_t 的定义
class task_tft_t : public task_t {
public:
        __INLINE__ task_tft_t();        // 构造函数
        //task_tft_t();        // 构造函数

private:
        void Io_Set(unsigned char pin);           //单个IO口置位函数
        void Io_Clr(unsigned char pin);           //单个IO口清零函数
        void OUT_DATA(unsigned char data);
        void delay(unsigned int i);           //延时
        void delayms (unsigned int i);
        void LCD_WDATA(unsigned char data);         //写入8位数据
        //写8位数据函数
        void LCD_WR_DATA1(unsigned char data);
        //写寄存器地址函数
        void LCD_WR_REG(unsigned char data);
        //写16位数据函数
        void LCD_WR_DATA_BYTE(unsigned char DataH,unsigned char DataL);
        //写16位数据函数
        void LCD_WR_DATA(unsigned int val);
        void LCD_WR_COM( unsigned int com);               
        void LCD_WR_COM_DATA( int com1,int dat1);
        void LCD_SET_LOCATION(unsigned int i,unsigned int j);        //设置X、Y坐标,做好写RAM的准备
        
public:        
        //清屏函数   
        //x,y:起始坐标
        //len,wid:长宽
        void LCD_CLEAR(unsigned char x,unsigned int y,unsigned char len,unsigned int wid);
        //在指定位置显示一个字符
        //x:0~234
        //y:0~308
        //num:要显示的字符:" "--->"~"
        void LCD_ShowChar(unsigned char x,unsigned int y,unsigned char num);
        //显示字符串
        //x,y:起点坐标  
        //*p:字符串起始地址
        void LCD_ShowString(unsigned char x,unsigned int y,const char *p);
        //初始化函数
        void LCD_Init(void);
        //显示
        void LCD_Display(void);
};

#endif
tft.cpp
#include "tft.h"

unsigned int color[]={0xf8,0x00,0x07,0xe0,0x00,0x1f,0xff,0xe0,0x00,0x00,0xff,0xff,0x07,0xff,0xf8,0x1f};
unsigned int POINT_COLOR=0XF800;//默认红色   

//--------  类task_tft_t成员函数定义 -------------------------------
//类 task_tft_t 的构造函数
__INLINE__ task_tft_t::task_tft_t()
{
        // TODO: 在此初始化 task_led3_t 的类成员
}
void task_tft_t::Io_Set(unsigned char pin)           //单个IO口置位函数
{
        unsigned int io_data=1;
        io_data=io_data<<pin;
        //LPC_GPIO0 -> FIOSET=io_data;         //IOSET0为IO线上置位寄存器,1有效,0无
        GPIOC.DOUT = GPIOC.DOUT | io_data;
}
void task_tft_t::Io_Clr(unsigned char pin)           //单个IO口清零函数
{
        unsigned int io_data=1;
        io_data=io_data<<pin;
        //LPC_GPIO0 -> FIOCLR=io_data;         //IOCLR0为IO线上清零寄存器,1有效,0无
        GPIOC.DOUT = GPIOC.DOUT & (~io_data);
}

void task_tft_t::OUT_DATA(unsigned char data)
{
        unsigned int k;
        k=data;
        GPIOA.DOUT=k<<2;
}



//延时
void task_tft_t::delay(unsigned int i)
{
        unsigned int k=10;
        i=i+2;
        while(i>0)
        {
                i--;
        }
        while(k>1)k--;
}


void task_tft_t::delayms (unsigned int i)
{
        unsigned int n;
        while(i>1)
        {
                for(n=65535;n>1;n--);
                i--;
        }
}

//写入8位数据
void task_tft_t:CD_WDATA(unsigned char data)
{   
        Io_Clr(CS);

        OUT_DATA(data);

        Io_Clr(WR);

        Io_Set(WR);

        Io_Set(CS);

        Io_Clr(RS);

}  
//写8位数据函数
void task_tft_t:CD_WR_DATA1(unsigned char data)
{
        Io_Set(RS);;//写数据  
        LCD_WDATA(data);
}
//写寄存器地址函数
void task_tft_t:CD_WR_REG(unsigned char data)
{
        Io_Clr(RS);//写地址
        LCD_WDATA(data);
}  
//写16位数据函数
void task_tft_t:CD_WR_DATA_BYTE(unsigned char DataH,unsigned char DataL)
{  
   Io_Set(RS);//A0=1;
        Io_Clr(CS);
         OUT_DATA(DataH);//DPTR=DH;                                                
  
        Io_Clr(WR);
        Io_Set(WR);
        OUT_DATA(DataL);//P3=DPL;        
                                       
        Io_Clr(WR);
        Io_Set(WR);
        Io_Set(CS);        
}
//写16位数据函数
void task_tft_t:CD_WR_DATA(unsigned int val)
{  
   Io_Set(RS);//A0=1;
        Io_Clr(CS);
         OUT_DATA(val>>8);//DPTR=DH;                                                
  
        Io_Clr(WR);
        Io_Set(WR);
        OUT_DATA(val);//P3=DPL;        
                                       
        Io_Clr(WR);
        Io_Set(WR);
        Io_Set(CS);        
}


void task_tft_t:CD_WR_COM( unsigned int com)               
{        
    Io_Clr(RS);
        Io_Clr(CS);        
   OUT_DATA(com>>8);//        DPTR=CH;                                
//        P3=DPH;        
   Io_Clr(WR);
        Io_Set(WR);
        OUT_DATA(com);//P3=DPL;               
        Io_Clr(WR);
        Io_Set(WR);
        Io_Set(CS);        
}

void task_tft_t:CD_WR_COM_DATA( int com1,int dat1)
{
   LCD_WR_COM(com1);
   LCD_WR_DATA(dat1);
   
}

void task_tft_t:CD_SET_LOCATION(unsigned int i,unsigned int j)                //设置X、Y坐标,做好写RAM的准备
{
    LCD_WR_COM_DATA(0x0020,0);//设置X坐标位置
    LCD_WR_COM_DATA(0x0021,0);//设置Y坐标位置
    LCD_WR_COM(0x0022);                                //指向RAM寄存器,准备写数据到RAM
}

//清屏函数   
//x,y:起始坐标
//len,wid:长宽
void task_tft_t:CD_CLEAR(unsigned char x,unsigned int y,unsigned char len,unsigned int wid)
{                    
    unsigned long n,temp;
    LCD_WR_COM_DATA(0x0020,0);//设置X坐标位置
    LCD_WR_COM_DATA(0x0021,0);//设置Y坐标位置
    LCD_WR_COM(0x0022);                                //指向RAM寄存器,准备写数据到RAM
        temp=(unsigned long)len*wid;   
        for(n=0;n<temp;n++)LCD_WR_DATA(0xffff);//显示白色
}
//在指定位置显示一个字符
//x:0~234
//y:0~308
//num:要显示的字符:" "--->"~"

void task_tft_t:CD_ShowChar(unsigned char x,unsigned int y,unsigned char num)
{      
#define MAX_CHAR_POSX 234
#define MAX_CHAR_POSY 308
    unsigned char temp;
    unsigned char pos,t;      
    if(x>MAX_CHAR_POSX||y>MAX_CHAR_POSY)return;
    //设定一个字符所占的大小
    //开辟空间
//        LCD_WR_CMD(0,0x2,x);//
//        LCD_WR_CMD(1,0x3,y);
//        LCD_WR_CMD(0,0x04,x+5);        //结束列数(0~239)        
//        LCD_WR_CMD(1,0x05,y+11);//结束行数(0~319)   
//        LCD_WR_REG(0x0E);  
   LCD_WR_COM_DATA(0x0020,x);//设置X坐标位置
    LCD_WR_COM_DATA(0x0021,y);//设置Y坐标位置

        LCD_WR_COM_DATA(0x0050, x); // Horizontal GRAM Start Address
        LCD_WR_COM_DATA(0x0052, y); // Vertical GRAM Start Address  
        LCD_WR_COM_DATA(0x0051, x+5); // Horizontal GRAM End Address      
        LCD_WR_COM_DATA(0x0053, y+11); // Vertical GRAM end Address

    LCD_WR_COM(0x0022);                                //指向RAM寄存器,准备写数据到RAM
         
        num=num-' ';//得到偏移后的值
        for(pos=0;pos<12;pos++)
        {
            temp=asc2[num][pos];
            for(t=0;t<6;t++)
            {                 
                if(temp&0x01)LCD_WR_DATA(POINT_COLOR);
                else LCD_WR_DATA(0xffff);//白色   
                temp>>=1;
            }
        }
        LCD_WR_COM_DATA(0x0050, 0x0000); // Horizontal GRAM Start Address
        LCD_WR_COM_DATA(0x0051, 0x00EF); // Horizontal GRAM End Address
        LCD_WR_COM_DATA(0x0052, 0x0000); // Vertical GRAM Start Address
        LCD_WR_COM_DATA(0x0053, 0x013F); // Vertical GRAM Start Address
}
                                                         
//显示字符串
//x,y:起点坐标  
//*p:字符串起始地址
void task_tft_t:CD_ShowString(unsigned char x,unsigned int y,const char *p)
{         
    while(*p!='\0')
    {      
        if(x>MAX_CHAR_POSX){x=0;y+=12;}
        if(y>MAX_CHAR_POSY){y=x=0;LCD_CLEAR(0,0,240,320);}
        LCD_ShowChar(x,y,*p);
        x+=6;
        p++;
    }  
}         
//初始化函数
void task_tft_t:CD_Init(void)
{      
            //液晶接口初始化   
               
        //        LCD_RST = 0;//硬件复位
        //        delay_ms(200);
        //        LCD_RST = 1;
        //        delay_ms(200);
                //initializing funciton 1
        //************* Start Initial Sequence **********//
        LCD_WR_COM_DATA(0x0001, 0x0100); // set SS and SM bit
        //LCD_WR_COM_DATA(0x0001, 0x0000); // set SS and SM bit
        LCD_WR_COM_DATA(0x0002, 0x0700); // set 1 line inversion
        LCD_WR_COM_DATA(0x0003, 0x1030); // set GRAM write direction and BGR=1.
        LCD_WR_COM_DATA(0x0004, 0x0000); // Resize register
        LCD_WR_COM_DATA(0x0008, 0x0202); // set the back porch and front porch
        LCD_WR_COM_DATA(0x0009, 0x0000); // set non-display area refresh cycle ISC[3:0]
        LCD_WR_COM_DATA(0x000A, 0x0000); // FMARK function
        LCD_WR_COM_DATA(0x000C, 0x0000); // RGB interface setting
        LCD_WR_COM_DATA(0x000D, 0x0000); // Frame marker Position
        LCD_WR_COM_DATA(0x000F, 0x0000); // RGB interface polarity
        //*************Power On sequence ****************//
        LCD_WR_COM_DATA(0x0010, 0x0000); // SAP, BT[3:0], AP, DSTB, SLP, STB
        LCD_WR_COM_DATA(0x0011, 0x0007); // DC1[2:0], DC0[2:0], VC[2:0]
        LCD_WR_COM_DATA(0x0012, 0x0000); // VREG1OUT voltage
        LCD_WR_COM_DATA(0x0013, 0x0000); // VDV[4:0] for VCOM amplitude
        LCD_WR_COM_DATA(0x0007, 0x0001);
        delay(60); // Dis-charge capacitor power voltage
        LCD_WR_COM_DATA(0x0010, 0x1690); // SAP, BT[3:0], AP, DSTB, SLP, STB
        LCD_WR_COM_DATA(0x0011, 0x0227); // R11h=0x0221 at VCI=3.3V, DC1[2:0], DC0[2:0], VC[2:0]
        delay(50); // Delay 50ms
        LCD_WR_COM_DATA(0x0012, 0x001A); // External reference voltage= Vci;
        delay(50); // Delay 50ms
        LCD_WR_COM_DATA(0x0013, 0x1400); // R13=1200 when R12=009D;VDV[4:0] for VCOM amplitude
        LCD_WR_COM_DATA(0x0029, 0x0024); // R29=000C when R12=009D;VCM[5:0] for VCOMH
        LCD_WR_COM_DATA(0x002B, 0x000C); // Frame Rate
        delay(50); // Delay 50ms
        LCD_WR_COM_DATA(0x0020, 0x0000); // GRAM horizontal Address
        LCD_WR_COM_DATA(0x0021, 0x0000); // GRAM Vertical Address
        // ----------- Adjust the Gamma Curve ----------//
        LCD_WR_COM_DATA(0x0030, 0x0007);
        LCD_WR_COM_DATA(0x0031, 0x0604);
        LCD_WR_COM_DATA(0x0032, 0x0007);
        LCD_WR_COM_DATA(0x0035, 0x0504);
        LCD_WR_COM_DATA(0x0036, 0x0808);
        LCD_WR_COM_DATA(0x0037, 0x0007);
        LCD_WR_COM_DATA(0x0038, 0x0301);
        LCD_WR_COM_DATA(0x0039, 0x0007);
        LCD_WR_COM_DATA(0x003C, 0x0302);
        LCD_WR_COM_DATA(0x003D, 0x0808);
        //------------------ Set GRAM area ---------------//
        LCD_WR_COM_DATA(0x0050, 0x0000); // Horizontal GRAM Start Address
        LCD_WR_COM_DATA(0x0051, 0x00EF); // Horizontal GRAM End Address
        LCD_WR_COM_DATA(0x0052, 0x0000); // Vertical GRAM Start Address
        LCD_WR_COM_DATA(0x0053, 0x013F); // Vertical GRAM Start Address
        LCD_WR_COM_DATA(0x0060, 0xA700); // Gate Scan Line
        LCD_WR_COM_DATA(0x0061, 0x0001); // NDL,VLE, REV
        LCD_WR_COM_DATA(0x006A, 0x0000); // set scrolling line
        //-------------- Partial Display Control ---------//
        LCD_WR_COM_DATA(0x0080, 0x0000);
        LCD_WR_COM_DATA(0x0081, 0x0000);
        LCD_WR_COM_DATA(0x0082, 0x0000);
        LCD_WR_COM_DATA(0x0083, 0x0000);
        LCD_WR_COM_DATA(0x0084, 0x0000);
        LCD_WR_COM_DATA(0x0085, 0x0000);
        //-------------- Panel Control -------------------//
        LCD_WR_COM_DATA(0x0090, 0x0010);
        LCD_WR_COM_DATA(0x0092, 0x0600);
        LCD_WR_COM_DATA(0x0007, 0x0133); // 262K color and display ON
}
//显示测试
void task_tft_t:CD_Display(void)
{
    POINT_COLOR=0xf100;//画笔颜色
    LCD_ShowString(50,100,"This is a test for TFTLCD!");
}
led.h
#include "look_config.h"
#include <look.h>
//#include <instantiate>

// 任务类 task_led1_t 的定义
class task_led1_t : public task_t {
public:
        __INLINE__ task_led1_t();        // 构造函数
        
protected:
        void routine();                // 任务例程
};

// 任务类 task_led1_t 的构造函数
__INLINE__ task_led1_t::task_led1_t()
{
        // TODO: 在此初始化 task_led1_t 的类成员
}

//extern instantiate::task<task_led1_t, LOOK_STACK_SIZE> task_led1;

// 任务类 task_led2_t 的定义
class task_led2_t : public task_t {
public:
        __INLINE__ task_led2_t();        // 构造函数
        
protected:
        void routine();                // 任务例程
};

// 任务类 task_led2_t 的构造函数
__INLINE__ task_led2_t::task_led2_t()
{
        // TODO: 在此初始化 task_led2_t 的类成员
}


extern instantiate::task<task_led1_t, LOOK_STACK_SIZE> task_led1;
extern instantiate::task<task_led2_t, LOOK_STACK_SIZE> task_led2;
led.cpp
#include "led.h"

#define LOOK_H 1

#if LOOK_H == 0
#include "NUC1xx.h"
#include "NUC1xxM051Seriescfg.h"
#else
#define __HAVE_GPIO
#include <nuc120re3an.h>
using namespace nuvoton;
#endif

#include "tft.h"

task_tft_t tftObj;                //创建tft对象


//-------------------------------------------------------------------------------------------------------------------------
//                         类task_led3_t相关定义
//-------------------------------------------------------------------------------------------------------------------------
// 任务类 task_led3_t 的定义
class task_led3_t : public task_t {
public:
        __INLINE__ task_led3_t();        // 构造函数
        
public:
        void led_off(void);
};

// 任务类 task_led3_t 的构造函数
__INLINE__ task_led3_t::task_led3_t()
{
        // TODO: 在此初始化 task_led3_t 的类成员
}

void task_led3_t::led_off(void)
{
        static uint32_t data = 0b100;
        GPIOA.DMASK(-1)
                 .DMASK2(0);
    GPIOA.DOUT = data;
        data ^= 0b100;
}

task_led3_t led3;         //创建对象

//-------------------------------------------------------------------------------------------------------------------------
//               
//-------------------------------------------------------------------------------------------------------------------------
// 任务类 task_led_t 的例程
void task_led1_t::routine()
{
        // TODO: 在此编写 task_led_t 例程的内容
        uint32_t data = ~0b1000;
        
        tftObj.LCD_Init();
//        test_lcd_mon();
        tftObj.LCD_CLEAR(0,0,240,320);
         while (true) {
                // TODO: 在此编写 task_led_t 例程的内容
                tftObj.LCD_Display();
//
//                data &= 0b111000;
//                data <<= 1;
//                data += data >> 3;
//#if LOOK_H == 0
//                GPIOAs.DMASK.Regs = ~0b111000;
//                GPIOAs.DOUT.Regs = data;
//#else
//                GPIOA.DMASK(-1)
//                     .DMASK5(0)
//                         .DMASK4(0)
//                         .DMASK3(0);
//            GPIOA.DOUT = data;
//#endif
                delay(LOOK_TICKS_PER_SEC / 2);
//                led3.led_off();

         }
}
// 任务类 task_led_t 的例程
void task_led2_t::routine()
{
        // TODO: 在此编写 task_led_t 例程的内容
        uint32_t data = 0b100;
         while (true) {
                // TODO: 在此编写 task_led_t 例程的内容
#if LOOK_H == 0
                GPIOAs.DMASK.Regs = ~0b100;
                GPIOAs.DOUT.Regs = data;
#else
                GPIOA.DMASK(-1)
                         .DMASK2(0);
            GPIOA.DOUT = data;
#endif
                data ^= 0b100;
                delay(LOOK_TICKS_PER_SEC / 10);
         }
}



#ifdef LOOK_SCHEDULING_PRIORITY
instantiate::task<task_led1_t, LOOK_STACK_SIZE> task_led1(0);
instantiate::task<task_led2_t, LOOK_STACK_SIZE> task_led2(0);
#else
instantiate::task<task_led1_t, LOOK_STACK_SIZE> task_led1;
//instantiate::task<task_led2_t, LOOK_STACK_SIZE> task_led2;
//instantiate::task<task_led3_t, LOOK_STACK_SIZE> task_led3;
#endif
工程文件 LOOK_TFT3.rar (1.33 MB)

谢谢大家!

相关帖子

沙发
gdmgb520|  楼主 | 2011-9-28 23:14 | 只看该作者
抱歉,工程中有些不必要的代码没有删掉!

使用特权

评论回复
板凳
john_lee| | 2011-9-29 00:38 | 只看该作者
很浅显的错误。 楼主在tft.h中定义了task_tft_t类,并且有inline的构造函数声明:
__INLINE__ task_tft_t();        // 构造函数

但没有在这个头文件中定义构造函数的函数体(function body)。

然后,楼主在led.cpp中创建了task_tft_t类的实例:
task_tft_t tftObj;                //创建tft对象


编译器在编译led.cpp时,发现了task_tft_t类的实例tftObj,并且通过头文件知道task_tft_t类有一个inline的构造函数,但是,却没有找到这个函数的函数体。所以,编译器报错:function body not available。

这个函数体在什么地方?原来楼主把它写在了tft.cpp文件中。

楼主,明白问题在哪里了吗?

使用特权

评论回复
地板
gdmgb520|  楼主 | 2011-9-29 05:45 | 只看该作者
3# john_lee

谢谢lee老师。老师睡得这么晚。

把 task_tft_t类的构造函数从tft.cpp中剪切到tft.h中,编译成功。

原因分析:(请lee老师看看是否正确)
“在CPP中,名称有内部链接和外部链接之别。对于外部链接,如函数定义,因为它可以在其他文件中使用,所以不能允许在程序中重复定义,因此它不能放在头文件中。对于内部链接,如,类型定义、枚举定义、全局常量定义、inline函数和模板定义等,因为他们只能在自己的程序文件使用,故可以跨文件重复定义。”
——《C++程序设计教程》

使用特权

评论回复
5
Swallow_0322| | 2011-9-29 08:10 | 只看该作者
Lee老师讲的够细致,受教了!
也需要向gdmgb520学习!

使用特权

评论回复
6
gdmgb520|  楼主 | 2011-9-29 12:48 | 只看该作者
谢谢鼓励

使用特权

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

本版积分规则

个人签名:了解新东西才知道自己的不足。 www.elecbench.com

67

主题

452

帖子

1

粉丝