會員登陸
帳號:

密碼:

記住我



忘記密碼?

現在註冊!
網站導航
最新下載
訪問統計 (自2012/5/3)


正在流覽:   1 名訪客





ADC自動抓取與中斷程式問題-PIC16F1823
中級會員
註冊日期:
2016/05/03 21:00
所屬群組:
註冊會員
文章: 54
等級: 6; EXP: 19
HP : 0 / 129
MP : 18 / 1410
離線
我用的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 = 1 ;         //令RC1為輸入腳   AN5= C1
    
TRISAbits.TRISA2 = 1 ;        //令RA2=輸入腳 控制Start/Stop
    
TRISCbits.TRISC5 = 0 ;        //設RC5/PIA為輸出腳   
    
TRISCbits.TRISC4 = 0 ;        //設RC4/PIB為輸出腳
    
TRISCbits.TRISC3 = 0 ;        //設RC3/PIC為輸出腳
    
TRISCbits.TRISC2 = 0 ;        //設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;      //允莧D中斷
    
PIR1bits.ADIF = 0;    //清除AD中斷旗標
    
return;
}

2016/10/17 09:44
轉換PDF檔 列印


Re: ADC自動抓取與中斷程式問題-PIC16F1823
版主
註冊日期:
2004/04/30 10:53
來自 CAE, Microchip
所屬群組:
站務管理者
註冊會員
MICROCHIP
文章: 14924
等級: 73; EXP: 71
HP : 1090 / 1817
MP : 4974 / 83505
離線
有個位元叫 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
轉換PDF檔 列印


Re: ADC自動抓取與中斷程式問題-PIC16F1823
中級會員
註冊日期:
2016/05/03 21:00
所屬群組:
註冊會員
文章: 54
等級: 6; EXP: 19
HP : 0 / 129
MP : 18 / 1410
離線
謝謝版主每次的悉心指導~
主程式加入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
轉換PDF檔 列印


Re: ADC自動抓取與中斷程式問題-PIC16F1823
中級會員
註冊日期:
2016/05/03 21:00
所屬群組:
註冊會員
文章: 54
等級: 6; EXP: 19
HP : 0 / 129
MP : 18 / 1410
離線
自問自答了:
中斷"if(ADIF)"完成後加個else{GO_nDONE=1;},需手動讓它執行下次轉換,改成這樣就正常了

2016/10/17 11:58
轉換PDF檔 列印


Re: ADC自動抓取與中斷程式問題-PIC16F1823
版主
註冊日期:
2004/04/30 10:53
來自 CAE, Microchip
所屬群組:
站務管理者
註冊會員
MICROCHIP
文章: 14924
等級: 73; EXP: 71
HP : 1090 / 1817
MP : 4974 / 83505
離線
ADC 的啟動轉換位元 GO_nDONE 或 GO (可以在 p16f1823.h 檔裡看到好幾種的名稱宣告) 只要將 ADCON0bits.GO = 1 就可以啟動 ADC 的轉換,轉換完成該位元會自動清除為零的。

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

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

2016/10/17 14:52
轉換PDF檔 列印






無法在此發表文章
可以在此觀看文章
無法回覆文章
無法編輯自己的文章
無法刪除自己的文章
無法發起投票調查
無法在此投票
無法上傳附加檔案
無法不經審核直接發表文章

[進階搜尋]


搜尋
Microchip連結
產品技術問題產品技術支援專線:0800-717718 台北02-25088600 新竹03-5778366 Ext. 8600 高雄07-2137830 MicrochipDIRECT 專線: 07-2137830
Powered by XOOPS © 2001-2012 The XOOPS Project