會員登陸
帳號:

密碼:

記住我



忘記密碼?

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


正在流覽:   1 名訪客



(1) 2 3 4 »


如何寫多通道AD做過電壓保護中斷程式
初級會員
註冊日期:
1月05日 17:30:44
所屬群組:
註冊會員
文章: 35
等級: 4; EXP: 68
HP : 0 / 92
MP : 11 / 192
離線
以下是我寫的一個AD通道中斷程式
但是這樣寫會讓跑馬燈不會動作一直處於中斷(?)
要怎麼讓他可以執行while的程式 當AD超過某值可以觸發中斷去發出一個保護訊號呢 而且要多個AD通道同時進行
/**
跑馬燈是用來測試以模擬其他程式在執行時
LCD程式是便於監看電壓值用
請問如果要用多個通道 且要做AD平均該怎麼做呢
測試板是使用PIC16F877A
**/
#include <pic.h>
__CONFIG(HS&WRTEN&WDTDIS&BOREN&PWRTDIS&UNPROTECT&DUNPROT&DEBUGDIS&LVPDIS);
#define OCP_ON RC0
#define E RB3
#define RW RB4
#define RS RB5
unsigned int adbuf;
const unsigned char TAB[13]=
{ //
0x02, //表格第2步數據0B00000010
0x04, //表格第3步數據0B00000100
0x08, //表格第4步數據0B00001000
0x10, //表格第5步數據0B00010000
0x20, //表格第6步數據0B00100000
0x40, //表格第7步數據0B01000000
0x80, //表格第8步數據0B10000000
0x40, //表格第9步數據0B11000000
0x20, //表格第10步數據0B11100000
0x10, //表格第11步數據0B11110000
0x08, //表格第12步數據0B11111000
0x04, //表格第13步數據0B11111100
0x02, //表格第14步數據0B11111110
//表格第16步數據0B00000000
};
void LED(void) //流水燈 做測試用
{
for(x=0;x<3000;x++);//延时若干时间,具体时长暂不理会
if(++y>12) y=0; //y做加1操作,并限制在0-15以内
PORTC=TAB[y]; //将TAB[y]的值送入RD口输出
}
void Delay1602(unsigned int t)
{
unsigned int k;
for(k=0;k<t;k++);
}

void LCD1602_busy(void)
{
TRISD7=1;
RS=0;
RW=1;
E=1;
while(RD7==1);
E=0;
TRISD7=0;
}

void LCD1602_Write_com(unsigned char combuf)
{
RS=0;
RW=0;
PORTD=combuf;
E=1;
asm("NOP");
E=0;
}


void LCD1602_Write_com_busy(unsigned char combuf)
{
LCD1602_busy();
LCD1602_Write_com(combuf);
}

void LCD1602_Write_data_busy(unsigned char databuf)
{
LCD1602_busy();
RS=1;
RW=0;
PORTD=databuf;
E=1;
asm("NOP");
E=0;
}

void LCD1602_Write_address(unsigned char x,unsigned char y)
{
x&=0x0f;
y&=0x01;
if(y==0)
LCD1602_Write_com_busy(x|0x80);
else
LCD1602_Write_com_busy((x+0x40)|0x80);
}

void LCD1602_init(void)
{
Delay1602(1500);
LCD1602_Write_com(0x38);
Delay1602(500);
LCD1602_Write_com(0x38);
Delay1602(500);
LCD1602_Write_com(0x38);
LCD1602_Write_com_busy(0x38);
LCD1602_Write_com_busy(0x08);
LCD1602_Write_com_busy(0x01);
LCD1602_Write_com_busy(0x06);
LCD1602_Write_com_busy(0x0C);
}

