圣龙扬特-AVR电子

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1284|回复: 5
打印 上一主题 下一主题

使用MEGA8异步晶振做定时器例程

[复制链接]

17

主题

2

好友

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

UID
1
帖子
54
精华
0
注册时间
2013-2-20
在线时间
72 小时
跳转到指定楼层
楼主
发表于 2013-2-27 21:50:43 |只看该作者 |倒序浏览
  转载请注明出自圣龙扬特-AVR电子网Http://www.avrbase.com
  MEGA8单片机的T/C2 是一个通用单通道8 位定时/ 计数器,其中一个重要特点是,允许使用外部的32.768 kHz 手表晶振作为独立的I/O 时钟源,接PB6、PB7。
  Bascom-AVR设置语句结构如下:
  Config Timer2 = Timer , Async = On/Off , Prescale = 1/8/32/64/64/128/256/1024
  Async参数是指是否采用异步晶振。
  当使用后勤工作步晶振时,要注意几点:
  1、芯片主时钟要设置为使用内部RC;
  2、主时钟必须比晶振高4 倍以上;
  3、CKOPT熔丝位使能(即设置为0)。
  第3条是否绝对笔者没有进一步验证,笔者在调试时,异步时针不工作,当把CKOPT设置为0后,工作正常。
  
  下面把笔者的倒记时器源程序奉上,供参考。程序中,Prescale分频设置为64,即每0.5秒产生一次T2中断。
  
'-------------------------------------------------------------------------------
'Name                     : Timer2.bas
'Copyright                : http://www.avrbase.com
'Micro                    : AtMega8

'Author                   : slyt/箫天
'-------------------------------------------------------------------------------
$regfile = "m8def.dat"
$crystal = 1000000
$hwstack = 40
$swstack = 40
$framesize = 64

'*******************************************************************************
Config Timer0 = Timer , Prescale = 64                       
On Timer0 Tim0_isr

Config Timer2 = Timer , Async = On , Prescale = 64
On Timer2 One_second

Config Clock = User

Config Int1 = Falling
On Int1 Button_down

'*******************************************************************************
Declare Sub Set_digital(byval Dat As Byte)
Declare Sub Play_music()
Declare Sub Power_off()

'*******************************************************************************
Dim Seconds As Long
Dim Set_seconds As Eram Long At 21
Dim Secd As Byte , Minutes As Byte , Hours As Byte
Dim Set_hours As Eram Byte At 11 , Set_minutes As Eram Byte At 12
Dim Segment As Word
Dim Seg_v As Byte
Dim Seg_index As Byte
Dim Seg_digital(4) As Byte
Dim Decrtime As Bit
Dim Key_down As Bit
Dim Key As Byte
Dim Key_time As Byte

'*******************************************************************************
'A-F
Ddrc = &HFF
'G
Ddrd.0 = 1

Key1 Alias Pind.1 : Ddrd.1 = 0 : Portd.1 = 1
Key2 Alias Pind.2 : Ddrd.2 = 0 : Portd.2 = 1
Key3 Alias Pind.4 : Ddrd.4 = 0 : Portd.4 = 1
Intk Alias Pind.3 : Ddrd.3 = 0 : Portd.3 = 1

V4 Alias Portd.6 : Ddrd.6 = 1
V3 Alias Portd.7 : Ddrd.7 = 1
V2 Alias Portb.0 : Ddrb.0 = 1
V1 Alias Portb.1 : Ddrb.1 = 1
Pp Alias Portb.2 : Ddrb.2 = 1

Spk Alias Portd.5 : Ddrd.5 = 0 : Spk = 0

Seg_v = &B00100010
Segment = &H4321
Key_down = 0

'*******************************************************************************
'initial original time
If Set_seconds = &HFFFFFFFF Then Set_seconds = 659          '10 minutes
Seconds = Set_seconds

'*******************************************************************************
Enable Int1
Enable Timer0
Enable Timer2
Enable Interrupts

'*******************************************************************************

