qdvenus 发表于 2009-4-28 15:24:06

请教马老师:能用外部中断启动定时器?

#include "avr/io.h"
#include "avr/interrupt.h"
#include "compat/ina90.h"
#definemotor PD7
#definemotorh PORTD |=(1<<PD7)
#definemotorl PORTD &=~(1<<PD7)
volatile unsigned int pwm;
/**************************************************
写16 位寄存器时,应先写入该寄存器的高位字节。而读16 位寄存器时应先读取该寄存器的低位字节
使用“C” 语言时,编译器会自动处理16 位操作。
在对16 位寄存器操作时,最好首先屏蔽中断响应,防止在主程序读写16 位寄存器的两条指令之间发
生这样的中断:它也访问同样的寄存器或其他的16 位寄存器,从而更改了临时寄存器
*****************************************************/
/***************-------TCCR1A---------************************************
COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WGM11 WGM10

比较输出模式,非PWM
COM1A1/COM1B1 COM1A0/COM1B0    说明
   0                0      普通端口操作,非OC1A/OC1B 功能
   0                1      比较匹配时OC1A/OC1B 电平取反
   1                0      比较匹配时清零OC1A/OC1B( 输出低电平)
   1                1      比较匹配时置位 OC1A/OC1B ( 输出高电平)
-------------------------------------------------------------------
比较输出模式,快速 PWM(1)
COM1A1/COM1B1   COM1A0/COM1B0   说明
   0               0          普通端口操作,非OC1A/OC1B 功能
   0               1          WGM13:0 = 15: 比较匹配时OC1A 取反,OC1B 不占用物理引脚。WGM13:0 为其它值时为普通端口操作,非OC1A/OC1B 功能
   1               0          比较匹配时清零OC1A/OC1B, OC1A/OC1B在TOP 时置位
   1               1          比较匹配时置位 OC1A/OC1B, OC1A/OC1B在TOP 时清零
--------------------------------------------------------------------------------
比较输出模式,相位修正及相频修正 PWM 模式(1)
COM1A1/COM1B1   COM1A0/COM1B0       说明
   0             0          普通端口操作,非OC1A/OC1B 功能
   0             1          WGM13:0 = 9 或14: 比较匹配时OC1A 取反,OC1B 不占用物理引脚。 WGM13:0为其它值时为普通端口操作,非OC1A/OC1B 功能
   1             0          升序记数时比较匹配将清零OC1A/OC1B,降序记数时比较匹配将置位OC1A/OC1B
   1             1          升序记数时比较匹配将置位OC1A/OC1B,降序记数时比较匹配将清零OC1A/OC1B
--------------------------------------------------------------------------------
模式WGM13WGM12(CTC1)WGM11(PWM11)WGM10(PWM10) 定时器/ 计数器工作模式计数上限值TOPOCR1x更新时刻TOV1置位时刻
0      0      0            0               0          普通模式               0xFFFF      立即更新         MAX
1      0      0            0               1         8位相位修正PWM          0x00FF            TOP          BOTTOM
2      0      0            1               0         9位相位修正PWM          0x01FF            TOP          BOTTOM
3 0 0 1 1 10位相位修正PWM 0x03FF TOP BOTTOM
4 0 1 0 0 CTC OCR1A 立即更新MAX
5 0 1 0 1 8位快速PWM 0x00FF TOP TOP
6 0 1 1 0 9位快速PWM 0x01FF TOP TOP
7 0 1 1 1 10位快速PWM 0x03FF TOP TOP
8 1 0 0 0 相位与频率修正PWM ICR1 BOTTOM BOTTOM
9 1 0 0 1 相位与频率修正PWM OCR1A BOTTOM BOTTOM
10 1 0 1 0 相位修正PWM ICR1 TOP BOTTOM
11 1 0 1 1 相位修正PWM OCR1A TOP BOTTOM
12 1 1 0 0 CTC ICR1 立即更新MAX
13 1 1 0 1 保留– – –
14 1 1 1 0 快速PWM ICR1 TOP TOP
15 1 1 1 1 快速PWM OCR1A TOP TOP
快速PWM时,TC1工作在单程向上计数模式
相位可调PWM时,TC1工作在双程计数方式
相位频率可调PWM时,TC1工作在双程计数方式
***************************************************************************/
/***************   ADMUX****************************************
7   6   5   4   3   2    1    0
REFS1 REFS0 ADLAR MUX4 MUX3 MUX2 MUX1 MUX0
REFS1 REFS0 参考电压选择
0 0 AREF, 内部Vref 关闭
0 1 AVCC, AREF 引脚外加滤波电容
1 0 保留
1 1 2.56V 的片内基准电压源, AREF 引脚外加滤波电容
////////   ADCSRA      ///////////////////////////////
ADEN ADSC ADATE ADIF ADIE ADPS2 ADPS1 ADPS0
ADPS2 ADPS1 ADPS0 分频因子
0       0   0      2
0       0   1      2
0       1   0      4
0       1   1      8
1       0   0      16
1       0   1      32
1       1   0      64
1       1   1      128
**************************************************************************/
void init_timer1()
{
       TCCR1B = (1<<WGM13)|(1<<WGM12)|(0<<CS12)|(0<<CS11)|(0<<CS10);//8M系统时钟,启动时用8分频,计数时钟1M,每一个时钟1us
       TCCR1A = (1<<COM1A1)|(0<<COM1A0)|(1<<COM1B1)|(0<<COM1B0)|(1<<WGM11)|(0<<WGM10);//模式14,计数上限值ICR1=10000(10ms)
       ICR1 =10000-1;//10ms对应到50HZ市电的半周期
       TIMSK = (1<<OCIE1A)|(1<<OCIE1B)|(1<<TOIE1);
       TIFR= (1<<OCF1A)|(1<<TOV1);//清中断标致
}
void init_port()
{
    DDRA=0;//输入//采样外部电位器的电压,用于控制可控硅的导通角
    PORTA=0;
        DDRB=0xff;
        PORTB=0xff;
        DDRC=0xff;
        PORTC=0xff;
        DDRD= 0xf1; //必须设置INT0,INT1对应口为输入,PD0为控制输出
        PORTD=0xff;
}

