Главная » Статьи » Proton PICBasic

Часы на МК PIC16F628A с двумя таймерами.

Предлагаю Вашему вниманию – Часы на МК PIC16F628A.

Данный «прибор» (назовем его так), имеет на борту 2 независимых таймера, часы и … Чтобы заполнить память МК и рационально использовать данный МК, был внедрен в него термодатчик на DS18B20.

Изначально, в качестве экрана, я хотел использовать LED индикатор, 7х8 (семисегментный – восьмиразрядный), но что то пошло не так… А именно, из-за отсутствия опыта при работе с 74НС595 (или похожими регистрами сдвига) и примеров, я отказался от него…

Но благодаря этому, я начал экспериментировать с экранами фирмы Holtek, а именно с НТ1611.

«Полазив» по форуму http://www.picbasic.ru , а также по просторам инета, был очень сильно огорчен… Информации об использовании данных экранов на Proton IDE, не было…

Хотел использовать в качестве часов RTC DS1302, из-за того, что никогда раньше не работал с таймерами. Но благодаря Андрею (Andriy76) и статьям Максима (Админ), я начал пробовать работать с таймерами… Приношу им свою благодарность!!! Честно говоря, еще не разобрался, но думаю разберусь… Я смог отказаться от RTC и тем самым уменьшить стоимость самого прибора!!!

Итак, данный прибор снабжен 2-мя таймерами, которые работают не зависимо друг от друга, причем, на экран выводится остаточное время, наименьшего таймера!!!

На экране отображается (в левой его части 5 разрядов, ХХ-ХХ) часы, они отображаются постоянно. В правой части, когда таймер не включен, то 9, 10 - разряд отображает температуру (у меня он показывает температуру в помещении, так что, отрицательную температуру он не показывает, но это легко исправить).

Когда включаешь хоть один таймер (напомню, у меня их 2), на экране в 7 разряде показывает № таймера, а в 9, 10 – значение: Х-ХХ. Если таймер установлен на n-время (получилось 2 по 99 мин каждый), раз в 10 мин, отображается температура.

Весь этот прибор питается от АКК мобильного телефона без DC/DC конверторов!!! Для зарядки АКК я использую спец м/с LTC4054. Единственная проблема, она поддерживает АКК до 800мА.

В связи с тем, что МК PIC16F628A не имеет своего АЦП, пришлось собрать схему, для контроля состояния АКК. Когда АКК в «норме», на вход МК приходит логическая «1», по мере разряда (подбирается экспериментально) на вход МК приходит логический «0». МК «обрабатывает событие» и сигнализирует (при помощи св. диода) о том, что «АКК разряжен». При подключении ЗУ, он также сигнализирует о процессе зарядки. Когда зарядка окончена, индикатор отключается. Данный прибор, имеет 4 пункта меню. В котором, можно выбирать 3 таймера (программно третий отключен по не надобности и при желании, можно удалить из кода) и установку часов. В связи с тем, что данный экран, не может выводить символы (кроме некоторых, а в частности «F» и «Р») , все реализовано числами, за исключении входа в меню. При входе в меню, в 6 разряде, загорается «F» (можно Р, это как кому нравится…)
Вся манипуляция, осуществлена при помощи 4 кнопок: S – Setup, Up – вверх, Down – вниз и Enter или ОК (опять же, как кому легче).
При срабатывании таймера, он выдает звуковой сигнал через пьезоизлучатель с генератором «КРХ-1203В», он будет работать, пока не нажать кнопку «ОК».
Загрузка памяти МК составляет ~68,65%, так что, при желании можно еще что либо добавить…
Данный прибор, НЕ является окончательным продуктом и может изменится, в зависимости от найденных дефектов или улучшений.
Так что, если будут обнаружены ошибки, пишите.
P.S. Фотки часов выложу позже!!!



Схема прибора:

Исходный код:

Code

'-------------------------- Опции компилятора --------------------------------
   
Declare SHOW_SYSTEM_VARIABLES = OFF ' При симуляции в Proteus не показывать внутренние переменные
Declare FSR_CONTEXT_SAVE = OFF ' Не заботиться о сохранении содержимого регистра FSR
Declare Reminders = OFF ' Выключить напоминания компилятора  
Declare Warnings = OFF ' Выключить предупреждения компилятора  
Declare Optimiser_Level 0 ' Выключить оптимизацию программы  
   
;-------------------------- Общие настройки------------------------------------
   
