Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Прошу помощи в создании часов с RTC


Прошу помощи в создании часов с RTC

Сообщений 1 страница 4 из 4

1

Добрый вечер форумчане!
Хочу сделать часы на Atmega8 с использованием RTC DS1307 и 4х разрядным семисегментным индикатором. Для начала просто часы, потом возможно добавлю еще какой то функционал.
Для динамической индикации решил использовать готовый код, найденный тут: http://bascom.at.ua/publ/issledovanie_r … m/1-1-0-89
Несколько изменил его под себя - оставил только общий анод, и 4 разряда. + добавил непосредственно функционал часов, пока в зачаточном состоянии.
По нажатию на кнопки настройки 1 и 2 должны увеличиваться часы и минуты соответственно.
Но я столкнулся со странной вещью: пока выводимое значение меньше 10, все работает правильно. Но как только значение становиться равно или больше 10, то при нажатии на кнопку на индикаторе появляется число на несколько значений больше чем должно быть, а стоит отпустить кнопку - и появляется изначальное число увеличенное на 1, как и задумано.
Т.е. число 9 - ненадолго нажали кнопку - на индикаторе появилось число 16 - отпустили кнопку - на индикаторе 10.   
Категорически не могу понять откуда берется лишнее число. Надеюсь на вашу помощь. Когда все заработает в финальном варианте размещу готовый проект на форуме.

Код:
'*******************************************************************************
'******************     Поразрядная 7-seg LED индикация     ********************
'*******************************************************************************

' Контроллер: ATMEGA8A или любой другой "AVR" с небольшими переделками исходника
' Версия компилятора: BASCOM-AVR 2.0.7.1
' Автор: sasha_1973

'*******************************************************************************
'-------------------------------------------------------------------------------
'---------------     Конфигурация используемого контроллера     ----------------
'-------------------------------------------------------------------------------
  $regfile = "m8def.dat" : $crystal = 4000000 : $hwstack = 40 : $swstack = 16 : $framesize = 32
'-------------------------------------------------------------------------------
 '******************************************************************************
'-------------------------------------------------------------------------------
'---------------     Настройка портов МК для LED индикации     -----------------
'-------------------------------------------------------------------------------
' ******************************************************************************
'-------------------------------------------------------------------------------
'-------------     Присваиваем собственные имена, для удобства     -------------
'-------------------------------------------------------------------------------

  A Alias Portb.0                                           ' Порт МК, к которому подключен сегмент "А" LED индикатора
  B Alias Portb.1                                           ' Порт МК, к которому подключен сегмент "B" LED индикатора
  C Alias Portb.2                                           ' Порт МК, к которому подключен сегмент "C" LED индикатора
  D Alias Portb.3                                           ' Порт МК, к которому подключен сегмент "D" LED индикатора
  E Alias Portb.4                                           ' Порт МК, к которому подключен сегмент "E" LED индикатора
  F Alias Portb.5                                           ' Порт МК, к которому подключен сегмент "F" LED индикатора
  G Alias Portb.6                                           ' Порт МК, к которому подключен сегмент "G" LED индикатора
  H Alias Portb.7                                           ' Порт МК, к которому подключен сегмент "H" LED индикатора

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

  Разряд_1 Alias Portc.0                                    ' Порт МК, к которому подключен "1 разряд" LED индикатора
  Разряд_2 Alias Portc.1                                    ' Порт МК, к которому подключен "2 разряд" LED индикатора
  Разряд_3 Alias Portc.2                                    ' Порт МК, к которому подключен "3 разряд" LED индикатора
  Разряд_4 Alias Portc.3                                    ' Порт МК, к которому подключен "4 разряд" LED индикатора


'-------------------------------------------------------------------------------
'---------     Коммутация портов (вход, выход или висим в воздухе)     ---------
'-------------------------------------------------------------------------------

  Config Portb = Output                                     ' Настраиваем сразу весь порт МК на выход

'          можно так

'  Config Portb.0 = Output                                   ' Настраиваем одну ножку порта на выход
'  Config Portb.1 = Output                                   ' Настраиваем одну ножку порта на выход
'  Config Portb.2 = Output                                   ' Настраиваем одну ножку порта на выход
 ' Config Portb.3 = Output                                   ' Настраиваем одну ножку порта на выход
