打印
[AVR单片机]

大家都来看看我的FrameAVR

[复制链接]
1992|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
discovery0x01|  楼主 | 2009-11-6 01:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 discovery0x01 于 2009-11-6 01:40 编辑

在很多的单片机编程中,我一直保持着寻找捷径,哪怕是想方设法的少打一对{}也好。在编写基于C语言的程序时,大家一定会少不了编写main()函数,对各式各样的外部硬件予以init(),对响应遥控和按键也是通过不停的查询来完成。这些工作经常复制来,复制去的,很是麻烦。而且特别是硬件编程,有时候在PCB改动的时候,会牵连到一大片的内容。我不喜欢这样的编程方式,我更偏爱于兼容性更好的编程方式,把能够通过#define定义的最低级操作全都放在mydef.h里,把原先编写好的程序放在c:\inc\的目录下,让编译器自己去找。而且有了IAR编译器C++的支持,很多硬件的init()函数可以在CLASS的构造函数里完成,当我们实例化一个类的时候,它就已经初始化了,而如果我们在头文件了已经实例化了一个类的话,在我们的main.cpp里,只需要#include" c:\inc\xxx.h"就已经基本上满足我们的要求。废话不多说了,先让大家来看看我的FrameAVR。这个框架是经过很多程序验证了的。源程序如下:有些头文件大家不必详知,只要理解这个class的工作过程即可。


/*
本程序框架适用于IAR
定义一下宏打开某项特定功能
//                                           定义MCU型号,编译器将会自动添加相应的io.h
#define  MCU_MEGA32
//                                           定义MCU时钟,它会影响到很多时序程序
#define  OSC_8M
//                                           定义MCU时钟偏移 默认值为1.00
#define  OSC_REL 1.00
//                                           打开MSG消息驱动(KEY),由msg传递给proc
#define  KEY_PORT (PINB&0x3F)
//                                          打开遥控接收程序,选择其中一个,不可同时打开2个。将会占用INT0和T0
//#define  REMOTE_SAA3010
//#define  REMOTE_TC9012
//#define  REMOTE_HT6221
//                                          打开此宏后AVR的Run()将与IRQ_RTOS同步,当完成AVR::Run()后MCU进入睡眠状态
//                                          打开此宏后需要在main.cpp里添加一个中断函数通过调用RE_START()来
//                                          唤醒CPU主程序
//#define IRQ_RTOS IRQ_T2
//                                          定义RTOS的时间(uS)
//#define TIMER_RTOS  10000
//                                          打开此宏后将定义AVR::Timer()与AVR::Run()的调用比例
#define AVR_TIMER 10
//                                          看门狗计时最大时间,定义此宏后AVR_MAIN在完成RUN()后将复位WDT
#define WDT_TIME  WDT_2200ms
*/
#ifndef AVR_MAIN_H
#define AVR_MAIN_H

#include "c:\inc\message.h"
#define NULL 0

#ifdef WDT_TIME
#include "c:\inc\avr_wdt.h"
#endif

#ifdef RTOS
#include "c:\inc\stanby.h"

STANBY stanby;

void ExitStanby()
{
  stanby.exit();
}

#ifdef IRQ_RTOS_TIMER0
#include "c:\inc\avr_t0.h"
#endif
#ifdef IRQ_RTOS_TIMER1
#include "c:\inc\avr_t1.h"
#endif
#ifdef IRQ_RTOS_TIMER2
#include "c:\inc\avr_t2.h"
#endif
#endif


class FrameAVR
{
private:
  
#ifdef AVR_TIMER
  UINT avr_timer;
  void Timer();//        如果定义了AVR_TIMER ,这个函数会以AVR_TIMER:1的比例相对于Run()运行Timer()
#endif
  
public:
  void init();   //          这两个函数需要在main.cpp里重新编写。编写剩余IO的处理
  void Run();//            主程序需要重复运行的程序放在这里,如果定义了RTOS,那么Run()将会以RTOS定义的时间重复调用,否则将会接连不停的调用,仿佛我们平时的main()主循环

  
  FrameAVR()
  {
   
#ifdef AVR_TIMER
   
    UINT avr_i;
    avr_timer=AVR_TIMER+0;
   
#endif
   
#ifdef RTOS
#ifdef IRQ_RTOS_TIMER0
   
    timer0.init(true,RTOS,ExitStanby);
#endif
   
#ifdef IRQ_RTOS_TIMER1
   
    timer1.init(true,RTOS,ExitStanby);
#endif   
#ifdef IRQ_RTOS_TIMER2
   
    timer2.init(true,RTOS,ExitStanby);
#endif
#endif
   
    init();//                     初始化用户定义的IO
    msg.flush();//            初始化MSG
    seI();//                      使能IRQ
//                                初始化WDT
#ifdef WDT_TIME
    initWDT(WDT_TIME);
#endif
    while(1)
    {
#ifdef _REMOTE_MSG_H_
      msg.GetREM();//               获取遥控信号
#endif
#ifdef KEY_PORT
      msg.GetKEY(KEY_PORT);//  获取按键信号
#endif
//                                 TIMER呼叫延迟
      Run();//                              运行
#ifdef AVR_TIMER
      if(avr_timer)//                     计算比例
      {
        if(++avr_i >= avr_timer)
        {
          avr_i=0;
          Timer();//                        运行FrameAVR::Timer()
#ifdef _MESSAGE_H_
         
          msg = ON_TIMER ;
         
#endif
        }
      }
#endif
//                                  自动复位WDT
#ifdef WDT_TIME
      ResetWDT();
#endif
//                                  系统休闲
#ifdef RTOS
    stanby.start();//        在stanby类里,我们可以获取MCU的占用率
#endif
    }
  }
};

int main()
{
  FrameAVR avr_main;//      我把FrameAVR放在main()内部实例化是为了让其它硬件先能够得到构造
  return 0;
}
#endif


把上面这个程序复制到保存为c:\inc\FrameAVR.h.那么在我们的main.cpp里,无需编写void main()函数,因为它已经有了。而且它能够满足我们的需求。这个框架是基于消息的,所有的按键和遥控编码都会通过msg类转换为特定的消息,我们无需再去查看自己的PCB到底按键在哪个引脚,只要在一开始的时候定义#define  KEY_PORT (PINB&0x3F)即可,最大支持16位的按键输入。是不是很方便呢?我在编写基于DS1302的程序的时候,框架会在1s到来的时候向我们特定的函数发送msg,这个特点是我在win32编程里学到的。呵呵,大家有时间多多交流,我是懒人,少做一件重复的事是我的快乐。

相关帖子

沙发
suoma| | 2009-11-7 22:00 | 只看该作者
谢谢楼主分享

使用特权

评论回复
板凳
wangwo| | 2009-11-7 23:11 | 只看该作者
开始还以为是问题呢:L

使用特权

评论回复
地板
zjswuyunbo| | 2009-11-8 10:44 | 只看该作者
不错,厉害……另,楼主什么编译器支持c++?

使用特权

评论回复
5
voidx| | 2009-11-8 12:40 | 只看该作者
iar

使用特权

评论回复
6
lovelyegle| | 2009-11-9 12:55 | 只看该作者
挺厉害的

使用特权

评论回复
7
Karlshen| | 2009-11-10 20:58 | 只看该作者
不错,支持!

使用特权

评论回复
8
xtldw| | 2014-9-12 17:52 | 只看该作者
顶一个先,但是没有看懂.

使用特权

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

本版积分规则

3

主题

18

帖子

1

粉丝