volatile unsigned char ADC_OK; //ADC状态,会在中断服务程序中被修改,须加volatile限定
unsigned int LED_Volt; //变换后的电压mV
int LED_Curr; //变换后的电流100uA
//仿真时在watch窗口,监控这些全局变量。
unsigned int read_adc(unsigned char adc_input)//查询方式读取ADC单端通道
{
ADMUX=(0xc0|adc_input); //adc_input:单端通道 0x00~0x07,0x1E,0x1F
//0xc0:选择内部2.56V参考电压
ADCSRA|=(1<<ADSC); //启动AD转换
loop_until_bit_is_set(ADCSRA,ADIF); //方法1 等待AD转换结束
// while ((ADCSRA&(1<<ADIF))==0); //写法2 这种写法优化不好
// loop_until_bit_is_clear(ADCSRA,ADSC); //方法2 检测ADSC=0也行
ADCSRA|=(1<<ADIF); //写1清除标志位
return ADC; //ADC=ADCH:ADCL
}
int read_adc_diff(unsigned char adc_input)//查询方式读取ADC差分通道
{
unsigned int ADC_FIX;
ADMUX=(0xc0|adc_input); //adc_input:差分通道 0x08~0x1D
_delay_ms(1); //等待差分增益稳定>125uS
ADCSRA|=(1<<ADSC);
loop_until_bit_is_set(ADCSRA,ADIF);
ADCSRA|=(1<<ADIF);
//当切换到差分增益通道,由于自动偏移抵消电路需要沉积时间,第一次转换结果准确率很低。用户最好舍弃第一次转换结果。
ADCSRA|=(1<<ADSC);
loop_until_bit_is_set(ADCSRA,ADIF);
ADCSRA|=(1<<ADIF);
ADC_FIX=ADC;
//输出结果用2的补码形式表示
//可正可负 +/-9bit -512~+511
//即M16差分通道的ADC+输入端的电压可以大于ADC-,也可以小于ADC-。
//Tiny26就不行,ADC+输入端的电压必须大于或等于ADC-,为+10bit
if (ADC_FIX>=0x0200) //负数要变换,正数不用
{
ADC_FIX|=0xFC00; //变换成16位无符号整数
}
return (int)ADC_FIX;
}
SIGNAL(SIG_ADC) //ADC中断服务程序
{
//硬件自动清除ADIF标志位
ADC_INT_SE=ADC; //读取结果
ADC_OK=1;
}
int main(void)
{
long teMP32;
ADC_SingleEnded =0;
ADC_Diff=0;
ADC_INT_SE=0;
//上电默认DDRx=0x00,PORTx=0x00 输入,无上拉电阻
PORTB=0xFF; //不用的管脚使能内部上拉电阻。
PORTC=0xFF;
PORTD=0xFF;
PORTA=~((1<<in_Single)|(1<<in_Diff_P)|(1<<in_Diff_N));
//作ADC输入时,不可使能内部上拉电阻。
ADCSRA=(1<<ADEN)|0x06; //使能ADC,时钟64分频 125KHz@8MHz system cLOCk
sei(); //使能全局中断
while (1)
{
//实测的Vref引脚电压 =2556mV
ADC_SingleEnded=read_adc(AD_SE_ADC0);
//查询方式读取ADC0
temp32=(long)ADC_SingleEnded*Vref;
LED_Volt=(unsigned int)(temp32/1024);
ADC_Diff =read_adc_diff(AD_Diff3_2_10x);
ADC_Diff-=read_adc_diff(AD_Diff2_2_10x);//校准OFFSET
temp32=(long)ADC_Diff*Vref;
LED_Curr=(unsigned int)(temp32/(512*10)); //[单位为100uA]
//查询方式读取ADC3+,ADC2- 10倍放大 max +/-255.6mV
//10欧姆 1mA=10mV max +/-25.56mA
//分辨率约0.5mV=50uA,显示取整为100uA单位
ADCSRA|=(1<<ADIE); //使能ADC中断
ADMUX=0xC0|AD_SE_ADC0; //单端输入ADC0
ADC_OK=0; //软件标志清零
ADCSRA|=(1<<ADSC); //启动AD转换
while(ADC_OK==0); //等待ADC完成,实际程序中可以运行其它任务
ADCSRA&=~(1<<ADIE); //禁止ADC中断
//查询方式和中断方式要注意 ADIF标志位的处理。
}
}
上一页 [1] [2]
本文关键字:程序 AVR单片机,单片机-工控设备 - AVR单片机