Device = 16F628A ' Используемый микроконтроллер
Xtal = 4 ' Частота осциллятора 4 МГц
   
'-------------------------- Конфигурация программирования --------------------
   
Config BODEN_OFF, BOREN_OFF, CP_OFF, DATA_CP_OFF, PWRTE_ON, WDT_OFF, LVP_OFF, MCLRE_ON, XT_OSC  
   
'-------------------------- Настройки портов ---------------------------------
   
PortB_Pullups = Off ' Выключить подтягивающие резисторы на PORTB
Declare All_Digital = Off ' Каждый порт выполняет свою функцию по умолчанию
   
'-------------------------- OPTION_REG ----------------------------------------

Symbol PS0 = OPTION_REG.0 ' Бит установки предделителя TMR0
Symbol PS1 = OPTION_REG.1 ' Бит установки предделителя TMR0
Symbol PS2 = OPTION_REG.2 ' Бит установки предделителя TMR0
Symbol PSA = OPTION_REG.3 ' Выбор включения предделителя
Symbol T0SE = OPTION_REG.4 ' Выбор фронта приращения TMR0 при внешнем тактовом сигнале
Symbol T0CS = OPTION_REG.5 ' Выбор тактового сигнала для TMR0  
Symbol INTEDG = OPTION_REG.6 ' Выбор активного фронта сигнала на входе внешнего прерывания INT
Symbol NOT_RBPU = OPTION_REG.7 ' Включение подтягивающих резисторов на PORTB
   
'-------------------------- INTCON --------------------------------------------
   
Symbol RBIF = INTCON.0 ' Флаг внешнего прерывания по PORTB.4-PORTB.7
Symbol INTF = INTCON.1 ' Флаг внешнего прерывания по PORTB.0(INT)
Symbol T0IF = INTCON.2 ' Флаг переполнения TMR0
Symbol RBIE = INTCON.3 ' Бит разрешения прерывания по PORTB.4-PORTB.7
Symbol INTE = INTCON.4 ' Бит разрешения прерывания по PORTB.0(INT)  
Symbol T0IE = INTCON.5 ' Бит разрешения прерывания по переполнению TMR0
Symbol PEIE = INTCON.6 ' Бит разрешения прерывания от периферийных устройств
Symbol GIE = INTCON.7 ' Бит глобального разрешения прерываний
   
'-------------------------- Определение переменных ---------------------------
   
Dim J As Byte
Dim X As Byte
Dim I As Byte
Dim N As Byte
Dim Busy As Bit ' Busy Status-Bit
Dim R_Temp As Word ' RAW Temperature readings
Dim Cold_Bit As R_Temp.11 '  
Dim Cel As Byte '  
Dim Cel_ot As Word '
'Dim M As Byte '
'Dim MM As Byte '
Dim Tmp As Byte '
Dim TmpVal As Byte '
Dim TmpVal1 As Byte '
Dim Mass[10] As Byte ' Массив для вывода нужной инф. на экран
Dim HRS As Byte ' Часы
Dim Mins As Byte ' Минуты
Dim Sec As Byte ' Секунды
Dim OldSec As Byte '
Dim BIG As Dword ' переменная для счета секунд
Dim BIG1 As BIG.HighWord '  
Dim Delay As Byte ' Пауза

'-----------------Timer 1---------------
'Dim Time1 As Byte
Dim Des1 As Byte
Dim Sot1 As Byte
Dim Sum1 As Byte
Dim Pr1 As Byte
Dim T1 As Byte

'-----------------Timer 2---------------
'Dim Time2 As Byte
Dim Des2 As Byte
Dim Sot2 As Byte
Dim Sum2 As Byte
Dim Pr_2 As Byte
'Dim T2 As Byte

'-----------------Timer 3 Не активен!!!---------------
'Dim Time2 As Byte
Dim Des3 As Byte
Dim Sot3 As Byte
Dim Sum3 As Byte
Dim Pr_3 As Byte

'-------------------------- Начало -------------------------------------------
'TRISB = $00

Symbol Beep = PORTB.0
Symbol Lamp = PORTB.1
Symbol Akk_OK = PORTB.2
Symbol Akk_Low = PORTB.3
Symbol DataPin = PORTB.4  
Symbol ClockPin = PORTB.5  

Symbol Comm_Pin = PORTA.4
Symbol Setup = PORTA.0
Symbol Up = PORTA.1
Symbol Down = PORTA.2
Symbol Ent = PORTA.3
Clear

