Mixed programming of basic language and assembly language --- electronic watch

Publisher:科技创新实践者Latest update time:2020-09-17 Source: 51hei Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

This is a program from a foreign website, which is programmed in a mixed language of basic and assembly language on the bascom avr platform. I downloaded it and made some modifications to it:
I removed the lcd16x4 and used the popular oled screen emulation instead.
I added Chinese setting prompts.
Note: The source program is written using Bascom-Avr-1.11.9.1. In the new version of Bascom-Avr, you need to add "!" before the assembly instructions in the non-assembly block.



$regfile = "m8def.dat"
$framesize = 32
$swstack = 32
$hwstack = 32
$crystal = 8000000

Config Portb.1 = Output 'A pin is configured as LED output

'******** LCD ******************************************************
''Set the pins of the LCD module according to your own connection if necessary
' Config Lcdpin = Pin , Db4 = Portc.2 , Db5 = Portc.3 , Db6 = Portc.4 , Db7 = Portc.5 , E = Portc.1 , Rs = Portc.0
'Config Lcdmode = Port
'Config Lcdbus = 4 '4 bit mode
' Config Lcd = 20 * 4
' Initlcd
'Cursor Off
Config Scl = Portc.5 ' Use I2C pins Scl = Portc.5, Sda = Portc.4
Config Sda = Portc.4
Config Twi = 400000 ' I2c speed

I2cinit
$lib "i2c_twi.lbx" ' Do not use software to simulate I2c, but use twi
$lib "glcdSSD1306-I2C.lib" ' Replace the default library with the glcdSSD1306-I2C library to be added to the bascom avr library

#if _build < 20784
Dim ___lcdrow As Byte , ___lcdcol As Byte ' Compile with the old version variable format
#endif

Config Graphlcd = Custom , Cols = 128 , Rows = 64 , Lcdname = "SSD1306" 'Configure the graphics display


'********* ISR Timer 2 ******************************************************
Config Clock = User 'Configure the timer for the Time$ and Date$ variables.

' You can debounce at 128Hz (max delay 4/128 = 0.031s)
Config Timer2 = Timer , Async = On , Prescale = 1 ' Prescaler 8->16Hz or 1->128Hz
On Ovf2 _isr_t2ovf Nosave
Enable Ovf2

Enable Interrupts

Config Date = ymd , Separator = - ' Configure date format Europe: dmy USA: mdy Asia: ymd
_sec = 00 : _min = 15 : _hour = 14 : _day = 21 : _month = 08 : _year = 20

Dim Flagrtc_changed As Bit
Dim Tick_128hz As Byte

'******** Enter Key and Debounce************************************************
' Assign buttons to pins - they must all be connected to the same port!
Const Key_plus = &B0000_1000 '1 = button inputConst
Key_minus = &B0001_0000
Const Key_enter = &B0010_0000

Const Pinb_mask = Key_plus + Key_minus + Key_enter 'Mask to filter inputConst
Pinb_mask_compl = &HFF - Pinb_mask 'Pinb_mask compliment

'This is a button on PortB
Ddrb = Ddrb And Pinb_mask_compl 'DDRB:0=INPUT 1=OUTPUT
Portb = Portb Or Pinb_mask '1 = Activate internal pull-up resistor for input
Key_port Alias ​​Pinb

Dim Key_state As Byte '0/1 Inverted state of the button (1 = pressed)
Dim Key_press As Byte 'Trigger key press
Dim Key_rep As Byte 'Auto repeat counter
Dim Key_ct0 As Byte , Key_ct1 As Byte '2 bit counter for debounce

Const Key_repeat_start = 127 'Number -1 of timer ISR until auto repeat starts (approx. 500-1000ms)
Const Key_repeat_next = 15 'Number -1 of timer ISR for auto repeat repeat rate (approx. 125ms)

'Debounce initial value
Key_ct0 = 255 'Intercept routine to start from key press
Key_ct1 = 255
'Key_rep = Key_repeat_start 'Paranoia

