搜索
bottom↓
回复: 250

简洁实用的时间片调度法操作系统,献给大家

  [复制链接]

出0入0汤圆

发表于 2006-12-5 20:01:35 | 显示全部楼层 |阅读模式
在OURAVR潜水有段时间了,学到不少东西,参考一些资料,我写了一个简洁实用的时间片调度法操作系统,在我的一些产品中已经应用,非常稳定,在再献给大家



// RTOS HEAD FILE



#ifndef _RTOS_T0_H

#define _RTOS_T0_H



// 防止C编译器调用以下寄存器(可参考GCC说明),减少任务调度代码所占用的时间

register unsigned char tempR4  asm("r4");

register unsigned char tempR5  asm("r5");

register unsigned char tempR6  asm("r6");

register unsigned char tempR7  asm("r7");

register unsigned char tempR8  asm("r8");

register unsigned char tempR9  asm("r9");

register unsigned char tempR10 asm("r10");

register unsigned char tempR11 asm("r11");

register unsigned char tempR12 asm("r12");

register unsigned char tempR13 asm("r13");

register unsigned char tempR14 asm("r14");

register unsigned char tempR15 asm("r15");

register unsigned char tempR16 asm("r16");

register unsigned char tempR16 asm("r17");





#define PUSH_ALL()                                        \

asm volatile(                                        \

"PUSH        R2"        "
\t"                                \

"PUSH        R3"        "
\t"                                \

"PUSH        R18"        "
\t"                                \

"PUSH        R19"        "
\t"                                \

"PUSH        R20"        "
\t"                                \

"PUSH        R21"        "
\t"                                \

"PUSH        R22"        "
\t"                                \

"PUSH        R23"        "
\t"                                \

"PUSH        R24"        "
\t"                                \

"PUSH        R25"        "
\t"                                \

"PUSH        R26"        "
\t"                                \

"PUSH        R27"        "
\t"                                \

"PUSH        R28"        "
\t"                                \

"PUSH        R29"        "
\t"                                \

"PUSH        R30"        "
\t"                                \

"PUSH        R31"        "
\t"                                \

)                                                \



#define        POP_ALL()                                        \

asm volatile(                                        \

"POP        R31"                "
\t"                        \

"POP        R30"                "
\t"                        \

"POP        R29"                "
\t"                        \

"POP        R28"                "
\t"                        \

"POP        R27"                "
\t"                        \

"POP        R26"                "
\t"                        \

"POP        R25"                "
\t"                        \

"POP        R24"                "
\t"                        \

"POP        R23"                "
\t"                        \

"POP        R22"                "
\t"                        \

"POP        R21"                "
\t"                        \

"POP        R20"                "
\t"                        \

"POP        R19"                "
\t"                        \

"POP        R18"                "
\t"                        \

"POP        R3"                "
\t"                        \

"POP        R2"                "
\t"                        \

"POP        R0"                "
\t"                        \

"OUT        0x3F,R0"                "
\t"                        \

"POP        R0"                "
\t"                        \

"POP        R1"                "
\t"                        \

)                                                \





#define Total_Task_Num        8

#define Task_Stack_Size        50

#define Total_Stack_Size        Total_Task_Num * Task_Stack_Size



unsigned char uTaskStack[Total_Stack_Size];

unsigned char uCurrentTaskID;

unsigned char uTotalTaskNum;

unsigned char uCurrentProperty;



unsigned int uTaskEntry[Total_Task_Num];                        // 任务入口



void OS_Start(void);                                // 开启系统:0号任务开始

void OS_ScheduleTask(void);                        // 任务调度:处理任务调用属性

void OS_CreateTask( void (*pTaskEntry)(void), unsigned char *pTaskStack);

void OS_Timer0Init(void);                        // 定时中断:调度任务

void OS_CallNext(void);



#endif









// RTOS.C



#include <avr/io.h>

#include <avr/interrupt.h>

#include "RTOS_T0.h"



void OS_Timer0Init(void)

{

        TCNT0 = 0x00;

        OCR0 = 95;



        TCCR0 = (1<<CS01);                // ti = F_CPU(15360000) / OCR0(95+1) / n(8) / 2= 0.1ms



        TIMSK |= (1<<OCIE0);

}



SIGNAL(SIG_OUTPUT_COMPARE0)

{

        asm("JMP OS_ScheduleTask");

}



void OS_CreateTask( void (*pTaskEntry)(void), unsigned char *pTaskStack)

{

        *pTaskStack-- = (unsigned int)pTaskEntry;

        *pTaskStack-- = (unsigned int)pTaskEntry>>8;



        uTaskEntry[uTotalTaskNum++] = (unsigned int)pTaskStack;

}



void OS_Start(void)

{

        SP = uTaskEntry[0];



        TCNT0 = 0x00;

        asm("reti");

}



// 提前调度下一任务,节约时间片资源

void OS_CallNext(void)

{

        TCNT0 = OCR0-1;

        asm("nop");

        asm("nop");

        asm("nop");

        asm("nop");

        asm("nop");

        asm("nop");

        asm("nop");

        asm("nop");

        asm("nop");       

}



// 优化设置:-0s,其他形式下需要改变入栈与出栈代码



void OS_ScheduleTask(void)

{

        PUSH_ALL();



        uTaskEntry[uCurrentTaskID++] = SP+19;

        if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;

        SP =  uTaskEntry[uCurrentTaskID]-19;



        POP_ALL();



        TCNT0 = 0x00;

        asm("reti");

}

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

 楼主| 发表于 2006-12-5 20:12:51 | 显示全部楼层
应用如下,程序仅参考,我的系统功能如下:



芯片:mega16-16AU



A:采用PS/2键盘输入,设置设备参数

B:采用20X02LCD显示

C:扩展了32路数字输入32路数字输出(DC24V)

D:控制一套伺服

E:制三个交流感应电机

F:温度控制







#include <avr/io.h>

#include <util/delay.h>

#include <avr/interrupt.h>

#include <avr/eeprom.h>

#include <avr/pgmspace.h>



#include "RTOS_T0.h"







void Task_ScanExPort(void)

{

        ......



TaskStart:



        ......

       

        OS_CallNext();



        goto TaskStart;

}



void Task_Keyboard(void)

{

        ......



TaskStart:



        ......



        OS_CallNext();



        goto TaskStart;

}





void Task_System(void)

{



TaskStart:



        ......



        OS_CallNext();



        goto TaskStart;

}



void Task_Load(void)

{

        ......



TaskStart:



        ......       

       

        OS_CallNext();



        goto TaskStart;

}



void Task_Unload(void)

{

        ......



TaskStart:       



        ......



        OS_CallNext();



        goto TaskStart;

}



void Task_LED(void)

{

        ......



TaskStart:



        ......



        OS_CallNext();



        goto TaskStart;

}



void Task_CamDisc(void)

{

        ......



TaskStart:



        ......



        OS_CallNext();



        goto TaskStart;

}



void Task_Miss_Extra(void)

{

        ......



TaskStart:



        delay_ms(100);



        OS_CallNext();



        goto TaskStart;

}





int main(void)

{

        uTotalTaskNum = 0;

        uCurrentTaskID = 0;       

        OS_Timer0Init();

       

        OS_CreateTask(Task_ScanExPort, &uTaskStack[Total_Stack_Size-1]);



        OS_CreateTask(Task_Keyboard, &uTaskStack[Total_Stack_Size-Task_Stack_Size-1]);



        OS_CreateTask(Task_System, &uTaskStack[Total_Stack_Size-Task_Stack_Size*2-1]);



        OS_CreateTask(Task_Load, &uTaskStack[Total_Stack_Size-Task_Stack_Size*3-1]);



        OS_CreateTask(Task_Unload, &uTaskStack[Total_Stack_Size-Task_Stack_Size*4-1]);



        OS_CreateTask(Task_LED, &uTaskStack[Total_Stack_Size-Task_Stack_Size*5-1]);



        OS_CreateTask(Task_CamDisc, &uTaskStack[Total_Stack_Size-Task_Stack_Size*6-1]);



        OS_CreateTask(Task_Miss_Extra, &uTaskStack[Total_Stack_Size-Task_Stack_Size*7-1]);



        OS_Start();



        return(0);

}

出0入0汤圆

 楼主| 发表于 2006-12-5 20:14:39 | 显示全部楼层
OS_CallNext(); 可以根据实际需要而删除不用

出0入42汤圆

发表于 2006-12-5 21:03:26 | 显示全部楼层
好!顶一下,可以试试!

出0入42汤圆

发表于 2006-12-5 21:59:11 | 显示全部楼层
楼主用什么编译器?用Winavr好象不能编译过去!

出0入0汤圆

发表于 2006-12-5 22:35:15 | 显示全部楼层
楼主厉害啊:)

出0入0汤圆

发表于 2006-12-5 22:46:49 | 显示全部楼层
好利害,我都是用的“时间触发调度系统”方式,感觉也挺好的。

出0入0汤圆

 楼主| 发表于 2006-12-6 09:30:25 | 显示全部楼层
AVR Studio 4.12 SP2 Build 472 + WinAVR 2006-0421,开发很方便,直接在AVR Studio中利用WinAVR的GCC进行开发

出0入0汤圆

发表于 2006-12-6 11:00:37 | 显示全部楼层
register unsigned char tempR16 asm("r17");



这里应该是

register unsigned char tempR17 asm("r17");

出0入0汤圆

发表于 2006-12-6 11:13:20 | 显示全部楼层
多谢楼主的贡献精神!

出0入0汤圆

 楼主| 发表于 2006-12-6 12:05:34 | 显示全部楼层
输入贻误,谢谢指正

出0入42汤圆

发表于 2006-12-6 17:13:19 | 显示全部楼层
菜鸟请楼主指点一下:

   uTaskEntry[uCurrentTaskID++] = SP+19;

   if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;

   SP =  uTaskEntry[uCurrentTaskID]-19;

是什么意思啊,为什么要加19,后面又要减19呢?

出0入0汤圆

 楼主| 发表于 2006-12-6 17:58:31 | 显示全部楼层
在-0s优化中,GCC将Timer0的比较中断汇编为:



@000000EE: __vector_19