void LCD1602_Disp(unsigned char x,unsigned char y,unsigned char buf)
{
LCD1602_Write_address(x,y);
LCD1602_Write_data_busy(buf);
}
void interrupt ISR(void)
{
if(ADIF==1)
{
if(ADRESH>102)
OCP_ON=1; //大於2伏特 輸出保護訊號
else
OCP_ON=0;
ADIF=0;
adbuf=(int)(((float)ADRESH/255)*500); //AD轉電壓值
LCD1602_Disp(4,1,'O');
LCD1602_Disp(5,1,'C');
LCD1602_Disp(6,1,'P');
LCD1602_Disp(7,1,'=');
//***1602液晶显示0-255***********
LCD1602_Disp(8,1,adbuf/100+'0'); //在第2行的第9列顯示百位
LCD1602_Disp(9,1,'.');
LCD1602_Disp(10,1,(adbuf%100)/10+'0'); //在第2行的第10列顯示十位
LCD1602_Disp(11,1,adbuf%10+'0'); //在第2行的第11列顯示个位
LCD1602_Disp(12,1,'V');
//*******************************
}
ADGO=1; //開始進行A/D轉換
}
void main(void)
{
TRISA=0xFF;
TRISB=0xC7;
TRISC=0x00;
TRISD=0x00;
PORTA=0x00;
PORTB=0x00;
PORTC=0x00;
PORTD=0x00;
unsigned int x=0; //定義一个int型变量,做延时用
unsigned char y=14; //定義一个char型变量,查表索引用
LCD1602_init();
//OCP_DET=0;
OCP_ON=0;
ADCON1=0B00001110; //set right, AN0 enable.
ADIF=0;
ADIE=1; //允許A/D中斷
PEIE=1;
GIE=1;
ADCON0=0B00000001; //選擇AN0通道準備進行A/D轉換,啟動A/D模組
asm("NOP"); //略做延時
asm("NOP"); //略做延時
asm("NOP"); //略做延時
asm("NOP"); //略做延時
ADGO=1; //開始進行A/D轉換
while(1)
{
LED();
}
}

3月02日 12:46:36
轉換PDF檔 列印


Re: 如何寫多通道AD做過電壓保護中斷程式
資深會員
註冊日期:
2009/04/07 13:30
所屬群組:
註冊會員
文章: 158
等級: 11; EXP: 62
HP : 0 / 265
MP : 52 / 6572
離線
我猜想主要因素應該是 ADC 取樣(與ADC中斷)的次數太頻繁,
使得 執行ADC中斷程序 的比例遠遠大於 主程序執行.
所以主程序執行的速度緩慢到.....

改善的建議:
如果 ADC 取樣速率不需要如此快, 設置一個時間中斷去啟動它.
改善 ADC中斷執行的程序, 減少 ADC中斷程序執行的時間.
把 ADC取樣啟動安排在主程序的某些地方.

提供以下所示的改善方法,
因為硬體電路的關係, 要請你自行去測試與除錯了.


#include <pic.h>
__CONFIG(HS&WRTEN&WDTDIS&BOREN&PWRTDIS&UNPROTECT&DUNPROT&DEBUGDIS&LVPDIS);
#define OCP_ON RC0
#define E RB3
#define RW RB4
#define RS RB5
unsigned int adbuf;
const unsigned char TAB[13]=
{ //
0x02, //表格第2步數據0B00000010
0x04, //表格第3步數據0B00000100
0x08, //表格第4步數據0B00001000
0x10, //表格第5步數據0B00010000
0x20, //表格第6步數據0B00100000
0x40, //表格第7步數據0B01000000
0x80, //表格第8步數據0B10000000
0x40, //表格第9步數據0B11000000
0x20, //表格第10步數據0B11100000
0x10, //表格第11步數據0B11110000
0x08, //表格第12步數據0B11111000
0x04, //表格第13步數據0B11111100
0x02, //表格第14步數據0B11111110
//表格第16步數據0B00000000
};
void LED(void) //流水燈 做測試用
{
for(x=0;x<3000;x++);//延时若干时间,具体时长暂不理会
if(++y>12) y=0; //y做加1操作,并限制在0-15以内
PORTC=TAB[y]; //将TAB[y]的值送入RD口输出
}
void Delay1602(unsigned int t)
{
unsigned int k;
for(k=0;k<t;k++);
}

void LCD1602_busy(void)
{
TRISD7=1;
RS=0;
RW=1;
E=1;
while(RD7==1);
E=0;
TRISD7=0;
}

void LCD1602_Write_com(unsigned char combuf)
{
RS=0;
RW=0;
PORTD=combuf;
E=1;
asm("NOP");
E=0;
}


void LCD1602_Write_com_busy(unsigned char combuf)
{
LCD1602_busy();
LCD1602_Write_com(combuf);
}

void LCD1602_Write_data_busy(unsigned char databuf)
{
LCD1602_busy();
RS=1;
RW=0;
PORTD=databuf;
E=1;
asm("NOP");
E=0;
}

void LCD1602_Write_address(unsigned char x,unsigned char y)
{
x&=0x0f;
y&=0x01;
if(y==0)
LCD1602_Write_com_busy(x|0x80);
else
LCD1602_Write_com_busy((x+0x40)|0x80);
}

void LCD1602_init(void)
{
Delay1602(1500);
LCD1602_Write_com(0x38);
Delay1602(500);
LCD1602_Write_com(0x38);
Delay1602(500);
LCD1602_Write_com(0x38);
LCD1602_Write_com_busy(0x38);
LCD1602_Write_com_busy(0x08);
LCD1602_Write_com_busy(0x01);
LCD1602_Write_com_busy(0x06);
LCD1602_Write_com_busy(0x0C);
}

void LCD1602_Disp(unsigned char x,unsigned char y,unsigned char buf)
{
LCD1602_Write_address(x,y);
LCD1602_Write_data_busy(buf);
}

unsigned char ADC_CH=0;
unsigned char ADC_TIMES=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_TIMES > 0) ADC_SUM = ADC_SUM + ADRESH;
else ADC_SUM = 0;

ADC_TIMES++;
if(ADC_TIMES >= 5)
{ ADC_SUM >>= 2; // average (1/4)
switch(ADC_CH)
{ case 0: CH0_ADC = ADC_SUM;

if(CH0_ADC>102)
OCP_ON=1; //大於2伏特 輸出保護訊號
else
OCP_ON=0;

ADC_TIMES=0;
ADCON0=0B11000001; //選擇AN0通道準備進行A/D轉換,啟動A/D模組
ADC_CH=1;
break;
case 1: CH1_ADC = ADC_SUM;
ADC_TIMES=0;
ADCON0=0B11001001; //選擇AN1通道準備進行A/D轉換,啟動A/D模組
ADC_CH=2;
break;
case 2: CH2_ADC = ADC_SUM;
ADC_TIMES=0;
ADCON0=0B11010001; //選擇AN2通道準備進行A/D轉換,啟動A/D模組
ADC_CH=0;
break;
default: ADC_TIMES=0;
ADCON0=0B11000001; //選擇AN0通道準備進行A/D轉換,啟動A/D模組
ADC_CH=0;
}
ADCON1=0B01001110; //set right, AN0 enable.
}
ADIF=0;
ADGO=1; //開始進行A/D轉換
}
}

unsigned int V_VALUE=0;
long int V_compute=0;
char V_PRINT=0;
void V_Display(void)
{
switch(V_PRINT)
{ case 0: V_compute = CH0_ADC;
V_VALUE = V_compute * 500 / 255; //AD轉電壓值
break;
case 1: LCD1602_Disp(4,1,'O');
break;
case 2: LCD1602_Disp(5,1,'C');
break;
case 3: LCD1602_Disp(6,1,'P');
break;
case 4: LCD1602_Disp(7,1,'=');
break;
//***1602液晶?示0-255***********
case 5: LCD1602_Disp(8,1,V_VALUE/100+'0'); //在第2行的第9列顯示百位
break;
case 6: LCD1602_Disp(9,1,'.');
break;
case 7: LCD1602_Disp(10,1,(V_VALUE%100)/10+'0'); //在第2行的第10列顯示十位
break;
case 8: LCD1602_Disp(11,1,(V_VALUE%10)+'0'); //在第2行的第11列顯示?位
break;
case 9: LCD1602_Disp(12,1,'V');
break;
//*******************************
default: V_PRINT = -1;
}
V_PRINT++;
}

void main(void)
{
TRISA=0xFF;
TRISB=0xC7;
TRISC=0x00;
TRISD=0x00;
PORTA=0x00;
PORTB=0x00;
PORTC=0x00;
PORTD=0x00;
unsigned int x=0; //定義一个int型变量,做延时用
unsigned char y=14; //定義一个char型变量,查表索引用
LCD1602_init();
//OCP_DET=0;
OCP_ON=0;
ADCON1=0B01001110; //set right, AN0 enable.
ADIF=0;
ADIE=1; //允許A/D中斷
PEIE=1;
GIE=1;
ADCON0=0B11000001; //選擇AN0通道準備進行A/D轉換,啟動A/D模組
asm("NOP"); //略做延時
asm("NOP"); //略做延時
asm("NOP"); //略做延時
asm("NOP"); //略做延時
ADGO=1; //開始進行A/D轉換
while(1)
{
LED();
V_Display();
}
}

