안녕하세요. 그 동안 계속 저의 무식한 질문에 성실히 답변해 주셔서 너무 감사합니다.
이전에 가르쳐 주신 방법의 적용을 하고 싶었지만, 조금 힘들어 isr에 죄다 집어넣었습니다.
그래서 결과는 일단 6개의 fnd도 잘 나오고, 16개의 LED도 잘 뜨고, 스위치 입력시 원하는 LED가
깜빡깜빡 잘 거립니다. 그런데, 앞으로 main()에서 rs485통신과 운전 모드등을 추가하려면 해당되는
operation에 많은 타이머가 필요한데, 계속 isr에 타이머들을 덧붙이면 시스템 부하가 커질 까봐,
현재의 isr에 있는 fnd업데이트,led 업데이트, 스위치 스캔 을 최대한 main()의 while문으로 빼고 싶은데요..
그런데, 무작정 while문으로 뺄 수도 없는 것이, while문에 시간딜레이가 있는 것이 들어갑니다. 온도값을 받아오는
ad7705 16BIT-ADC 칩을 읽어 올때마다 calibration 하고 읽어와야만 하기 때문에 약 100m초 이상 의 딜레이가
항상 생깁니다. 그래서, 현재의 isr 루틴을 복귀 타이머 3ms로 해서 while문으로 빼면 fnd도 led도 약 1,5초마다 그냥 껌뻑껌뻑 거
리기만 합니다.
어떻게 하면, 효율적으로 현재의 isr 루틴을 main()의 while문으로 효율적으로 분배할 수 있을까요?...
-현재 isr과 관련 함수들이 있는 c파일 내용 첨부합니다.
volatile unsigned int disp_timer,LED_timer;
volatile unsigned char fnd_data[8], sw_input;
volatile unsigned char Led_one, Led_two;
volatile unsigned char LEDS[13];
const unsigned char fnd_pattern[18] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xa7,0x86,0xaf,0xc7,0x92,0x87,0xa3,0xbf};
//{0~9,c,E,r,L,S,t,o,-}
static unsigned char icounter=0,blink_flag=0;//kyein=0,kyein_flag=0,kyein_counter=0;
#pragma vector = TIMER1_COMPA_vect //2ms interrupt isr
__interrupt void timer1_compare_isr(void)
{ sw_input = KEYM;
//kyein = KEYM;
if(disp_timer>0) disp_timer--;
if(icounter == 8) {icounter = 0;}
DIGM = 1<<icounter;
////////////////////////////
if(icounter == 3){
if(blink_flag >0 && blink_flag < 9){
if(LED_timer<250){
Led_one = Led_one | (1<<(blink_flag-1));//OFF
SEGM = Led_one;}
else {
Led_one = Led_one & ~(1<<(blink_flag-1));//ON
SEGM = Led_one;}
}
else {
SEGM = Led_one; }
}
//////////////////////////////
else if(icounter == 7){
if(blink_flag >8){
if(LED_timer<250){
Led_two = Led_two | (1<<(blink_flag-9));//off
SEGM = Led_two;}
else {
Led_two = Led_two & ~(1<<(blink_flag-9));//on
SEGM = Led_two;}
}
else {
SEGM = Led_two; }
}
////////////////////////////////
else{SEGM =fnd_data[icounter];}
++icounter;
LED_timer++;
if(LED_timer >= 500){
LED_timer =0; }
}
oid FndDisp(unsigned char numb,unsigned char datafnd, unsigned char dotp){
if(dotp == 1) {fnd_data[numb]=(0x7f & fnd_pattern[datafnd]);}
else {fnd_data[numb] = fnd_pattern[datafnd];}
}
void LedDisp(unsigned char Lnum, unsigned char Ldata){
switch(Ldata) {
case 0: //off
LEDS[Lnum] =0;
if(Lnum <8) {
Led_one = (Led_one | (1<<Lnum)); }//clear
else {
Led_two = (Led_two | (1<<(Lnum-8))); }
blink_flag =0;
break;
case 1://on
LEDS[Lnum] =1;
if(Lnum <8) {
Led_one = (Led_one & ~(1<<Lnum)); }//set
else {
Led_two = (Led_two & ~(1<<(Lnum-8))); }
blink_flag =0;
break;
case 2://blink
//LEDS[Lnum] = LEDS[Lnum];
blink_flag = 1+Lnum;
break;
}
}
unsigned char SwInput(void){
unsigned char inmode;
if(sw_input == 0x77) return 0;
switch(sw_input){
case 0xfe: inmode=1; break;//설정 key
case 0xfd: inmode=2; break;//운전,up key
case 0xfb: inmode=3; break;//정지,down key
case 0xf7: inmode=4; break;//선택 key
case 0xfc: inmode=5; break;//설정 + 운전 key
}
sw_input=0x77; //키가 눌리지 않았음을 판단하기 위한 매직값.
return inmode;
}
-- 그리고 main에서의 while은 대략 이렇습니다.
while(1) {
adc_sint_B_1[0] = read_adc_value_B(1);//read Ch1 of A, 여기서 아주 짧은 딜레이가 생깁니다.
switch (SwInput()) {
case 1: LedDisp(0,2);
if(SwInput()==1) LedDisp(0,1);
break;
case 2: LedDisp(1,2);
if(SwInput()==2) LedDisp(1,1);
break;
case 3: LedDisp(2,2);
if(SwInput()==3) LedDisp(2,1);
break;
case 4: LedDisp(3,2);
if(SwInput()==4) LedDisp(3,1);
break;
case 5: LedDisp(4,2);
if(SwInput()==5) LedDisp(4,1);
break; }
}