Do
   Idle

   If Key_down = 1 Then
      Disable Int1
      Disable Timer2

      If Key_time > 20 Then                                'Waitms 20
         V1 = 1 : Pp = 0
         Key = Pind And &B11110                             'get key status
         Shift Key , Right , 1                             'shift right 1 bit

         Select Case Key
            Case &B1010                                     'Key1 down
               If Seconds < 43259 Then Seconds = Seconds + 60 'less than 12 hours , add one minute
            Case &B0011                                     'Key3 down
               If Seconds > 119 Then Seconds = Seconds - 60 'more than one minute
            Case &B1001                                     'key2 down
               Call Power_off                               'powerdown mode
            Case &B1111                                     'key up
               Key_down = 0
               Seconds = Seconds / 60
               Seconds = Seconds * 60
               Seconds = Seconds + 59
               Set_seconds = Seconds                        'write to EEPROM
               Enable Int1
               Enable Timer2
         End Select
         Key_time = 0
      End If
   End If

   If Seconds < 60 Then                                     'time out
      Disable Timer0
      Disable Timer2
      V1 = 1 : V2 = 1 : V3 = 1 : Pp = 1
      Set_digital &B111111
      Call Play_music
      Spk = 0
      Ddrd.5 = 0
      If Key_down = 1 Then                                  'any key press
         Key_down = 0
         If Key = &B1001 Then                               'key2 down
            Waitms 200
            Bitwait Intk , Set
            Call Power_off                                  'powerdown mode
            Else
            Waitms 200
         End If
         Else
            Waitms 100
            Call Power_off                                  'powerdown mode
      End If
      Seconds = Set_seconds                                 'read seconds form eeprom
      Enable Timer0
      Enable Timer2
   End If

   'Three Bytes for Seconds, Minutes and Hour must follow each other in SRAM.
   'The variable-name of the first Byte, that one for Second must be passed to the function.
   Secd = Time(seconds)
   Seg_digital(1) = Minutes Mod 10
   Seg_digital(2) = Minutes / 10
   Seg_digital(3) = Hours Mod 10
   Seg_digital(4) = Hours / 10

   Seg_index = Segment And &B1111

   V1 = 0
   V2 = 0
   V3 = 0
   V4 = 0
   If Seg_digital(3) = 0 Then Seg_digital(3) = 10
   If Seg_digital(4) = 0 Then Seg_digital(4) = 10
   Seg_digital(seg_index) = Lookup(seg_digital(seg_index) , Digital)
   Set_digital Seg_digital(seg_index)
   V1 = Seg_v.1
   V2 = Seg_v.2
   V3 = Seg_v.3
   V4 = Seg_v.4

Loop

'*******************************************************************************
Sub Set_digital(dat As Byte)
   Portc = Dat
   Portd.0 = Dat.6
End Sub

'*******************************************************************************
Sub Power_off()
   V1 = 0 : Pp = 0 : Spk = 0
   V2 = 0 : V3 = 0 : V4 = 0
   Set_digital &H00
   Do : Loop Until Key2 = 1
   Waitms 50
   Do : Loop Until Key2 = 1
   Config Int1 = Low Level
   Enable Int1
   Powerdown
   Waitms 200
   Do : Loop Until Intk = 1
   Config Int1 = Falling
   Enable Timer2
End Sub

'*******************************************************************************
Sub Play_music()
   Local I As Byte , J As Byte
   Local Dp As Single
   Local Duration As Word , Pulses As Word
   Ddrd.5 = 1
   For I = 1 To 10
      Restore Musicdata
      For J = 1 To 32
         Read Duration
         Read Pulses
         Sound Spk , Duration , Pulses
         If Key_down = 1 Then Exit Sub
      Next
      Waitms 500
   Next
End Sub

'*******************************************************************************
'5 ms
Tim0_isr:
   Timer0 = 180
   Rotate Seg_v , Left                                      '<- 00100010 <-
   Rotate Segment , Right , 4                               '-> 4321 ->
   Incr Key_time
Return

'*******************************************************************************
'get here every second with a 32768 Hz xtal
One_second:
   Toggle Pp
   Toggle Decrtime
   Seconds = Seconds - Decrtime
Return

'*******************************************************************************
Button_down:
   Key = Pind And &B11110                                   'get key status
   Shift Key , Right , 1                                   'shift right 1 bit
   Key_down = 1
   Key_time = 15
Return

'*******************************************************************************
Digital:
Data &H40 , &H79 , &H24 , &H30 , &H19 , &H12 , &H02 , &H78 , &H00 , &H10 , &HFF

'*******************************************************************************
'two tigers music
Musicdata:
Data 600% , 48% , 600% , 43% , 600% , 38% , 600% , 48%
Data 600% , 48% , 600% , 43% , 600% , 38% , 600% , 48%
Data 600% , 38% , 600% , 36% , 1200% , 32%
Data 600% , 38% , 600% , 36% , 1200% , 32%
Data 300% , 32% , 300% , 28% , 300% , 32% , 300% , 36%
Data 600% , 38% , 600% , 48%
Data 300% , 32% , 300% , 28% , 300% , 32% , 300% , 36%
Data 600% , 38% , 600% , 48%
Data 600% , 43% , 600% , 64% , 1200% , 48%
Data 600% , 43% , 600% , 64% , 1200% , 48%


回复

使用道具 举报

0

主题

1

好友

3101

积分

超级版主

Rank: 8Rank: 8

UID
31
帖子
36
精华
0
注册时间
2013-2-27
在线时间
5 小时
沙发
发表于 2013-2-28 14:16:10 |只看该作者
表四鄙人纯属随机路过。。。顺带帮顶。。。
回复

使用道具 举报

0

主题

0

好友

143

积分

初级会员

Rank: 2

UID
372
帖子
9
精华
0
注册时间
2013-4-26
在线时间
14 小时
板凳
发表于 2013-4-27 23:55:23 |只看该作者
没有这么复杂 用Config Clock = Soft 语句,程序自动计算年月日和时分秒
回复

使用道具 举报

67

主题

4

好友

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