3月04日 13:51:08

OuO... 於 2017年03月04日 14:15:04
轉換PDF檔 列印


Re: 如何寫多通道AD做過電壓保護中斷程式
資深會員
註冊日期:
2009/04/07 13:30
所屬群組:
註冊會員
文章: 158
等級: 11; EXP: 62
HP : 0 / 265
MP : 52 / 6572
離線
通道選定的設定值看來是錯了, 改一下.

unsigned char ADC_CH=0;
unsigned char ADC_TIMES=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_TIMES > 0) ADC_SUM = ADC_SUM + ADRESH;
else ADC_SUM = 0;

ADC_TIMES++;
if(ADC_TIMES >= 5)
{ ADC_SUM >>= 2; // average (1/4)
switch(ADC_CH)
{ case 0: CH0_ADC = ADC_SUM;

if(CH0_ADC>102)
OCP_ON=1; //大於2伏特 輸出保護訊號
else
OCP_ON=0;

ADC_TIMES=0;
ADCON0=0B11001001; //選擇AN1通道準備進行A/D轉換,啟動A/D模組
ADC_CH=1;
break;
case 1: CH1_ADC = ADC_SUM;
ADC_TIMES=0;
ADCON0=0B11010001; //選擇AN2通道準備進行A/D轉換,啟動A/D模組
ADC_CH=2;
break;
case 2: CH2_ADC = ADC_SUM;
ADC_TIMES=0;
ADCON0=0B11000001; //選擇AN0通道準備進行A/D轉換,啟動A/D模組
ADC_CH=0;
break;
default: ADC_TIMES=0;
ADCON0=0B11000001; //選擇AN0通道準備進行A/D轉換,啟動A/D模組
ADC_CH=0;
}
ADCON1=0B01001110; //set right, AN0 enable.
}
ADIF=0;
ADGO=1; //開始進行A/D轉換
}
}

3月04日 15:38:18
轉換PDF檔 列印


Re: 如何寫多通道AD做過電壓保護中斷程式
初級會員
註冊日期:
1月05日 17:30:44
所屬群組:
註冊會員
文章: 35
等級: 4; EXP: 68
HP : 0 / 92
MP : 11 / 192
離線
真的很謝謝先進 解決了多通道和平均問題
但是這樣反應時間太慢 因為還沒開起保護 目標電器很可能已經燒燬
請問要如何加速讓過電壓的時候可以立即瞬間的開啟保護打出一個保護高位
還是說以這個晶片的速度沒辦法呢 那我司是否就要改用assembly(?)或者是換更快的型號?
Thanks,
Best Regards.

3月06日 10:43:18
轉換PDF檔 列印


Re: 如何寫多通道AD做過電壓保護中斷程式
初級會員
註冊日期:
1月05日 17:30:44
所屬群組:
註冊會員
文章: 35
等級: 4; EXP: 68
HP : 0 / 92
MP : 11 / 192
離線
根據您的程式 因為switch外的ADC_CH預設為0 且不變 所以一直處在0
導致進入switch永遠只會啟動case 0也就是AN0 其他通道都不會啟動
請問要怎麼改呢 直接把switch case去掉嗎

3月06日 12:36:28
轉換PDF檔 列印


Re: 如何寫多通道AD做過電壓保護中斷程式
資深會員
註冊日期:
2009/04/07 13:30
所屬群組:
註冊會員
文章: 158
等級: 11; EXP: 62
HP : 0 / 265
MP : 52 / 6572
離線
試試吧!
不然把你目前試的程式貼上來,
好讓大家可以幫忙看還有什麼問題.

