:::


Browsing this Thread:   1 Anonymous Users






ADC自動抓取與中斷程式問題-PIC16F1823
#1
中級會員
中級會員


查看用戶資訊
我用的MCU是PIC16F1823
我的AD中斷好像不會觸發,我讀取數值的指令放在中斷程式內都毫無反應,就算Reset數值也都不會寫入
然後我把讀取數值的指令放在主程式的While(1)內,但也只有開機時抓取一次,無法自動循環
請問是為什麼呢?
#include<pic.h>
#include<pic16f1823.h>
#define Start 0
#define Stop 1
#define CW 0
#define CCW 1
#define FCY  4000000            // xtal = 5.0Mhz; PLLx8
#define MILLISEC FCY/14200            // 1 mSec delay constant 14200
void InitMCPWM(void);        // 初始化PWM參數
void InitADC10(void);        // 初始化ADC參數
void InitTMR2(void);         // 初始化TMR2參數
void DelayNmSec(unsigned int N); // Delay = N*1ms
unsigned int ADCValue;       // 10位AD紀錄值  0~VDD/0~1024
int CWGO=0;
int CCWGO=0;
/**************************************************************************
                                 中斷設定
**************************************************************************/
void interrupt ISR(void)
{
if(
ADIE && ADIF// AD中斷
{
ADIF 0//清除AD中斷旗標
ADCValue = (((ADRESH<<2)  + (ADRESL>>6)));             //ADCValue為10bit=1024
                                //高位元與低位元相加 需是PR2的4倍
                            //如PR2=128 則ADCValue 除2
        
CCP1CON |= (0x30&(ADCValue<<4));    //低位Duty cycle
        
CCPR1L  = (ADCValue>>2) ;            //高位Duty cycle     

}

}
/**************************************************************************
                 主程式
**************************************************************************/
int main(void)
{
    
InitMCPWM();                    // 初始化PWM
    
InitADC10();            // 初始化ADC
    
InitTMR2();
    
TRISCbits.TRISC0 1;       //令RC0=輸入腳 控制CW/CCW  (0對調
    
TRISCbits.TRISC1 ;         //令RC1為輸入腳   AN5= C1
    
TRISAbits.TRISA2 ;        //令RA2=輸入腳 控制Start/Stop
    
TRISCbits.TRISC5 ;        //設RC5/PIA為輸出腳   
    
TRISCbits.TRISC4 ;        //設RC4/PIB為輸出腳 
    
TRISCbits.TRISC3 ;        //設RC3/PIC為輸出腳 
    
TRISCbits.TRISC2 ;        //設RC2/PID為輸出腳 
    
ANSELA 0x00;    
    
ANSELC 0x02 ;         //令RC1為類比訊號 AN5= C1
    
OSCCON=0b11111010;        // b[6~3]= 1111 = 內部頻率FOSC=16MHZ  Fcy=16/4=4MHZ
    
while(1)
    {

        if(
RA2 == Stop )                //停止開關
        
{
            
CCP1CONbits.CCP1M 0b0000;        //PWM關閉
            
PORTCbits.RC5 0;            //禁止PWM輸出
            
PORTCbits.RC4 0;
            
PORTCbits.RC3 0;
            
PORTCbits.RC2 0;
        
        }
        if((
RA2 == Start))                //開關啟動
        
{
            if((
RC0 == CW) &&(CWGO==0))        //正轉判別
            
{   
                
CWGO=1;
                
DelayNmSec(10) ;        //防止開關彈跳
                
CCWGO=0;
            }
            if(
CWGO==1)                //正轉
            
{    
                
CWGO++;                //只執行一次
                
CCP1CONbits.CCP1M 0b0000;        //PWM停止
                
DelayNmSec(2000) ;        //Delay 200ms
            
if(RC0==CW)
                {
CCP1CONbits.P1M =  0b01;    //全橋正轉 P1D=PWM P1A=HIGH
                
CCP1CONbits.CCP1M 0b1100;    //PWM啟動
                
}
            }    

            if((
RC0 == CCW) &&(CCWGO==0))        //反轉判別
            
{   
                
CCWGO=1;
                
DelayNmSec(10) ;        //防止開關彈跳
                
CWGO=0;
            }
            if(
CCWGO==1)                //正轉
            
{    
            
CCWGO++;                //只執行一次
            
CCP1CONbits.CCP1M 0b0000;        //PWM停止
            
DelayNmSec(2000) ;            //Delay 200ms
            
if(RC0==CCW)
            {
            
CCP1CONbits.P1M =  0b11;        //全橋反轉轉 P1C=PWM P1B=HIGH
            
CCP1CONbits.CCP1M 0b1100;        //PWM啟動

            
}
            }    
        }
[
color=FF0000]//    ADCValue = (((ADRESH<<2)  + (ADRESL>>6)));     //ADCValue為10bit=1024
                                                            
//        CCP1CON |= (0x30&(ADCValue<<4));    //低位Duty cycle
//        CCPR1L  = (ADCValue>>2) ;        //高位Duty cycle[/color]
    
        
    
}        
}      
/**************************************************************************
             ADC10 初始化設定
**************************************************************************/
void InitADC10(void)
{
    
ADCON0 0x17;        //使用AN5;自動轉換;啟動ADC  //AN4=13 AN5= 17
    
ADCON1 0x00;        //右對齊;Fosc/4;
                           //結果存在 ADRESH =0x00000011 與ADRESL = 0x11111111

    
PIE1bits.ADIE 1;      //允許AD中斷
    
PIR1bits.ADIF 0;    //清除AD中斷旗標
    
return;
}

發表於: 2016/10/17 9:44
Twitter Facebook Google Plus Linkedin Del.icio.us Digg Reddit Mr. Wong 頂部


Re: ADC自動抓取與中斷程式問題-PIC16F1823
#2
版主
版主


查看用戶資訊
有個位元叫 GIE (Globa Interrupt Enable) & PEIE (Peripheral Interrupt Enable) 兩個位元要設定,這樣中斷才會開啟。

PIC16F1823 的周邊可以用 MCC 的軟體來做設定,簡單好上手。可以參考教育訓練光碟下的:
http://www.microchip.com.tw/Data_CD/

PIC101 X IDE & MCC & XC8 的綜合基礎課程 New!
MCC201 v1.00 MPLAB Code Configurator New!
CIP102v2.00 進階獨立式週邊 (Advanced CIP) 的應用 New!

發表於: 2016/10/17 10:29
Twitter Facebook Google Plus Linkedin Del.icio.us Digg Reddit Mr. Wong 頂部


Re: ADC自動抓取與中斷程式問題-PIC16F1823
#3
中級會員
中級會員


查看用戶資訊
謝謝版主每次的悉心指導~
主程式加入GIE與PEIE的設定後中斷功能即有作用了,但一個新的問題就是又變成只有開機時抓取一次
我必須把初始設定"InitADC10();"放到主程式的While(1)迴圈內才能讓ADC中斷程式重複循環的抓取數據
這裡我就搞不懂了,我看滿多範例都不會這樣子寫,大多都放在主程式起始位置只執行一次
我試過抓取完後要在中斷程式內把GO_nDONE清0 但依然沒有效果。

/**************************************************************************
                                 中斷設定
**************************************************************************/
void interrupt ISR(void)
{
if(
ADIF&&ADIE// AD中斷
{
ADIF 0//清除AD中斷旗標
ADCValue = (((ADRESH<<2)  + (ADRESL>>6)));     //ADCValue為10bit=1024
                        //高位元與低位元相加 需是PR2的4倍
                        //如PR2=128 則ADCValue 除2
        
CCP1CON |= (0x30&(ADCValue<<4));//低位Duty cycle
        
CCPR1L  = (ADCValue>>2) ;    //高位Duty cycle    

//ADCON0bits.GO_nDONE=0;
}
/**************************************************************************
             ADC10 初始化設定
**************************************************************************/
void InitADC10(void)
{
    
ADIE=1;
    
ADIF=0;
    
ADCON0 0x17;        //使用AN5;自動轉換;啟動ADC  //AN4=13 AN5= 17
    
ADCON1 0x00;        //右對齊;Fosc/4;
                           //結果存在 ADRESH =0x00000011 與ADRESL = 0x11111111

    
return;
}

發表於: 2016/10/17 11:44
Twitter Facebook Google Plus Linkedin Del.icio.us Digg Reddit Mr. Wong 頂部


Re: ADC自動抓取與中斷程式問題-PIC16F1823
#4
中級會員
中級會員


查看用戶資訊
自問自答了:
中斷"if(ADIF)"完成後加個else{GO_nDONE=1;},需手動讓它執行下次轉換,改成這樣就正常了

發表於: 2016/10/17 11:58
Twitter Facebook Google Plus Linkedin Del.icio.us Digg Reddit Mr. Wong 頂部


Re: ADC自動抓取與中斷程式問題-PIC16F1823
#5
版主
版主


查看用戶資訊
ADC 的啟動轉換位元 GO_nDONE 或 GO (可以在 p16f1823.h 檔裡看到好幾種的名稱宣告) 只要將 ADCON0bits.GO = 1 就可以啟動 ADC 的轉換,轉換完成該位元會自動清除為零的。

ADC 因為轉換時間很短,一般是可以不用 ADC 中斷方式來做轉換的。可以值接將底下的轉換值接加到主程式裡的 (這樣就不需要中斷)

ADCON0bits.GO = 1; // 開始轉換
while (ADCON0bits.GO); // 轉換完成 ?

發表於: 2016/10/17 14:52
Twitter Facebook Google Plus Linkedin Del.icio.us Digg Reddit Mr. Wong 頂部







You can view topic.
You cannot start a new topic.
You cannot reply to posts.
You cannot edit your posts.
You cannot delete your posts.
You cannot add new polls.
You cannot vote in polls.
You cannot attach files to posts.
You cannot post without approval.
You cannot use topic type.
You cannot use HTML syntax.
You cannot use signature.
You cannot create PDF files.
You cannot get print page.

[進階搜尋]