HRS = 12
Mins = 28
Delay = 100

Mass[2] = $FF
Mass[7] = $FF  

'-------------------------- Настройка TMR0 для прерываний --------------------
OPTION_REG = %10000111
TMR0 = $06 ' Значение регистра TMR0
T0IE = 1 ' Разрешение прерывания при переполнении TMR0 с частотой 15,625000 Гц
GIE = 1 ' Разрешение глобального прерывания
BIG = 1000000
   
On_Interrupt GoTo Int_Label
GoTo MainProgram
   
'-------------------------- Прерывания--------------------------
   
Int_Label:
Context Save '  

If T0IF = 1 Then Dec BIG1 ' Если сработал TMR0, то отнимаем единицу из старшего байта переменной BIG1,  
OldSec = Sec
If BIG < 0 Then BIG = BIG + 1000000 : Inc Sec
T0IF = 0  
   
Context Restore ' Возврат из обработчика прерывания
   
'-------------------------- Главная программа -------------------------
MainProgram:
   
While 1 = 1

If Akk_OK = 1 And Akk_Low = 1 Then
  Low Lamp
Else
  If OldSec = Sec Then  
  High Lamp
  Else
  Low Lamp
  EndIf
EndIf

If Pr1 = 0 And Pr_2 = 0 Then
  GoSub Temper
  Low Beep
Else
  If Pr1 = 1 And Sum1 = 0 Then  
  If Ent = 0 Then Pr1 = 0 : Sum1 = 0 : Low Beep
' Mass[6] = $01
  For X = 0 To 1
  TmpVal1 = Sum1 Dig X
  GoSub Conv : TmpVal1 = 9 - X : Mass[TmpVal1] = TmpVal  
  Next X  
  If OldSec = Sec Then  
  High Beep
  DelayMS 5
  Else
  Low Beep
  DelayMS 5
  EndIf
  EndIf
   
  If Pr_2 = 1 And Sum2 = 0 Then  
  If Ent = 0 Then Pr_2 = 0 : Sum2 = 0 : Low Beep
  For X = 0 To 1
  TmpVal1 = Sum2 Dig X
  GoSub Conv : TmpVal1 = 9 - X : Mass[TmpVal1] = TmpVal  
  Next X  
  If OldSec = Sec Then  
  High Beep
  DelayMS 5
  Else
  Low Beep
  DelayMS 5
  EndIf
  EndIf
EndIf

If Mass[6] = 1 And Pr1 = 1 And Ent = 0 Then Pr1 = 0 : Sum1 = 0 : Low Beep : GoSub Temper

If Mass[6] = 2 And Pr_2 = 1 And Ent = 0 Then Pr_2 = 0 : Sum2 = 0 : Low Beep : GoSub Temper

OldSec = Sec
GoSub Tim

If Mins = 00 Or Mins = 10 Or Mins = 20 Or Mins = 30 Or Mins = 40 Or Mins = 50 Then GoSub Temper

GoSub Conv  
GoSub Led

If Setup = 0 Then DelayMS Delay : J = 1 : GoSub Menu

Wend
'---------------------------------- Меню -------------------------------------------------------
Menu:
Mass[5] = 11
  If Up = 0 Then DelayMS Delay : Inc J
  If J > 4 Then J = 1
  If Down = 0 Then DelayMS Delay : Dec J
  If J < 1 Then J = 4
  If J <> 4 Then Mass[7] = $FF : GoSub Tim
Select J
  Case 1  
  TmpVal1 = J : GoSub Conv : Mass[6] = TmpVal
  TmpVal1 = Des1 : GoSub Conv : Mass[8] = TmpVal
  TmpVal1 = Sot1 : GoSub Conv : Mass[9] = TmpVal
  If Ent = 0 Then DelayMS Delay : GoSub Timer1

  Case 2
  TmpVal1 = J : GoSub Conv : Mass[6] = TmpVal
  TmpVal1 = Des2 : GoSub Conv : Mass[8] = TmpVal
  TmpVal1 = Sot2 : GoSub Conv : Mass[9] = TmpVal
  If Ent = 0 Then DelayMS Delay : GoSub Timer2
   
  Case 3  
  TmpVal1 = J : GoSub Conv : Mass[6] = TmpVal
  TmpVal1 = Des3 : GoSub Conv : Mass[8] = TmpVal
  TmpVal1 = Sot3 : GoSub Conv : Mass[9] = TmpVal

  Case 4
  Mass[0] = $04 : Mass[1] = $FF : Mass[3] = $FF : Mass[4] = $00
  If Ent = 0 Then DelayMS Delay : GoSub Time  
