由一个长延时想到了程序结构(ATmega128+ICCAVR)【原理篇】[实战篇将讲述基于GPRS无
/******************************************************************************函数说明: 任务1,LED闪烁(0.5s亮,0.5S灭)
函数实现: 采用状态机的方法实现
#define LED_INIT 0
#define LED_ON 1 //LED任务的定义
#define LED_OFF 2
-------------------------------------------------------------------------------
时间:2008-05-29
作者:胡玉贵
说明:在数据采集仪的设计过程中用到长延时,可能要延时1~10S的时间。如果编写一个简
单的延时函数系统的响应将是不能忍受的,所以只能考虑采用其他的办法实现很长的
延时。
办法1:采用uCosII这样的操作系统,应为有任务的调度,所以实时性的延时很容易实
现。
任务函数()
{
系统的延时函数(延时时间);//任务被挂起,直到延时时间到达
执行函数();
}
方法是很好的,我也研究了一段时间,但是网上能用的CODE(ucosII ON m128
ICCAVR)没有。****再加上我的系统实时性不是要求那么高,只要能避免很长
时间的延时函数就行。***
办法2:没有uCOSII那样的实时调度,调度采用主函数中的while(1)实现
声明的几点:系统的实时性不要求非常高的,因此短的延时函数保留,大于100ms
的延时采用状态机实现
eg:以LEDTask为例,任务有两个状态,ON和OFF,ON-》OFF的延时为500ms,OFF
-》ON的延时同样为500ms。如果采用一般的延时函数MCU基本可以不用干其他
事了。***用定时器+状态机很好的解决了这个问题***
步骤1:为函数定义一个全局的延时变量G_delaytime;
步骤2:初始化定时器,这里以25ms为中断对G_delaytime减一处理,当为0是延时
时间到
步骤3:分析函数的状态,一般多建一个初始化状态,此状态只运行一次。
******************************************************************************/
void LEDTask(void)
{
static unsigned char ledstate;//LEDTask函数的状态变量,控制LED的变化
switch(ledstate)
{
case LED_INIT://led任务初始化状态
PORTB&=~BIT(0);
G_delaytime=20;//打开延时这里是关键
ledstate=LED_ON;//状态的转变
break;
case LED_ON:
if(G_delaytime==0)//等待延时的结束,此时延时已经用定时器实现,25ms减一,20个单位=25×20=500ms
{
PORTB|=BIT(0);
G_delaytime=20;
ledstate=LED_OFF;
}
break;
case LED_OFF:
if(G_delaytime==0)
{
PORTB&=~BIT(0);
G_delaytime=20;
ledstate=LED_ON;
}
break;
default :break;
}
}
点击此处下载 ourdev_296796.rar(文件大小:125K) (原文件名:Multask.rar) //TIMER1 initialize - prescale:8
// WGM: 4) CTC, TOP=OCRnA
// desired value: 25mSec
// actual value: 25.000mSec (0.0%)
void timer1_init(void)
{
TCCR1B = 0x00; //stop
TCNT1H = 0x79; //setup
TCNT1L = 0x02;
OCR1AH = 0x86;
OCR1AL = 0xFE;
OCR1BH = 0x86;
OCR1BL = 0xFE;
OCR1CH = 0x86;
OCR1CL = 0xFE;
ICR1H= 0x86;
ICR1L= 0xFE;
TCCR1A = 0x00;
TCCR1B = 0x0A; //start Timer
}
#pragma interrupt_handler timer1_compa_isr:13
void timer1_compa_isr(void)
{
//compare occured TCNT1=OCR1A
unsigned char i;
for(i=0;i<MAX_TASK_NUM;i++)
{
if(G_delaytime>0)
G_delaytime--;
}
} 程序的运行效果:http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_296795.JPG
串口任务+LED (原文件名:p.JPG) 顶一下,建议新手学学,这个东西很有用。 个人喜欢这样来做
volatile unsigned long tick;
//Timer4中断,25MS
void __T4_ISR _T4Interrupt(void)
{
tick++;
IFS1bits.T4IF = 0;
}
void LEDTask(void)
{
static unsigned char ledstate;//LEDTask函数的状态变量,控制LED的变化
static unsigned long count;
switch(ledstate)
{
case LED_INIT://led任务初始化状态
PORTB&=~BIT(0);
count = tick; //打开延时这里是关键
ledstate=LED_ON;//状态的转变
break;
case LED_ON:
if((tick - count) >= 20)
{
PORTB|=BIT(0);
count = 0;
ledstate=LED_OFF;
}
break;
case LED_OFF:
if((tick - count) >= 20)
{
PORTB&=~BIT(0);
count = 0;
ledstate=LED_ON;
}
break;
default :break;
}
} 收藏了!
谢谢! 学学... Mark 类似项目,顶一下 LZ
你的"实战篇将讲述基于GPRS无线模块的数据透明传输“
都一年半了还没出来啊 我也来看看,希望早日看到 以后慢慢学谢谢 这其实就是协同式多任务的写法。协同式通常都用状态机。 透传好还是非透传好呢?还没弄明白 mark 挖坟,谢谢楼主 也来学习下! 学习了。。。 mark...... 这么长时间的延时,我觉得sleep好一点,省电。 赞赞赞,下载的看看是不是 赞赞赞,下载的看看是不是
页:
[1]