?? ad轉換.txt
字號:
我的第二個作品,AD轉換濾波后LED顯示
對3個通道交替進行AD轉換,然后把轉換后的結果存在一個18個*3數據窗口中,濾波時對窗口內的18個數據進行去極值取平均值濾波,然后送LED顯示.
CODE:
#include "config.h"
uint8 ucADC_select; // 四通道AD選擇
uint8 ucADC_count; // AD轉換計數
uint8 config=0x10,config_temp=0x10; // 功能選擇設定
uint8 ucADC_select; // 四通道AD選擇
uint8 ucADV_count; //轉換計數器
uint16 ADC0_DATA,ADC1_DATA,ADC2_DATA; //AD轉換結果
volatile uint16 ADC0_value[18]; // 0通道AD,18個數據
volatile uint16 ADC1_value[18]; // 1通道AD,18個數據
volatile uint16 ADC2_value[18]; // 2通道AD,18個數據
uint32 time2_count; // TIME2 中斷計數N,0.1S計數
/*雙字節無符號數去極值平均濾波法子程序
*/
uint16 arr[18]; // 18個數據臨時寄存器
uint16 average(uint16 arr[18])
{
uint8 i;
uint16 temp=0,max=0,min=0x3ff;
for(i=0;i<18;i++){
if(max<arr[i])
{max=arr[i];}
else if(min>arr[i])
{min=arr[i];}
temp+=arr[i];
}
temp=(temp-max-min)/16;
return (temp);
}
/********由定時器T2中斷啟動 連續轉換3個ADC通道的值 **********/
#pragma interrupt_handler adc_isr:15
void adc_isr(void)
{
//uint8 num1,num2; // 臨時寄存器
//uint16 uitemp1,uitemp2; // 臨時寄存器
uint16 uiadc_value_temp;
uiadc_value_temp = ADCL;
uiadc_value_temp |= (uint16)ADCH << 8;
// SEI();
switch(ucADC_select)
{
case 0 : // ADC0通道 數據處理
{
//ADMUX = 0xc1; // 切換到ADC1通道,內部Vref
ADMUX = 0x01; // 外部Vref,ADC1通道
ADC0_value[ucADC_count] = uiadc_value_temp; //
// ADCSRA |= (1<<ADSC); // enable adc
ucADC_select ++ ; // 切換到ADC1通道
break;
}
case 1 : // ADC1通道 數據處理
{
//ADMUX = 0xc2; // 切換到ADC2通道,內部Vref
ADMUX = 0x02; // 外部Vref,ADC2通道
ADC1_value[ucADC_count] = uiadc_value_temp; //
// ADCSRA |= (1<<ADSC); // enable adc
ucADC_select ++ ; // 切換到ADC2通道
break;
}
case 2 : // ADC2通道 數據處理
{
//ADMUX = 0xc0; // 切換到ADC0通道,內部Vref,但不啟動,等待定時器T2啟動
ADMUX = 0x00; // 外部Vref,ADC0通道
ADC2_value[ucADC_count] = uiadc_value_temp; //
ucADC_select = 0 ; // 切換到ADC0通道,但不啟動,等待定時器T2啟動
ucADC_count++;
// if(ucADC_count>=18)
// {ucADC_count = 0 ;}
break;
// else
// {ADCSRA |= (1<<ADSC);} // enable adc
// break;
}
default :
{
ADMUX = 0xc0; // 切換到ADC0通道,內部Vref,但不啟動,等待定時器T2啟動
//ADCSRA |= (1<<ADSC); // enable adc
ucADC_select = 0 ; // 切換到ADC0通道,但不啟動,等待定時器T2啟動
// ucADC_count = 0 ;
break;
}
} // switch end
} // AD中斷處理 end
/********由定時器T2中斷啟動 連續轉換3個ADC通道的值 ****** end */
// *********** ADC的設定及函數****************
//ADC initialize
// Conversion time: 128KHz(系統位8MHz,128分頻)
void adc_init(void)
{
ADCSRA= 0x00; //disable adc
ACSR = (1<<ACD); //disable comparator
//ADMUX = 0xc0; //內部Vref,ADC0通道
ADMUX = 0x00; //外部Vref,ADC0通道
//ADCSRA= (1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS0); // enable adc,中斷允許,32分頻|(1<<ADSC)
//ADCSRA= (1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1); //enable adc,64分頻
ADCSRA= (1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);//enable adc,128分頻
}
// *********** ADC的設定及函數**************end**
// ICC-AVR application builder : 2007-9-25
// Target : M16
// Crystal: 8Mhz
// 工程5led 七段數碼管顯示
#include "config.h"
extern const led_data[16]; //聲明外部led顯示數據,led_data在led.c中
extern uint16 uiADC_value_sum[4]; // 四通道AD,64個數據加和值extern
extern uint16 ADC0_value_sum[18]; // 0通道AD,18個數據
extern uint16 ADC1_value_sum[18]; // 1通道AD,18個數據
extern uint16 ADC2_value_sum[18]; // 2通道AD,18個數據
extern uint8 ucADC_select; // 四通道AD選擇
extern uint8 ucADC_count; // AD轉換計數
extern uint8 config,config_temp; // 功能選擇設定
extern uint8 display_control; // LCD顯示的定時控制字節
extern uint8 ucADC_select; // 四通道AD選擇
extern uint16 uiadc_value_temp;
extern uint32 uladc_data,uladc_data2,time2_count; // ADC的轉換數據,
extern uint16 ADC0_value[18]; // 0通道AD,18個數據
extern uint16 ADC1_value[18]; // 1通道AD,18個數據
extern uint16 ADC2_value[18]; // 2通道AD,18個數據
extern uint16 ADC0_DATA,ADC1_DATA,ADC2_DATA; // AD轉換結果
uint8 time2_cmp_i=54; // TIME2 比較中斷i=采樣率*AD通道數
extern uint16 countdata;
extern uint8 count;
extern uint8 dot;
//端口初始化
void port_init(void)
{
PORTA = 0x00;
DDRA = 0x00;
PORTB = 0x00;
DDRB = 0x00;
PORTC = 0x00; //m103 output only
DDRC = 0x00;
PORTD = 0x00;
DDRD = 0x00;
}
//TIMER2 initialize - prescale:1024
// WGM: CTC
// actual value: 1SEC采樣100次,0.01SEC中斷一次
void timer2_init(void)
{
TCCR2 = 0x00; //stop
ASSR = 0x00; //關閉異步方式
TCNT2 = 0x00; //setup
OCR2 = 0x25; //
TCCR2 = (1<<WGM21)|(1<<CS22)|(1<<CS21)|(1<<CS20); //內部時鐘1024分頻
TIMSK |= (1<<OCIE2); //timer2 中斷允許
}
//Watchdog initialize
// prescale: 2048K
void watchdog_init(void)
{
WDR(); //this prevents a timout on enabling
WDTCR = 0x1F; //WATCHDOG ENABLED - dont forget to issue WDRs
WDTCR = 0x0F; //WATCHDOG ENABLED - 看門狗定時器預分頻設為2048K,2.1S
WDR();
}
/******定時器T2中斷*****************************
*1、喂狗;2、啟動ADC;
*3、將ADC的加和值平均,計算電壓值
************************************************/
#pragma interrupt_handler timer2_comp_isr:8
void timer2_comp_isr(void) // TIME2做三通道ADC0、ADC1、ADC2的積分濾波 10Hz,18采樣率
{
WDR(); //喂狗
time2_cmp_i --;
count--;
if(count<1)
{count=4;}
if((time2_cmp_i % 0x03) == 0x00)
{ADC0_DATA=average(ADC0_value);
ADC1_DATA=average(ADC1_value);
ADC2_DATA=average(ADC2_value);
ADCSRA |= (1<<ADSC); // 啟動ADC,18次采樣率
}
if(time2_cmp_i == 0)
{time2_cmp_i = 54;}
// SEI();
// time2_count ++; // 0.1S計數
}
//******定時器T2中斷************************* end */
/*************************************************
主程序
*************************************************/
void main(void)
{
CLI(); //disable all interrupts
port_init();
led_init(); //5位7段數碼管顯示
timer2_init(); // 使能AD轉換
watchdog_init();
adc_init(); // 使能ADC
SEI(); //re-enable interrupts
while(1)
{
dot=4;
display(countdata,dot,count); //普通模式,顯示countdata的值,countdata將在timer1定時一秒溢出時改變
countdata=ADC0_DATA;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -