2011年11月2日 星期三

A/D , TIMER0 and RB interrupt

//**************************************************************************
//*  MCU : PIC16F886
//*  DATE : 20111003 EDITED BY GARY KAO
//*  轉動可變電阻, 透過A/D 10bit轉換, 取ADRESH 8bit結果, 顯示於RB LED
//*  啟動時進入sleep mode, 按下RB4 wake up, 觸發RBIF中斷, 啟動AD (GO = 1), enableRB4INT = 1
//*  while(1)判斷enableRB4INT是否為1, 且AD是否轉換完成(GO = 0)
//*  若條件成立, show BAT level, 利用TIMER 0延遲8秒後再進入sleep mode

//**************************************************************************
//*  此程式使用RB中斷喚醒MCU, 沒使用 A/D中斷
//**************************************************************************
/*
說明:
此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 InitTMR0();

void sleep();
void showChargingState();

bit enableRB4INT;
unsigned char TMR0_1ms;
unsigned char TMR0_100ms;
unsigned char TMR0_1s;


void main(void)
{
OSCCON = 0x61;  // Fosc : 4MHz

enableRB4INT = 0;
InitIO();
InitAD();
InitTMR0();

TMR0 = 0x06; // TMR0: 6~256 ; 250次
TMR0_1ms = 0;
TMR0_100ms = 0;
TMR0_1s = 0;

RBIE = 1;
GIE = 1;
// GO = 1;
sleep();

while(1)
{
if(enableRB4INT == 1)
{
if(GO == 0) // if A/D completed
{

showChargingState();
T0IE = 1; // ENABLE TIMER0 INT

if(TMR0_1s == 8)
{
PORTBbits.RB0 = 0;
PORTBbits.RB1 = 0;
PORTBbits.RB2 = 0;
PORTBbits.RB3 = 0;
T0IE = 0; // Disable TIMER0 INT
TMR0_1s = 0;
enableRB4INT = 0;
sleep();
}

}

}


}
}

void showChargingState()
{

if(ADRESH < 180) // < 3.5v
{
PORTBbits.RB0 = !PORTBbits.RB0;
PORTBbits.RB1 = !PORTBbits.RB1;
PORTBbits.RB2 = !PORTBbits.RB2;
PORTBbits.RB3 = !PORTBbits.RB3;
DelayMs(200);
//PORTB = 0x0f;
//DelayMs(200);
}
else if ( (ADRESH >= 180) && (ADRESH < 186) ) // 3.51v ~ 3.62v
{
PORTBbits.RB0 = 1;
PORTBbits.RB1 = !PORTBbits.RB1;
PORTBbits.RB2 = !PORTBbits.RB2;
PORTBbits.RB3 = !PORTBbits.RB3;
//PORTB = 0X01;
DelayMs(200);
}
else if ( (ADRESH >= 186) && (ADRESH < 198) ) // 3.63v ~ 3.86v
{
PORTBbits.RB0 = 1;
PORTBbits.RB1 = 1;
PORTBbits.RB2 = !PORTBbits.RB2;
PORTBbits.RB3 = !PORTBbits.RB3;
DelayMs(200);
}
else if ( (ADRESH >= 198) && (ADRESH < 209) ) // 3.87v ~ 4.07v
{
PORTBbits.RB0 = 1;
PORTBbits.RB1 = 1;
PORTBbits.RB2 = 1;
PORTBbits.RB3 = !PORTBbits.RB3;
DelayMs(200);
}
else // > 4.08v
{
PORTB = 0X0F;
}

}

//*****************
//  TIMER0 INITIALIZE
//*****************
void InitTMR0()
{
//OPTION_REG = 0X00;
OPTION_REGbits.PS0 = 1; // PRESCALER 1:4; 4us加1, 4us*250 = 1ms
OPTION_REGbits.PS1 = 0;
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()
{
ANSELH = 0X00; // disable AN8~AN13
TRISB = 0x10; // RB4 : INPUT
PORTB = 0x10; // RB4 : INPUT
WPUB = 0X10; // enable RB4 weak pull high
IOCB = 0X10; // enable RB4 interrupt
OPTION_REGbits.nRBPU = 0; // enable weak pull high
OPTION_REGbits.INTEDG = 0; // falling edge interrupt

//TRISB = 0x00;
//PORTB = 0x00;

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

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

TRISA = 0X01; // RA0:input
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 INT
}

interrupt void AD_isr()
{
/*if(ADIF == 1)
{


ADIF = 0;
}*/

if(T0IF) // 1ms
{
TMR0_1ms++;
if(TMR0_1ms == 100) // 100ms
{
//PORTBbits.RB0 = !PORTBbits.RB0;


TMR0_100ms++;
if(TMR0_100ms == 10) // 1s
{
//PORTBbits.RB3 = !PORTBbits.RB3;

TMR0_1s++;

//if(TMR0_1s == 3) // 1s * 3 = 3s
// pressed3Sec = 1;
//else
// PORTBbits.RB0 = 0;

TMR0_100ms = 0;
}

TMR0_1ms = 0;
}
T0IF = 0;
}

if(RBIF)
{
if(PORTBbits.RB4 == 0) // RB4 pressed
{
DelayUs(100);
GO = 1;  // A/D start
enableRB4INT = 1;
}

RBIF = 0;
}

}

void sleep()
{
     #asm
          SLEEP
     #endasm
}

2011年11月1日 星期二

Cooper Maa: Chapter 7 -- Analog Modules

Cooper Maa: Chapter 7: 註: 本文為中文翻譯,原文請見底下網址: http://www.mikroe.com/eng/chapters/view/6/chapter-5-ccp-modules/ TOC Introduction Ch. 1 Ch. 2 Ch. 3 C...

Cooper Maa: Chapter 1 -- PIC16F887 Microcontroller - Device Overview

Cooper Maa: Chapter 1: 註: 本文為中文翻譯,原文請見底下網址: http://www.mikroe.com/eng/chapters/view/2/chapter-1-pic16f887-microcontroller-device-overview/ TOC Introducti...

Cooper Maa: Chapter 2 -- Core SFRs

Cooper Maa: Chapter 2: 註: 本文為中文翻譯,原文請見底下網址: http://www.mikroe.com/eng/chapters/view/3/chapter-2-core-sfrs/ TOC Introduction Ch. 1 Ch. 2 Ch. 3 Ch 4. ...

Cooper Maa: Chapter 3 -- I/O Port

Cooper Maa: Chapter 3: 註: 本文為中文翻譯,原文請見底下網址: http://www.mikroe.com/eng/chapters/view/4/chapter-3-i-o-ports/ TOC Introduction Ch. 1 Ch. 2 Ch. 3 Ch 4. ...

Cooper Maa: Chapter 4 -- TIMER

Cooper Maa: Chapter 4: 註: 本文為中文翻譯,原文請見底下網址: http://www.mikroe.com/eng/chapters/view/5/chapter-4-timers/ TOC Introduction Ch. 1 Ch. 2 Ch. 3 Ch 4. C...