'  Config Portb.4 = Output                                   ' Настраиваем одну ножку порта на выход
'  Config Portb.5 = Output                                   ' Настраиваем одну ножку порта на выход
 ' Config Portb.6 = Output                                   ' Настраиваем одну ножку порта на выход
  'Config Portb.7 = Output                                   ' Настраиваем одну ножку порта на выход

'          или так, кому, как больше нравится

'  Ddrb = &B11111111                                         ' Настройка каждого вывода всего порта (PORTB - сегменты), в одну строчку

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

  Config Portc.0 = Output                                   ' Настраиваем одну ножку порта на выход
  Config Portc.1 = Output                                   ' Настраиваем одну ножку порта на выход
  Config Portc.2 = Output                                   ' Настраиваем одну ножку порта на выход
  Config Portc.3 = Output                                   ' Настраиваем одну ножку порта на выход


'           или так, кому, как больше нравится

'  Ddrd = &B11111111                                         ' Настройка каждого вывода всего порта (PORTD - разряды), в одну строчку
' ------------------------------------------------------------------------------

'  Немного отвлечемся.
'  Бытует мнение, что компилятор не дружит с кирилицей.
'  Исходя из личного опыта могу сказать, конфликтов не наблюдалось.
'  Единсвенное ограничение - количество символов в именах. Думаю Вам хватит с избытком.

Config Pind.5 = Input
Config Pind.6 = Input
Config Pind.7 = Input

Portd.5 = 1                                                 ' включим внутренний подтягивающий резистор для кнопки
Portd.6 = 1                                                 ' включим внутренний подтягивающий резистор для кнопки
Portd.7 = 1


Btn1 Alias Pind.5
Btn2 Alias Pind.6
Btn3 Alias Pind.7


'-------------------------------------------------------------------------------
'-----------------     Определение переменных и констант     -------------------
'-------------------------------------------------------------------------------
Начальные_настройки:                                        ' Просто метка, для удобства
'-------------------------------------------------------------------------------



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

  Const Общее_количество_разрядов = 4                       ' Переменная, для хранения значения общего количества используемых разрядов

  Const Скорость_изменения_переменной = 100                 ' Переменная, для хранения значения задержки "Waitms"
  Const Значение_регистра_tcnt0_timer0 = 250                ' Переменная, для хранения значения регистра TCNT0

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

  Dim Цикл_led As Byte                                      ' Переменная, для хранения количества выводимых разрядов (нужна для разбивки значения на разряды)
  Dim Счетчик_миганий As Word                               ' Счетчик для обработки частоты и длительности мигания
  Dim Частота_мигания As Word                               ' Переменная, для хранения значения частоты мигания при Флаг_мигание(n) = 1
  Dim Счетчик_разрядов As Byte                              ' Счетчик перебора разрядов

  Dim Переменная_word_1 As Word                             ' Переменная, которую будем менять


  Dim Выводимая_цифра_led As Byte                           ' Переменная, для загрузки цифр в порт
  Dim Выводимые_данные_led As Word                          ' Переменная, для хранения выводимых данных
  Dim Копия_выводимые_данные_led As Word                    ' Переменная, для временного хранения выводимых данных (нужна для разбивки значения на разряды)
  Dim 1_канал_выводимые_данные_led As Word                  ' Переменная, для хранения выводимых данных

  Dim Длительность_горения_при_мигании As Word              ' Переменная, для хранения значения длительности горения знакоместа при "Флаг_мигание(n) = 1"
  Dim Цифра(общее_количество_разрядов) As Byte              ' Значение разряда для 8-ми разрядов
  Dim Флаг_точка(общее_количество_разрядов) As Byte         ' Флаг точки для 8-ми разрядов
  Dim Флаг_гашение(общее_количество_разрядов) As Byte       ' Флаг гашения нужного разряда для 8-ми разрядов
  Dim Флаг_мигание(общее_количество_разрядов) As Byte       ' Флаг мигания нужного разряда для 8-ми разрядов
  Dim Дополнительный_символ(общее_количество_разрядов) As Byte       ' Переменная, для хранения значения дополнительного символа при Флаг_дополнительный_символ(n) = 1
  Dim Флаг_дополнительный_символ(общее_количество_разрядов) As Byte       ' Флаг сигнализирующий о выводе дополнительных символов для 8-ми разрядов

Dim Mine As Byte
Dim Hour As Byte
Dim Seco As Byte
 Dim Hour1 As Long
 Dim Hour2 As Long