char ADC_CH=0;
unsigned char CH0_count=0;
unsigned char CH1_count=0;
unsigned char CH2_count=0;
unsigned int CH0_SUM=0;
unsigned int CH1_SUM=0;
unsigned int CH2_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)
{
switch(ADC_CH)
{
case 0:
ADCON0=0B11001001; //選擇AN1通道準備進行A/D轉換,啟動A/D模組
ADCON1=0B00000000; //set right, all AN enable.

if(ADRESH>102)
OCP_ON=1; //大於2伏特 輸出保護訊號
else
OCP_ON=0;

CH0_SUM = CH0_SUM + ADRESH;
CH0_count++;
if(CH0_count >= 4)
{ CH0_ADC = (CH0_SUM >> 2);
CH0_count = 0;
CH0_SUM = 0;
}
break;
case 1:
ADCON0=0B11010001; //選擇AN2通道準備進行A/D轉換,啟動A/D模組
ADCON1=0B00000000; //set right, all AN enable.

CH1_SUM = CH1_SUM + ADRESH;
CH1_count++;
if(CH1_count >= 4)
{ CH1_ADC = (CH1_SUM >> 2);
CH1_count = 0;
CH1_SUM = 0;
}
break;
case 2:
ADCON0=0B11000001; //選擇AN0通道準備進行A/D轉換,啟動A/D模組
ADCON1=0B00000000; //set right, all AN enable.

CH2_SUM = CH2_SUM + ADRESH;
CH2_count++;
if(CH2_count >= 4)
{ CH2_ADC = (CH2_SUM >> 2);
CH2_count = 0;
CH2_SUM = 0;
}
ADC_CH=-1;
break;
default:
ADCON0=0B11000001; //選擇AN0通道準備進行A/D轉換,啟動A/D模組
ADCON1=0B00000000; //set right, all AN enable.
ADC_CH=-1;
}
ADC_CH++;
ADIF=0;
ADGO=1; //開始進行A/D轉換
}
}

3月06日 14:40:09
轉換PDF檔 列印


Re: 如何寫多通道AD做過電壓保護中斷程式
中級會員
註冊日期:
2014/05/28 13:30
所屬群組:
註冊會員
文章: 43
等級: 5; EXP: 35
HP : 0 / 108
MP : 14 / 1059
離線
我想樓主應該是想要做掃描通道的功能,
這顆並沒有自動掃描的功能,
要達到你要的結果就只能選擇一個通道-->轉換,
切換下一個通道-->轉換,
一直不斷的輪詢下去,

至於您程式可以修改的地方,
OuO前輩已有做修改,
大致上就是LCD盡量避免放在中斷執行,

另外再借個版面提個疑問,
在中斷服務函式中放ADGO=1;
那結果完成後不就又進中斷了嗎??
這也許也是樓主遇到一直卡在中斷的原因?

3月06日 16:04:58
轉換PDF檔 列印


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

以現在這個程式的狀況,
ADGO=1 放在中斷程序的最尾,
從這才啟動新的 ADC 轉換到 ADIF 再舉起,
相差了 ADC 進行轉換的時間,
pic16F887A 的 10 bits ADC 的話,
這段時間約為 11 個 Tad。

3月06日 17:32:20
轉換PDF檔 列印