EndSelect

GoSub Led
   
If Setup = 0 Then DelayMS Delay : Mass[5] = 0 : Return

GoTo Menu
'------------------------------------Timer 1-----------------------------------------------
Timer1:
   
If T1 = 0 Then  
  Mass[8] = 0
  If Up = 0 Then DelayMS Delay : Inc Des1
  If Des1 > 9 Then Des1 = 0
  If Down = 0 Then DelayMS Delay : Dec Des1
  If Des1 < 0 Then Des1 = 9
Else
  Mass[9] = 0
  If Up = 0 Then DelayMS Delay : Inc Sot1
  If Sot1 > 9 Then Sot1 = 0
  If Down = 0 Then DelayMS Delay : Dec Sot1
  If Sot1 < 0 Then Sot1 = 9
EndIf

GoSub Led
   
  TmpVal1 = Des1 : GoSub Conv : Mass[8] = TmpVal
  TmpVal1 = Sot1 : GoSub Conv : Mass[9] = TmpVal
   
  Sum1 = Des1 * 10 + Sot1

  If Ent = 0 Then DelayMS Delay : Inc T1

  If T1 = 2 Then  
  T1 = 0  
  If Sum1 > 0 Then  
  Pr1 = 1
  Else
  Pr1 = 0
  EndIf
  Des1 = 0
  Sot1 = 0
  Return
  EndIf

  GoSub Led

GoTo Timer1  
'------------------------------------Timer 2-----------------------------------------------
Timer2:
   
If T1 = 0 Then  
  Mass[8] = 0
  If Up = 0 Then DelayMS Delay : Inc Des2
  If Des2 > 9 Then Des2 = 0
  If Down = 0 Then DelayMS Delay : Dec Des2
  If Des2 < 0 Then Des2 = 9
Else
  Mass[9] = 0
  If Up = 0 Then DelayMS Delay : Inc Sot2
  If Sot2 > 9 Then Sot2 = 0
  If Down = 0 Then DelayMS Delay : Dec Sot2
  If Sot2 < 0 Then Sot2 = 9
EndIf

GoSub Led
   
  TmpVal1 = Des2 : GoSub Conv : Mass[8] = TmpVal
  TmpVal1 = Sot2 : GoSub Conv : Mass[9] = TmpVal
   
  Sum2 = Des2 * 10 + Sot2

  If Ent = 0 Then DelayMS Delay : Inc T1

  If T1 = 2 Then  
  T1 = 0  
  If Sum2 > 0 Then  
  Pr_2 = 1
  Else
  Pr_2 = 0
  EndIf
  Des2 = 0
  Sot2 = 0
  Return
  EndIf

  GoSub Led

GoTo Timer2  
'------------------------------------ Установка часов -------------------------------
Time:
  GoSub Tim
   
  If T1 = 0 Then
  Mass[0] = 0  
  Mass[1] = 0
  If Up = 0 Then DelayMS Delay : Inc HRS  
  If HRS > 23 Then HRS = 0
  If Down = 0 Then DelayMS Delay : Dec HRS
  If HRS < 0 Then HRS = 23
  Else
  Mass[3] = 0  
  Mass[4] = 0
  If Up = 0 Then DelayMS Delay : Inc Mins
  If Mins > 59 Then Mins = 0
  If Down = 0 Then DelayMS Delay : Dec Mins
  If Mins < 0 Then Mins = 59
  EndIf
   
  GoSub Led
   
  If Ent = 0 Then DelayMS Delay : Inc T1  

  If T1 = 2 Then  
  T1 = 0  
  Return
  EndIf

  GoSub Tim  
  GoSub Led
   
GoTo Time
'------------------------- Обработка событий ------------------------------------------------------------
Tim:
  If Sec > 59 Then ' Если прошло 60 сек
  Sec = 0  
  Inc Mins  
  Dec Sum1
  Dec Sum2
  If Sum1 < 0 Then Sum1 = 0
  If Sum2 < 0 Then Sum2 = 0
  EndIf

