|
楼主 |
发表于 2009-11-19 12:24:00
|
显示全部楼层
上传代码:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
#define fosc (11059200UL) //系统时钟
#define SCH_MAX_TASKS 2 // 调度器支持的任务个数,用户在调用调度器的时候必须设置
#define TXB8 0
#define RXB8 1
#define UPE 2
#define OVR 3
#define FE 4
#define UDRE 5
#define RXC 7
#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<OVR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)
// 定义调度器数据结构,每一个任务消耗 4 bytes RAM
typedef struct
{
//定义函数类型指针,const关键字意思是这是一个指向flash的指针
const void (*pTask)(void);
uchar Delay; // 任务第一次被执行前的延迟时间,如果为0则立即执行
uchar Period; // 任务的执行间隔时间,如果为0,则只执行一次
uchar RunMe; // 任务执行标志位:1 等待执行,0 不需要执行
} sTask; // sTask是结构体变量
uchar Comm0Temp[150];
uchar Comm1Temp[150];
volatile uchar usart0_recv_flag=0; //usart0接收到字符串标志
volatile uchar usart1_recv_flag=0; //usart1接收到字符串标志
volatile uchar SameFrameFlag0=3; //不等于0为同一帧,否则为下一帧
volatile uchar SameFrameFlag1=3;
sTask SCH_tasks_G[SCH_MAX_TASKS];// 任务调度器数组
void Usart0CommandDeal(void);
void Usart1CommandDeal(void);
//定时器0初始化
void SCH_Init_T0(void)
{
TCNT0=0;
TCCR0 = ((1<<WGM01)|(7<<CS00)); //1024分频
OCR0=130; //108:10ms,130:12ms,162:15ms t(ms)=10*OCR0/108
TIMSK |= (1<<OCIE0); // Interrupt Timer 0 enabled
}
//增加任务
uchar SCH_Add_Task( const void (*pFunction)(void), uchar DELAY, uchar PERIOD)
{
uchar Index = 0;
while ((SCH_tasks_G[Index].pTask != 0) && (Index < SCH_MAX_TASKS))// Have we reached the end of the list?
{
Index++;
}
if (Index == SCH_MAX_TASKS)// Task list is full
{
return SCH_MAX_TASKS;
}
SCH_tasks_G[Index].pTask = pFunction; // If we're here, there is a space in the task array
SCH_tasks_G[Index].Delay = DELAY;
SCH_tasks_G[Index].Period = PERIOD;
SCH_tasks_G[Index].RunMe = 0;
return Index; // return position of task (to allow later deletion)
}
SIGNAL(TIMER0_COMP_vect)//(SIG_OVERFLOW0)
{
uchar Index;
for ( Index = 0; Index < SCH_MAX_TASKS; Index++ )
{
if (SCH_tasks_G[Index].Delay == 0)
{
//给可以被调度的任务设置标志位
//说明:任务运行标志位不具有存储功能,也就是说,如果在规定的
// 间隔内没有被运行,则机会丧失
SCH_tasks_G[Index].RunMe = 1; // Inc. the 'Run Me' flag
SCH_tasks_G[Index].Delay = SCH_tasks_G[Index].Period;//将任务需要的延时装入
}
else
{
SCH_tasks_G[Index].Delay --;//延时-1
}
}
}
//串口0初始化
void usart0_init( uint baud )
{
uint UBRR;
PORTE|=0x03;
DDRE|=0x03;
UBRR=(fosc/16/baud)-1;
/* 设置波特率*/
UBRR0H = (UBRR>>8);
UBRR0L = UBRR;
UCSR0B = (1<<RXCIE0)|(1<<TXCIE0)|(1<<RXEN0)|(1<<TXEN0); /* 接收器与发送器使能*/
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00); /* 设置帧格式: 8 个数据位, 1 个停止位 */
}
// 定义 USART0 接收变量**********************************************
#define RX_BUFFER_SIZE0 80
uchar rx_buffer0[RX_BUFFER_SIZE0]; //接收缓存
// USART0 写、读指示及缓存中数据的字节数
volatile uchar rx_wr_index0=0;
volatile uchar rx_rd_index0=0;
volatile uchar rx_counter0=0;
// USART0 接收中断*****************************************************
SIGNAL(SIG_UART0_RECV)
{
uchar Temp;
usart0_recv_flag=1;
SameFrameFlag0=3;
//判断有无错误,(FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN)=0X1C
if((UCSR0A&(FRAMING_ERROR|PARITY_ERROR|DATA_OVERRUN))==0)
{
rx_buffer0[rx_wr_index0]=UDR0; //接收数据至缓存区
if(++rx_wr_index0==RX_BUFFER_SIZE0)
rx_wr_index0=0; //缓存区满后写指示指向缓存区头
if(++rx_counter0==RX_BUFFER_SIZE0) //缓存区数据满后
rx_counter0=0; //清零字节记数值
}
else
Temp=UDR0;
}
// USART0 将缓存区数据读出到数组
uchar usart0_getstring(uchar *pGet)
{
uchar n=0;
while(rx_counter0)
{
*pGet++=rx_buffer0[rx_rd_index0];
if(++rx_rd_index0==RX_BUFFER_SIZE0)
rx_rd_index0=0; //缓存数据读完后读指示指向缓存区头
asm volatile("cli");
--rx_counter0;
asm volatile("sei");
n++;
}
return n;
}
#define TX_BUFFER_SIZE0 80
uchar tx_buffer0[TX_BUFFER_SIZE0]; //发送缓存
// USART0 发送读写指示及缓存区字节数
volatile uchar tx_wr_index0=0;
volatile uchar tx_rd_index0=0;
volatile uchar tx_counter0=0;
// USART0 发送***************************************************************
SIGNAL(SIG_UART0_TRANS) // USART0 发送中断
{
if(tx_counter0)
{
tx_counter0-=1; //发送字节数减一
UDR0=tx_buffer0[tx_rd_index0]; //缓存区数据载入发送寄存器
if((++tx_rd_index0)==TX_BUFFER_SIZE0)
tx_rd_index0=0; //如果数据发送完读指示指向缓存区头
}
}
// USART0 将数据写入发送缓存区
void usart0_putchar(uchar c)
{
while(tx_counter0>=TX_BUFFER_SIZE0); //等待发送缓存中数据发送
asm volatile("cli"); //关全局中断
//如果缓存区有数据或正在发送数据
if(tx_counter0||((UCSR0A&DATA_REGISTER_EMPTY)==0))
{
tx_buffer0[tx_wr_index0]=c; //数据写入缓存区
if((++tx_wr_index0)==TX_BUFFER_SIZE0)tx_wr_index0=0;
tx_counter0+=1;
}
else
{
UDR0=c;
}
asm volatile("sei");
asm volatile("nop");
}
// USART0 发送ram中的字符串
void usart0_putramstring(uchar *str,uchar n)
{
while(n--)
{
usart0_putchar( *str++ );
}
}
// USART0 发送flash中的字符串
void usart0_putflashstring(char *str)
{
uchar temp=pgm_read_byte(str);
while(temp!='\0')
{
usart0_putchar( temp );
temp=pgm_read_byte(++str);
}
}
// USART0 发送n字符
void Usart0PutNChar(uchar *str,uchar n)
{
uchar i;
for(i=0;i<n;i++)
{
usart0_putchar( *str++ );
}
}
//串口1初始化
void usart1_init( uint baud )
{
uint UBRR;
PORTD|=0x0C;
DDRD|=0x0C;
UBRR=(fosc/16/baud)-1;
/* 设置波特率*/
UBRR1H = (UBRR>>8);
UBRR1L = UBRR;
UCSR1B = (1<<RXCIE1)|(1<<TXCIE1)|(1<<RXEN1)|(1<<TXEN1); /* 接收器与发送器使能*/
UCSR1C = (1<<UCSZ11)|(1<<UCSZ10); /* 设置帧格式: 8 个数据位, 1 个停止位 */
}
// 定义 USART1 接收变量**********************************************
#define RX_BUFFER_SIZE1 80
uchar rx_buffer1[RX_BUFFER_SIZE1]; //接收缓存
// USART1 写、读指示及缓存中数据的字节数
volatile uchar rx_wr_index1=0;
volatile uchar rx_rd_index1=0;
volatile uchar rx_counter1=0;
// USART1 接收中断*****************************************************
SIGNAL(SIG_UART1_RECV)
{
uchar Temp;
usart1_recv_flag=1;
SameFrameFlag1=3;
//判断有无错误,(FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN)=0X1C
if((UCSR1A&(FRAMING_ERROR|PARITY_ERROR|DATA_OVERRUN))==0)
{
rx_buffer1[rx_wr_index1]=UDR1; //接收数据至缓存区
if(++rx_wr_index1==RX_BUFFER_SIZE1)
rx_wr_index1=0; //缓存区满后写指示指向缓存区头
if(++rx_counter1==RX_BUFFER_SIZE1) //缓存区数据满后
rx_counter1=0; //清零字节记数值
}
else
Temp=UDR1;
}
// USART1 将缓存区数据读出到数组
uchar usart1_getstring(uchar *pGet)
{
uchar n=0;
while(rx_counter1)
{
*pGet++=rx_buffer1[rx_rd_index1];
if(++rx_rd_index1==RX_BUFFER_SIZE1)
rx_rd_index1=0; //缓存数据读完后读指示指向缓存区头
asm volatile("cli");
--rx_counter1;
asm volatile("sei");
n++;
}
return n;
}
#define TX_BUFFER_SIZE1 80
uchar tx_buffer1[TX_BUFFER_SIZE1]; //发送缓存
// USART1 发送读写指示及缓存区字节数
volatile uchar tx_wr_index1=0;
volatile uchar tx_rd_index1=0;
volatile uchar tx_counter1=0;
// USART1 发送***************************************************************
SIGNAL(SIG_UART1_TRANS) // USART1 发送中断
{
if(tx_counter1)
{
tx_counter1-=1; //发送字节数减一
UDR1=tx_buffer1[tx_rd_index1]; //缓存区数据载入发送寄存器
if((++tx_rd_index1)==TX_BUFFER_SIZE1)
tx_rd_index1=0; //如果数据发送完读指示指向缓存区头
}
}
// USART1 将数据写入发送缓存区
void usart1_putchar(uchar c)
{
while(tx_counter1>=TX_BUFFER_SIZE1); //等待发送缓存中数据发送
asm volatile("cli"); //关全局中断
//如果缓存区有数据或正在发送数据
if(tx_counter1||((UCSR1A&DATA_REGISTER_EMPTY)==0))
{
tx_buffer1[tx_wr_index1]=c; //数据写入缓存区
if((++tx_wr_index1)==TX_BUFFER_SIZE1)tx_wr_index1=0;
tx_counter1+=1;
}
else
{
UDR1=c;
}
asm volatile("sei");
asm volatile("nop");
}
// USART1 发送ram中的字符串
void usart1_putramstring(uchar *str,uchar n)
{
while(n--)
{
usart1_putchar( *str++ );
}
}
// USART1 发送flash中的字符串
void usart1_putflashstring(char *str)
{
uchar temp=pgm_read_byte(str);
while(temp!='\0')
{
usart1_putchar( temp );
temp=pgm_read_byte(++str);
}
}
// USART1 发送n字符
void Usart1PutNChar(uchar *str,uchar n)
{
uchar i;
for(i=0;i<n;i++)
{
usart1_putchar( *str++ );
}
}
void sys_init(void)
{
usart0_init(9600);
usart1_init(9600);
asm("sei");
usart0_putflashstring(PSTR("Usart test,please wait!"));
usart0_putchar( '\r' );
usart0_putchar( '\n' );
SCH_Add_Task((void*)Usart0CommandDeal, 1, 2);
SCH_Add_Task((void*)Usart1CommandDeal, 0, 2);
SCH_Init_T0();
}
void Usart0CommandDeal(void)
{
static uchar *pUsartRece=Comm0Temp;
uchar Rcounter;
if(SameFrameFlag0)
SameFrameFlag0--;
if(usart0_recv_flag) //接收数据,是同一帧的数据合并
{
usart0_recv_flag=0;
Rcounter=usart0_getstring(pUsartRece);
if(SameFrameFlag0)
{
pUsartRece+=Rcounter;
if(pUsartRece-Comm0Temp>100)
{
Usart0PutNChar(Comm0Temp,pUsartRece-Comm0Temp);
pUsartRece=Comm0Temp;
}
}
}
if(SameFrameFlag0==0) //一帧接收完,处理数据
{
SameFrameFlag0=3;
Rcounter=pUsartRece-Comm0Temp;
pUsartRece=Comm0Temp;
Usart0PutNChar(Comm0Temp,Rcounter);
}
}
void Usart1CommandDeal(void)
{
static uchar *pUsartRece=Comm1Temp;
uchar Rcounter;
if(SameFrameFlag1)
SameFrameFlag1--;
if(usart1_recv_flag) //接收数据,是同一帧的数据合并
{
usart1_recv_flag=0;
Rcounter=usart1_getstring(pUsartRece);
if(SameFrameFlag1)
{
pUsartRece+=Rcounter;
if(pUsartRece-Comm1Temp>100)
{
Usart1PutNChar(Comm1Temp,pUsartRece-Comm1Temp);
pUsartRece=Comm1Temp;
}
}
}
if(SameFrameFlag1==0) //一帧接收完,处理数据
{
SameFrameFlag1=3;
Rcounter=pUsartRece-Comm1Temp;
pUsartRece=Comm1Temp;
Usart1PutNChar(Comm1Temp,Rcounter);
}
}
int main(void)
{
uchar Index;
sys_init();
while(1)
{
// 调度器调度任务
for (Index = 0; Index < SCH_MAX_TASKS; Index++)
{
if (SCH_tasks_G[Index].RunMe)
{
(*SCH_tasks_G[Index].pTask)(); // 运行任务
SCH_tasks_G[Index].RunMe = 0; // 清除任务标志位
}
}
}
} |
|