'************ General *****************************************************
Dim I As Byte , J As Byte , K As Byte , L As Byte
Dim q As Byte
Dim Setdatetime_index As Byte
Setdatetime_index = 2 'The first index of the date array is 1, 2 = _min

Dim Date_array(6) As Byte At _sec Overlay 'The array of seconds/minutes/hours/days/months/years specifies the overlay variable in memory.

'********* Main loop***************************************************
Do

' Home 'Cursor origin
' Lcd Date$ ; " " ; Time$ 'Display date and time
' Locate 2 , 1
' Lcd "Set: " ; Lookupstr(setdatetime_index , Data_dateset) 'var = LOOKUPSTR (index, label) returns a string from the table
Setfont font8x8
Lcdat 2, 16 , Date$
Setfont font12x16
Lcdat 4, 16 ,Time$
Setfont font8x8
'Lcdat 7, 16 , "Set: " ; Lookupstr(setdatetime_index , Data_dateset) 'LOOKUPSTR (index, label) returns a string from the table
'In order to save power, a 128Hz loop was written in ASM:
Setfont font12x16
q=Lookup(setdatetime_index , Data_set)
Lcdat 7, 16 ,chr(134);chr(135); ": " ; chr(q)

   Flagrtc_changed = 0
   Enable Interrupts 'Paranoia
   'Do power save cycle until ((Flagrtc_changed = 1) or (Key_press > 0))

Main_1:

Config Powermode = Powersave 'Configure power mode = power save mode If Timer/Counter 2 is enabled, it will keep running during sleep
                                                                    'Power save mode only applies to 8535, Mega8, Mega163.
! lds r16,{Key_press} 'Did the button get pressed?
  ! TST r16
  ! BRNE main_2
  ! lds r16,{flagRTC_Changed} 'Another second?
! sbrS r16,bit.flagRTC_Changed
! RJMP Main_1

Main_2:

If Key_press > 0 Then Gosub Setdatetime_input

Loop


'---------------------------------------------------------------
'Subroutine: Setdatetime_input Set datetime input

'Call from: main

'Purpose: Set date and clock

'Parameters: Key input
'---------------------------------------------------------------
Setdatetime_input:

Disable Interrupts                                         '禁用中断
    I = Key_press                                           '读取键
    Key_press = 0

    L = Lookup(setdatetime_index , Date_max)
    If Setdatetime_index = 4 Then
       L = Lookup(_month , Date_month)
       K = _year And 3
       If _month = 2 Then If K = 0 Then Incr L
    End If
    K = Lookup(setdatetime_index , Date_min)

    J = Date_array(setdatetime_index)
    If I = Key_plus Then
        If J < L Then Incr J Else J = K
    End If
    If I = Key_minus Then
        If J > K Then Decr J Else J = L
    End If
    Date_array(setdatetime_index) = J

Enable Interrupts                                          '启用中断

    If I = Key_enter Then
        If Setdatetime_index < 6 Then Incr Setdatetime_index Else Setdatetime_index = 1
    End If

Return


'********ISR计时器2***************************************************

'---------------------------------------------------------------

'子程序:'u isr_t2ovf

'呼叫来源:定时器2(128Hz)

'目的:RTC,去抖动

'结果:RTC:_秒、_min、u小时、u天、u月、u年
'          '反跳:请参见下文
'---------------------------------------------------------------
$external _soft_clock
Const _sectic = 0                                          'CONFIG CLOCK = USER,GOSUB <> SECTIC的编译器语句

_isr_t2ovf:
$asm
        push    r16
        in      r16,sreg
        push    r16                                        ' 将R16和SREG保存在堆栈中

' 防抖键
        push    r17                                         '现在保存所有使用的寄存器
        push    r18
        PUSH    r19
       Call Debounce_port
        POP     r19                                        '恢复寄存器
        pop     r18
        pop     r17

        lds     r16,{tick_128hz}                            '每1/128秒增加一次tick_128
        inc     r16
        sts     {tick_128hz},r16
        andi    r16,128-1                                   '如果_tick128不是128的倍数
        brne    _T2OVF_END                                  '   set_digit退出isr,否则已过去一秒钟

