外部中断应用实例续——使用外部振荡源

1996天前 · AVR单片机 · 211次阅读

硬件设计

在外部中断应用实例中,采用调用CVAVR中软件延时函数的方法给出了一个使用6个数码管组成的时钟系统。采用软件延时,时钟是不准确的,因为一旦系统中使用了中断,就可能打断延时程序的执行,使得延时时间发生变化。下面给出以外部振荡源为基准,采用外部中断方式实现的时钟系统的设计。
在AVR-51多功能实验开发板上,有一个采用CD4060和2.048MHz晶体构成的50%占空比、0~5V的标准方波振荡源。将其10个标准频率中500Hz的输出端与ATmega16的PD3引脚连接,作为外部输入信号。如果INT1采用下降沿方式触发中断,那么500次中断就是1s。此时,外部500Hz的振荡源就是时钟系统的计时基准,这样的时钟系统比使用软件延时的方法要准确得多。
时钟系统显示部分的硬件电路与动态扫描数码管图里的一样,只需要使用一根连线,将板上标准方波振荡源的500Hz输出端与ATmega16的PD3引脚连接在一起即可。

软件设计

实现程序如下:

/******-
File name            :demo_7_2.c
Chip type            :ATmega16
Program type         :Application
Clock frequency      :4.000000MHz
Memory model         :Small
External SRAM size   :0
Data Stack size      :256
******/
#include<mega16.h>
flash unsigned char led_7[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
flash unsigned char position[6] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
unsigned char time[3];
unsigned char dis_buff[6];
int time_counter;
unsigned char posit;
bit point_on,time_1s_ok;
void display(void)
{
    PORTC = 0xff;
    PORTA = led_7[dis_buff[posit]];
    if (point_on && (posit==2 || posit==4)) PORTA |= 0x80;
    PORTC = position[posit];
    if (++ posit >= 6) posit = 0;
}

//外部中断INT1服务函数
interrupt [EXT_INT1] void ext_int1_isr(void)
{
    display();
    if (++time_counter >= 500)
    {
        time_counter = 0;
        time_1s_ok = 1;
    }
}

void time_to_disbuffer(void)//时钟时间送显示缓冲区函数
{
    unsigned char i,j = 0;
    for (i=0;i<=2;i++)
    {
        dis_buff[j++] = time[i] % 10;
        dis_buff[j++] = time[i] / 10;
    }
}

void main(void)
{
    PORTA = 0x00;//显示控制I/O端口初始化
    DDRA = 0xFF;
    PORTC = 0x3F;
    DDRC = 0x3F;
    time[2] = 23;time[1]=58;time[0]=55;
    posit = 0;
    time_to_disbuffer();
    GICR |= 0x80;                //INT1中断允许
    MCUCR = 0x80;                //INT1下降沿触发
    GIFR = 0x80;                //清INT1中断标志
    #asm("sei")                    //全局中断允许
    
    while(1)
    {
        if (time_1s_ok)//1s到
        {
            time_1s_ok = 0;
            point_on = ~point_on;
            if (++time[0] >= 60)//调整时间
            {
                time[0] = 0;
                if (++time[1] >= 60)
                {
                    time[1] = 0;
                    if (++time[2] >= 24) time[2] = 0;
                }
            }
            time_to_disbuffer();//新调整好的时间送显示缓冲区
        }
    }
}

思考与实践

//略 应该不会摘抄上来

👍 0

none

最后修改于1996天前

评论

贴吧 狗头 原神 小黄脸
收起

贴吧

狗头

原神

小黄脸

目录

avatar

未末

迷失

126

文章数

275

评论数

7

分类