Re: 如何寫多通道AD做過電壓保護中斷程式
初級會員
註冊日期:
1月05日 17:30:44
所屬群組:
註冊會員
文章: 35
等級: 4; EXP: 68
HP : 0 / 92
MP : 11 / 192
離線
目前照著OuO前輩的程式去修改並先去掉LCD監控
但上機測試發現AD轉換結果值ADRESH有共用的情形
沒辦法各一去分別動作
因為只接上任意一個AD通道去改變電壓值
其他通道卻會一起產生保護 代表這三個AD轉換結果值被重複占用了
所以不管在哪個case 這三個值互相同步了 變成這三值相等CH0_ADC=CH1_ADC=CH2_ADC
請問該如何改呢 p.s 我只使用左對齊的一個AD高位暫存器 所以是8bit
energy0364前輩 請問有哪顆8bit PIC有自動掃描的功能嗎?
當前程式如下:
#include <pic.h>
__CONFIG(HS&WRTEN&WDTDIS&BOREN&PWRTDIS&UNPROTECT&DUNPROT&DEBUGDIS&LVPDIS);
#define OCP0_ON RC0
#define OCP1_ON RC1
#define OCP2_ON RC2
const unsigned char TAB[9]=
{
0x08, //表格第1步數據0B00001000
0x10, //表格第2步數據0B00010000
0x20, //表格第3步數據0B00100000
0x40, //表格第4步數據0B01000000
0x80, //表格第5步數據0B10000000
0x40, //表格第6步數據0B01000000
0x20, //表格第7步數據0B00100000
0x10, //表格第8步數據0B00010000
0x08, //表格第9步數據0B00001000
};
unsigned int x=0;
unsigned char y=10;
void LED(void) //流水燈 做測試用
{
for(x=0;x<3000;x++);
if(++y>8) y=0;
PORTC=TAB[y];
}
char ADC_CH=0;
unsigned char CH0_count=0;
unsigned char CH1_count=0;
unsigned char CH2_count=0;
unsigned int CH0_SUM=0;
unsigned int CH1_SUM=0;
unsigned int CH2_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)
{
switch(ADC_CH)
{
case 0:
ADCON0=0B11001001; //選擇AN0通道準備進行A/D轉換,啟動A/D模組
ADCON1=0B00000000; //set right, all AN enable.
CH0_SUM = 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=0B11000001; //選擇AN1通道準備進行A/D轉換,啟動A/D模組
ADCON1=0B00000000; //set right, all AN enable.

CH1_SUM = 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=0B11001001; //選擇AN2通道準備進行A/D轉換,啟動A/D模組
ADCON1=0B00000000; //set left justified, all AN enable.

CH2_SUM = 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=0B11010001; //選擇AN2通道準備進行A/D轉換,啟動A/D模組
ADCON1=0B00000000; //set left justified, all AN enable.
ADC_CH=-1;
}
ADC_CH++;
ADIF=0;
ADGO=1; //開始進行A/D轉換
}
}
void main(void)
{
TRISA=0xFF;
TRISB=0xC7;
TRISC=0x00;
TRISD=0x00;
PORTA=0x00;
PORTB=0x00;
PORTC=0x00;
PORTD=0x00;
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=0B11000001; //選擇AN0通道準備進行A/D轉換,啟動A/D模組
asm("NOP"); //略做延時
asm("NOP"); //略做延時
asm("NOP"); //略做延時
asm("NOP"); //略做延時
ADGO=1; //開始進行A/D轉換
while(1)
{
LED();
}
}

Best Regards.

3月06日 18:12:52

ben.huang 於 2017年03月06日 18:42:50
轉換PDF檔 列印


Re: 如何寫多通道AD做過電壓保護中斷程式
資深會員
註冊日期:
2009/04/07 13:30
所屬群組:
註冊會員
文章: 158
等級: 11; EXP: 62
HP : 0 / 265
MP : 52 / 6572
離線
注意你的程式, 其中紅色的部分是否是你確實所要的值,
這個設定值指的是接著要轉換的 ADC 設定(通道選擇).
目前似乎是不太對的, 因為至少有兩處填入了相同的設定值.

另外, 對於比較的輸出情況請再說明一下,
是指一下子3個輸出全有,
還是指一個輸入在改變時, 依序 (低) (中) (高) 分別做輸出了.



char ADC_CH=0;
unsigned char CH0_count=0;
unsigned char CH1_count=0;
unsigned char CH2_count=0;
unsigned int CH0_SUM=0;
unsigned int CH1_SUM=0;
unsigned int CH2_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)
{
switch(ADC_CH)
{
case 0:
ADCON0=0B11001001; //選擇AN0通道準備進行A/D轉換,啟動A/D模組
ADCON1=0B00000000; //set right, all AN enable.
CH0_SUM = 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=0B11000001; //選擇AN1通道準備進行A/D轉換,啟動A/D模組
ADCON1=0B00000000; //set right, all AN enable.

CH1_SUM = 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=0B11001001; //選擇AN2通道準備進行A/D轉換,啟動A/D模組
ADCON1=0B00000000; //set left justified, all AN enable.

CH2_SUM = 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=0B11010001; //選擇AN2通道準備進行A/D轉換,啟動A/D模組
ADCON1=0B00000000; //set left justified, all AN enable.
ADC_CH=-1;
}
ADC_CH++;
ADIF=0;
ADGO=1; //開始進行A/D轉換
}
}

3月06日 19:05:58
轉換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