void init_interrupt()
{
MCUCR = (1<<ISC01)|(0<<ISC00);//0x08;//INT0 的下降沿产生异步中断请求
GICR= (1<<INT0);//INT0使能
}
//ADEN ADSC ADATE ADIF ADIE ADPS2 ADPS1 ADPS0 ADCSRA
void init_adc()
{
        ADMUX = 0b01100000; // PA0 -> ADC0, ADLAR=1 (8bit)
    ACSR=(1<<ACD);
        ADCSRA |= (1<<ADEN)|(1<<ADSC)|(1<<ADATE)|(1<<ADIF)|(0<<ADIE)|(0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // Enable ADC,自动连续转换,8分频
}

void main()
{
    int tmp;
      cli();
          pwm=1;
          init_port();
          init_timer1();
          init_interrupt();
          init_adc();
//    set_sleep_mode(SLEEP_MODE_IDLE);
          sei();
      tmp=10000/256;//将10MS同比例分成256等份
      while (1)
        {
           (!(ADCSRA&(1<<ADIF)));
               ADCSRA|=(1<<ADIF); //清除中断请求标志
               pwm=ADCH*tmp;//置初值,也就是廷时开通时间,
             OCR1A=pwm;
        }
}

ISR(INT0_vect)//市电过零中断,大约10MS中断一次
{
    TCCR1B |= (1<<CS11);//8M系统时钟,8分频,计数时钟1M,每一个时钟1us
    TCNT1=0;
    motorl;//过零时不触发
}

ISR(TIMER1_OVF_vect)
{
    TCCR1B = (1<<WGM13)|(1<<WGM12)|(0<<CS12)|(0<<CS11)|(0<<CS10);//关闭定时器
    TCNT1=0;
    motorl;//溢出则关闭
    OCR1A=pwm;
}
ISR(TIMER1_COMPA_vect)
{
        motorh;   //延时时间到达后触发
}
请教马老师,我想用外部中断来启动定时器,在匹配和溢出后分别触发控制,实现无级变速,这样方式能实现吗?

qdvenus 发表于 2009-4-28 22:16:36

解决了
页: [1]
查看完整版本: 请教马老师:能用外部中断启动定时器?