22:       {

+000000EE:   921F        PUSH    R1               Push register on stack

+000000EF:   920F        PUSH    R0               Push register on stack

+000000F0:   B60F        IN      R0,0x3F          In from I/O location

+000000F1:   920F        PUSH    R0               Push register on stack

+000000F2:   2411        CLR     R1               Clear Register

23:               asm("JMP OS_ScheduleTask");

+000000F3:   940C0124    JMP     0x00000124       Jump

+000000F5:   900F        POP     R0               Pop register from stack

+000000F6:   BE0F        OUT     0x3F,R0          Out to I/O location

+000000F7:   900F        POP     R0               Pop register from stack

+000000F8:   901F        POP     R1               Pop register from stack

+000000F9:   9518        RETI                     Interrupt return



执行asm("JMP OS_ScheduleTask");后进入函数OS_ScheduleTask,汇编为:

@00000124: OS_ScheduleTask

57:       {

+00000124:   922F        PUSH    R2               Push register on stack

+00000125:   923F        PUSH    R3               Push register on stack

+00000126:   932F        PUSH    R18              Push register on stack

+00000127:   933F        PUSH    R19              Push register on stack

+00000128:   934F        PUSH    R20              Push register on stack

+00000129:   935F        PUSH    R21              Push register on stack

+0000012A:   936F        PUSH    R22              Push register on stack

+0000012B:   937F        PUSH    R23              Push register on stack

+0000012C:   938F        PUSH    R24              Push register on stack

+0000012D:   939F        PUSH    R25              Push register on stack

+0000012E:   93AF        PUSH    R26              Push register on stack

+0000012F:   93BF        PUSH    R27              Push register on stack

+00000130:   93CF        PUSH    R28              Push register on stack

+00000131:   93DF        PUSH    R29              Push register on stack

+00000132:   93EF        PUSH    R30              Push register on stack

+00000133:   93FF        PUSH    R31              Push register on stack

60:               uTaskEntry[uCurrentTaskID++] = SP+19;

+00000134:   91200106    LDS     R18,0x0106       Load direct from data space

+00000136:   2FE2        MOV     R30,R18          Copy register

+00000137:   27FF        CLR     R31              Clear Register

+00000138:   0FEE        LSL     R30              Logical Shift Left

+00000139:   1FFF        ROL     R31              Rotate Left Through Carry

+0000013A:   50E0        SUBI    R30,0x00         Subtract immediate

+0000013B:   4FFF        SBCI    R31,0xFF         Subtract immediate with carry

+0000013C:   B78D        IN      R24,0x3D         In from I/O location

+0000013D:   B79E        IN      R25,0x3E         In from I/O location

+0000013E:   9643        ADIW    R24,0x13         Add immediate to word

+0000013F:   8391        STD     Z+1,R25          Store indirect with displacement

+00000140:   8380        STD     Z+0,R24          Store indirect with displacement

+00000141:   5F2F        SUBI    R18,0xFF         Subtract immediate

+00000142:   93200106    STS     0x0106,R18       Store direct to data space

61:               if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;

+00000144:   91800107    LDS     R24,0x0107       Load direct from data space

+00000146:   1728        CP      R18,R24          Compare

+00000147:   F010        BRCS    PC+0x03          Branch if carry set

+00000148:   92100106    STS     0x0106,R1        Store direct to data space

62:               SP =  uTaskEntry[uCurrentTaskID]-19;

+0000014A:   91800106    LDS     R24,0x0106       Load direct from data space

+0000014C:   2FE8        MOV     R30,R24          Copy register

+0000014D:   27FF        CLR     R31              Clear Register

+0000014E:   0FEE        LSL     R30              Logical Shift Left

+0000014F:   1FFF        ROL     R31              Rotate Left Through Carry

+00000150:   50E0        SUBI    R30,0x00         Subtract immediate

+00000151:   4FFF        SBCI    R31,0xFF         Subtract immediate with carry

+00000152:   8180        LDD     R24,Z+0          Load indirect with displacement

+00000153:   8191        LDD     R25,Z+1          Load indirect with displacement

+00000154:   9743        SBIW    R24,0x13         Subtract immediate from word

+00000155:   BF9E        OUT     0x3E,R25         Out to I/O location

+00000156:   BF8D        OUT     0x3D,R24         Out to I/O location

64:               POP_ALL();

+00000157:   91FF        POP     R31              Pop register from stack

+00000158:   91EF        POP     R30              Pop register from stack

+00000159:   91DF        POP     R29              Pop register from stack

+0000015A:   91CF        POP     R28              Pop register from stack

+0000015B:   91BF        POP     R27              Pop register from stack

+0000015C:   91AF        POP     R26              Pop register from stack

+0000015D:   919F        POP     R25              Pop register from stack

+0000015E:   918F        POP     R24              Pop register from stack

+0000015F:   917F        POP     R23              Pop register from stack

+00000160:   916F        POP     R22              Pop register from stack

+00000161:   915F        POP     R21              Pop register from stack

+00000162:   914F        POP     R20              Pop register from stack

+00000163:   913F        POP     R19              Pop register from stack

+00000164:   912F        POP     R18              Pop register from stack

+00000165:   903F        POP     R3               Pop register from stack

+00000166:   902F        POP     R2               Pop register from stack

+00000167:   900F        POP     R0               Pop register from stack

+00000168:   BE0F        OUT     0x3F,R0          Out to I/O location

+00000169:   900F        POP     R0               Pop register from stack

+0000016A:   901F        POP     R1               Pop register from stack

66:               TCNT0 = 0x00;

+0000016B:   BE12        OUT     0x32,R1          Out to I/O location

67:               asm("reti");

+0000016C:   9518        RETI                     Interrupt return

+0000016D:   9508        RET                      Subroutine return



中断函数出口处,需要将入栈的寄存器出栈,在出栈前更改堆栈指针SP,出栈后运行至asm("reti");后不会返回至Timer0的比较中断函数,而是直接运行至SP所指的位置,也就是每个任务在释放CPU控制权后保存的SP

出0入0汤圆

 楼主| 发表于 2006-12-6 18:15:02 | 显示全部楼层
uTaskEntry[uCurrentTaskID++] = SP+19;

保存中断前一个任务的SP



if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;  

如果每个任务已经执行了,重新从0号任务开始执行



SP =  uTaskEntry[uCurrentTaskID]-19;

获取即将执行的任务的SP



因为每个任务所处的环境不同,所以实际就是在进行任务切换前先保存刚刚执行过的任务环境,再取得已保存的下一个任务的环境,形成一个循环,这样的好处是很多的,比如说本任务处于一个等待状态,因为定时器的中断,将不会阻碍其他任务的执行,在工业控制中非常实用,而且工业控制中的实时性要求并不是很高,比如说I/O信号处理,间隔1ms采集一次远远足够。



各任务间的数据共享可以定义成全局变量如: volatile unsigned char ucCount;

volatile 不可少,至于作用,可以参考本站的许多帖子。



AVR系列在此的优势非常明显:大容量的RAM,这关系到任务数量

出0入42汤圆

发表于 2006-12-6 19:40:12 | 显示全部楼层
多谢楼主指点,不过我在#define PUSH_ALL() 和#define POP_ALL() 这两个宏的编译不能通过,语法错误,不知道什么问题。

出0入0汤圆

 楼主| 发表于 2006-12-6 20:15:25 | 显示全部楼层
什么错误?有可能是你在“\”后有空格符号,我遇到这样的情况

出0入42汤圆

发表于 2006-12-6 20:21:57 | 显示全部楼层
果然是空格多了,谢谢楼主,楼主大好人啊!

出0入0汤圆

发表于 2006-12-7 01:14:41 | 显示全部楼层
支持好贴!

出0入0汤圆

发表于 2006-12-7 02:49:04 | 显示全部楼层
樓主您好!想問問Inter Process Communication/Synchronization 在您的應用中怎樣實現?

出0入0汤圆

发表于 2006-12-7 10:25:58 | 显示全部楼层
盼望搂住给一个完整的应用程序啊,谢谢啊1

出0入0汤圆

 楼主| 发表于 2006-12-7 11:23:21 | 显示全部楼层
下面是我一台设备的程序(第二版本,第一台已经用于生产),程序完成量80%

功能:PS/2键盘输入,键F1设置设备的几个参数(需要密码,密码可以更改),键F2设备生产中需要改变的数据,有操作人员修改,其他的就是一些I/O信号的处理



// main



#include <avr/io.h>

#include <util/delay.h>

#include <avr/interrupt.h>

#include <avr/eeprom.h>

#include <avr/pgmspace.h>



#include "RTOS_T0.h"

#include "1602LCD.h"

#include "Head.h"



void Task_ScanExPort(void)

{

        DDR_CS = 0x3F;

        PORT_CS = 0x00;       



        DisplayString(0,0,9, ucMachineInfo0);

        DisplayString(15,1,4, ucMachineInfo1);       

        delay_ms(500);



        LCD_Clean_Screen();

        DisplayString(0,0,10, ucMasterInfo0);

        DisplayString(10,1,10, ucMasterInfo1);

        delay_ms(500);



        sbi(PORT_CS, EP_LE);



        sbi(ucSystemFlag, SF_BE_LOG);



        unsigned char ucExPort_Temp;

        unsigned char ucExPort_Index;

        unsigned char ucExPort_PortValue;



TaskStart:



        for(ucExPort_Index = 0; ucExPort_Index < 8; ucExPort_Index++)

        {

                PORT_CS &= 0xF0;

                PORT_CS |= ucExPort_Index;



                if(ucExPort_Index >= 4)

                {

                        DDR_EP = 0xFF;               

                        PORT_EP = ucEP_OUT[ucExPort_Index-4];               

                }       



                sbi(PORT_CS, CS_OE);

                asm("nop");                                // can not be ignore



                if(ucExPort_Index < 4)

                {

                        DDR_EP = 0x00;

                        PORT_EP = 0xFF;

                        asm("nop");



                        ucExPort_PortValue =  ~PIN_EP;



                        ucExPort_Temp = ucExPort_PortValue ^ ucEP_IN[ucExPort_Index].ucPV;



                        ucEP_IN[ucExPort_Index].ucBD        = ucExPort_Temp & ucEP_IN[ucExPort_Index].ucPV;

                        ucEP_IN[ucExPort_Index].ucBA        = ucExPort_Temp & ucExPort_PortValue;

                        ucEP_IN[ucExPort_Index].ucPV        = ucExPort_PortValue;

                }

        }

       

        OS_CallNext();



        goto TaskStart;

}



void Task_Keyboard(void)

{

        loop_until_bit_is_set(ucSystemFlag, SF_BE_LOG);



        DDRD &= 0xF3;

        PORTD |= 0x0C;



        MCUCR = (1<<ISC01);                                                                // INT0 下降沿触发

        GICR |= (1<<INT0);



        ucKeyPulse = 10;



TaskStart:



        if( ucKeyCode == F2 )                                                        // Menu Select

        {

                if( ucCurrentMenu == MENU_PROD )                        // Prod

                {       

                        sbi(ucSystemFlag, SF_BE_SET);

                        delay_ms(10);



                        LCD_Clean_Screen();

                        DisplayString(0,0,12, ucProdMenu);

                        DisplayString(0,1,5, ucSetFlag);

                        LCD_DisplayNum(16,1, uiProdQty);

                        ucCurrentMenu = MENU_TAIL;



                        MenuUpdate(MENU_PROD);                       

                }

                else if( ucCurrentMenu == MENU_TAIL )                // Tail

                {

                        LCD_Clean_Screen();

                        DisplayString(0,0,9, ucTailMenu);

                        DisplayString(0,1,5, ucSetFlag);

                        LCD_DisplayNum(16,1, uiTailQty);

                        ucCurrentMenu = MENU_LEAD;

                                               

                        MenuUpdate(MENU_TAIL);                       

                }

                else if( ucCurrentMenu == MENU_LEAD )                // Lead

                {

                        LCD_Clean_Screen();

                        DisplayString(0,0,9, ucLeadMenu);

                        DisplayString(0,1,5, ucSetFlag);

                        LCD_DisplayNum(16,1, uiLeadQty);                       

                        ucCurrentMenu = MENU_USET;



                        MenuUpdate(MENU_LEAD);                       

                }

                else if( ucCurrentMenu == MENU_USET )                // Return

                {                       

                        ucKeyCode = 0;

                        ucCurrentMenu = 0;

                        PrimalScreen();



                        cbi(ucSystemFlag, SF_BE_SET);

                }

        }

        else if(ucKeyCode == F1)

        {

                if( ucCurrentMenu == MENU_PW )                                // Password

                {

                        sbi(ucSystemFlag, SF_BE_SET);

                        delay_ms(10);



                        LCD_Clean_Screen();

                        DisplayString(0,0,9, ucPassword);

                        DisplayString(0,1,5, ucSetFlag);

                        DisplayString(16,1,4, ucPWS);

                        ucCurrentMenu = MENU_HD;                       



                        SetParameters(MENU_PW);

                }

                else if( ucCurrentMenu == MENU_HD )                        // Heat delay time

                {

                        LCD_Clean_Screen();

                        DisplayString(0,0,14, ucHeat);

                        DisplayString(0,1,5, ucSetFlag);

                        LCD_DisplayNum(16,1, uiHeatDly);                       

                        ucCurrentMenu = MENU_LD;



                        SetParameters(MENU_HD);                       

                }

                else if( ucCurrentMenu == MENU_LD )                        // load delay time

                {

                        LCD_Clean_Screen();

                        DisplayString(0,0,14, ucLoad);

                        DisplayString(0,1,5, ucSetFlag);

                        LCD_DisplayNum(16,1, uiLoadDly);

                        ucCurrentMenu = MENU_UD;



                        SetParameters(MENU_LD);                       

                }

                else if( ucCurrentMenu == MENU_UD )                        // unload delay time

                {

                        LCD_Clean_Screen();

                        DisplayString(0,0,15, ucUnload);

                        DisplayString(0,1,5, ucSetFlag);

                        LCD_DisplayNum(16,1, uiUnloadDly);                       

                        ucCurrentMenu = MENU_NP;



                        SetParameters(MENU_UD);                       

                }

                else if( ucCurrentMenu == MENU_NP )                        // New password

                {

                        LCD_Clean_Screen();

                        DisplayString(0,0,13, ucNewPWD);

                        DisplayString(0,1,5, ucSetFlag);

                        DisplayString(16,1,4, ucPWS);

                        ucCurrentMenu = MENU_USET;



                        SetParameters(MENU_NP);                       

                }

                else if( ucCurrentMenu == MENU_USET )                // Return

                {                       

                        ucKeyCode = 0;

                        ucCurrentMenu = 0;

                        PrimalScreen();



                        cbi(ucSystemFlag, SF_BE_SET);

                }

        }

        else if(ucKeyCode == F3 && ucErrorCode == 0)

        {

                if( bit_is_clear(ucSystemFlag, SF_BE_LEAD) )

                {

                        ucKeyCode = 0;

                        sbi(ucSystemFlag, SF_BE_LEAD);

                        delay_ms(10);



                        ShowLead();

                       

                        while(true)

                        {

                                DisplayString(16,1,4, ucSpace);

                                LCD_DisplayNum(16,1, uiLeadResidual);

                               

                                delay_ms(2500);

                               

                                                               



                                if(ucKeyCode == ESC || uiLeadResidual == 0)

                                {

                                        ucKeyCode = 0;

                                        uiLeadResidual = uiLeadQty;

                                        break;

                                }



                                if(ucErrorCode)        break;



                                uiLeadResidual -= 3;

                        }



                        cbi(ucSystemFlag, SF_BE_LEAD);                       

                        PrimalScreen();

                        delay_ms(10);

                        cbi(ucSystemFlag, SF_BE_ERR);                       

                }

        }



        OS_CallNext();



        goto TaskStart;

}





void Task_System(void)

{

        loop_until_bit_is_set(ucSystemFlag, SF_BE_LOG);



TaskStart:



        if( bit_is_set(ucEP_IN[0].ucPV, IN_UNLOAD) )        sbi(ucEP_OUT[3], OUT_ENABLE_UNLOAD_MOTOR);

       

        if( bit_is_set(ucEP_IN[0].ucPV, IN_LOAD) )                sbi(ucEP_OUT[3], OUT_ENABLE_LOAD_MOTOR);       





        OS_CallNext();



        goto TaskStart;

}



void Task_Load(void)

{

        loop_until_bit_is_set(ucSystemFlag, SF_BE_LOG);



TaskStart:



        if( bit_is_clear(ucEP_IN[0].ucPV, IN_LOAD) )

        {

                if( bit_is_set(ucEP_OUT[3], OUT_ENABLE_LOAD_MOTOR) )

                {

                        delay_ms(uiLoadDly);

                        cbi(ucEP_OUT[3], OUT_ENABLE_LOAD_MOTOR);

                }

        }       

       

        OS_CallNext();



        goto TaskStart;

}



void Task_Unload(void)

{

        loop_until_bit_is_set(ucSystemFlag, SF_BE_LOG);



TaskStart:       



        if( bit_is_clear(ucEP_IN[0].ucPV, IN_UNLOAD) )

        {

                if( bit_is_set(ucEP_OUT[3], OUT_ENABLE_UNLOAD_MOTOR) )

                {

                        delay_ms(uiUnloadDly);

                        cbi(ucEP_OUT[3], OUT_ENABLE_UNLOAD_MOTOR);

                }

        }



        OS_CallNext();



        goto TaskStart;

}



void Task_SystemStatus(void)

{

        loop_until_bit_is_set(ucSystemFlag, SF_BE_LOG);



        unsigned char ucIndex;



TaskStart:



        if( bit_is_clear(ucEP_IN[1].ucPV, IN_SVO_IS_ON) )                        sbi(ucErrorCode, EC_SVO); else {cbi(ucErrorCode, EC_SVO);cbi(ucErrorFlag, EC_SVO);}



        if( bit_is_clear(ucEP_IN[1].ucPV, IN_HOST_READY) )                        sbi(ucErrorCode, EC_HRD); else {cbi(ucErrorCode, EC_HRD);cbi(ucErrorFlag, EC_HRD);}



        if( bit_is_set(ucEP_IN[0].ucPV, IN_NOT_AT_T_ALARM) )                 sbi(ucErrorCode, EC_NAT); else {cbi(ucErrorCode, EC_NAT);cbi(ucErrorFlag, EC_NAT);}



        if( bit_is_set(ucEP_IN[0].ucPV, IN_LOW_COVER_TAPE_ALARM) )         sbi(ucErrorCode, EC_LCT); else {cbi(ucErrorCode, EC_LCT);cbi(ucErrorFlag, EC_LCT);}

       

        if( bit_is_set(ucEP_IN[0].ucPV, IN_PART_UP_IN_TAPE_ALARM) )        sbi(ucErrorCode, EC_PIT); else {cbi(ucErrorCode, EC_PIT);cbi(ucErrorFlag, EC_PIT);}



        if( ucErrorCode )

        {

                if( bit_is_set(ucErrorCode, EC_MIS) )                        // Missing

                {

                        ucEP_OUT[2] &= 0xF8;

                        ucEP_OUT[2] |= 0x01;

                }

                else if( bit_is_set(ucErrorCode, EC_EXT) )                // Extra

                {

                        ucEP_OUT[2] &= 0xF8;

                        ucEP_OUT[2] |= 0x02;

                }

                else if( bit_is_set(ucErrorCode, EC_PIT) )                // Part up

                {

                        ucEP_OUT[2] &= 0xF8;

                        ucEP_OUT[2] |= 0x03;

                }

                else if( bit_is_set(ucErrorCode, EC_LCT) )                // Low cover tape

                {

                        ucEP_OUT[2] &= 0xF8;

                        ucEP_OUT[2] |= 0x06;

                }

                else if( bit_is_set(ucErrorCode, EC_NAT) )                // Not at temperature

                {

                        ucEP_OUT[2] &= 0xF8;

                        ucEP_OUT[2] |= 0x04;

                }

                else

                {

                        ucEP_OUT[2] &= 0xF8;

                }



                for(ucIndex=0; ucIndex<7; ucIndex++)

                {

                        if( bit_is_set(ucErrorCode, ucIndex) )

                        {

                                ShowError(ucIndex);

                                break;

                        }

                }



                for(++ucIndex; ucIndex<7; ucIndex++)

                {

                        cbi(ucErrorFlag, ucIndex);

                }



                eoi(ucEP_OUT[3], OUT_SYSTEM_LED);

                delay_ms(250);



                cbi(ucSystemFlag, SF_BE_ERR);

        }

        else

        {

                sbi(ucEP_OUT[3], OUT_SYSTEM_LED);



                if( bit_is_clear(ucSystemFlag, SF_BE_ERR) && bit_is_clear(ucSystemFlag, SF_BE_SET) )

                {

                        PrimalScreen();

                        sbi(ucSystemFlag, SF_BE_ERR);

                }



                if( bit_is_clear(ucSystemFlag, SF_BE_SET) )

                {

                        if( bit_is_clear(ucSystemFlag, SF_BE_LEAD) && bit_is_clear(ucSystemFlag, SF_BE_TAIL) ) ShowProdResidual();

                }

        }



        OS_CallNext();



        goto TaskStart;

}



void Task_CamDisc(void)

{

        loop_until_bit_is_set(ucSystemFlag, SF_BE_LOG);



TaskStart:



        // Test code

        if( bit_is_set(ucEP_IN[3].ucBD, 7) )

        {

                uiProdResidual -= 3;



                if(uiProdResidual == 0) uiProdResidual = uiProdQty;

        }



        OS_CallNext();



        goto TaskStart;

}



void Task_Miss_Extra(void)

{

        loop_until_bit_is_set(ucSystemFlag, SF_BE_LOG);



TaskStart:



        // Test code

        eoi(ucEP_OUT[1],0);

        delay_ms(100);



        OS_CallNext();



        goto TaskStart;

}





int main(void)

{

        LCD_Init();



        uiHeatDly = eeprom_read_word(0);

        uiLoadDly = eeprom_read_word(2);

        uiUnloadDly = eeprom_read_word(4);



        uiProdQty = uiProdResidual = eeprom_read_word(6);

        uiTailQty = uiTailResidual = eeprom_read_word(8);

        uiLeadQty = uiLeadResidual = eeprom_read_word(10);



        ucPWD[0] = eeprom_read_byte(12);

        ucPWD[1] = eeprom_read_byte(13);

        ucPWD[2] = eeprom_read_byte(14);

        ucPWD[3] = eeprom_read_byte(15);



        if(ucPWD[0] == 0xFF) ucPWD[0] = '1';

        if(ucPWD[1] == 0xFF) ucPWD[1] = '2';

        if(ucPWD[2] == 0xFF) ucPWD[2] = '3';

        if(ucPWD[3] == 0xFF) ucPWD[3] = '4';



        uTotalTaskNum = 0;

        uCurrentTaskID = 0;       

        OS_Timer0Init();

       

        OS_CreateTask(Task_ScanExPort, &uTaskStack[Total_Stack_Size-1]);



        OS_CreateTask(Task_Keyboard, &uTaskStack[Total_Stack_Size-Task_Stack_Size-1]);



        OS_CreateTask(Task_System, &uTaskStack[Total_Stack_Size-Task_Stack_Size*2-1]);



        OS_CreateTask(Task_Load, &uTaskStack[Total_Stack_Size-Task_Stack_Size*3-1]);



        OS_CreateTask(Task_Unload, &uTaskStack[Total_Stack_Size-Task_Stack_Size*4-1]);



        OS_CreateTask(Task_SystemStatus, &uTaskStack[Total_Stack_Size-Task_Stack_Size*5-1]);



        OS_CreateTask(Task_CamDisc, &uTaskStack[Total_Stack_Size-Task_Stack_Size*6-1]);



        OS_CreateTask(Task_Miss_Extra, &uTaskStack[Total_Stack_Size-Task_Stack_Size*7-1]);



        OS_Start();



        return(0);

}







// Head.h

#ifndef _HEAD_H

#define _HEAD_H





#define DDR_CS                DDRA

#define PORT_CS                PORTA

#define PIN_CS                PINA



#define DDR_EP                DDRB

#define PORT_EP                PORTB

#define PIN_EP                PINB



#define CS_OE                3

#define EP_LE                4       



//        PORTA

//        6,7:        NC

//        5:                A/B

//        4:                OUT_E

//        3:                OE1 138

//        A2-A0        addr



volatile struct PORT_EX_I

{

        unsigned char ucPV;

        unsigned char ucBA;                // Ascend

        unsigned char ucBD;                // Descend

}

ucEP_IN[4];



volatile unsigned char ucEP_OUT[4];



const unsigned char ucSetFlag[5] PROGMEM = "[SET]";

const unsigned char ucErrFlag[5] PROGMEM = "[ERR]";

const unsigned char ucSucFlag[5] PROGMEM = "[SUC]";



const unsigned char ucMasterInfo0[10] PROGMEM = "Rising Sun";

const unsigned char ucMasterInfo1[10] PROGMEM = "Automation";



const unsigned char ucMachineInfo0[9] PROGMEM = "TAPE REEL";

const unsigned char ucMachineInfo1[4] PROGMEM = "V1.1";



const unsigned char ucProdMenu[12] PROGMEM = "Product QTY:";

const unsigned char ucTailMenu[9] PROGMEM = "Tail QTY:";

const unsigned char ucLeadMenu[9] PROGMEM = "Lead QTY:";



const unsigned char ucPWS[4] PROGMEM = "____";

const unsigned char ucPassword[9] PROGMEM = "PASSWORD:";

const unsigned char ucHeat[14] PROGMEM = "HEATER DELAY:";

const unsigned char ucLoad[14] PROGMEM = "LOADER DELAY:";

const unsigned char ucUnload[15] PROGMEM = "UNLOADER DELAY:";

const unsigned char ucNewPWD[13] PROGMEM = "NEW PASSWORD:";



const unsigned char ucErr[6] PROGMEM = "ERROR:";

const unsigned char ucErr_Code[][18] PROGMEM = {"SERVO OFF","HOST IS NOT READY","NOT AT TEMPERATURE","LOW COVER TAPE","PART UP IN TAPE","EXTRA PART","MISSING PART"};

const unsigned char ucErr_Leng[7] = {9,17,18,14,15,10,12};



const unsigned char ucSpace[20] PROGMEM = "                    ";



unsigned char ucStrTemp[20];



volatile unsigned char ucPWD[4];



volatile unsigned int uiHeatDly;

volatile unsigned int uiLoadDly;

volatile unsigned int uiUnloadDly;



volatile unsigned int uiProdQty;

volatile unsigned int uiProdResidual;

volatile unsigned int uiProdTemp;



volatile unsigned int uiTailQty;

volatile unsigned int uiTailResidual;



volatile unsigned int uiLeadQty;

volatile unsigned int uiLeadResidual;



volatile unsigned char ucKeyPulse;

volatile unsigned char ucKeyCode;

volatile unsigned char ucKeyFlag;

volatile unsigned char ucKeyTemp;





volatile unsigned char ucErrorFlag;

#define EF_BE_SVO        0

#define EF_BE_HRD        1

#define EF_BE_NAT        2

#define EF_BE_LCT        3

#define EF_BE_PIT        4

#define EF_BE_EXT        5

#define EF_BE_MIS        6

// 0: is svo on ?

// 1: is host ready ?

// 2: is not at temperatue ?

// 3: is low cover tape ?

// 4: is part up in tape ?

// 5: is extra part in tape ?

// 6: is missing part in tape



volatile unsigned char ucErrorCode;

#define EC_SVO        0

#define EC_HRD        1

#define EC_NAT        2

#define EC_LCT        3

#define EC_PIT        4

#define EC_EXT        5

#define EC_MIS        6

// 0: is servo on ?

// 1: is host ready ?

// 2: is not at temperature ?

// 3: is low cover tape ?

// 4: is part up in tape ?

// 5: is extra part in tape ?

// 6: is missing part in tape



volatile unsigned char ucSystemFlag;

#define SF_BE_LOG        0

#define SF_BE_SET        1

#define SF_BE_ERR        2

#define SF_BE_PROD        3

#define SF_BE_TAIL        4

#define SF_BE_LEAD        5

// 0: is finished to login ?

// 1: is in setting ?

// 2: is an error in system ?

// 3: is run porduct ?

// 4: is run tail ?

// 5: is run lead ?



volatile unsigned char ucCurrentMenu;

#define MENU_PROD        0

#define MENU_TAIL        1

#define MENU_LEAD        2

#define MENU_USET        0xFF



#define MENU_PW                0

#define MENU_HD                1

#define MENU_LD                2

#define MENU_UD                3

#define MENU_NP                4





#define true        1

#define false        0



#define KB_CLK        2

#define KB_DAT        3



#define F1                0xF1        //0x05

#define F2                0x06

#define F3                0x04

#define F4                0x0C

#define F5                0x03

#define F6                0x0B

#define N0                0x30        //0x70

#define N1                0x31        //0x69

#define N2                0x32        //0x72

#define N3                0x33        //0x7A

#define N4                0x34        //0x6B

#define N5                0x35        //0x73

#define N6                0x36        //0x74

#define N7                0x37        //0x6C

#define N8                0x38        //0x75

#define N9                0x39        //0x7D

#define ESC                0x76

#define ENTER        0x5A

#define POINT        0x71

#define CLEAR        0x66





//        Input Channel 0



#define        IN_LOAD                                                        0                // 上料传感器 OMRON EE-SX670A

#define IN_UNLOAD                                                1                // 下料传感器 OMRON EE-SX670A

#define IN_CAM_HIGH                                                2                // 凸轮高位          OMRON EE-SX670A

#define IN_CAM_LOW                                                3                // 凸轮低位          OMRON EE-SX670A



#define IN_NOT_AT_T_ALARM                                4                // 稳控器报警 OMRON E5GN

#define IN_LOW_COVER_TAPE_ALARM                        5                // 光纤传感器 KEYENCE FS-V12

#define IN_MISS_EXTRA_PART_ALARM                6                // 光纤传感器 KEYENCE FS-V12

#define IN_PART_UP_IN_TAPE_ALARM                7                // 光纤传感器 KEYENCE FS-V12



// Input Channel 1



#define IN_HOST_READY                                        0                // 主机就绪

#define IN_HOST_NEXT_STEP                                1                // 主机通知步进一步

#define IN_HOST_RESET_SIGNAL                        2                // 主机复位信号



#define IN_SVO_IS_READY                                        3                // SVO 就绪

#define IN_SVO_IS_ON                                        4                // SVO ON

#define IN_SVO_IS_TPOS                                        5                // SVO 目标位置到达

#define IN_SVO_IS_ALARM                                        6                // SVO 报警







// Output Channel 3



#define OUT_ENABLE_LOAD_MOTOR                        7                // 上料电机使能

#define OUT_ENABLE_UNLOAD_MOTOR                        6                // 下料电机使能

#define OUT_ENABLE_CAM_MOTOR                        5                // 凸轮电机使能

#define OUT_SYSTEM_LED                                        4                // 系统状态指示灯

#define OUT_ELEC_VALVE_PUSH                                3                // 汽缸电磁阀下推

#define OUT_ELEC_VALVE_PULL                                2                // 汽缸电磁阀上拉

#define OUT_SVO_CTRG                                        1                // SVO 步进触发

#define OUT_SVO_RESET                                        0                // SVO 错误复位

                                       

// Output Channel 2

#define OUT_HOST_WAIT_FOR_TAIL                        5                // HOST 701

#define OUT_HOST_WAIT_FOR_NEXT_PART                4                // HOST 702

#define OUT_HOST_WAIT_FOR_NEXT_LOT                3                // HOST 703

#define OUT_HOST_ALARM_BIT6                                2                // HOST 704

#define OUT_HOST_ALARM_BIT5                                1                // HOST 705

#define OUT_HOST_ALARM_BIT4                                0                // HOST 706



//                                                4        5        6

//                                1                0        0        1        : Missing part in Tape

//                                2                0        1        0        : Extra part in tape               

//                                3                0        1        1        : Part up in tape

//                                4                1        0        0        : Not at temperature       

//                                5                1        0        1        : Tape Index Failure                       

//                                6                1        1        0        : Low cover tape               





void DisplayString(unsigned char X, unsigned char Y, unsigned char ucLen, const prog_uchar* ucString)

{

        unsigned char n;

        for(n=0;n<20;n++) ucStrTemp[n] = 0;



        memcpy_P(ucStrTemp, ucString, ucLen);

        LCD_DisplayString(X,Y, ucStrTemp);

}





void ShowProd(void)

{

        LCD_Clean_Screen();

        DisplayString(0,0,12, ucProdMenu);

        LCD_DisplayNum(0,1, uiProdQty);

        LCD_DisplayNum(16,1, uiProdResidual);       

}



void ShowTail(void)

{

        LCD_Clean_Screen();

        DisplayString(0,0,9, ucTailMenu);

        LCD_DisplayNum(0,1, uiTailQty);

        LCD_DisplayNum(16,1, uiTailResidual);       

}



void ShowLead(void)

{

        LCD_Clean_Screen();

        DisplayString(0,0,9, ucLeadMenu);

        LCD_DisplayNum(0,1, uiLeadQty);

        LCD_DisplayNum(16,1, uiLeadResidual);       

}



void ShowProdResidual(void)

{

        if(uiProdTemp != uiProdResidual)

        {

                DisplayString(16,1,4, ucSpace);

                LCD_DisplayNum(16,1, uiProdResidual);

                uiProdTemp = uiProdResidual;

        }

}



void PrimalScreen(void)

{

        if(ucErrorCode)

        {

                ucErrorFlag = 0;        // reset error flag that show error

        }

        else

        {

                if( bit_is_clear(ucSystemFlag, SF_BE_LEAD) && bit_is_clear(ucSystemFlag, SF_BE_TAIL) ) ShowProd();

        }

}



void EscMenu(void)

{

        ucCurrentMenu = 0;

       

        PrimalScreen();



        cbi(ucSystemFlag, SF_BE_SET);

}



void SetERR(void)

{

        DisplayString(0,1,5, ucErrFlag);

        delay_ms(500);

        DisplayString(0,1,5, ucSetFlag);

}



void SetSUC(void)

{

        DisplayString(0,1,5, ucSucFlag);

        delay_ms(500);       

}



void SetParameters(unsigned char ucParaIndex)

{

        unsigned char ucPos = 0;

        unsigned int ucTemp = 0;       

        unsigned char ucIndex = 0;

        unsigned char ucInput[4];       



        while(true)

        {

                ucKeyCode = 0;       

                while(!ucKeyCode);                                // wait_until_key_is_pressed               



                if(ucKeyCode >= N0 && ucKeyCode <= N9 && ucPos < 4)

                {

                        if(ucParaIndex == MENU_PW || ucParaIndex == MENU_NP)

                        {

                                if(ucKeyCode >= N0 && ucKeyCode <= N9 && ucPos < 4)

                                {

                                        LCD_Set_XY(16+ucPos, 1);

                                        LCD_Send_Command('*', 1);                                       

                                        ucInput[ucPos++] = ucKeyCode;

                                }

                        }

                        else

                        {                       

                                if(ucPos)

                                {

                                        LCD_Set_XY(16+ucPos, 1);

                                        LCD_Send_Command(ucKeyCode, 1);                                       

                                        ucInput[ucPos++] = ucKeyCode-0x30;

                                }

                                else if(!ucPos && ucKeyCode != N0)

                                {

                                        DisplayString(16,1,4, ucSpace);

                                        LCD_Set_XY(16+ucPos, 1);

                                        LCD_Send_Command(ucKeyCode, 1);

                                        ucInput[ucPos++] = ucKeyCode-0x30;

                                }

                        }

                }

                else if(ucKeyCode == ENTER)

                {

                        if(ucParaIndex == MENU_PW)

                        {

                                for(ucIndex = 0; ucIndex < ucPos; ucIndex++)

                                {

                                        if(ucPWD[ucIndex] != ucInput[ucIndex])

                                        {

                                                SetERR();



                                                DisplayString(16,1,4, ucPWS);                                               

                                                break;

                                        }



                                        ucInput[ucIndex] = 0;

                                }



                                ucPos = 0;



                                if(ucIndex == 4)

                                {

                                        SetSUC();



                                        ucKeyCode = F1;

                                        break;

                                }                               

                        }

                        else if(ucParaIndex == MENU_NP)

                        {

                                if(ucPos < 4)

                                {

                                        SetERR();



                                        DisplayString(16,1,4, ucPWS);                                       

                                        ucPos = 0;                                                                                                       

                                }

                                else

                                {

                                        eeprom_write_byte(12, ucInput[0]);

                                        eeprom_write_byte(13, ucInput[1]);

                                        eeprom_write_byte(14, ucInput[2]);

                                        eeprom_write_byte(15, ucInput[3]);



                                        ucPWD[0] = ucInput[0];

                                        ucPWD[1] = ucInput[1];

                                        ucPWD[2] = ucInput[2];

                                        ucPWD[3] = ucInput[3];

                                       

                                        SetSUC();



                                        ucKeyCode = F1;

                                        break;

                                }



                                for(ucIndex = 0; ucIndex < 4; ucIndex++) ucInput[ucIndex] = 0;                               

                        }

                        else

                        {

                                ucTemp = 0;

                                for(ucIndex = 0; ucIndex < ucPos; ucIndex++)

                                {

                                        ucTemp = ucTemp*10 + ucInput[ucIndex];

                                        ucInput[ucIndex] = 0;

                                }

                                       

                                if( ucTemp < 50)

                                {

                                        SetERR();

                       

                                        if(ucParaIndex == MENU_HD)                         LCD_DisplayNum(16,1, uiHeatDly);

                                        else if(ucParaIndex == MENU_LD)         LCD_DisplayNum(16,1, uiLoadDly);

                                        else if(ucParaIndex == MENU_UD)         LCD_DisplayNum(16,1, uiUnloadDly);

                                               

                                        ucPos = 0;

                                        ucTemp = 0;

                                }

                                else

                                {

                                        if(ucParaIndex == MENU_HD)

                                        {

                                                uiHeatDly = ucTemp;

                                                eeprom_write_word(0, ucTemp);

                                        }

                                        else if(ucParaIndex == MENU_LD)

                                        {

                                                uiLoadDly = ucTemp;

                                                eeprom_write_word(2, ucTemp);

                                        }

                                        else if(ucParaIndex == MENU_UD)

                                        {

                                                uiUnloadDly = ucTemp;

                                                eeprom_write_word(4, ucTemp);

                                        }



                                        SetSUC();



                                        ucKeyCode = F1;

                                        break;

                                }

                        }                                       

                }

                else if(ucKeyCode == ESC)

                {

                        delay_ms(10);

                        EscMenu();

                        break;

                }

                else if(ucKeyCode == CLEAR)

                {

                        if(ucParaIndex == MENU_PW || ucParaIndex == MENU_NP)

                        {       

                                if(ucPos)

                                {

                                        --ucPos;



                                        LCD_Set_XY(16+ucPos, 1);

                                        LCD_Send_Command('_', 1);

                                        ucInput[ucPos] = 0;

                                }

                        }

                        else

                        {

                                DisplayString(16,1,4, ucSpace);



                                ucTemp = 0;

                                for(ucIndex = 0; ucIndex < ucPos-1; ucIndex++)

                                {

                                        ucTemp = ucTemp*10 + ucInput[ucIndex];

                                }



                                if(ucPos)        ucPos--;

                                ucInput[ucPos] = 0;



                                LCD_DisplayNum(16,1, ucTemp);

                        }

                }

                else if(ucKeyCode == F1 && ucPos == 0 && ucParaIndex != MENU_PW)

                {

                        ucKeyCode = F1;

                        break;

                }

        }               

}



void MenuUpdate(unsigned char ucMenuIndex)

{

        unsigned char ucPos = 0;

        unsigned int ucTemp = 0;       

        unsigned char ucIndex = 0;

        unsigned char ucInput[4];       



        while(true)

        {

                ucKeyCode = 0;       

                while(!ucKeyCode);                                // wait_until_key_is_pressed               



                if(ucKeyCode >= N0 && ucKeyCode <= N9 && ucPos < 4)

                {

                        if(ucPos)

                        {

                                LCD_Set_XY(16+ucPos, 1);

                                LCD_Send_Command(ucKeyCode, 1);

                                ucInput[ucPos++] = ucKeyCode-0x30;

                        }



                        else

                                               

                        if(!ucPos && ucKeyCode != N0)

                        {

                                DisplayString(16,1,4, ucSpace);

                                LCD_Set_XY(16+ucPos, 1);

                                LCD_Send_Command(ucKeyCode, 1);

                                ucInput[ucPos++] = ucKeyCode-0x30;

                        }

                }

                else if(ucKeyCode == ENTER)

                {

                        ucTemp = 0;

                        for(ucIndex = 0; ucIndex < ucPos; ucIndex++)

                        {

                                ucTemp = ucTemp*10 + ucInput[ucIndex];

                                ucInput[ucIndex] = 0;

                        }

                                       

                        if( ucTemp%3 || ucTemp==0)

                        {

                                SetERR();

                       

                                if(ucMenuIndex == MENU_PROD)                 LCD_DisplayNum(16,1, uiProdQty);

                                else if(ucMenuIndex == MENU_TAIL)         LCD_DisplayNum(16,1, uiTailQty);

                                else if(ucMenuIndex == MENU_LEAD)         LCD_DisplayNum(16,1, uiLeadQty);

                                               

                                ucPos = 0;

                                ucTemp = 0;

                        }

                        else

                        {

                                if(ucMenuIndex == MENU_PROD)

                                {

                                        uiProdQty = uiProdResidual = ucTemp;

                                        eeprom_write_word(6, ucTemp);

                                }

                                else if(ucMenuIndex == MENU_TAIL)

                                {

                                        uiTailQty = uiTailResidual = ucTemp;

                                        eeprom_write_word(8, ucTemp);

                                }

                                else if(ucMenuIndex == MENU_LEAD)

                                {

                                        uiLeadQty = uiLeadResidual = ucTemp;

                                        eeprom_write_word(10, ucTemp);

                                }



                                SetSUC();



                                ucKeyCode = F2;



                                break;

                        }                                       

                }

                else if(ucKeyCode == ESC)

                {

                        delay_ms(10);

                        EscMenu();                               

                        break;

                }

                else if(ucKeyCode == CLEAR)

                {

                        DisplayString(16,1,4, ucSpace);



                        ucTemp = 0;

                        for(ucIndex = 0; ucIndex < ucPos-1; ucIndex++)

                        {

                                ucTemp = ucTemp*10 + ucInput[ucIndex];

                        }



                        if(ucPos)        ucPos--;

                        ucInput[ucPos] = 0;



                        LCD_DisplayNum(16,1, ucTemp);



                }

                else if(ucKeyCode == F2 && ucPos == 0)

                {

                        ucKeyCode = F2;

                        break;

                }

        }       

}



void ShowError(unsigned char ucCode)

{

        if( bit_is_clear(ucErrorFlag, ucCode) && bit_is_clear(ucSystemFlag, SF_BE_SET) )

        {

                LCD_Clean_Screen();

                DisplayString(0,0,6, ucErr);

                DisplayString(20-ucErr_Leng[ucCode],1,ucErr_Leng[ucCode], ucErr_Code[ucCode]);



                sbi(ucErrorFlag, ucCode);

        }

}



SIGNAL(SIG_INTERRUPT0)

{

        if( ucKeyPulse < 8 )                        // Data

        {

                if( bit_is_set(PIND, KB_DAT) ) sbi(ucKeyTemp, ucKeyPulse);

                else cbi(ucKeyTemp, ucKeyPulse);



                ++ucKeyPulse;

        }

        else



        if( ucKeyPulse == 8)                        // Parity

        {

                ++ucKeyPulse;

        }



        else



        if( ucKeyPulse == 9)                        // Stopbit

        {

                if( bit_is_set(PIND, KB_DAT) )

                {

                        if( ucKeyTemp == 0xE0 )

                        {

                                ucKeyFlag = 1;

                        }

                        else if( ucKeyTemp == 0xF0 )

                        {

                                ucKeyFlag = 2;

                        }

                        else

                        {

                                if(ucKeyFlag)

                                {

                                        if(ucKeyFlag == 2)

                                        {

                                                if(ucKeyTemp == ENTER) ucKeyCode = ENTER;

                                        }

                                       

                                        ucKeyFlag = 0;

                                }

                                else

                                {

                                        if(ucKeyTemp == 0x70)                 ucKeyCode = N0;

                                        else if(ucKeyTemp == 0x69)         ucKeyCode = N1;

                                        else if(ucKeyTemp == 0x72)         ucKeyCode = N2;

                                        else if(ucKeyTemp == 0x7A)         ucKeyCode = N3;

                                        else if(ucKeyTemp == 0x6B)         ucKeyCode = N4;

                                        else if(ucKeyTemp == 0x73)         ucKeyCode = N5;

                                        else if(ucKeyTemp == 0x74)         ucKeyCode = N6;

                                        else if(ucKeyTemp == 0x6C)         ucKeyCode = N7;

                                        else if(ucKeyTemp == 0x75)         ucKeyCode = N8;

                                        else if(ucKeyTemp == 0x7D)         ucKeyCode = N9;

                                        else if(ucKeyTemp == 0x05)        ucKeyCode = F1;

                                        else                                                  ucKeyCode = ucKeyTemp;

                                }

                        }



                }



                ++ucKeyPulse;

        }



        else



        if( ucKeyPulse == 10)                        // Startbit

        {

                if( bit_is_clear(PIND, KB_DAT) )  ucKeyPulse = 0;

        }

}





#endif



// 1602LCD_H





#ifndef _1602LCD_H

#define _1602LCD_H



//                PORTD

//                 1:        E                        read(1->0); write(1);

//

//                0:        RS                        0:        read( p->address counter )

//                                                write( p->command register)

//                                        1:        p->data register

//                4-7: DATA



#define LCD_PORT        PORTD

#define LCD_DDR                DDRD



#define LCD_E        1

#define LCD_RS        0



#define NumL        4

#define LCD_DELAY_TIME        2



extern void LCD_Init();

extern void LCD_DisplayString(unsigned char X, unsigned char Y, unsigned char* uString);

extern void LCD_DisplayNum(unsigned char X, unsigned char Y, unsigned int ulNum);



void LCD_Clean_Screen();

void LCD_Set_XY(unsigned char X, unsigned char Y);

void LCD_Send_Command(unsigned char udata, unsigned char uCode);



#define sbi(Port, Bit)        (Port |= (1<<Bit))       

#define cbi(Port, Bit)        (Port &= ~(1<<Bit))       

#define eoi(Port, Bit)        (Port ^= (1<<Bit))

#define IsTrue(Pin, Bit)        (Pin & (1<<Bit) )



#endif





// 1602LCD.c

//        ************************************        1602 LCD Drive        ************************************



#include <avr/io.h>

#include <util/delay.h>

#include <avr/interrupt.h>

#include "1602LCD.h"

#include "RTOS_T0.h"



//        uCode = 0:        Send Command

//        uCode = 1:        Send Data



void LCD_Send_Command(unsigned char udata, unsigned char uCode)

{

        if(uCode)        sbi(LCD_PORT, LCD_RS);

        else                cbi(LCD_PORT, LCD_RS);



        LCD_PORT &= 0x0F;                                                // HIGH

        LCD_PORT |= (udata & 0xF0);       

        sbi(LCD_PORT, LCD_E);

        cbi(LCD_PORT, LCD_E);

       

        LCD_PORT &= 0x0F;                                                // LOW

        LCD_PORT |= (udata << 4);       

        sbi(LCD_PORT, LCD_E);

        cbi(LCD_PORT, LCD_E);



        cbi(LCD_PORT, LCD_RS);



        delay_ms(LCD_DELAY_TIME);       

}



void LCD_Clean_Screen()

{

        LCD_Send_Command(0x01, 0);       

}



void LCD_Set_XY(unsigned char X, unsigned char Y)

{

        if( Y )        X = 0xc0 + X;

        else         X = 0x80 + X;



        LCD_Send_Command(X, 0);

}



void LCD_DisplayString(unsigned char X, unsigned char Y, unsigned char* uString)

{

        LCD_Set_XY(X, Y);

       

        while( *uString )

        {

                LCD_Send_Command(*uString, 1);

                *uString++;

        }

}



void LCD_DisplayNum(unsigned char X, unsigned char Y, unsigned int ulNum)

{

        LCD_Set_XY(X, Y);



        unsigned char i;

        unsigned char charNum[NumL];



        for(i=0; i < NumL; i++)

        {

                charNum[NumL-1-i] = 0x30 + ulNum%10;

                ulNum = ulNum/10;

        }



        for(i = 0; i < NumL-1; i++)

        {

                if(charNum != 0x30)        break;                               

        }       



        for(; i < NumL; i++)

        {

                LCD_Send_Command(charNum, 1);

        }

}



void LCD_Init()

{

        LCD_DDR = 0b11110011;



        delay_ms(500);

               

        LCD_Send_Command(0x33, 0);

        LCD_Send_Command(0x32, 0);

        LCD_Send_Command(0x28, 0);

        LCD_Send_Command(0x0C, 0);



        LCD_Clean_Screen();

}



//        ************************************        LCD Drive End        ************************************



RTOS部分就是前面提到的那些了,仅参考

出0入0汤圆

发表于 2006-12-7 11:24:57 | 显示全部楼层
register unsigned char ---tempR16--- asm("r16");  

register unsigned char ---tempR16--- asm("r17");

正确吗?

出0入0汤圆

 楼主| 发表于 2006-12-7 11:31:36 | 显示全部楼层
不正确,前面说过了,应该是:

register unsigned char ---tempR16--- asm("r16");   

register unsigned char ---tempR17--- asm("r17");

出0入0汤圆

发表于 2006-12-8 14:44:03 | 显示全部楼层
3Q

出0入0汤圆

发表于 2006-12-8 21:22:29 | 显示全部楼层
TO  zhudlmax  



  好人 啊 ,  这个 例子 好 ,  DOWN  下 来 好好 研究 ~!



另外 , 我也 有个 设备是 用 PC 键盘 控制 的 ,  PS2 键盘做好 了 , 但是 现在 要兼容 AT  ,  XT , VT 键盘 ,  你有没有 XT  , VT  键盘的 资料 或者 是 键盘实体 呢 ?

出0入0汤圆

发表于 2006-12-8 22:59:01 | 显示全部楼层
楼主啊,谢谢啊!能不能提供打包下载啊?不好意思了!

出0入0汤圆

发表于 2006-12-8 23:41:42 | 显示全部楼层
高手!!作个 标记,有空来看看!!

出0入0汤圆

 楼主| 发表于 2006-12-9 02:33:58 | 显示全部楼层
TO:jackiezeng,键盘协议见附件



TO:yjbin,所以代码以在上列出,你可以复制过去的



因现在工作比较忙,相机也被朋友借走了,等几天,上传点实际的东东给大伙瞧瞧,在此谢谢大家的支持





点击此处打开armok01137597.pdf

出0入0汤圆

发表于 2006-12-9 11:11:58 | 显示全部楼层
有几个问题请楼主指点一下



#define Task_Stack_Size   50      为什么要定义为50呢?这个数是怎么样计算得到的?



// 防止C编译器调用以下寄存器(可参考GCC说明),减少任务调度代码所占用的时间

register unsigned char tempR4  asm("r4");  

register unsigned char tempR5  asm("r5");  

register unsigned char tempR6  asm("r6");  

register unsigned char tempR7  asm("r7");  

register unsigned char tempR8  asm("r8");  

register unsigned char tempR9  asm("r9");  

register unsigned char tempR10 asm("r10");  

register unsigned char tempR11 asm("r11");  

register unsigned char tempR12 asm("r12");  

register unsigned char tempR13 asm("r13");  

register unsigned char tempR14 asm("r14");  

register unsigned char tempR15 asm("r15");  

register unsigned char tempR16 asm("r16");  

register unsigned char tempR16 asm("r17");



为什么要禁用这些寄存器呢,而不是其他?

出0入0汤圆

发表于 2006-12-9 12:38:20 | 显示全部楼层
我以前也写过类似的贴子,为什么就没被站长评为"酷"呢? 



OS学习初探 --- 时间片轮转调度 (GCC)

http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=663028&bbs_page_no=1&bbs_id=1000



呵呵,开个玩笑. :)



前段我也在研究这个,现在好久没搞了.希望楼主继续下去.

出0入0汤圆

 楼主| 发表于 2006-12-9 19:13:55 | 显示全部楼层
我参考的是:《建立一个属于自己的AVR的RTOS》



点击此处下载armok01137640.htm



TO:shusheng 书生



#define Task_Stack_Size   50



每个任务中因OS_ScheduleTask()会占用固定数量的RAM,再加上每个任务自己独立需要占有的RAM,其实具体到底占有多少我没研究过,但假如Task_Stack_Size设置过低,系统程序就无法运行,按照我上面公布的程序,给每个任务分配了相同的RAM,因任务占有的RAM不一定一样,所以对RAM资源的利用有一定的浪费,不过假如系统RAM资源很丰富,也没必要去斤斤计较,OS_ScheduleTask更安全的代码可以写成如下方式:



void OS_ScheduleTask(void)

{

        asm("PUSH        R2               
\t");

        asm("PUSH        R3               
\t");

        asm("PUSH        R4               
\t");

        asm("PUSH        R5               
\t");

        asm("PUSH        R6               
\t");

        asm("PUSH        R7               
\t");

        asm("PUSH        R8               
\t");

        asm("PUSH        R9               
\t");

        asm("PUSH        R10               
\t");

        asm("PUSH        R11               
\t");

        asm("PUSH        R12               
\t");

        asm("PUSH        R13               
\t");

        asm("PUSH        R14               
\t");

        asm("PUSH        R15               
\t");

        asm("PUSH        R16               
\t");

        asm("PUSH        R17               
\t");

        asm("PUSH        R18               
\t");

        asm("PUSH        R19               
\t");

        asm("PUSH        R20               
\t");

        asm("PUSH        R21               
\t");

        asm("PUSH        R22               
\t");

        asm("PUSH        R23               
\t");

        asm("PUSH        R24               
\t");

        asm("PUSH        R25               
\t");

        asm("PUSH        R26               
\t");

        asm("PUSH        R27               
\t");

        asm("PUSH        R28               
\t");

        asm("PUSH        R29               
\t");

        asm("PUSH        R30               
\t");

        asm("PUSH        R31               
\t");





        TaskCtrlBlock[uCurrentTask].uTaskStackEntry = SP+33;



        if(uCurrentTask >= uValidTaskIndex-1) uCurrentTask=0;

        else        uCurrentTask++;



        SP = TaskCtrlBlock[uCurrentTask].uTaskStackEntry;



        SP -= 33;





        asm("POP        R31               
\t");

        asm("POP        R30               
\t");

        asm("POP        R29               
\t");

        asm("POP        R28               
\t");

        asm("POP        R27               
\t");

        asm("POP        R26               
\t");

        asm("POP        R25               
\t");

        asm("POP        R24               
\t");

        asm("POP        R23               
\t");

        asm("POP        R22               
\t");

        asm("POP        R21               
\t");

        asm("POP        R20               
\t");

        asm("POP        R19               
\t");

        asm("POP        R18               
\t");

        asm("POP        R17               
\t");

        asm("POP        R16               
\t");

        asm("POP        R15               
\t");

        asm("POP        R14               
\t");

        asm("POP        R13               
\t");

        asm("POP        R12               
\t");

        asm("POP        R11               
\t");

        asm("POP        R10               
\t");

        asm("POP        R9               
\t");

        asm("POP        R8               
\t");

        asm("POP        R7               
\t");

        asm("POP        R6               
\t");

        asm("POP        R5               
\t");

        asm("POP        R4               
\t");

        asm("POP        R3               
\t");

        asm("POP        R2               
\t");



        asm("POP        R0               
\t");               

        asm("OUT        0x3F,R0       
\t");               

        asm("POP        R0               
\t");

        asm("POP        R1               
\t");



        TCNT0 = 0;

        asm("reti       
\t");

}



在此希望大家多多参与,优化、强大此系统,在应用中,一个好的稳定简洁的系统对于开发来说更为重要,想得更远,某天,MS倒闭...,呵呵~~~~也不是不可能啊,不过那得靠团队精神,好象对于中国人,很现实的说法是:一个中国人是条龙,一群中国人是一堆虫,扯远了,无意冒犯,别扔鸡蛋...呵呵

出0入0汤圆

 楼主| 发表于 2006-12-9 19:17:46 | 显示全部楼层
To: zhb2000



OS思路跟您的一模一样,我参考的是《建立一个属于自己的AVR的RTOS》作者是不是armok啊?

出0入0汤圆

发表于 2006-12-10 13:11:54 | 显示全部楼层
谢谢先

还有个问题 "  每个任务自己独立需要占有的RAM" 是不是指在那个任务里面定义的局部变量?还是指其他变量?

出0入0汤圆

发表于 2006-12-11 13:59:38 | 显示全部楼层
楼主大哥,

       您能不能打个包, 传上来呢 ?  我编译出现很多的警告, 我的水平低啊 ~!



还有就是你上传的那个是 PS/2 的资料, 你有没有 XT , VT 键盘的资料呢?

出0入42汤圆

发表于 2006-12-11 15:21:08 | 显示全部楼层
楼主指导一下:

uTaskEntry[uCurrentTaskID++] = SP+19;

后面的系数19是怎么算出来的,我弄了半天都没弄明白。谢谢!

出0入0汤圆

 楼主| 发表于 2006-12-11 20:20:37 | 显示全部楼层
看了大家的一些问题,我仔细找了一些资料,将关键代码更改如下:



.....



register unsigned char tempR2  asm("r2");

register unsigned char tempR3  asm("r3");

register unsigned char tempR4  asm("r4");

register unsigned char tempR5  asm("r5");

register unsigned char tempR6  asm("r6");

register unsigned char tempR7  asm("r7");

register unsigned char tempR8  asm("r8");

register unsigned char tempR9  asm("r9");

register unsigned char tempR10 asm("r10");

register unsigned char tempR11 asm("r11");

register unsigned char tempR12 asm("r12");

register unsigned char tempR13 asm("r13");

register unsigned char tempR14 asm("r14");

register unsigned char tempR15 asm("r15");

register unsigned char tempR16 asm("r16");

register unsigned char tempR17 asm("r17");

register unsigned int tempRY   asm("r28");





#define PUSH_ALL()                                        \

asm volatile(                                                \

"PUSH        R18"        "
\t"                                \

"PUSH        R19"        "
\t"                                \

"PUSH        R20"        "
\t"                                \

"PUSH        R21"        "
\t"                                \

"PUSH        R22"        "
\t"                                \

"PUSH        R23"        "
\t"                                \

"PUSH        R24"        "
\t"                                \

"PUSH        R25"        "
\t"                                \

"PUSH        R26"        "
\t"                                \

"PUSH        R27"        "
\t"                                \

"PUSH        R30"        "
\t"                                \

"PUSH        R31"        "
\t"                                \

)                                                                        \



#define        POP_ALL()                                        \

asm volatile(                                                \

"POP        R31"                "
\t"                        \

"POP        R30"                "
\t"                        \

"POP        R27"                "
\t"                        \

"POP        R26"                "
\t"                        \

"POP        R25"                "
\t"                        \

"POP        R24"                "
\t"                        \

"POP        R23"                "
\t"                        \

"POP        R22"                "
\t"                        \

"POP        R21        "                "
\t"                        \

"POP        R20"                "
\t"                        \

"POP        R19"                "
\t"                        \

"POP        R18"                "
\t"                        \

"POP        R0"                        "
\t"                        \

"OUT        0x3F,R0"        "
\t"                        \

"POP        R0"                        "
\t"                        \

"POP        R1"                        "
\t"                        \

)



.......





void OS_ScheduleTask(void)

{

        PUSH_ALL();



        uTaskEntry[uCurrentTaskID++] = SP+15;

        if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;

        SP =  uTaskEntry[uCurrentTaskID]-15;



        POP_ALL();



        TCNT0 = 0x00;

        asm("reti");

}



.....



在AVR GCC中对寄存器的描述是这样的:



r0        可用做暂时寄存器。如果用户汇编代码使用了r0,且要调用C代码,则在调用之前必须保存r0。C中断例程会自动保存和恢复r0。



r1        C编译器假定此寄存器内容为“0”。如果用户使用了此寄存器,则在汇编代码返回之前须将其清零。C中断例程会自动保存和恢复r1。



r2-r17,r28,r29          C编译器使用这些寄存器。如果用户汇编代码需要使用这些寄存器,则必须保存并恢复这些寄存器。



R18-r27,r30,r31 如果用户汇编代码不调用C代码则无需保存和恢复这些寄存器。如果用户要调用C代码,则在调用之前须保存。





uTaskEntry[uCurrentTaskID++] = SP+15;



加减15的原因:先看GCC编译的汇编



SIGNAL(SIG_OUTPUT_COMPARE0)

{

        asm("JMP OS_ScheduleTask");

}



@000002B0: __vector_19

22:       {

+000002B0:   921F        PUSH    R1               Push register on stack

+000002B1:   920F        PUSH    R0               Push register on stack

+000002B2:   B60F        IN      R0,0x3F          In from I/O location

+000002B3:   920F        PUSH    R0               Push register on stack

+000002B4:   2411        CLR     R1               Clear Register

23:               asm("JMP OS_ScheduleTask");

+000002B5:   940C02E6    JMP     0x000002E6       Jump

+000002B7:   900F        POP     R0               Pop register from stack

+000002B8:   BE0F        OUT     0x3F,R0          Out to I/O location

+000002B9:   900F        POP     R0               Pop register from stack

+000002BA:   901F        POP     R1               Pop register from stack

+000002BB:   9518        RETI                     Interrupt return



....





void OS_ScheduleTask(void)

{

        PUSH_ALL();



        uTaskEntry[uCurrentTaskID++] = SP+15;

        if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;

        SP =  uTaskEntry[uCurrentTaskID]-15;



        POP_ALL();



        TCNT0 = 0x00;

        asm("reti");

}



@0000030D: OS_ScheduleTask

57:       {

+0000030D:   932F        PUSH    R18              Push register on stack

+0000030E:   933F        PUSH    R19              Push register on stack

+0000030F:   934F        PUSH    R20              Push register on stack

+00000310:   935F        PUSH    R21              Push register on stack

+00000311:   936F        PUSH    R22              Push register on stack

+00000312:   937F        PUSH    R23              Push register on stack

+00000313:   938F        PUSH    R24              Push register on stack

+00000314:   939F        PUSH    R25              Push register on stack

+00000315:   93AF        PUSH    R26              Push register on stack

+00000316:   93BF        PUSH    R27              Push register on stack

+00000317:   93EF        PUSH    R30              Push register on stack

+00000318:   93FF        PUSH    R31              Push register on stack

60:               uTaskEntry[uCurrentTaskID++] = SP+15;

+00000319:   912002F1    LDS     R18,0x02F1       Load direct from data space

+0000031B:   2FE2        MOV     R30,R18          Copy register

+0000031C:   27FF        CLR     R31              Clear Register

+0000031D:   0FEE        LSL     R30              Logical Shift Left

+0000031E:   1FFF        ROL     R31              Rotate Left Through Carry

+0000031F:   51EF        SUBI    R30,0x1F         Subtract immediate

+00000320:   4FFD        SBCI    R31,0xFD         Subtract immediate with carry

+00000321:   B78D        IN      R24,0x3D         In from I/O location

+00000322:   B79E        IN      R25,0x3E         In from I/O location

+00000323:   960F        ADIW    R24,0x0F         Add immediate to word

+00000324:   8391        STD     Z+1,R25          Store indirect with displacement

+00000325:   8380        STD     Z+0,R24          Store indirect with displacement

+00000326:   5F2F        SUBI    R18,0xFF         Subtract immediate

+00000327:   932002F1    STS     0x02F1,R18       Store direct to data space

61:               if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;

+00000329:   918002F3    LDS     R24,0x02F3       Load direct from data space

+0000032B:   1728        CP      R18,R24          Compare

+0000032C:   F010        BRCS    PC+0x03          Branch if carry set

+0000032D:   921002F1    STS     0x02F1,R1        Store direct to data space

62:               SP =  uTaskEntry[uCurrentTaskID]-15;

+0000032F:   918002F1    LDS     R24,0x02F1       Load direct from data space

+00000331:   2FE8        MOV     R30,R24          Copy register

+00000332:   27FF        CLR     R31              Clear Register

+00000333:   0FEE        LSL     R30              Logical Shift Left

+00000334:   1FFF        ROL     R31              Rotate Left Through Carry

+00000335:   51EF        SUBI    R30,0x1F         Subtract immediate

+00000336:   4FFD        SBCI    R31,0xFD         Subtract immediate with carry

+00000337:   8180        LDD     R24,Z+0          Load indirect with displacement

+00000338:   8191        LDD     R25,Z+1          Load indirect with displacement

+00000339:   970F        SBIW    R24,0x0F         Subtract immediate from word

+0000033A:   BF9E        OUT     0x3E,R25         Out to I/O location

+0000033B:   BF8D        OUT     0x3D,R24         Out to I/O location

64:               POP_ALL();

+0000033C:   91FF        POP     R31              Pop register from stack

+0000033D:   91EF        POP     R30              Pop register from stack

+0000033E:   91BF        POP     R27              Pop register from stack

+0000033F:   91AF        POP     R26              Pop register from stack

+00000340:   919F        POP     R25              Pop register from stack

+00000341:   918F        POP     R24              Pop register from stack

+00000342:   917F        POP     R23              Pop register from stack

+00000343:   916F        POP     R22              Pop register from stack

+00000344:   915F        POP     R21              Pop register from stack

+00000345:   914F        POP     R20              Pop register from stack

+00000346:   913F        POP     R19              Pop register from stack

+00000347:   912F        POP     R18              Pop register from stack

+00000348:   900F        POP     R0               Pop register from stack

+00000349:   BE0F        OUT     0x3F,R0          Out to I/O location

+0000034A:   900F        POP     R0               Pop register from stack

+0000034B:   901F        POP     R1               Pop register from stack

66:               TCNT0 = 0x00;

+0000034C:   BE12        OUT     0x32,R1          Out to I/O location

67:               asm("reti");

+0000034D:   9518        RETI                     Interrupt return

+0000034E:   9508        RET                      Subroutine return



....



执行PUSH后 SP+1,执行POP后 SP-1, 中断处理中最明显的特征就是保存与恢复现场环境。

出0入0汤圆

 楼主| 发表于 2006-12-11 20:41:35 | 显示全部楼层
看了大家的一些问题,我仔细找了一些资料,将关键代码更改如下:



.....



register unsigned char tempR2  asm("r2");

register unsigned char tempR3  asm("r3");

register unsigned char tempR4  asm("r4");

register unsigned char tempR5  asm("r5");

register unsigned char tempR6  asm("r6");

register unsigned char tempR7  asm("r7");

register unsigned char tempR8  asm("r8");

register unsigned char tempR9  asm("r9");

register unsigned char tempR10 asm("r10");

register unsigned char tempR11 asm("r11");

register unsigned char tempR12 asm("r12");

register unsigned char tempR13 asm("r13");

register unsigned char tempR14 asm("r14");

register unsigned char tempR15 asm("r15");

register unsigned char tempR16 asm("r16");

register unsigned char tempR17 asm("r17");

register unsigned int tempRY   asm("r28");





#define PUSH_ALL()                                        \

asm volatile(                                                \

"PUSH        R18"        "
\t"                                \

"PUSH        R19"        "
\t"                                \

"PUSH        R20"        "
\t"                                \

"PUSH        R21"        "
\t"                                \

"PUSH        R22"        "
\t"                                \

"PUSH        R23"        "
\t"                                \

"PUSH        R24"        "
\t"                                \

"PUSH        R25"        "
\t"                                \

"PUSH        R26"        "
\t"                                \

"PUSH        R27"        "
\t"                                \

"PUSH        R30"        "
\t"                                \

"PUSH        R31"        "
\t"                                \

)                                                                        \



#define        POP_ALL()                                        \

asm volatile(                                                \

"POP        R31"                "
\t"                        \

"POP        R30"                "
\t"                        \

"POP        R27"                "
\t"                        \

"POP        R26"                "
\t"                        \

"POP        R25"                "
\t"                        \

"POP        R24"                "
\t"                        \

"POP        R23"                "
\t"                        \

"POP        R22"                "
\t"                        \

"POP        R21        "                "
\t"                        \

"POP        R20"                "
\t"                        \

"POP        R19"                "
\t"                        \

"POP        R18"                "
\t"                        \

"POP        R0"                        "
\t"                        \

"OUT        0x3F,R0"        "
\t"                        \

"POP        R0"                        "
\t"                        \

"POP        R1"                        "
\t"                        \

)



.......





void OS_ScheduleTask(void)

{

        PUSH_ALL();



        uTaskEntry[uCurrentTaskID++] = SP+15;

        if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;

        SP =  uTaskEntry[uCurrentTaskID]-15;



        POP_ALL();



        TCNT0 = 0x00;

        asm("reti");

}



.....



在AVR GCC中对寄存器的描述是这样的:



r0        可用做暂时寄存器。如果用户汇编代码使用了r0,且要调用C代码,则在调用之前必须保存r0。C中断例程会自动保存和恢复r0。



r1        C编译器假定此寄存器内容为“0”。如果用户使用了此寄存器,则在汇编代码返回之前须将其清零。C中断例程会自动保存和恢复r1。



r2-r17,r28,r29          C编译器使用这些寄存器。如果用户汇编代码需要使用这些寄存器,则必须保存并恢复这些寄存器。



R18-r27,r30,r31 如果用户汇编代码不调用C代码则无需保存和恢复这些寄存器。如果用户要调用C代码,则在调用之前须保存。





uTaskEntry[uCurrentTaskID++] = SP+15;



加减15的原因:先看GCC编译的汇编



SIGNAL(SIG_OUTPUT_COMPARE0)

{

        asm("JMP OS_ScheduleTask");

}



@000002B0: __vector_19

22:       {

+000002B0:   921F        PUSH    R1               Push register on stack

+000002B1:   920F        PUSH    R0               Push register on stack

+000002B2:   B60F        IN      R0,0x3F          In from I/O location

+000002B3:   920F        PUSH    R0               Push register on stack

+000002B4:   2411        CLR     R1               Clear Register

23:               asm("JMP OS_ScheduleTask");

+000002B5:   940C02E6    JMP     0x000002E6       Jump

+000002B7:   900F        POP     R0               Pop register from stack

+000002B8:   BE0F        OUT     0x3F,R0          Out to I/O location

+000002B9:   900F        POP     R0               Pop register from stack

+000002BA:   901F        POP     R1               Pop register from stack

+000002BB:   9518        RETI                     Interrupt return



....





void OS_ScheduleTask(void)

{

        PUSH_ALL();



        uTaskEntry[uCurrentTaskID++] = SP+15;

        if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;

        SP =  uTaskEntry[uCurrentTaskID]-15;



        POP_ALL();



        TCNT0 = 0x00;

        asm("reti");

}



@0000030D: OS_ScheduleTask

57:       {

+0000030D:   932F        PUSH    R18              Push register on stack

+0000030E:   933F        PUSH    R19              Push register on stack

+0000030F:   934F        PUSH    R20              Push register on stack

+00000310:   935F        PUSH    R21              Push register on stack

+00000311:   936F        PUSH    R22              Push register on stack

+00000312:   937F        PUSH    R23              Push register on stack

+00000313:   938F        PUSH    R24              Push register on stack

+00000314:   939F        PUSH    R25              Push register on stack

+00000315:   93AF        PUSH    R26              Push register on stack

+00000316:   93BF        PUSH    R27              Push register on stack

+00000317:   93EF        PUSH    R30              Push register on stack

+00000318:   93FF        PUSH    R31              Push register on stack

60:               uTaskEntry[uCurrentTaskID++] = SP+15;

+00000319:   912002F1    LDS     R18,0x02F1       Load direct from data space

+0000031B:   2FE2        MOV     R30,R18          Copy register

+0000031C:   27FF        CLR     R31              Clear Register

+0000031D:   0FEE        LSL     R30              Logical Shift Left

+0000031E:   1FFF        ROL     R31              Rotate Left Through Carry

+0000031F:   51EF        SUBI    R30,0x1F         Subtract immediate

+00000320:   4FFD        SBCI    R31,0xFD         Subtract immediate with carry

+00000321:   B78D        IN      R24,0x3D         In from I/O location

+00000322:   B79E        IN      R25,0x3E         In from I/O location

+00000323:   960F        ADIW    R24,0x0F         Add immediate to word

+00000324:   8391        STD     Z+1,R25          Store indirect with displacement

+00000325:   8380        STD     Z+0,R24          Store indirect with displacement

+00000326:   5F2F        SUBI    R18,0xFF         Subtract immediate

+00000327:   932002F1    STS     0x02F1,R18       Store direct to data space

61:               if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;

+00000329:   918002F3    LDS     R24,0x02F3       Load direct from data space

+0000032B:   1728        CP      R18,R24          Compare

+0000032C:   F010        BRCS    PC+0x03          Branch if carry set

+0000032D:   921002F1    STS     0x02F1,R1        Store direct to data space

62:               SP =  uTaskEntry[uCurrentTaskID]-15;

+0000032F:   918002F1    LDS     R24,0x02F1       Load direct from data space

+00000331:   2FE8        MOV     R30,R24          Copy register

+00000332:   27FF        CLR     R31              Clear Register

+00000333:   0FEE        LSL     R30              Logical Shift Left

+00000334:   1FFF        ROL     R31              Rotate Left Through Carry

+00000335:   51EF        SUBI    R30,0x1F         Subtract immediate

+00000336:   4FFD        SBCI    R31,0xFD         Subtract immediate with carry

+00000337:   8180        LDD     R24,Z+0          Load indirect with displacement

+00000338:   8191        LDD     R25,Z+1          Load indirect with displacement

+00000339:   970F        SBIW    R24,0x0F         Subtract immediate from word

+0000033A:   BF9E        OUT     0x3E,R25         Out to I/O location

+0000033B:   BF8D        OUT     0x3D,R24         Out to I/O location

64:               POP_ALL();

+0000033C:   91FF        POP     R31              Pop register from stack

+0000033D:   91EF        POP     R30              Pop register from stack

+0000033E:   91BF        POP     R27              Pop register from stack

+0000033F:   91AF        POP     R26              Pop register from stack

+00000340:   919F        POP     R25              Pop register from stack

+00000341:   918F        POP     R24              Pop register from stack

+00000342:   917F        POP     R23              Pop register from stack

+00000343:   916F        POP     R22              Pop register from stack

+00000344:   915F        POP     R21              Pop register from stack

+00000345:   914F        POP     R20              Pop register from stack

+00000346:   913F        POP     R19              Pop register from stack

+00000347:   912F        POP     R18              Pop register from stack

+00000348:   900F        POP     R0               Pop register from stack

+00000349:   BE0F        OUT     0x3F,R0          Out to I/O location

+0000034A:   900F        POP     R0               Pop register from stack

+0000034B:   901F        POP     R1               Pop register from stack

66:               TCNT0 = 0x00;

+0000034C:   BE12        OUT     0x32,R1          Out to I/O location

67:               asm("reti");

+0000034D:   9518        RETI                     Interrupt return

+0000034E:   9508        RET                      Subroutine return



....



PUSH以上的寄存器是保存刚释放CPU控制权的任务的环境,而执行PSUH后SP逐加1,在恢复下一个任务的环境时开始执行POP,POP语句SP逐减1。



TASK [SP] -> JMP(OR RJMP) [SP-2] -> PUSH [ SP-2-N_push] -> POP [SP-2-N_push+M_pop] -> RET(OR RETI) [SP-2-N_push+M_pop+2]



PUSH 与 POP 是相反过程,JMP、RJMP、RET、RETI是与SP专门打交道的指令,加减多少是根据你编译后实际的汇编代码确定的

出0入0汤圆

 楼主| 发表于 2006-12-11 20:50:25 | 显示全部楼层
【35楼】的本想放弃的,“提交”误点,赶忙取消,我以为OK,没想到我这网速这么快,呵呵,阿莫,帮我删掉吧,谢谢先



TO jackiezeng:XT,VT键盘资料我没有,你上网搜索就是了,网络是个好东东,可以很好利用的,按你的要求,先打包上传

点击此处下载armok01137758.rar

出0入0汤圆

发表于 2006-12-11 20:51:36 | 显示全部楼层
楼主厉害,佩服啊~

出0入42汤圆

发表于 2006-12-11 22:32:33 | 显示全部楼层
多谢楼主!

出0入0汤圆

发表于 2006-12-11 22:41:10 | 显示全部楼层
楼主大哥,



     

    我在网络上找了很久 , 只有一点点协议,  协议比 PS/2 的 更简单 , VT , XT 键盘 都是 单向通信的, 只有 键盘发送信息给PC 。



但是我找不到东西来测试 , 不知道自己的程序 能不能 工作 啊 ,





    谢谢您 打包 的资料 ,  我请教 个 问题 ,  .elf  是 什么 文件 ?

为什么一定要打开它 才能 编译  呢 ?



    我不会用GCC , 我的理解 是  只要 有 .c 和 .h  文件 ,  和 makefale  文件 就可以 编译了,对么 ?

    但是为什么要.elf 呢 ?

出0入0汤圆

 楼主| 发表于 2006-12-11 23:17:20 | 显示全部楼层
叫兄弟就成,大哥不敢当,呵呵



makefile 我用AVR STUDIO内带的,只改了频率、优化两项,我用的是MEGA16,程序编译通过,是我正在进行中的一个项目,只刚刚写了一点点,给一家实验室控制水流用的,本周四得交货,现在急啊,我也不太清楚ELF,你再看看开发环境与我的有何不同?

出0入0汤圆

发表于 2006-12-12 00:22:45 | 显示全部楼层
zhudlmax 兄 :



     我现在大概弄明白 这个 WINAVR 了 , 现在晚了, 明天找个 板子  也学着写两个任务来 运行 一 下  ~!



     THANK YOU

出0入42汤圆

发表于 2006-12-19 11:28:53 | 显示全部楼层
楼主支招啊,我的系统怎么不能调度?仿真的时候是能正常调度的,下载到单片机里就只运行一圈之后就不知道跑那里去了,不调度任务了,

出0入0汤圆

 楼主| 发表于 2006-12-19 11:59:04 | 显示全部楼层
上传你的代码看看,一般是由于分配的RAM过小造成的,将Task_Stack_Size改大点看看



#define Total_Task_Num   8

#define Task_Stack_Size   50

#define Total_Stack_Size   Total_Task_Num * Task_Stack_Size

出0入42汤圆

发表于 2006-12-19 12:04:49 | 显示全部楼层
好的,我试试看把Task_Stack_Size改大一点,不过问一下zhudlmax大侠:Task_Stack_Size与Task里的什么东西有关,也就是说任务里的变量还是其他什么东西需要用到Task_Stack?

出0入42汤圆

发表于 2006-12-19 12:28:14 | 显示全部楼层
现在我的程序在没有开始任务调度之前的系统初始化中,一旦调用子程序就会提示在调用的地方堆栈溢出

出0入42汤圆

发表于 2006-12-19 12:35:09 | 显示全部楼层
仿真进入了任务调度之后就不出现堆栈溢出的问题了

出0入4汤圆

发表于 2006-12-19 12:54:41 | 显示全部楼层
全局变量存取冲突的控制呢?

出0入42汤圆

发表于 2006-12-20 10:07:55 | 显示全部楼层
代码已经贴出,麻烦楼主大哥帮我看一下.程序是四个单刀双掷开关控制四个电机的上升和下降,驱动电机继电器的是芯片是2803.PB口驱动电机,PC口为按键口,芯片为M16

点击此处下载armok01138397.rar

出0入42汤圆

发表于 2006-12-20 21:34:58 | 显示全部楼层
打错了,是四个双刀双掷按键控制四个电机

出0入42汤圆

发表于 2006-12-26 10:36:50 | 显示全部楼层
问题解决了,谢谢楼主大哥!

出0入0汤圆

发表于 2008-6-4 10:04:09 | 显示全部楼层
cool

出0入0汤圆

发表于 2008-6-4 15:01:36 | 显示全部楼层
学习学习~~

出0入0汤圆

发表于 2008-6-4 16:02:15 | 显示全部楼层
楼主厉害

出0入0汤圆

发表于 2008-6-4 17:49:57 | 显示全部楼层
很强大

出0入0汤圆

发表于 2008-6-4 19:25:35 | 显示全部楼层
谢谢共享!

出0入0汤圆

发表于 2008-6-28 11:35:10 | 显示全部楼层
标记,谢谢楼主!

出0入0汤圆

发表于 2008-6-28 12:21:11 | 显示全部楼层
zhudlmax和my_avr 大哥能不能帮小弟看一下程序,怎么不行,我程序中最简单的就创建了两个任务,POTRB和PORTC两个口取反一下,程序执行结果是 两个任务都只执行一次,就一直进入SIGNAL(SIG_OUTPUT_COMPARE0)中断程序了,一直在重复的执行,搞了两天,郁闷了两天点击此处下载 ourdev_329742.rar(文件大小:44K) (原文件名:AVR时间片法调度.rar)

出0入0汤圆

发表于 2008-7-4 08:51:29 | 显示全部楼层
记号

出75入4汤圆

发表于 2008-7-4 20:15:25 | 显示全部楼层
mark。

出0入0汤圆

发表于 2008-8-8 12:15:30 | 显示全部楼层
能看懂以后在看

出0入0汤圆

发表于 2008-10-6 22:54:50 | 显示全部楼层
楼主厉害,跟着学习!

出0入0汤圆

发表于 2008-10-9 17:12:35 | 显示全部楼层
楼主写得非常详细,谢谢分享

出0入0汤圆

发表于 2008-10-21 14:03:46 | 显示全部楼层
不错,写得非常详细,,有机会自己也用一用.太感谢了!

出0入0汤圆

发表于 2008-10-24 12:48:37 | 显示全部楼层
记下

出0入0汤圆

发表于 2008-10-24 14:01:45 | 显示全部楼层
mark!

出0入0汤圆

发表于 2008-10-24 14:40:06 | 显示全部楼层
mark!&nbsp;

出0入0汤圆

发表于 2008-10-24 14:50:01 | 显示全部楼层
学习

出0入0汤圆

发表于 2008-10-30 16:37:40 | 显示全部楼层
ucOS好像没有此功能...不过仍然不失为一个优秀的嵌入式操作系统

出0入0汤圆

发表于 2008-12-28 17:42:06 | 显示全部楼层
mark

出0入0汤圆

发表于 2008-12-28 18:32:45 | 显示全部楼层
强帖留名

出330入0汤圆

发表于 2008-12-28 18:51:53 | 显示全部楼层
嘿,这里的宝藏真多啊,继续呆几天,挖完收工歇息。

出0入0汤圆

发表于 2008-12-29 16:58:17 | 显示全部楼层
up

出0入0汤圆

发表于 2009-3-1 01:09:03 | 显示全部楼层
收藏,学习。

出0入0汤圆

发表于 2009-5-12 05:10:20 | 显示全部楼层
顶一下!

出0入0汤圆

发表于 2009-5-12 15:35:24 | 显示全部楼层
m

出0入0汤圆

发表于 2009-5-14 23:37:41 | 显示全部楼层
不错,这个坛子里讨论问题的气氛比较好

出0入0汤圆

发表于 2009-5-18 08:02:50 | 显示全部楼层
// 防止C编译器调用以下寄存器(可参考GCC说明),减少任务调度代码所占用的时间
register unsigned char tempR4  asm("r4");  
register unsigned char tempR5  asm("r5");  
register unsigned char tempR6  asm("r6");  
register unsigned char tempR7  asm("r7");  
register unsigned char tempR8  asm("r8");  
register unsigned char tempR9  asm("r9");  
register unsigned char tempR10 asm("r10");  
register unsigned char tempR11 asm("r11");  
register unsigned char tempR12 asm("r12");  
register unsigned char tempR13 asm("r13");  
register unsigned char tempR14 asm("r14");  
register unsigned char tempR15 asm("r15");  
register unsigned char tempR16 asm("r16");  
register unsigned char tempR16 asm("r17");  


这个怎么移植到ICC编译器上?

出0入0汤圆

发表于 2009-7-12 20:49:45 | 显示全部楼层
很有价值的贴呀

出0入0汤圆

发表于 2009-7-16 17:10:39 | 显示全部楼层
强贴留名

出0入0汤圆

发表于 2009-8-29 14:51:50 | 显示全部楼层
牛啊啊  就是都不会啊

出0入0汤圆

发表于 2009-8-29 15:21:18 | 显示全部楼层
强贴留名

出0入0汤圆

发表于 2009-9-12 15:55:40 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-9-12 23:53:45 | 显示全部楼层
强帖记下。

出0入0汤圆

发表于 2009-9-28 09:15:38 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-9-28 10:09:23 | 显示全部楼层
good

出0入0汤圆

发表于 2009-9-28 10:48:23 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-9-29 10:41:54 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-11-12 09:59:39 | 显示全部楼层
good!

出0入0汤圆

发表于 2009-11-17 16:55:40 | 显示全部楼层

出0入0汤圆

发表于 2009-12-9 16:48:24 | 显示全部楼层

出0入0汤圆

发表于 2009-12-9 17:49:37 | 显示全部楼层
好贴,要顶。

出0入0汤圆

发表于 2009-12-9 17:51:01 | 显示全部楼层
打标。

出0入0汤圆

发表于 2009-12-9 18:10:27 | 显示全部楼层
不错,比较简洁也很实用。

出75入4汤圆

发表于 2009-12-9 22:37:05 | 显示全部楼层
好用。谢谢lz

出0入0汤圆

发表于 2009-12-16 19:37:40 | 显示全部楼层
mark

出10入95汤圆

发表于 2009-12-25 22:02:40 | 显示全部楼层
好!谢谢!

出0入0汤圆

发表于 2009-12-30 19:57:49 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-30 23:09:40 | 显示全部楼层
cool..
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-24 09:16

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表