'-------------------------------------------------------------------------------
'----------------------     Определение подпрограмм     ------------------------
'-------------------------------------------------------------------------------

  Declare Sub Гашение_разрядов()
  Declare Sub Индикация_7seg_led()
  Declare Sub Обработка_прерывания_timer0()

'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'------------     Настройка таймера для обновления LED индикации     -----------
'-------------------------------------------------------------------------------

Config Timer0 = Timer , Prescale = 1024 , Clear Timer = 0
Tcnt0 = Значение_регистра_tcnt0_timer0                      ' Настройка дополнительного делителя таймера (значение = 250)
On Timer0 Обработка_прерывания_timer0                       ' Переход на подпрограмму после каждого прерывания TIMER0


'-----------------------     Первоначальные установки    -----------------------
'-------------------------------------------------------------------------------

  Частота_мигания = 200                                     ' Значение частоты мигания знакоместа на LED дисплее при "Флаг_мигание(n) = 1"
  Длительность_горения_при_мигании = Частота_мигания / 2    ' Значение длительности горения знакоместа на LED дисплее при "Флаг_мигание(n) = 1"

'-------------------------------------------------------------------------------
'------------------------     Работа с прерываниями     ------------------------
'-------------------------------------------------------------------------------

    Enable Timer0                                           ' Разрешаем работу прерывания по ПЕРЕПОЛНЕНИЮ  таймера

    Enable Interrupts                                       ' Разрешаем работу всех прерываний

    Config Sda = Portc.4
    Config Scl = Portc.5
'-------------------------------------------------------------------------------
'*******************************************************************************
'-------------------------------------------------------------------------------
'--------------------------     Начало программы     ---------------------------
'-------------------------------------------------------------------------------




If Btn2 = 0 And Btn1 = 0 Then                                'если зажаты две кнопки то сбрасываем время что бы выставить его
  Hour = 0
  Mine = 0
  Seco = 1

  Seco = Makebcd(seco)
  I2cstart
  I2cwbyte &HD0
  I2cwbyte 0
  I2cwbyte Seco
  I2cstop

  Mine = Makebcd(mine)
  I2cstart
  I2cwbyte &HD0
  I2cwbyte 1
  I2cwbyte Mine
  I2cstop

  Hour = Makebcd(hour)
  I2cstart
  I2cwbyte &HD0
  I2cwbyte 2
  I2cwbyte Hour
  I2cstop
End If



  Do                                                        ' Крутимся между Do и Loop, ожидая прерывания TIMER0, для обновления LED индикации

'--------------------------
  I2cstart
  I2cwbyte &HD0
  I2cwbyte &H00
  I2cstart
  I2cwbyte &HD1
  I2crbyte Seco , Ack
  I2crbyte Mine , Ack
  I2crbyte Hour , Nack
  I2cstop
  Seco = Makedec(seco)
  Mine = Makedec(mine)
  Hour = Makedec(hour)                                      'ПОЛУЧИЛИ ЗНАЧЕНИЯ ВРЕМЕНИ


  If Btn2 = 0 Then                                          'если надо Кнопаками увеличиваем время и передаем его в РТЦ

      If Mine = 59 Then
         Mine = 0
      Else
         Incr Mine
      End If

      Mine = Makebcd(mine)
      I2cstart
      I2cwbyte &HD0
      I2cwbyte 1
      I2cwbyte Mine
      I2cstop
   Else
      If Btn1 = 0 Then

         If Hour = 23 Then
            Hour = 0
         Else
            Incr Hour
         End If

         Hour = Makebcd(hour)
         I2cstart
         I2cwbyte &HD0
         I2cwbyte 2
         I2cwbyte Hour
         I2cstop
      End If
   End If



    Hour1 = Hour * 100                                      'тут переводим времяв целое четырехзначное число
    Hour2 = Hour1 + Mine                                    'и добавляем минутьы
    1_канал_выводимые_данные_led = Hour2
    Флаг_точка(2) = 1





'--------------------------
      Waitms Скорость_изменения_переменной                  ' Задержка, для частоты смены показаний индикаторов
  Loop

 End




'-------------------------------------------------------------------------------
'*******************************************************************************
'*****************   Подпрограмма обработки прерывания TIMER0   ****************
'*****************          происходит каждые 1,536 ms          ****************
'*******************************************************************************
'-------------------------------------------------------------------------------
  Обработка_прерывания_timer0:
'-------------------------------------------------------------------------------

    Rcall Индикация_7seg_led

