會員登陸
帳號:

密碼:

記住我



忘記密碼?

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


正在流覽:   1 名訪客



« 1 (2) 3 4 »


Re: 如何寫多通道AD做過電壓保護中斷程式
初級會員
註冊日期:
1月05日 17:30:44
所屬群組:
註冊會員
文章: 35
等級: 4; EXP: 68
HP : 0 / 92
MP : 11 / 189
離線
ADCON0有改正確但情況一樣
我後來有加上LCD去監控三組電壓值
例如當AN0接上可變電阻調整電壓 AN1 AN0未接電壓時
三組的電壓卻都跟著AN0改變成相同電壓值

3月06日 19:11:54
轉換PDF檔 列印


Re: 如何寫多通道AD做過電壓保護中斷程式
資深會員
註冊日期:
2009/04/07 13:30
所屬群組:
註冊會員
文章: 158
等級: 11; EXP: 62
HP : 0 / 265
MP : 52 / 6564
離線
那你不試試把電源關掉,
然後實際拿電表量一量 AN0 - AN1, AN1 - AN2 的電阻值嗎?

3月06日 19:19:50
轉換PDF檔 列印


Re: 如何寫多通道AD做過電壓保護中斷程式
資深會員
註冊日期:
2009/04/07 13:30
所屬群組:
註冊會員
文章: 158
等級: 11; EXP: 62
HP : 0 / 265
MP : 52 / 6564
離線
又想到了一件事...

例如當AN0接上可變電阻調整電壓 AN1 AN0未接電壓時

意思是指 AN1 直接空著嗎!
如果是, 並不是太好的測試方式,
請把空著的腳位接上 1K ~ 3K 的電阻然後接地,
這樣才容易看出是否有那樣的問題.

3月06日 19:37:44
轉換PDF檔 列印


Re: 如何寫多通道AD做過電壓保護中斷程式
初級會員
註冊日期:
1月05日 17:30:44
所屬群組:
註冊會員
文章: 35
等級: 4; EXP: 68
HP : 0 / 92
MP : 11 / 189
離線
謝謝前輩 我後來各別都加上一組可變電阻 可以個別動作了 並且把AN2先關掉
但是請問為什麼AN0 AN1各別調整電壓時會互相干擾0.01V~0.02V
而且不知道為什麼AN0 AN1的保護動作、顯示電壓值都互換了 通道確定設定無誤 就是調整AN0的電壓 保護訊號卻打在2通道 電壓顯示卻也顯示在AN1
還一個問題 為什麼LCD程式要每行用switch做 是為了不讓主程式一個迴圈時間過長而影響效率嗎 謝謝前輩

