打印
[AVR单片机]

AVR之裸奔框架C++程序源码(菜农C++裸奔**之四)

[复制链接]
8422|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hotpower|  楼主 | 2008-6-14 04:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/*------------------------------------------------------------------------
                 AVR之裸奔框架C++程序源码(菜农C++裸奔大法之四)
本程序主要表现了C++多文件系统的MCU构建方法,任何支持C++的MCU/ARM/DSP都可用
此法构建。
特别要注意变量的重复定义问题:
      最好每个C/CPP文件包含与自己同名的H头文件,在其H头文件中再包含一个中间
起桥梁作用的H头文件,我一般喜欢main.h
    变量或函数要在C/CPP中定义,绝对不要在H头文件中定义!
但一定要在H头文件中用extern加变量或函数声明。
    C++中要切记全局的类的构造函数肯定要在main()前运行,对于IAR编译器有个
__low_level_init()函数也会在main()前运行,它主要控制所有变量或类的初始化
    一般类的成员函数是不能作为中断服务程序ISR()的,但Cortex-M3确是一个意外
总之中断程序要用__interrupt修饰的ISR()的,其类成员函数不能为ISR()
    最好用一个单独的文件interrupt.cpp来编写所有中断服务程序ISR(),可能其
H头文件什么都没有也最好加上。
    每个头文件的构成结构基本如下:
#include "main.h"

#ifdef  __IAR_SYSTEMS_ICC__
#ifndef _SYSTEM_BUILD
#pragma system_include
#endif
#endif

//上面的是IAR特有的

#ifndef __M48_INTERRUPT_H
#define __M48_INTERRUPT_H

#ifdef __cplusplus
extern "C"
{
#endif

//在此添加C++代码

#ifdef __cplusplus
}
#endif

#endif//__M48_INTERRUPT_H

"桥梁"H头文件要包含所有用到的H头文件!!!否则"桥梁"倒塌~~~

菜农HotPower@126.com   2008.6.14 4:18 作于特殊的节日来奉贤给大家~~~
-------------------------------------------------------------------------*/

#include "main.h"
/*-------------------------------------------------
IAR对位的支持举例如下:
    PORTB_Bit2 = 1;//等同下句
    PORTB |= (1 << PB2);//等同上句
    PORTB = (1 << PB2) | (1 << PB1);//直接写
    PORTB_Bit2 = 1;PORTB_Bit1 = 1;//代码长度等同上句,分2次控制
    PORTB |= (1 << PB2) | (1 << PB1);//先读后写
    PORTB = (1 << PB2) | (1 << PB1) | (1 << PB0);//直接写
    __no_operation ();//IAR自带的__nop()
    _NOP();//IAR自带的__nop()
--------------------------------------------------*/

/*-----------------------------------------------
IAR的变量定位很不错举例如下:
#pragma location = 0x00
__eeprom unsigned char DataTbl0[] = {1, 2};
#pragma location = 0x10
__eeprom unsigned char DataTbl1[] = {2, 3};

__flash unsigned char DataTbl2[] @ 0x1ff = {2, 3};

__no_init unsigned char test[10] @ 0x8ff;
-----------------------------------------------*/

/*------------------------------------------
在*.XCL文件尾部加入以下3句(M48为iom48.xcl)
// Output
-Ointel-extended,(CODE)=.hex//输出hex文件
-Ointel-extended,(XDATA)=.eep//输出eep文件
-------------------------------------------*/