'-------------------------------------------------------------------------------
' Делитель TIMER0 = 1000/(4000000/1024/(256-250))=1000/(3 906,25 / 6) = 1,536 ms
'-------------------------------------------------------------------------------

    Tcnt0 = Значение_регистра_tcnt0_timer0

'-------------------------------------------------------------------------------
  Return
'-------------------------------------------------------------------------------
'*******************************************************************************



'-------------------------------------------------------------------------------
'*******************************************************************************
'*****************   Подпрограмма для обработки LED индикации   ****************
'*******************************************************************************
'-------------------------------------------------------------------------------
  Индикация_7seg_led:
'-------------------------------------------------------------------------------
'----------   Смотрим, что будем выводить и делаем копию переменной    ---------
'-------------------------------------------------------------------------------
      Выводимые_данные_led = 1_канал_выводимые_данные_led   '

      Копия_выводимые_данные_led = Выводимые_данные_led
'-------------------------------------------------------------------------------
'------------------   В цикле разбиваем на разряды, с 4 по 1   -----------------
'-------------------------------------------------------------------------------
      For Цикл_led = 4 To 1 Step -1                         ' цикл в котором разбивается переменная на 4 числа
          Выводимые_данные_led = Копия_выводимые_данные_led Mod 10
          Цифра(цикл_led) = Выводимые_данные_led            '
          Копия_выводимые_данные_led = Копия_выводимые_данные_led / 10       '
      Next

'-------------------------------------------------------------------------------
'----------------------   Гасим все разряды индикатора   -----------------------
'-------------------------------------------------------------------------------
    rCall Гашение_разрядов                                  ' Переход к подпрограмме гашения индикаторов
'-------------------------------------------------------------------------------
'----   Перебираем разряды, в каждом прерывании выводим следующий разряд   -----
'-------------------------------------------------------------------------------
    Incr Счетчик_разрядов
'-------------------------------------------------------------------------------
'-----   Выбираем разряд для загрузки в обработчик вывода на 7-seg LED    ------
'-------------------------------------------------------------------------------
    If Счетчик_разрядов > Общее_количество_разрядов Then
        Счетчик_разрядов = 1
    End If
'------------------------------------------------------------------------------------
' Участок кода отвечающий за мигание, тушение разрядов и выводит точку в нужном месте
'------------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'----------------------------   Подготовка к миганию  --------------------------
'-------------------------------------------------------------------------------
    Incr Счетчик_миганий

    If Счетчик_миганий > Частота_мигания Then Счетчик_миганий = 1
'-------------------------------------------------------------------------------
'------------------   Если надо, то мигаем в нужных разрядах  ------------------
'-------------------------------------------------------------------------------
    If Флаг_мигание(счетчик_разрядов) = 1 And Счетчик_миганий > Длительность_горения_при_мигании Or Флаг_гашение(счетчик_разрядов) = 1 Then       ' Если флаг мигания этого разряда выставлен и счетчик > 200
        Select Case Счетчик_разрядов
          Case 1 To 4
                Выводимая_цифра_led = Lookup(11 , Цифры_oa) ' Выводим пустое место в 1 - 4 разрядах
        End Select
      Else
'-------------------------------------------------------------------------------
'-----------------------   Выводим дополнительные симвоы   ---------------------
'-------------------------------------------------------------------------------
        If Флаг_дополнительный_символ(счетчик_разрядов) = 1 Then
            Select Case Счетчик_разрядов
              Case 1 To 4
              Выводимая_цифра_led = Lookup(дополнительный_символ(счетчик_разрядов) , Цифры_oa)       ' Выводим дополнительный_символ в 1 - 4 разрядах
            End Select
          Else
'-------------------------------------------------------------------------------
'-------   Если не мигаем и ничего другого не выводим, выводим основное   ------
'-------------------------------------------------------------------------------
            Выводимая_цифра_led = Цифра(счетчик_разрядов)
              Select Case Счетчик_разрядов
                Case 1 To 4
                      Выводимая_цифра_led = Lookup(выводимая_цифра_led , Цифры_oa)       ' Если не выводим дополнительную информацию, выводим основную в 1 - 4 разрядах
              End Select
        End If
'-------------------------------------------------------------------------------
'-------------   Если необходимо, выводим точку в нужном разряде   -------------
'-------------------------------------------------------------------------------
      If Флаг_точка(счетчик_разрядов) = 1 Then
          Выводимая_цифра_led = Выводимая_цифра_led Xor &H80       '&H80 или &B10000000 добавляем к выводимой цифре точку
      End If
    End If