void interrupt ISR(void)
{
if(ADIE==1 && ADIF==1)
{
switch(ADC_CH)
{
case 0:
ADCON0=0B01000001; //選擇AN0通道準備進行A/D轉換,啟動A/D模組
ADCON1=0B00000000; //set Left justified, 8 TOSC, all AN enable.
CH0_SUM += ADRESH;
CH0_count++;
if(CH0_count >= 4)
{
CH0_ADC = (CH0_SUM >> 2);
CH0_count = 0;
CH0_SUM = 0;
}
if(CH0_ADC>102)
OCP0_ON=1; //大於2伏特 輸出保護訊號
else
OCP0_ON=0;
break;
case 1:
ADCON0=0B01001001; //選擇AN1通道準備進行A/D轉換,啟動A/D模組
ADCON1=0B00000000; //set Left justified, 8 TOSC, all AN enable.

CH1_SUM += ADRESH;
CH1_count++;
if(CH1_count >= 4)
{ CH1_ADC = (CH1_SUM >> 2);
CH1_count = 0;
CH1_SUM = 0;
}
if(CH1_ADC>132)
OCP1_ON=1; //大於2.58伏特 輸出保護訊號
else
OCP1_ON=0;
break;
case 2:
/*ADCON0=0B01000001; //選擇AN0通道準備進行A/D轉換,啟動A/D模組 /*先整段加上註解符號關閉AN2*/
ADCON1=0B00000000; //set Left justified, 8 TOSC, all AN enable.

CH2_SUM += ADRESH;
CH2_count++;
if(CH2_count >= 4)
{ CH2_ADC = (CH2_SUM >> 2);
CH2_count = 0;
CH2_SUM = 0;
}
if(CH2_ADC>162)
OCP2_ON=1; //大於3.18伏特 輸出保護訊號
else
OCP2_ON=0;
ADC_CH=-1;*/
break;
default:
ADCON0=0B01010001; //選擇AN2通道準備進行A/D轉換,啟動A/D模組
ADCON1=0B00000000; //set Left justified, 8 TOSC, all AN enable.
ADC_CH=-1;
}
ADC_CH++;
ADIF=0;
ADGO=1; //開始進行A/D轉換
}
}
unsigned int V_VALUE=0;
long int V_compute=0;
char V_PRINT=0;
void V_Display(void)
{
V_compute = CH0_ADC;
V_VALUE = V_compute * 500 / 255; //AD轉電壓值
LCD1602_Disp(0,0,'A');
LCD1602_Disp(1,0,'N');
LCD1602_Disp(2,0,'0');
LCD1602_Disp(3,0,'1');
LCD1602_Disp(4,0,'=');
LCD1602_Disp(5,0,V_VALUE/100+'0');
LCD1602_Disp(6,0,'.');
LCD1602_Disp(7,0,(V_VALUE%100)/10+'0');
LCD1602_Disp(8,0,(V_VALUE%10)+'0');
LCD1602_Disp(9,0,'V');
V_compute = CH1_ADC;
V_VALUE = V_compute * 500 / 255; //AD轉電壓值
LCD1602_Disp(10,0,',');
LCD1602_Disp(11,0,V_VALUE/100+'0');
LCD1602_Disp(12,0,'.');
LCD1602_Disp(13,0,(V_VALUE%100)/10+'0');
LCD1602_Disp(14,0,(V_VALUE%10)+'0');
LCD1602_Disp(15,0,'V');
V_compute = CH2_ADC;
V_VALUE = V_compute * 500 / 255; //AD轉電壓值
LCD1602_Disp(4,1,'A');
LCD1602_Disp(5,1,'N');
LCD1602_Disp(6,1,'2');
LCD1602_Disp(7,1,'=');
LCD1602_Disp(8,1,V_VALUE/100+'0');
LCD1602_Disp(9,1,'.');
LCD1602_Disp(10,1,(V_VALUE%100)/10+'0');
LCD1602_Disp(11,1,(V_VALUE%10)+'0');
LCD1602_Disp(12,1,'V');
}
Best regards.

3月07日 11:48:41
轉換PDF檔 列印


Re: 如何寫多通道AD做過電壓保護中斷程式
資深會員
註冊日期:
2009/04/07 13:30
所屬群組:
註冊會員
文章: 158
等級: 11; EXP: 62
HP : 0 / 265
MP : 52 / 6564
離線
問題: 但是請問為什麼AN0 AN1各別調整電壓時會互相干擾0.01V~0.02V

的確是會有這種情形,
主因是這個pic16F877A的 ADC 構造在通道選擇改變時有什麼現象.
(可以的話你應該去翻翻手冊中 ADC 的章節了解)
這個 ADC 中設計了一個電容,
因為訊號源到這個電容的途中有訊號源阻抗、線路阻抗...等因素的關係,
實際的 ADC 輸入值是沒辨法立即等於訊號值的. (需要時間充/放電改變)

改善的方法是, 切換通道選擇後要等待足夠的時間再啟動 ADC 轉換.
如果你還是要依現在的程式方法繼續的話,
應該選擇最初提供的做法,
通道改變後, 對同一通道進行數次 ADC 轉換,
並略過切換通道後的幾次取樣值.
而不要選擇現在每轉換一次就再切換通道的做法.


問題: 而且不知道為什麼AN0 AN1的保護動作、顯示電壓值都互換了

