简洁实用的时间片调度法操作系统,献给大家
在OURAVR潜水有段时间了,学到不少东西,参考一些资料,我写了一个简洁实用的时间片调度法操作系统,在我的一些产品中已经应用,非常稳定,在再献给大家// RTOS HEAD FILE
#ifndef _RTOS_T0_H
#define _RTOS_T0_H
// 防止C编译器调用以下寄存器(可参考GCC说明),减少任务调度代码所占用的时间
register unsigned char tempR4asm("r4");
register unsigned char tempR5asm("r5");
register unsigned char tempR6asm("r6");
register unsigned char tempR7asm("r7");
register unsigned char tempR8asm("r8");
register unsigned char tempR9asm("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;
unsigned char uCurrentTaskID;
unsigned char uTotalTaskNum;
unsigned char uCurrentProperty;
unsigned int uTaskEntry; // 任务入口
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 = (unsigned int)pTaskStack;
}
void OS_Start(void)
{
SP = uTaskEntry;
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 = SP+19;
if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;
SP =uTaskEntry-19;
POP_ALL();
TCNT0 = 0x00;
asm("reti");
} 应用如下,程序仅参考,我的系统功能如下:
芯片: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);
OS_CreateTask(Task_Keyboard, &uTaskStack);
OS_CreateTask(Task_System, &uTaskStack);
OS_CreateTask(Task_Load, &uTaskStack);
OS_CreateTask(Task_Unload, &uTaskStack);
OS_CreateTask(Task_LED, &uTaskStack);
OS_CreateTask(Task_CamDisc, &uTaskStack);
OS_CreateTask(Task_Miss_Extra, &uTaskStack);
OS_Start();
return(0);
} OS_CallNext(); 可以根据实际需要而删除不用 好!顶一下,可以试试! 楼主用什么编译器?用Winavr好象不能编译过去! 楼主厉害啊:) 好利害,我都是用的“时间触发调度系统”方式,感觉也挺好的。 AVR Studio 4.12 SP2 Build 472 + WinAVR 2006-0421,开发很方便,直接在AVR Studio中利用WinAVR的GCC进行开发 register unsigned char tempR16 asm("r17");
这里应该是
register unsigned char tempR17 asm("r17"); 多谢楼主的贡献精神! 输入贻误,谢谢指正 菜鸟请楼主指点一下:
uTaskEntry = SP+19;
if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;
SP =uTaskEntry-19;
是什么意思啊,为什么要加19,后面又要减19呢? 在-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 = 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-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 uTaskEntry = SP+19;
保存中断前一个任务的SP
if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;
如果每个任务已经执行了,重新从0号任务开始执行
SP =uTaskEntry-19;
获取即将执行的任务的SP
因为每个任务所处的环境不同,所以实际就是在进行任务切换前先保存刚刚执行过的任务环境,再取得已保存的下一个任务的环境,形成一个循环,这样的好处是很多的,比如说本任务处于一个等待状态,因为定时器的中断,将不会阻碍其他任务的执行,在工业控制中非常实用,而且工业控制中的实时性要求并不是很高,比如说I/O信号处理,间隔1ms采集一次远远足够。
各任务间的数据共享可以定义成全局变量如: volatile unsigned char ucCount;
volatile 不可少,至于作用,可以参考本站的许多帖子。
AVR系列在此的优势非常明显:大容量的RAM,这关系到任务数量 多谢楼主指点,不过我在#define PUSH_ALL() 和#define POP_ALL() 这两个宏的编译不能通过,语法错误,不知道什么问题。 什么错误?有可能是你在“\”后有空格符号,我遇到这样的情况 果然是空格多了,谢谢楼主,楼主大好人啊! 支持好贴! 樓主您好!想問問Inter Process Communication/Synchronization 在您的應用中怎樣實現? 盼望搂住给一个完整的应用程序啊,谢谢啊1 下面是我一台设备的程序(第二版本,第一台已经用于生产),程序完成量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;
}
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.ucPV;
ucEP_IN.ucBD = ucExPort_Temp & ucEP_IN.ucPV;
ucEP_IN.ucBA = ucExPort_Temp & ucExPort_PortValue;
ucEP_IN.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.ucPV, IN_UNLOAD) ) sbi(ucEP_OUT, OUT_ENABLE_UNLOAD_MOTOR);
if( bit_is_set(ucEP_IN.ucPV, IN_LOAD) ) sbi(ucEP_OUT, 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.ucPV, IN_LOAD) )
{
if( bit_is_set(ucEP_OUT, OUT_ENABLE_LOAD_MOTOR) )
{
delay_ms(uiLoadDly);
cbi(ucEP_OUT, 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.ucPV, IN_UNLOAD) )
{
if( bit_is_set(ucEP_OUT, OUT_ENABLE_UNLOAD_MOTOR) )
{
delay_ms(uiUnloadDly);
cbi(ucEP_OUT, 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.ucPV, IN_SVO_IS_ON) ) sbi(ucErrorCode, EC_SVO); else {cbi(ucErrorCode, EC_SVO);cbi(ucErrorFlag, EC_SVO);}
if( bit_is_clear(ucEP_IN.ucPV, IN_HOST_READY) ) sbi(ucErrorCode, EC_HRD); else {cbi(ucErrorCode, EC_HRD);cbi(ucErrorFlag, EC_HRD);}
if( bit_is_set(ucEP_IN.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.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.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 &= 0xF8;
ucEP_OUT |= 0x01;
}
else if( bit_is_set(ucErrorCode, EC_EXT) ) // Extra
{
ucEP_OUT &= 0xF8;
ucEP_OUT |= 0x02;
}
else if( bit_is_set(ucErrorCode, EC_PIT) ) // Part up
{
ucEP_OUT &= 0xF8;
ucEP_OUT |= 0x03;
}
else if( bit_is_set(ucErrorCode, EC_LCT) ) // Low cover tape
{
ucEP_OUT &= 0xF8;
ucEP_OUT |= 0x06;
}
else if( bit_is_set(ucErrorCode, EC_NAT) ) // Not at temperature
{
ucEP_OUT &= 0xF8;
ucEP_OUT |= 0x04;
}
else
{
ucEP_OUT &= 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, OUT_SYSTEM_LED);
delay_ms(250);
cbi(ucSystemFlag, SF_BE_ERR);
}
else
{
sbi(ucEP_OUT, 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.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,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 = eeprom_read_byte(12);
ucPWD = eeprom_read_byte(13);
ucPWD = eeprom_read_byte(14);
ucPWD = eeprom_read_byte(15);
if(ucPWD == 0xFF) ucPWD = '1';
if(ucPWD == 0xFF) ucPWD = '2';
if(ucPWD == 0xFF) ucPWD = '3';
if(ucPWD == 0xFF) ucPWD = '4';
uTotalTaskNum = 0;
uCurrentTaskID = 0;
OS_Timer0Init();
OS_CreateTask(Task_ScanExPort, &uTaskStack);
OS_CreateTask(Task_Keyboard, &uTaskStack);
OS_CreateTask(Task_System, &uTaskStack);
OS_CreateTask(Task_Load, &uTaskStack);
OS_CreateTask(Task_Unload, &uTaskStack);
OS_CreateTask(Task_SystemStatus, &uTaskStack);
OS_CreateTask(Task_CamDisc, &uTaskStack);
OS_CreateTask(Task_Miss_Extra, &uTaskStack);
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;
volatile unsigned char ucEP_OUT;
const unsigned char ucSetFlag PROGMEM = "";
const unsigned char ucErrFlag PROGMEM = "";
const unsigned char ucSucFlag PROGMEM = "";
const unsigned char ucMasterInfo0 PROGMEM = "Rising Sun";
const unsigned char ucMasterInfo1 PROGMEM = "Automation";
const unsigned char ucMachineInfo0 PROGMEM = "TAPE REEL";
const unsigned char ucMachineInfo1 PROGMEM = "V1.1";
const unsigned char ucProdMenu PROGMEM = "Product QTY:";
const unsigned char ucTailMenu PROGMEM = "Tail QTY:";
const unsigned char ucLeadMenu PROGMEM = "Lead QTY:";
const unsigned char ucPWS PROGMEM = "____";
const unsigned char ucPassword PROGMEM = "PASSWORD:";
const unsigned char ucHeat PROGMEM = "HEATER DELAY:";
const unsigned char ucLoad PROGMEM = "LOADER DELAY:";
const unsigned char ucUnload PROGMEM = "UNLOADER DELAY:";
const unsigned char ucNewPWD PROGMEM = "NEW PASSWORD:";
const unsigned char ucErr PROGMEM = "ERROR:";
const unsigned char ucErr_Code[] 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 = {9,17,18,14,15,10,12};
const unsigned char ucSpace PROGMEM = " ";
unsigned char ucStrTemp;
volatile unsigned char ucPWD;
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 = 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;
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 = ucKeyCode;
}
}
else
{
if(ucPos)
{
LCD_Set_XY(16+ucPos, 1);
LCD_Send_Command(ucKeyCode, 1);
ucInput = ucKeyCode-0x30;
}
else if(!ucPos && ucKeyCode != N0)
{
DisplayString(16,1,4, ucSpace);
LCD_Set_XY(16+ucPos, 1);
LCD_Send_Command(ucKeyCode, 1);
ucInput = ucKeyCode-0x30;
}
}
}
else if(ucKeyCode == ENTER)
{
if(ucParaIndex == MENU_PW)
{
for(ucIndex = 0; ucIndex < ucPos; ucIndex++)
{
if(ucPWD != ucInput)
{
SetERR();
DisplayString(16,1,4, ucPWS);
break;
}
ucInput = 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);
eeprom_write_byte(13, ucInput);
eeprom_write_byte(14, ucInput);
eeprom_write_byte(15, ucInput);
ucPWD = ucInput;
ucPWD = ucInput;
ucPWD = ucInput;
ucPWD = ucInput;
SetSUC();
ucKeyCode = F1;
break;
}
for(ucIndex = 0; ucIndex < 4; ucIndex++) ucInput = 0;
}
else
{
ucTemp = 0;
for(ucIndex = 0; ucIndex < ucPos; ucIndex++)
{
ucTemp = ucTemp*10 + ucInput;
ucInput = 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 = 0;
}
}
else
{
DisplayString(16,1,4, ucSpace);
ucTemp = 0;
for(ucIndex = 0; ucIndex < ucPos-1; ucIndex++)
{
ucTemp = ucTemp*10 + ucInput;
}
if(ucPos) ucPos--;
ucInput = 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;
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 = ucKeyCode-0x30;
}
else
if(!ucPos && ucKeyCode != N0)
{
DisplayString(16,1,4, ucSpace);
LCD_Set_XY(16+ucPos, 1);
LCD_Send_Command(ucKeyCode, 1);
ucInput = ucKeyCode-0x30;
}
}
else if(ucKeyCode == ENTER)
{
ucTemp = 0;
for(ucIndex = 0; ucIndex < ucPos; ucIndex++)
{
ucTemp = ucTemp*10 + ucInput;
ucInput = 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;
}
if(ucPos) ucPos--;
ucInput = 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,1,ucErr_Leng, ucErr_Code);
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;
for(i=0; i < NumL; i++)
{
charNum = 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部分就是前面提到的那些了,仅参考 register unsigned char ---tempR16--- asm("r16");
register unsigned char ---tempR16--- asm("r17");
正确吗? 不正确,前面说过了,应该是:
register unsigned char ---tempR16--- asm("r16");
register unsigned char ---tempR17--- asm("r17"); 3Q TOzhudlmax
好人 啊 ,这个 例子 好 ,DOWN下 来 好好 研究 ~!
另外 , 我也 有个 设备是 用 PC 键盘 控制 的 ,PS2 键盘做好 了 , 但是 现在 要兼容 AT,XT , VT 键盘 ,你有没有 XT, VT键盘的 资料 或者 是 键盘实体 呢 ? 楼主啊,谢谢啊!能不能提供打包下载啊?不好意思了! 高手!!作个 标记,有空来看看!! TO:jackiezeng,键盘协议见附件
TO:yjbin,所以代码以在上列出,你可以复制过去的
因现在工作比较忙,相机也被朋友借走了,等几天,上传点实际的东东给大伙瞧瞧,在此谢谢大家的支持
点击此处打开armok01137597.pdf 有几个问题请楼主指点一下
#define Task_Stack_Size 50 为什么要定义为50呢?这个数是怎么样计算得到的?
// 防止C编译器调用以下寄存器(可参考GCC说明),减少任务调度代码所占用的时间
register unsigned char tempR4asm("r4");
register unsigned char tempR5asm("r5");
register unsigned char tempR6asm("r6");
register unsigned char tempR7asm("r7");
register unsigned char tempR8asm("r8");
register unsigned char tempR9asm("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");
为什么要禁用这些寄存器呢,而不是其他? 我以前也写过类似的贴子,为什么就没被站长评为"酷"呢?
OS学习初探 --- 时间片轮转调度 (GCC)
http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=663028&bbs_page_no=1&bbs_id=1000
呵呵,开个玩笑. :)
前段我也在研究这个,现在好久没搞了.希望楼主继续下去. 我参考的是:《建立一个属于自己的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.uTaskStackEntry = SP+33;
if(uCurrentTask >= uValidTaskIndex-1) uCurrentTask=0;
else uCurrentTask++;
SP = TaskCtrlBlock.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倒闭...,呵呵~~~~也不是不可能啊,不过那得靠团队精神,好象对于中国人,很现实的说法是:一个中国人是条龙,一群中国人是一堆虫,扯远了,无意冒犯,别扔鸡蛋...呵呵 To: zhb2000
OS思路跟您的一模一样,我参考的是《建立一个属于自己的AVR的RTOS》作者是不是armok啊? 谢谢先
还有个问题 "每个任务自己独立需要占有的RAM" 是不是指在那个任务里面定义的局部变量?还是指其他变量? 楼主大哥,
您能不能打个包, 传上来呢 ?我编译出现很多的警告, 我的水平低啊 ~!
还有就是你上传的那个是 PS/2 的资料, 你有没有 XT , VT 键盘的资料呢? 楼主指导一下:
uTaskEntry = SP+19;
后面的系数19是怎么算出来的,我弄了半天都没弄明白。谢谢! 看了大家的一些问题,我仔细找了一些资料,将关键代码更改如下:
.....
register unsigned char tempR2asm("r2");
register unsigned char tempR3asm("r3");
register unsigned char tempR4asm("r4");
register unsigned char tempR5asm("r5");
register unsigned char tempR6asm("r6");
register unsigned char tempR7asm("r7");
register unsigned char tempR8asm("r8");
register unsigned char tempR9asm("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 = SP+15;
if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;
SP =uTaskEntry-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 = 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 = SP+15;
if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;
SP =uTaskEntry-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 = 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-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, 中断处理中最明显的特征就是保存与恢复现场环境。 看了大家的一些问题,我仔细找了一些资料,将关键代码更改如下:
.....
register unsigned char tempR2asm("r2");
register unsigned char tempR3asm("r3");
register unsigned char tempR4asm("r4");
register unsigned char tempR5asm("r5");
register unsigned char tempR6asm("r6");
register unsigned char tempR7asm("r7");
register unsigned char tempR8asm("r8");
register unsigned char tempR9asm("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 = SP+15;
if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;
SP =uTaskEntry-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 = 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 = SP+15;
if(uCurrentTaskID >= uTotalTaskNum) uCurrentTaskID = 0;
SP =uTaskEntry-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 = 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-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 -> JMP(OR RJMP) -> PUSH [ SP-2-N_push] -> POP -> RET(OR RETI)
PUSH 与 POP 是相反过程,JMP、RJMP、RET、RETI是与SP专门打交道的指令,加减多少是根据你编译后实际的汇编代码确定的 【35楼】的本想放弃的,“提交”误点,赶忙取消,我以为OK,没想到我这网速这么快,呵呵,阿莫,帮我删掉吧,谢谢先
TO jackiezeng:XT,VT键盘资料我没有,你上网搜索就是了,网络是个好东东,可以很好利用的,按你的要求,先打包上传
点击此处下载armok01137758.rar 楼主厉害,佩服啊~ 多谢楼主! 楼主大哥,
我在网络上找了很久 , 只有一点点协议,协议比 PS/2 的 更简单 , VT , XT 键盘 都是 单向通信的, 只有 键盘发送信息给PC 。
但是我找不到东西来测试 , 不知道自己的程序 能不能 工作 啊 ,
谢谢您 打包 的资料 ,我请教 个 问题 ,.elf是 什么 文件 ?
为什么一定要打开它 才能 编译呢 ?
我不会用GCC , 我的理解 是只要 有 .c 和 .h文件 ,和 makefale文件 就可以 编译了,对么 ?
但是为什么要.elf 呢 ? 叫兄弟就成,大哥不敢当,呵呵
makefile 我用AVR STUDIO内带的,只改了频率、优化两项,我用的是MEGA16,程序编译通过,是我正在进行中的一个项目,只刚刚写了一点点,给一家实验室控制水流用的,本周四得交货,现在急啊,我也不太清楚ELF,你再看看开发环境与我的有何不同? zhudlmax 兄 :
我现在大概弄明白 这个 WINAVR 了 , 现在晚了, 明天找个 板子也学着写两个任务来 运行 一 下~!
THANK YOU 楼主支招啊,我的系统怎么不能调度?仿真的时候是能正常调度的,下载到单片机里就只运行一圈之后就不知道跑那里去了,不调度任务了, 上传你的代码看看,一般是由于分配的RAM过小造成的,将Task_Stack_Size改大点看看
#define Total_Task_Num 8
#define Task_Stack_Size 50
#define Total_Stack_Size Total_Task_Num * Task_Stack_Size 好的,我试试看把Task_Stack_Size改大一点,不过问一下zhudlmax大侠:Task_Stack_Size与Task里的什么东西有关,也就是说任务里的变量还是其他什么东西需要用到Task_Stack? 现在我的程序在没有开始任务调度之前的系统初始化中,一旦调用子程序就会提示在调用的地方堆栈溢出 仿真进入了任务调度之后就不出现堆栈溢出的问题了 全局变量存取冲突的控制呢? 代码已经贴出,麻烦楼主大哥帮我看一下.程序是四个单刀双掷开关控制四个电机的上升和下降,驱动电机继电器的是芯片是2803.PB口驱动电机,PC口为按键口,芯片为M16
点击此处下载armok01138397.rar 打错了,是四个双刀双掷按键控制四个电机 问题解决了,谢谢楼主大哥! cool 学习学习~~ 楼主厉害 很强大 谢谢共享! 标记,谢谢楼主! zhudlmax和my_avr 大哥能不能帮小弟看一下程序,怎么不行,我程序中最简单的就创建了两个任务,POTRB和PORTC两个口取反一下,程序执行结果是 两个任务都只执行一次,就一直进入SIGNAL(SIG_OUTPUT_COMPARE0)中断程序了,一直在重复的执行,搞了两天,郁闷了两天点击此处下载 ourdev_329742.rar(文件大小:44K) (原文件名:AVR时间片法调度.rar) 记号 mark。 能看懂以后在看 楼主厉害,跟着学习! 楼主写得非常详细,谢谢分享 不错,写得非常详细,,有机会自己也用一用.太感谢了! 记下 mark! mark! 学习 ucOS好像没有此功能...不过仍然不失为一个优秀的嵌入式操作系统 mark 强帖留名 嘿,这里的宝藏真多啊,继续呆几天,挖完收工歇息。 up 收藏,学习。 顶一下! m 不错,这个坛子里讨论问题的气氛比较好 // 防止C编译器调用以下寄存器(可参考GCC说明),减少任务调度代码所占用的时间
register unsigned char tempR4asm("r4");
register unsigned char tempR5asm("r5");
register unsigned char tempR6asm("r6");
register unsigned char tempR7asm("r7");
register unsigned char tempR8asm("r8");
register unsigned char tempR9asm("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编译器上? 很有价值的贴呀 强贴留名 牛啊啊就是都不会啊 强贴留名 mark 强帖记下。 mark good mark mark good! 好 顶 好贴,要顶。 打标。 不错,比较简洁也很实用。 好用。谢谢lz mark 好!谢谢! mark cool..