' -------------------------- Обработка таймеров и вывод на экран, остаточное время, меньшего таймера
If Sum1 > 0 Or Sum2 > 0 Then
  Mass[7] = $FF
  If Sum1 > Sum2 Then
  If Pr_2 = 1 Then ' Sum2 > 0 Then
  Mass[6] = $02
  For X = 0 To 1
  TmpVal1 = Sum2 Dig X
  GoSub Conv : TmpVal1 = 9 - X : Mass[TmpVal1] = TmpVal  
  Next X  
  Else
  Mass[6] = $01
  For X = 0 To 1
  TmpVal1 = Sum1 Dig X
  GoSub Conv : TmpVal1 = 9 - X : Mass[TmpVal1] = TmpVal  
  Next X  
  EndIf  
  Else
  If Pr1 = 1 Then ' Sum1 > 0 Then
  Mass[6] = $01
  For X = 0 To 1
  TmpVal1 = Sum1 Dig X
  GoSub Conv : TmpVal1 = 9 - X : Mass[TmpVal1] = TmpVal  
  Next X  
  Else
  Mass[6] = $02
  For X = 0 To 1
  TmpVal1 = Sum2 Dig X
  GoSub Conv : TmpVal1 = 9 - X : Mass[TmpVal1] = TmpVal  
  Next X  
  EndIf
  EndIf  
EndIf
   
  If Mins > 59 Then Mins = 0 : Inc HRS ' Если прошло 60 минут
  If HRS > 23 Then HRS = 0

  For X = 0 To 1
  If X = 0 Then
  TmpVal1 = HRS Dig X
  GoSub Conv : Mass[1] = TmpVal  
  Else  
  TmpVal1 = HRS Dig X
  GoSub Conv : Mass[0] = TmpVal  
  EndIf
  Next X

  For X = 0 To 1
  If X = 0 Then
  TmpVal1 = Mins Dig X
  GoSub Conv : Mass[4] = TmpVal  
  Else  
  TmpVal1 = Mins Dig X
  GoSub Conv : Mass[3] = TmpVal  
  EndIf
  Next X
Return
'-------------------------- Температура -----------------------------------------------------
Temper:
  OWrite Comm_Pin, 1, [$CC, $44]
  ORead Comm_Pin, 1, [Busy]  
' If Busy = 0 Then Err
  OWrite Comm_Pin, 1, [$CC, $BE] ' Skip ROM search & read scratchpad memory
  ORead Comm_Pin, 2, [R_Temp.LowByte, R_Temp.HighByte] ' Read two bytes / end comms
  If R_Temp = 0 Then Mass[6] = 0 : Mass[7] = $FF : Mass[8] = $FF : Mass[9] = $FF : Return

If Cold_Bit <> 1 Then  
  Cel = R_Temp / 16
  Mass[6] = $00
  Mass[7] = $00
Else
  Cel_ot = 65535 - R_Temp
  Cel_ot = Cel_ot + 1
  Cel = Cel_ot / 16
  Mass[6] = $00
  Mass[7] = $FF
EndIf  

For X = 0 To 1
  TmpVal1 = Cel Dig X
  GoSub Conv : TmpVal1 = 9 - X : Mass[TmpVal1] = TmpVal  
Next X  

Return
'---------------------- Выводим на экран -----------------------------------------------------
Led:
  SHOut DataPin, ClockPin, MsbFirst, [Mass[0]\4, Mass[1]\4, Mass[2]\4, Mass[3]\4, Mass[4]\4, Mass[5]\4, Mass[6]\4, Mass[7]\4, Mass[8]\4, Mass[9]\4]
  DelayMS 200  
Return
'---------------------- Таблица преобразования для экрана -----------------------------------
Conv:
  TmpVal = LookUp TmpVal1, [$0A, $01, $02, $03, $04, $05, $06, $07, $08, $09]
Return  

Архив с исходниками можно скачать здесь




Категория: Proton PICBasic | Добавил: Matrix252005 (02.11.2011)
Просмотров: 9605 | Комментарии: 3 | Теги: АКБ, HT1611, RTC, таймер, АЦП, ds1302 | Рейтинг: 5.0/2
Всего комментариев: 3
1 ADMIN   (09.11.2011 13:00)
Вот еще бы комментарии...

2 Andriy76   (22.11.2011 11:29)
Хорошее описание , у меня так не получаеться smile

3 S_moke   (10.01.2012 15:55)
Надеюсь, что помогу, сам голову ломал...
http://www.picbasic.ru/publ....1-0-120

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]