雖然你以為通道選定的設定值正確,
其實並不對喔!
case 0 中, 處理的是存下 AN0 已經轉換完成的值,
而設定的通道選定是接著要進行的 AN1 ,
這樣執行到 case 1 時, 取得的轉換值才會是 AN1 的輸入值.



switch(ADC_CH)
{
case 0:
ADCON0=0B01001001; //選擇AN1通道準備進行A/D轉換,啟動A/D模組
ADCON1=0B00000000; //set Left justified, 8 TOSC, all AN enable.
:
:
:
case 1:
ADCON0=0B01000001; //選擇AN0通道準備進行A/D轉換,啟動A/D模組
ADCON1=0B00000000; //set Left justified, 8 TOSC, all AN enable.
}


問題: 為什麼LCD程式要每行用switch做 是為了不讓主程式一個迴圈時間過長而影響效率嗎

是的, 因為你一開始有提到還要執行其它的項目 (如LED),
而顯示電壓值感覺上是零點幾杪達成就可以的動作,
所以不希望執行顯示電壓值的總執行時間 比 其它主程式項目 的佔比過高.



想改善切換通道時輸入值受影響, 可以試試以下

unsigned char ADC_CH=0;
unsigned char ADC_count=0;
unsigned int ADC_SUM=0;
unsigned char CH0_ADC=0;
unsigned char CH1_ADC=0;
unsigned char CH2_ADC=0;
void interrupt ISR(void)
{
if(ADIE==1 && ADIF==1)
{
if(ADC_count > 1) ADC_SUM = ADC_SUM + ADRESH;
else ADC_SUM = 0;

ADC_count++;
if(ADC_count >= 6)
{
ADC_count = 0;
ADC_SUM >>= 2; // average (1/4)
ADCON1=0B00000000; //set right, all AN enable.
switch(ADC_CH)
{
case 0:
ADCON0=0B11001001; //選擇AN1通道準備進行A/D轉換,啟動A/D模組
CH0_ADC = ADC_SUM;

if(CH0_ADC>102)
OCP0_ON=1; //大於2伏特 輸出保護訊號
else
OCP0_ON=0;
break;
case 1:
ADCON0=0B11010001; //選擇AN2通道準備進行A/D轉換,啟動A/D模組
CH1_ADC = ADC_SUM;

if(CH1_ADC>132)
OCP1_ON=1; //大於2.58伏特 輸出保護訊號
else
OCP1_ON=0;
break;
case 2:
ADCON0=0B11000001; //選擇AN0通道準備進行A/D轉換,啟動A/D模組
CH2_ADC = ADC_SUM;

ADC_CH=-1;
break;
}
ADC_CH++;
}
ADIF=0;
ADGO=1; //開始進行A/D轉換
}
}

3月07日 16:10:32
轉換PDF檔 列印


Re: 如何寫多通道AD做過電壓保護中斷程式
初級會員
註冊日期:
1月05日 17:30:44
所屬群組:
註冊會員
文章: 35
等級: 4; EXP: 68
HP : 0 / 92
MP : 11 / 189
離線
終於懂了 真的感謝前輩熱心指導
那請問前輩的中斷程式是多久會進AD中斷一次? 每次迴圈完一次嗎
那AD中斷是從initial開始觸發嗎 所以這樣initial設定任何一個通道都可以嗎
那為什麼這樣PIC就不會一直卡在中斷裡處理會去處理while? 謝謝
主函式:
void main(void)
{
TRISA=0xFF;
TRISB=0xC7;
TRISC=0x00;
TRISD=0x00;
PORTA=0x00;
PORTB=0x00;
PORTC=0x00;
PORTD=0x00;
LCD1602_init();
OCP0_ON=0;
OCP1_ON=0;
OCP2_ON=0;
ADCON1=0B00000000; //set left justified, All AN enable.
ADIF=0; //AD中斷旗標
ADIE=1; //AD中斷允許位
PEIE=1; //外設中斷允許位
GIE=1; //全局中斷允許位
ADCON0=0B01010001; //選擇AN2通道準備進行A/D轉換,啟動A/D模組
asm("NOP"); //略做延時
asm("NOP"); //略做延時
asm("NOP"); //略做延時
asm("NOP"); //略做延時
ADGO=1; //開始進行A/D轉換
while(1)
{
V_Display();
LED();
}
}

