/*------------------------------------------------------------------------ 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 |