UID
2
帖子
343
精华
0
注册时间
2013-2-20
在线时间
366 小时
地板
发表于 2014-3-15 18:49:39 |只看该作者
zzzd 发表于 2013-4-27 23:55
没有这么复杂 用Config Clock = Soft 语句,程序自动计算年月日和时分秒

与你说的是两码事。
这是主频与异频分开用的功能。
回复

使用道具 举报

0

主题

0

好友

143

积分

初级会员

Rank: 2

UID
372
帖子
9
精华
0
注册时间
2013-4-26
在线时间
14 小时
5#
发表于 2014-3-17 17:58:22 |只看该作者
本帖最后由 zzzd 于 2014-3-17 18:01 编辑


其实有更简单的方法
AVR单片机的定时器2 具有异步操作功能,也就是外接一个32.768KHz的晶振构成一个独立于系统时钟的时钟源
本实验硬件非常简单,只要在端口PORTB.6和PORTB.7(接外晶振的管脚)接一个32.768KHz的晶振即可。系统时钟选内部RC振荡器。通过串口将单片机与PC机连接,在模拟中端上显示时间。
需说明一点,BASCOM 的这套语句并不支持48芯片,可能是因为其内存太小。实验中使用的是Atmega8芯片。

程序代码
'----------------利用AVR单片机定时器2的异步操作实现时钟BASIC 程序 --------------  
$regfile = "m8def.dat"
$crystal = 8000000
$baud = 19200
Enable Interrupts
'
'
Config Date = Ymd , Separator = -
Config Clock = Soft
'以上语句定义了中断服务程序,所以你不能再使用TIMER2!
' 系统将自动定义时间变量:Date$和Time$
Date$ = "09-04-08"
Time$ = "23:59:50"
Do
Wait 1
Print Date$ ; Spc(2) ; Time$ ;Spc(2) ; _year ; "年" ; _month ; "月" ; _day ; "日" ; _hour ; "时" ; _min ; "分" ; _sec ; "秒"
Loop
''
' 日期格式:YY-MM-DD
' 时间格式:hh:mm:ss
'
'
' 输出显示时间(本语句为一行)
'
'  


程序讲解
CONFIG CLOCK语句
CONFIG CLOCK = SOFT | USER [, GOSUB = SECTIC]
这条语句告诉编译系统自动配置用于异步操作的定时器,并定义系统变量Date$和Time$。自动生成的中断服务程序负责更新这两个变量。所以程序员只需调用这两个变量即可。对其赋值就是将其初始化(写),将其放在等号右侧即为取值(读)。
•SOFT:定义使用定时器的异步功能,至于是哪一个系统会根据注册文件($regfile)自动判断。系统自动生成一个每秒中断一次的中断服务程序。

•USER:如果使用I2C类的专用时钟芯片,则要程序员自己编写读写程序。

•GOSUB = SECTIC:该语句给程序员一个编写自己的中断服务程序的机会,以便完成特定任务。该中断服务程序必须以SECTIC为入口标志。该选项只配和SOFT选项使用,使用这一功能将占用30个字节的硬件资源。

使用这个语句,编译器将自动定义如下系统变量:_sec , _min , _hour, _day , _month , _year,同时还有TIME$ 和 DATE$。
CONFIG DATE语句
CONFIG DATE = DMY , Separator = char

•DMY:年、月、日的顺序,可以是DMY, MDY 或 YMD

•char:定义分隔符:/、-、。(点)

DATE$语句

存放日期的内部变量
语法:

•DATE$ = "mm/dd/yy"
按CONFIG DATE语句给定的格式赋值,即初始化。该语句也将同时影响 _day ,_month , _year这三个变量。

•var = DATE$
读出DATE$变量中的值。

TIME$语句

存放时间的内部变量
语法:

•TIME$ = "hh:mm:ss"
赋值,即初始化。该语句也将同时影响 _Sec,_Min , _Hour 这三个变量。

•var = TIME$
读出TIME$变量中的值。



回复

使用道具 举报

67

主题

4

好友

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

UID
2
帖子
343
精华
0
注册时间
2013-2-20
在线时间
366 小时
6#
发表于 2014-3-18 09:47:55 |只看该作者
zzzd 发表于 2014-3-17 17:58
其实有更简单的方法
AVR单片机的定时器2 具有异步操作功能,也就是外接一个32.768KHz的晶振构成一个独立于 ...

嗯,你说的是其中一种使用方法,在以前做的东西中用过,但失去了自由使用的TIMER2中断,无法使用中断服务,在时间的使用上也要不断查询,在实际运用的系统中,中断服务使用更为广泛。如果做RTC用,还是选用专用芯片更合适,而且更愿选用带有输出中断引脚的RTC芯片。
我提供的这个程序只是个应用例子,用soft clock也可以很容易实现此功能。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

Archiver|手机版|圣龙扬特-AVR电子 ( 鲁ICP备05022832号 )

GMT+8, 2024-4-25 17:59 , Processed in 0.248110 second(s), 20 queries .

Powered by Discuz! X2.5

© 2001-2012 Comsenz Inc.

回顶部