Best Regards.

3月07日 16:39:09
轉換PDF檔 列印


Re: 如何寫多通道AD做過電壓保護中斷程式
資深會員
註冊日期:
2009/04/07 13:30
所屬群組:
註冊會員
文章: 158
等級: 11; EXP: 62
HP : 0 / 265
MP : 52 / 6564
離線
因為現在除了第一次是在 main 裡啟動轉換外,
其它皆是在 中斷處理程序尾端 再次啟動,
所以每次間隔時間就約是 ADC 的轉換時間.

手冊裡有說明 ADC 轉換時間約為 11 個 Tad,
而中斷程序裡的

ADCON1=0B00000000; //set right, all AN enable.

ADCON0=0B11001001; //選擇AN1通道準備進行A/D轉換,啟動A/D模組

指明了現在的 Tad 為 Internal A/D module RC oscillator (2-6 us).
( 典型值為 4 us )

所以每次中斷離開後再進中斷的時間間隔約為 11 * 4 us = 44 us




中斷從哪裡開始?

void main(void)
{
TRISA=0xFF;
TRISB=0xC7;
TRISC=0x00;
TRISD=0x00;
PORTA=0x00;
PORTB=0x00;
PORTC=0x00;
PORTD=0x00;
LCD1602_init();
OCP0_ON=0;
OCP1_ON=0;
OCP2_ON=0;
ADCON1=0B00000000; //set left justified, All AN enable.
ADIF=0; //AD中斷旗標
ADIE=1; //AD中斷允許位
PEIE=1; //外設中斷允許位
GIE=1; //全局中斷允許位
ADCON0=0B01010001; //選擇AN2通道準備進行A/D轉換,啟動A/D模組
asm("NOP"); //略做延時
asm("NOP"); //略做延時
asm("NOP"); //略做延時
asm("NOP"); //略做延時
ADGO=1; //開始進行A/D轉換 這裡開始進行轉換, 那再等 11 * Tad 就會進中斷了
while(1)
{
V_Display();
LED();
}
}



這樣initial設定任何一個通道都可以嗎?

是可以.....
不過呢! unsigned char ADC_CH=0; 的初值已經是 '"0" 了,
main 裡要啟動的通道如果並不是 ch0 的話, 第一次取樣平圴後的數值就 "不是ch0" 的輸入了,
但是之後的執行, 因為中斷程序裡會再設定, 就不會出現不一致的問題.



為什麼這樣PIC就不會一直卡在中斷裡處理會去處理while?
請參考下圖,
最原始的程式在 主程式LOOP 的執行占比太小,
導致在主程式中的動作感覺極度緩慢,
甚至以為是停止了.

附加檔案:



jpg  中斷程序占比.JPG (39.16 KB)
5620_58be8bf516efc.jpg 501X500 px

3月07日 18:31:29
轉換PDF檔 列印


Re: 如何寫多通道AD做過電壓保護中斷程式
初級會員
註冊日期:
1月05日 17:30:44
所屬群組:
註冊會員
文章: 35
等級: 4; EXP: 68
HP : 0 / 92
MP : 11 / 189
離線
謝謝前輩真的很熱心指導!!

再請問一個問題 LED程式會拖慢很多整個主程式
如果今天產品必要這個程式 那不就執行效率會變很慢嗎?
有什麼解決方法?
但是LED流水燈程式是不是不會拖慢到AD中斷?
另外請問我是使用4M外部晶振 那是不識就要設定8 TOSC
/* ADCS2:ADCS1:ADCS0 = 001 */
ADCON0=0B01000001;
ADCON1=0B00000000;
是不是比較不推薦RC震盪 聽說不穩定?
謝謝前輩!!

Best Regards.

3月07日 19:02:27
轉換PDF檔 列印