'  该位变量将每隔一秒钟设置一次
        lds     r16,{flagRTC_Changed}                       '位变量
        sbr     r16,2^bit.flagRTC_Changed
        sts     {flagRTC_Changed},r16                       '注意标志是重置标志的主要代码责任

'  转至内部Bascom ISR例行程序:软时钟
        pop r16 'Get contents of SREG
        !out sreg,r16 'Restore sreg
        pop r16
        JMP _SOFT_CLOCK 'Original RETI

_t2ovf_end:
        pop r16 'Get contents of SREG
        !out sreg,r16 'Restore SREG
        pop r16

$end Asm
Return 'Leave isr with RETI

'********Debounce******************************************************
'------------------------------------------------- --------------
'Subroutine: Debounce_port
''Detects up to 8 keys simultaneously, with debounce and auto-repeat capabilities
'Each key is scanned 3 times to change state
'Registers used: R16, R17, R18, R19
'Variables: Key_state state for key 0/1
'Key_rep repeat counter for auto-repeat
'Key_ct0 / Key_ct1 2-bit counter for debounce
'Result: Key_press: pin bit goes to 1 when key press is detected
'After reading it out, reset the state of Key_press in Main!
'Thanks to Peter Dannegger
'---------------------------------------------------------------
Debounce_port: 'About 108 bytes
  $asm
    in R18, key_port
    com R18 'Pin active low
    ANDI R18, Pinb_mask 'Filter pins with Pinb_mask
    LDS R19, {Key_state}
    eor R18, R19 'Detect level change at pin input

    LDS R16, {Key_ct0} '8 channel 2-bit counter
    LDS R17, {Key_ct1}
    and R16, R18 'Reset 2-bit counter in R17: R16
    and R17, R18
    com R16 'Decrement R17: R16
    eor R17, R16
    STS {Key_ct0} , R16 'Save counter
    STS {Key_ct1} , R17

    and R18, R16 'IF counter=&B11 Set digital input blanking
    and R18, R17
    eor R19, R18 '0<->1 switch state
    STS {Key_state} , R19

    LDS R16, {key_press}
    and R18, R19
    or R16, R18 'Detected "0->1 key press

    LDS R17, {Key_rep}
    tst R19 'Key_state: Is any key pressed?
    breq Key_isr_rep
    dec R17
    brpl Key_isr_finish 'IF Key_rep <0 set_digit wait time expires
    mov R16, R19 'Auto repeat key_press = key_state
    ldi R17,key_repeat_next 'Set up auto-reply repeat timer
    rjmp Key_isr_finish

Key_isr_rep:
    ldi R17, key_repeat_start 'Reset auto reply start

timerKey_isr_finish:
    STS {Key_rep} , R17 'Save auto reply timerSTS
    {key_press} , R16 'Save debounce key
  $end Asm
Return


'******** RTC *******************************************************
'The following empty routine if you want to use
'time/date bascom functions. , 31 , 28 , 31 , 30 , 31 , 30 , 31 , 30 ,     31 ,     30 , 31 '12 month end mark
Data_dateset : Data " " ,     " Sec " , "Min " , "Hour" , "Day " , "Month " , "Year" minimum mark Date_max: Data 0 , 59 , 59 , 23 , 31 , 12 , 99 ''Second " , "Min " , "Hour" , "Day " , "Month " , "Year" maximum mark Date_month: Data 0 , 31 , 28 , 31 , 30 , 31 , 30 , 31 , 30 , 31 , 30 , 31 '12 month end mark Data_dateset: Data " " , "Sec " , "Min " , "Hour" , "Day " , "Mon " , "Year" 'Seconds", "Minutes", "Hours", "Day", "Month", "Year" Data_set: Data 0 , 128, 129 , 130 , 131 , 132, 133 'Seconds", "Minutes", "Hours", "Day", "Month", "Year" $include "../font8x8.font" $include "../font12x16.font"  



















[1] [1]
Reference address:Mixed programming of basic language and assembly language --- electronic watch

Previous article:Bascom-avr program that can display temperature and time (and set alarm time)
Next article:BASCOM-AVR driver digital tube simple code

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号