/*------------------------------------------
IAR AVR C++程序运行顺序(以本程序为例)
1. __low_level_init()
   System.Init()
2. Timer.Init()
   Led.Init()
   Uart.Init()
   Twi.Init()
3. main()
-------------------------------------------*/
extern "C" __root char __low_level_init (void)
{
/*-----------------------------------------------------
    上电或复位后最好再关总中断(防止软件复位)
------------------------------------------------------*/
    __disable_interrupt ();//关闭总中断
/*-----------------------------------------------------
    上电或复位后最好再关看门狗(防止软件复位)
------------------------------------------------------*/
    __watchdog_disable ();//关闭内部看门狗
/*-----------------------------------------------------
    上电或复位后最好把所有IO设置为输入方式
------------------------------------------------------*/
    DDRB  = 0x00;
    DDRC  = 0x00;
    DDRD  = 0x00;
/*-----------------------------------------------------
    上电或复位后最好延时等待系统稳定
------------------------------------------------------*/
    __delay_cycles(500000);//等待系统稳定
/*---------------------------------------------
郁闷地IAR的看门狗函数竟然只有__watchdog_reset()
没有__watchdog_enable()还玩什么???
----------------------------------------------*/
//    __watchdog_enable (WDTO_2S);
/*---------------------------------------------
郁闷地IAR的休眠函数竟然只有__sleep()
没有__set_sleep_mode()还玩什么???
----------------------------------------------*/
    __set_sleep_mode (SLEEP_MODE_IDLE);
/*-------------------------------------------------
由于SystemObj声明了__no_init,故构造函数不能自动执行
这是IAR和GCC的一个不同之处,且记!!!
--------------------------------------------------*/
    System.Init ();
/*-----------------------------------------------------
__low_level_init()返回0将不初始化所有全局变量即类。
更可恨地是很多函数将不能正确地执行!!!
例: void a(const char *str);//或void a(const char str[]);
若: const str[]="123";
    a(str);//正确
    若: a("123");//不能识别"123"!!!
所以最好让__low_level_init()返回1,并将原本需要自动执行
构造函数的类前声明为__no_init,并将其构造函数的实体函数
Init()移入到__low_level_init()函数体内部显式调用!!!
------------------------------------------------------*/
    return 1;//0-不初始化,1-初始化
}

/*-----------------------------------------------------
System不初始化主要是为RamTest等变量掉电RAM数据的保持!
------------------------------------------------------*/
__no_init SystemObj System;//构造函数不能自动执行
TimerObj  Timer;//构造函数自动执行
LedObj    Led;//构造函数自动执行
UartObj   Uart;//构造函数自动执行
TwiObj    Twi;//构造函数自动执行

int main(void)
{
/*-----------------------------------------------------
RamTest在首句写0x55aa表示系统初始化正常结束。
------------------------------------------------------*/
    System.RamTest = 0x55aa;
/*-----------------------------------------------------
    最好在主循环外再开总中断
------------------------------------------------------*/
    Led.Display (0x1234);
    __enable_interrupt ();//开中断
    while (1)//主循环
    {
/*-----------------------------------------------------
    软件看门狗复位,通知喂狗程序主循环在工作
------------------------------------------------------*/
        System.MainExecFlag = 1;
/*-----------------------------------------------------
    主循环内休眠,此前必须调用__set_sleep_mode()
------------------------------------------------------*/
//        Led.Display ();
//        __delay_cycles(8000000);
       __watchdog_reset ();//硬件看门狗复位
       __sleep ();//依照__set_sleep_mode()的设定休眠
    }
}

相关链接:http://space.ednchina.com/upload/2008/6/14/87438431-5c51-40a2-88ad-e7ea63689497.rar

相关帖子

沙发
dai_weis| | 2008-6-14 11:24 | 只看该作者

好东西,留个记号

使用特权

评论回复
板凳
masashinakayama| | 2008-6-14 11:53 | 只看该作者

就这小东西还跑C++?

使用特权

评论回复
地板
phoenixmy| | 2008-6-14 11:55 | 只看该作者

哈哈



估计是看上了C++的结构性比较好吧

使用特权

评论回复
5
dcp| | 2008-6-14 12:47 | 只看该作者

注析很细很幽默

使用特权

评论回复
6
hxdlj| | 2008-6-21 20:45 | 只看该作者

没有看见c++的要素?

使用特权

评论回复
7
jianbo513| | 2008-11-21 16:51 | 只看该作者

好东西

不错

使用特权

评论回复
8
Sjj爱| | 2008-12-2 15:29 | 只看该作者

还真是好东东啊

使用特权

评论回复
9
hotpower|  楼主 | 2010-7-27 19:51 | 只看该作者
顶起来,这裤子不是俺自己穿的

使用特权

评论回复
10
xuyiyi| | 2010-7-28 12:07 | 只看该作者
哈!
HOT大叔挖墓!

使用特权

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

本版积分规则

1460

主题

21619

帖子

506

粉丝