求助高手解疑~~
我现在用mega16 做AD 转换,设置 AD自动转换模式,由定时器0比较匹配溢出中断来触发AD转换,现在的问题是程序编译好后,在AVRSTUDIO的环境里软件仿真,可以进入定时器中断服务函数,但是不能自动触发AD转换,必须在服务函数里再次开启AD转换才可以。请教高人,难道AD的自动转换模式我理解有误么? 可是这样的话,如果直接用定时器溢出去开启AD转换不就是间接地自动转换么?那么自动转化的意义何在?
可能我描述的不太清楚。。但是真的真的 想请教高手解答,AD与定时器的自动触发到底是怎么实现的? 谢谢~~不生感激。。
附上我的程序~
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#define uint8 unsigned char
#define uint16 unsigned int
//数字滤波
#define a 0xF4 // a=0.95
#define b 0x0D // b=1-a=0.05
//多路转换
volatile uint8 ADC_Value[]={0x00};
//通道选择
const uint8 ADChannel[32] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E, 0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F};
/******************************常量定义********************************
单端通道,不放大
0x00 ADC0
0x01 ADC1
0x02 ADC2
0x03 ADC3
0x04 ADC4
0x05 ADC5
0x06 ADC6
0x07 ADC7
差分通道ADC0作负端,10/200倍放大
0x08 ADC0+ ADC0-, 10倍放大,校准用
0x09 ADC1+ ADC0-, 10倍放大
0x0A ADC0+ ADC0-,200倍放大,校准用
0x0B ADC1+ ADC0-,200倍放大
差分通道ADC2作负端,10/200倍放大
0x0C ADC2+ ADC2-, 10倍放大,校准用
0x0D ADC3+ ADC2-, 10倍放大
0x0E ADC2+ ADC2-,200倍放大,校准用
0x0F ADC3+ ADC2-,200倍放大
差分通道ADC1作负端,不放大
0x10 ADC0+ ADC1-
0x11 ADC1+ ADC1-,校准用
0x12 ADC2+ ADC1-
0x13 ADC3+ ADC1-
0x14 ADC4+ ADC1-
0x15 ADC5+ ADC1-
0x16 ADC6+ ADC1-
0x17 ADC7+ ADC1-
差分通道ADC2作负端,不放大
0x18 ADC0+ ADC2-
0x19 ADC1+ ADC2-
0x1A ADC2+ ADC2-,校准用
0x1B ADC3+ ADC2-
0x1C ADC4+ ADC2-
0x1D ADC5+ ADC2-
单端通道,不放大
0x1E VBG 内部能隙1.22V电压基准,校准用
0x1F 接地 校准用
*********************************************************************/
const uint8 ADEnStatus[4] = {0xFE,0xFC,0xF8,0xF0};//设置使用AD转换占用的IO的通道
/*
0xFE 使用 AD0 AdDoor=0
0xFC 使用 AD0 AD1 AdDoor=1
0xF8 使用 AD0 AD1 AD2 AdDoor=2
0xF0 使用 AD0 AD1 AD2 AD3 AdDoor=3
*/
uint8 AdDoor; //AD转换IO通道选择
extern volatile uint8 Key; //用来设置AD转换通道
volatile uint8 AdChoose; //AD端口选择
uint16 AdcVal; //ADC转换值
uint16 AdcValConvert; //经过数字滤波之后的转换值
/*--------------------------------------------------------------------
程序名称:定时器0中断服务程序
程序功能:
注意事项:
提示说明:
输入:
返回:(14.7456Mhz/1024)=35.556ms
--------------------------------------------------------------------*/
ISR(TIMER0_COMP_vect)
{
OCR0 = 0x91; //重载计数数值
ADCSRA |= (1<<ADSC);//ADSC: AD start conversion
}
/*--------------------------------------------------------------------
程序名称:AD转换中断服务程序
程序功能:
注意事项:
提示说明:
输入:
返回:
--------------------------------------------------------------------*/
ISR(ADC_vect) //进入本中断,则软件自动屏蔽其他中断
{
volatile uint8 Key=AdDoor+1;
ADCSRA |= (1<<ADIF);//ADIF置1清位
//信号采集
AdcVal = ADCH&0xFF;
//数字滤波
AdcValConvert=(uint8)((uint16)a*AdcValConvert + (uint16)b*AdcVal);
ADC_Value[AdChoose]=AdcValConvert;
//这是多路采集的程序
AdChoose++;
if(AdChoose==Key) AdChoose=0;
ADMUX = (1<<REFS0)|(1<<ADLAR)|(ADChannel[AdChoose]);//使用 AVcc +5v 作为ADC参考电源
}
/*--------------------------------------------------------------------
程序名称:AD转换初始化程序
程序功能:
注意事项:
提示说明:
输入:
返回:
--------------------------------------------------------------------*/
void ADC_init()
{
/* 设置对应的IO口为输入高阻态 */
DDRA &= ADEnStatus[AdDoor];
PORTA &= ADEnStatus[AdDoor];
ADCSRA = 0x00;//disable ADC
ADMUX = (1<<REFS0)|(1<<ADLAR)|(0x00);//初始化时默认单通道,不放大,开启ADC0
/*
ADMUX (ADC Multiplexer Select Register)
bit7 bit6
REFS1 REFS0 参考电压选择
0 0 AREF,内部Vref关闭
0 1 AVCC,AREF引脚外加滤波电容
1 0 保留
1 1 2.56V的片内基准电压源,AREF引脚外加滤波电容
bit5 ADC结果左对齐选择 1=左对齐 0=右对齐
bit4~0 选择AD通道
*/
ACSR = (1<<ACD);//close analog comparator 关闭模拟比较器
ADCSRA=(1<<ADEN)|(1<<ADATE)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
/*
ADCSRA (ADC Control and Status Register A)
bit7 ADEN ADC使能=1
bit6 ADSC 启动ADC开始转换=1
bit5 ADATE 自己触发使能
bit4 ADIF ADC中断标志
bit3 ADIE ADC中断使能
bit2~0 ADPS0~2 ADC 预分频选择位 111=128时钟分频
*/
SFIOR=(1<<ADTS1)|(1<<ADTS0);
/*
SFIOR (Special Function IO Register) 自动触发源选择
bit7 bit6 bit5
ADTS2 ADTS1 ADTS0
0 0 0 连续转化模式
0 0 1 模拟比较器
0 1 0 外部中断请求0
0 1 1 定时器/计数器0比较匹配
1 0 0 定时器/计数器0溢出
1 0 1 定时器/计数器比较匹配B
1 1 0 定时器/计数器1溢出
1 1 1 定时器/计数器1捕捉事件
*/
}
/*--------------------------------------------------------------------
程序名称:void Sys_Init(void)
程序功能:系统初始化函数
注意事项:
提示说明:
输入:
返回:
--------------------------------------------------------------------*/
void Sys_Init(void)
{
cli(); //关总中断
PORTA = 0;
DDRA = 0x00; //设置PA
PORTB = 0;
DDRB = 0x00; //设置PB
PORTC = 0;
DDRC = 0; //设置PC
PORTD = 0;
DDRD = 0x00; //设置PD
MCUCR = 0x00; //全局MCU控制寄存器 电源管理项
GICR = 0x00; //全局向量配置寄存器 boot 选项
TCCR0 = (1<<WGM01)|(1<<CS02)|(1<<CS00);//start timer 1024分频 CTC比较输出
/*
*/
TCNT0= 0x01;
OCR0 = 0x91;
TIMSK = (1<<OCIE0); //开定时器T1比较匹配中断
}
/*--------------------------------------------------------------------
程序名称:main()主函数
程序功能:
注意事项:
提示说明:
输入:
返回:
--------------------------------------------------------------------*/
int main(void)
{
AdDoor = 1; //使用AD0 AD1,开放其对应的IO口
Sys_Init();
ADC_init();
sei(); //开放全局中断
while(1)
{
}
} |
|