'-------------------------------------------------------------------------------
'---------------------     Загружаем в порт код цифры     ----------------------
'-------------------------------------------------------------------------------
'                                  'ТАК
'           ----------------------------------------------------
             A = Выводимая_цифра_led.0                      ' Сегмент "А"
             B = Выводимая_цифра_led.1                      ' Сегмент "B"
             C = Выводимая_цифра_led.2                      ' Сегмент "C"
             D = Выводимая_цифра_led.3                      ' Сегмент "D"
             E = Выводимая_цифра_led.4                      ' Сегмент "E"
             F = Выводимая_цифра_led.5                      ' Сегмент "F"
             G = Выводимая_цифра_led.6                      ' Сегмент "G"
             H = Выводимая_цифра_led.7                      ' Сегмент "Точка"
'           ----------------------------------------------------
                                'ИЛИ ТАК (работает чуть быстрее, но если сегменты подключены к разным портам, преимущество в скорости теряется)
'           ----------------------------------------------------
'                       Portb = Выводимая_цифра_led       ' Загружаем в порт код цифры
'-------------------------------------------------------------------------------
'---------------   Включаем соответствующий разряд индикатора   ----------------
'-------------------------------------------------------------------------------
    Select Case Счетчик_разрядов


      Case 1 : Set Разряд_1
      Case 2 : Set Разряд_2
      Case 3 : Set Разряд_3
      Case 4 : Set Разряд_4

    End Select
'-------------------------------------------------------------------------------
  Return
'-------------------------------------------------------------------------------

  Гашение_разрядов:
        Reset Разряд_1 : Reset Разряд_2 : Reset Разряд_3 : Reset Разряд_4       ' Гасим индикаторы ОА
  Return
'-------------------------------------------------------------------------------

  Цифры_oa:
'-------------------------------------------------------------------------------
    Data &HC0 , &HF9 , &HA4 , &HB0 , &H99 , &H92 , &H82 , &HF8 , &H80 , &H90       '0,1,2,3,4,5,6,7,8,9
    Data &HBF , &HFF , &H9C , &HC6 , &H87 , &HA3 , &HC7 , &H8B , &HA1 , &H88       '"-", "", "значек градуса", "С", "t", "o", "L", "h", "d", "A"
    Data &HA7 , &HCE , &H89 , &H86 , &HAF , &H8E , &HE3 , &H8C , &HC8 , &H7F       '"c", "Г", "Н", "E", "r", "F", "U", "u", "P", "П", "."
    Data &HAB                                               ', &H , &H , &H , &H , &H , &H , &H , &H , &H '"n", "", "", "", "", "", "", "", "", "". ""
'-------------------------------------------------------------------------------
'*******************************************************************************

0

2

Здесь то, что Вам нужно.

Отредактировано sasha_1973 (2015-10-14 05:54:47)

0

3

sasha_1973 написал(а):

Здесь то, что Вам нужно.


Спасибо огромное за помощь! Код отличный, все разложено по полочкам, есть некоторые не совсем понятные моменты, но это уже у меня нехватка знаний, буду изучать документацию.

А можете пожалуйста в двух словах объяснить из за чего в моем изначальном варианте прошивки возникает такой странный эффект?

0

4

andrwo написал(а):

А можете пожалуйста в двух словах объяснить из за чего в моем изначальном варианте прошивки возникает такой странный эффект?

Вы успеваете вывести на индикацию значение в BCD формате, затем его-же выводите, но уже в привычном DEC формате.


По поводу кнопок, так не совсем правильно:

If Btn2 = 0 Then

Else

If Btn1 = 0 Then

End If


Надо так:

If Btn1 = 0 Then
    реакция на кнопку Btn1
 
Elseif  Btn2 = 0 Then
    реакция на кнопку Btn2

Elseif  Btn3 = 0 Then
    реакция на кнопку Btn3

End If  'Не забываем закрыть множественные условия


Или так:

If Btn1 = 0 Then
    реакция на кнопку Btn1
End If
 
If  Btn2 = 0 Then
    реакция на кнопку Btn2
End If

If  Btn3 = 0 Then
    реакция на кнопку Btn3
End If

Отредактировано sasha_1973 (2015-10-14 12:30:46)

0


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Прошу помощи в создании часов с RTC