2011年10月24日 星期一

AD

//**************************************************************************
//*  MCU : PIC16F886
//*  DATE : 20111003 EDITED BY GARY KAO
//*  轉動可變電阻, 透過A/D 10bit轉換, 取ADRESH 8bit結果, 顯示於RB LED
//**************************************************************************
/*
說明:
此AD解析度是10BIT, 若可變電阻接5V分壓, 則每跳動1 BIT變化0.0048V
5 / 1024 = 0.0048
若設定AD結果靠左, 且只取ADRESH, 忽略ADRESL時, 則每跳動1 BIT變化0.0048 * 4 = 0.0195V
因為ADRESL有3 BIT, 表示每次需經過3次,第4次會進位到ADRESH, ADRESH才會加1


所以若將5V分為5區間, 則判斷式設定如下
1. 0.25V / 0.0195 = 12.8
2. 1.25V / 0.0195 = 64
3. 2.5V  / 0.0195 = 128
4. 3.75V / 0.0195 = 192
5. 5V    / 0.0195 = 256
*/

#include <pic.h>
#include "DELAY.H"

// CONFIG
//__CONFIG(FOSC_INTRC_NOCLKOUT & WDTE_OFF & PWRTE_OFF & MCLRE_ON & BOREN_OFF & DEBUG_ON & CPD_OFF &LVP_ON&WRT_OFF&FCMEN_OFF&IESO_OFF&CP_OFF&BOR4V_BOR21V);
__CONFIG (FOSC_INTRC_CLKOUT & WDTE_OFF & PWRTE_OFF & MCLRE_ON & CP_OFF & CPD_OFF & BOREN_ON & IESO_OFF & FCMEN_OFF & LVP_OFF & DEBUG_ON);
__CONFIG (BOR4V_BOR21V & WRT_OFF);

void InitIO();
void InitAD();


void main(void)
{
InitIO();
InitAD();


OSCCON = 0x61;  // Fosc : 4MHz

GIE = 1;
while(1)
{



GO = 1;  // enable ad interrupt

}
}


//*****************
//  IO INITIALIZE
//*****************
void InitIO()
{

TRISB = 0x00;
PORTB = 0x00;

TRISC = 0X00;
TRISCbits.TRISC2 = 1;  // SET RC2 INPUT
//TRISC = 0X04;
}

//*****************
//  A/D INITIALIZE
//*****************
void InitAD()
{

TRISA = 0X01;
ANSEL = 0X01;

ADCON0 = 0X00; // RESET ADCON0
ADCS0 = 1; // OSC : FRC
ADCS1 = 1;
ADON = 1; // ENABLE ADC

ADCON1 = 0X00; // VREF : VSS-VDD
        ADFM = 0;                         // 0 : 左對位


ADRESL = 0X00;
ADRESH = 0X00;

//GIE = 1; // ENABLE GLOBLE INT
PEIE = 1;
ADIE = 1; // ENABLE ADC
}

interrupt void AD_isr()
{
if(ADIF == 1)
{
if(ADRESH <= 13)
{
PORTB = 0X00;
}
else if ( (ADRESH <= 64) && (ADRESH > 13) )
{
PORTB = 0X01;
}
else if ( (ADRESH < 128) && (ADRESH > 64) )
{
PORTB = 0X03;
}
else if ( (ADRESH < 192) && (ADRESH >= 128) )
{
PORTB = 0X07;
}
else
{
PORTB = 0X0F;
}

ADIF = 0;
}

}

TIMER0



//**************************************************************************
//*  MCU : PIC16F886
//*  DATE : 20111003 EDITED BY GARY KAO
//*  建立100ms , 1s 與 10s的TIMER0 中斷, 輸出到RB LED顯示
//**************************************************************************

#include <pic.h>
#include "DELAY.H"

// CONFIG
//__CONFIG(FOSC_INTRC_NOCLKOUT & WDTE_OFF & PWRTE_OFF & MCLRE_ON & BOREN_OFF & DEBUG_ON & CPD_OFF &LVP_ON&WRT_OFF&FCMEN_OFF&IESO_OFF&CP_OFF&BOR4V_BOR21V);
__CONFIG (FOSC_INTRC_CLKOUT & WDTE_OFF & PWRTE_OFF & MCLRE_ON & CP_OFF & CPD_OFF & BOREN_ON & IESO_OFF & FCMEN_OFF & LVP_OFF & DEBUG_ON);
__CONFIG (BOR4V_BOR21V & WRT_OFF);

void InitIO();
void InitAD();
void InitTMR0();

unsigned char a;
unsigned char TMR0_100ms;
unsigned char TMR0_1s;
unsigned char TMR0_10s;

void main(void)
{
InitIO();

InitTMR0();
//PORTB = 0X03;
//OSCCON = 0x61; // Fosc : 4MHz
OSCCON = 0X71; // 8MHz
/* if<PS2-PS0> SET 011, 預除器1:16, 表示當osc為4MHz時, 每16us TMR0加1
若要4ms時, TMR0產生溢位: 4ms/16us = 250 , 256-250=6
所以TMR0初值要設定為6,表示TMR0由6開始遞增, 遞增到256時觸發中斷
剛好為4ms
*/

/* 若Fosd : 8MHz, 表示 1 / (8Mhz/4) = 0.5us為一個指令週期,
預除器1:8,表示每 8 * 0.5us = 4us加1
若TMR0初值設定為6, 表示TMR0由6開始遞增, 遞增到256時觸發中斷, 總共遞增250次 (256-6)
所以觸發中斷時間為 4us * 250 = 1ms


*/
TMR0 = 0x06;

/* 如何產生1s的計時中斷?
1s / 4ms = 250
在中斷程式中判斷, 當第250次中斷發生時也是1s時間到了
此時再去執行真正想做的動作
*/
TMR0_100ms = 0;
TMR0_1s = 0;
TMR0_10s = 0;

//DelayMs(50); // delay 100ms @ 4MHz
GIE = 1;


while(1)
{


}
}

//*****************
//  TIMER0 INITIALIZE
//*****************
void InitTMR0()
{
//OPTION_REG = 0X00;
OPTION_REGbits.PS0 = 0; // PRESCALER 1:8
OPTION_REGbits.PS1 = 1;
OPTION_REGbits.PS2 = 0;
OPTION_REGbits.PSA = 0; // 0: TIMER0 ; 1: WDT
OPTION_REGbits.T0SE = 1; // 一般指clock由RA4/T0CKI輸入時
// 0:正緣觸發  ;  1:負緣觸發

OPTION_REGbits.T0CS = 0; // 0:TIMER(clock週期與指令週期相同)
// 1:COUNTER(clock由RA4/T0CKI輸入)

T0IE = 1; // ENABLE TIMER0 INT

}

//*****************
//  IO INITIALIZE
//*****************
void InitIO()
{

TRISB = 0x00;
PORTB = 0x00;

TRISC = 0X00;
TRISCbits.TRISC2 = 1;  // SET RC2 INPUT
//TRISC = 0X04;
}


interrupt void AD_isr()
{
if(T0IF)
{
TMR0_100ms++;
if(TMR0_100ms == 100)
{
PORTBbits.RB0 = !PORTBbits.RB0;
TMR0_100ms = 0;

TMR0_1s++;
if(TMR0_1s == 10) // 100ms * 10 = 1s
{
PORTBbits.RB1 = !PORTBbits.RB1;
TMR0_1s = 0;

TMR0_10s++;
if(TMR0_10s == 10) // 1s * 10 = 10s
{
PORTBbits.RB2 = !PORTBbits.RB2;
TMR0_10s = 0;
}

}

}



T0IF = 0;

}
}