Re: 如何寫多通道AD做過電壓保護中斷程式
資深會員
註冊日期:
2009/04/07 13:30
所屬群組:
註冊會員
文章: 158
等級: 11; EXP: 62
HP : 0 / 265
MP : 52 / 6564
離線
LED程式會拖慢很多整個主程式
如果今天產品必要這個程式 那不就執行效率會變很慢嗎?
有什麼解決方法?



我的確有偷懶的方法...

unsigned int LED_WAIT=0;
unsigned char LED_DO_SHIFT=0;
unsigned char y=0;
void LED(void) //流水燈 做測試用
{
if(LED_DO_SHIFT != 0);//延?若干??,具体???不理?
{
if(++y>12) y=0; //y做加1操作,并限制在0-15以?
PORTC=TAB[y]; //?TAB[y]的值送入RD口?出
}
}


unsigned char ADC_CH=0;
unsigned char ADC_count=0;
unsigned int ADC_SUM=0;
unsigned char CH0_ADC=0;
unsigned char CH1_ADC=0;
unsigned char CH2_ADC=0;
void interrupt ISR(void)
{
if(ADIE==1 && ADIF==1)
{
if(ADC_count > 1) ADC_SUM = ADC_SUM + ADRESH;
else ADC_SUM = 0;

ADC_count++;
if(ADC_count >= 6)
{
LED_WAIT++;
if(LED_WAIT >= 1000)
{
LED_WAIT = 0;
LED_DO_SHIFT = 1;
}

ADC_count = 0;
ADC_SUM >>= 2; // average (1/4)
ADCON1=0B00000000; //set right, all AN enable.
switch(ADC_CH)
{
:
:
:


但是LED流水燈程式是不是不會拖慢到AD中斷?

不會拖慢AD中斷, 當中斷情形發生時, 會優先跳往中斷去執行.




另外請問我是使用4M外部晶振 那是不識就要設定8 TOSC

關於這項嘛! 其實應該由你自已試最合適了, 因為你才能確知反應速度是否達到要求.
換成是我的話! 我會先選 /* ADCS2:ADCS1:ADCS0 = 010 */ (FOSC/32)
因為我覺得幾ms的反應對很多東西都已經是足夠快得了.




是不是比較不推薦RC震盪 聽說不穩定?

不會啊! 雖然它的確會造成不同一個的產品會有時間參差.
不過這是看每個人應用時的要求來選擇.
聽說不穩定?
這一項嘛! 我覺得形容的不對, 我的認知是 "不精確"
RC震盪具有誤差範圍在, 而且溫度改變大時也有變化的誤差在,
如果要求要精確, 當然要考慮好才可以.

不過若說是 "不穩定", 我倒沒聽說 "內部RC震盪" 無綠無故就突然失效的.

3月07日 21:05:52
轉換PDF檔 列印


Re: 如何寫多通道AD做過電壓保護中斷程式
資深會員
註冊日期:
2009/04/07 13:30
所屬群組:
註冊會員
文章: 158
等級: 11; EXP: 62
HP : 0 / 265
MP : 52 / 6564
離線
啊~~~ 又要捉漏了, 補一下.

unsigned int LED_WAIT=0;
unsigned char LED_DO_SHIFT=0;
unsigned char y=0;
void LED(void) //流水燈 做測試用
{
if(LED_DO_SHIFT != 0);//延?若干??,具体???不理?
{
LED_DO_SHIFT=0;
if(++y>12) y=0; //y做加1操作,并限制在0-15以?
PORTC=TAB[y]; //?TAB[y]的值送入RD口?出
}
}

3月07日 21:55:59
轉換PDF檔 列印



« 1 (2) 3 4 »



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

[進階搜尋]


搜尋
線上教學影片
網頁捷徑
2017 Summer Elite 報名
教育訓練
其它網站連結
電話: 02-25000405
產品技術問題產品技術支援專線:0800-717718 台北02-25088600 新竹03-5778366 Ext. 8600 高雄07-2137830 MicrochipDIRECT 專線: 07-2137830
Powered by XOOPS © 2001-2012 The XOOPS Project