참고해서 수정해 보세요.^^.
지금이라도 전체 구조를 변경하셔야 할듯합니다ㅡㅡ;
// 250uS 마다 동작하고 4번 동작시 1ms 가 된다. // Timer 0 output compare interrupt service routine interrupt [TIM0_COMP] void OnTimer0_comp_isr(void) { // 256uS X 4 마다 수행 if(stateKeyInput.uiTimer0) stateKeyInput.uiTimer0--; if(stateLedOut.uiTimer0) stateLedOut.uiTimer0--; TCNT0 =0x00; //위치 주의// 시간계산이 정확히 1mS로 안되기 때문에.. if(stateDisplayLCD.uiTimer0) stateDisplayLCD.uiTimer0--; if(stateOneSecond.uiTimer0) stateOneSecond.uiTimer0--; if(stateOperLED.uiTimer0) stateOperLED.uiTimer0--; if(statePIDCOOL.uiTimer0) statePIDCOOL.uiTimer0--; if(statePIDHEAT.uiTimer0) statePIDHEAT.uiTimer0--; if(statePIDHUMI.uiTimer0) statePIDHUMI.uiTimer0--; if(stateFAN.uiTimer0) stateFAN.uiTimer0--; if(stateMainClock.uiTimer0) stateMainClock.uiTimer0--; if(stateADC.uiTimer0) stateADC.uiTimer0--; if(infoReadTempHumi.uiTimer0) infoReadTempHumi.uiTimer0--; if(stateOUT_main.uiTimer0) stateOUT_main.uiTimer0--; if(stateCOMPCheck.uiTimer0) stateCOMPCheck.uiTimer0--; if(stateComp1.uiTimer0) stateComp1.uiTimer0--; if(stateComp2.uiTimer0) stateComp2.uiTimer0--; if(stateDefrost.uiTimer0) stateDefrost.uiTimer0--; if(stateDrain.uiTimer0) stateDrain.uiTimer0--; if(stateHEATCheck.uiTimer0) stateHEATCheck.uiTimer0--; if(stateHUMICheck.uiTimer0) stateHUMICheck.uiTimer0--; if(stateErrorCheckWaterLeak.uiTimer0) stateErrorCheckWaterLeak.uiTimer0--; if(stateErrorCheckRM.uiTimer0) stateErrorCheckRM.uiTimer0--; if(stateErrorCheckFire.uiTimer0) stateErrorCheckFire.uiTimer0--; // } }while(1) { #asm("WDR") OperatingOneSecond(&stateOneSecond); OperatingDisplayLCD(); OperatingLedOut(); OperatingRxFromMonitor(); OperatingPID(&statePIDCOOL); OperatingRxFromPC(); OperatingTxToPC(); OperatingLED(); OperatingADC(); }void OperatingOneSecond(struct _FUNC_INFO *structThisState){ if(structThisState->uiTimer0) return; structThisState->uiTimer0=1000; // ALARM OUT if (IsSystemError()) { OUTA_ON(OUTA_AL); }else{ OUTA_OFF(OUTA_AL); } }