Программа для термостата
#include "msp430x41x.h" ; Стандартные определения для MSP430x41x
;*****************************************************************************
; "41x Термостат"
; Эта программа представляет простой термостат на базе МК MSP430F41.
; MSP430 периодически снимает показания с термистора, отображает значение на ЖКИ
; и сравнивает их с установленным порогом. Если измеренное значение равно порогу или
; выше его, ЖКИ начинает мигать, а на выходе устанавливается лог. «1»
; Пользователь может изменять порог, который также отображается на ЖКИ
; во время его установки. Порог автоматически сохраняется во флеш-памяти
; на случай, если питание прибора будет выключено. Кроме этого, в устройстве
; реализованы часы реального времени, которые также могут быть выведены на ЖКИ.
; Программа автоматически переключает экран в режим отображения температуры по
; истечении определённого времени.
;
;
; 4.5 цифры, 3 mux ЖКИ
; /|\ MSP430x41x MCU # VIM-503-DP-FC-S-LV
; | _________________ __________________
; +-o\-+(100k)-----| P1.3 COM2 |-----|15 COM3 |
; | |'SET' COM1 |-----|14 COM2 |
; | /|\ | COM0 |-----|13 COM1 |
; | | | SEG0 |-----|10 |
; +-o\-+(100k)-----| P1.2 SEG1 |-----|12 |
; |'MODE' SEG2 |-----|11 |
; \|/ | SEG3 |-----|7 |
; +-(10K)---| P1.5 SEG4 |-----|9 |
; | | SEG5 |-----|8 |
; +-(Sense)-| P1.4 SEG6 |-----|4 |
; | | SEG7 |-----|6 |
; +------------| P1.6 SEG8 |-----|5 |
; | CA0 SEG9 |-----|1 |
; --- 0.1uf | SEG10|-----|3 |
; --- | SEG11|-----|2 |
; | | |
; | | |
; +------------|Gnd P2.5|-----> Лог. «1» когда температура
; \|/ ----------------- выше порога или равна ему
;
;
; Brian Merritt
; Texas Instruments Inc.
; October 2001
;
;--------------------------------------------- Использованные регистры ЦПУ-----------------
#define Index R5
;В R5 хранится информация о режиме:
; «Термостат» , «Установка температуры»,
; «Часы», «Секундомер»
#define Pointer R6
;R6 используется в качестве указателя на ячейку ;памяти
;;;;;;; R12, R13, R14, R15 ; служебные для различных подпрограмм
;---------------------------------------------Битовые константы----------------------------
Ref equ 20h ;опорный резистор на порту P1.5
Sensor equ 10h ;термистор на порту P1.4
SetSW equ 08h ;кнопка «Установка» на порту P1.3
ModeSW equ 04h ; кнопка «Режим» на порту P1.2
;-----------------------------Байтовые переменные в ОЗУ------------------------------------
SEC equ 0200h ; Счётчик секунд
MIN equ 0201h ; Счётчик минут
HOUR equ 0202h ; Счётчик часов
FLAG equ 0203h ; Байт флагов состояния
TestFreq equ 0204h ;Счётчик для измерения температуры
; ;один раз в несколько секунд
; для экономии батареи
SetPnt equ 0206h ; Температурный порог
AutoSW equ 0207h ; подсчёт времени нахождения в режиме
; «Часы»
;----------------------------Двухбайтовые переменные в ОЗУ---------------------------------
LCDTEMP equ 0216h ;временное хранение в подпрограмме ЖКИ
TEMP equ 0218h ;временное хранение в подпрограмме TEMP
RESULT equ 021Ah ; временное хранение в подпрограмме TEMP IRBIT
equ 021Ch ;используется для тестирования бит
IROP1 equ 021Eh ; первый операнд
IROP2L equ 0220h ; младшее слово второго операнда
IROP2H equ 0222h ; старшее слово второго операнда
IRACCL equ 0224h ; младшее слово результата
IRACCH equ 0226h ; старшее слово результата
;------------------------------------------------------------------------------------------
; Program RESET
;------------------------------------------------------------------------------------------
RSEG CODE
RESET mov #300h,SP ;Инициализация указателя стека
call #Setup ;Конфигурация MSP430
Mainloop bis #LPM3,SR ;Установить режим пониженного
; потребления LPM3
Loop br Mode(Index) ; Переход в соотв. режим
EVEN ;Выравнивание по чётному адресу
Mode DW Thermostat ; Режим «Термостат»
DW Setpoint ; Режим «Установка температуры»
DW Time ; Режим «Часы»
DW Second ; Режим «Секундомер»
;------------------------------------------------------------------------------------------
; Отображает время в часах и минутах
;-------------------------------------------------------------------------------
Time dec.b AutoSW ; Декремент счётчика автоматического
; переключения режима
jnz TimeDisplay ; Переход, если счётчик > 0
clr Index ; Режим 0 = «Термостат»
call #ClearLCD ; Вызов подпрограммы очистки ЖКИ
mov.b #10,AutoSW ; Перезагрузка счётчика
jmp Mainloop ; Возврат в режим термостата
TimeDisplay call #Dis_Clock ; Вызов подпрограммы отображения
; времени
xor.b #040h,&LCDM1+1 ; Мигающая точка между мин. и часами
jmp Mainloop
;
;------------------------------------------------------------------------------------------
; Отображение секунд
;------------------------------------------------------------------------------------------
Second mov.b SEC,R14 ; Передача содержимого ОЗУ через R14
call #ClearLCD ; Вызов подпрограммы очистки ЖКИ
mov.b #LCDM1,R15 ; В R15 указатель на первую позицию
; ЖКИ
call #OutLCD ; Вызов подпрограммы отображения
; секунд
jmp Mainloop
;------------------------------------------------------------------------------------------
; Измерение, вычисление и отображение температуры, сравнение с порогом
;------------------------------------------------------------------------------------------
Thermostat cmp.b #4,TestFreq ;Счётчик TestFreq = 4?
jz MeasTemp ; Если да – измеряем температуру
mov R12,R14 ; Сохранить последнее значение
; температуры в R14 для подпрограммы
; отображения
call #Display1 ; Вызов процедуры отображения
; последнего значения температуры
dec.b TestFreq ; Декремент счётчика
jnz Mainloop ; Если не 0, возврат в основной цикл
mov.b #4,TestFreq ; Перезагрузка счётчика
jmp Mainloop ; Переход в основной цикл
MeasTemp call #Measure ; Вызов процедуры измерения
; температуры
dec.b TestFreq ; Декремент счётчика
jmp Mainloop ; Переход в основной цикл
;------------------------------------------------------------------------------------------
; Установка значения температуры, при котором дисплей начинает мигать
;------------------------------------------------------------------------------------------
Setpoint mov SetPnt,R14 ; Передача содержимого ОЗУ через R14
call #Display2 ; Вызов процедуры отображения на ЖКИ
; символов "SP" и 2-цифрового значения
jmp Mainloop
;------------------------------------------------------------------------------------------
; Измерение опоры и датчика и переход к подпрограмме вычислений
;------------------------------------------------------------------------------------------
Measure mov #Ref,R14 ; R14 = Вывод Ref
bic.b #Ref,&P1DIR ; Сменить направление вывода Ref на
; ввод
call #Charge ; Заряд конденсатора и измерение опоры
mov R14,TEMP ; Сохранить время разряда опоры
mov #Sensor,R14 ; R14 = вывод Sensor
call #Charge ; Заряд конденсатора и измерение
; датчика
mov R14,RESULT ; Сохранить время разряда датчика
bis.b #Ref,&P1DIR ; Сменить направление вывода Ref на
; выход , остальные входы при этом
; остаются в лог. «0» - потребление в
; данном случае меньше, чем в
; неподключенном состоянии
br #Calculate ; Произвести вычисления и индикацию,
; после чего вернуться в основной цикл
;--------------------- Заряд конденсатора через опорный резистор---------------------------
Charge mov #TASSEL1+TACLR+MC1,&TACTL
;Тактирование от SMCLK, очистить
; счётчик, режим continous
bis.b #Ref,&P1OUT ; Лог. «1» на выводе Ref
bis.b #Ref,&P1DIR ; Вывод Ref ? выход
mov #5000,&CCR1 ; CCR1 ~ TAR+5ms (5tu)
mov #CCIE,&CCTL1 ; Прерывание в режиме сравнения
bis #LPM0,SR ; Ожидание прерывания от CCR1
bic.b #Ref,&P1DIR ; Вывод ref в третье состояние,
; заряд окончен
bic.b #Ref,&P1OUT ; Сбросить ref в «0»
;--------------------Измерение времени разряда --------------------------------------------
Discharge mov.b #CARSEL+CAREF0+CAON,&CACTL1
;Вход «-» компаратора = 0.25*Vcc,
; включить компаратор
mov.w #CM1+CCIS0+CAP+CCIE,&CCTL1
; прерывание по спаду от
; CCIB, режим захвата
push &TAR ; TAR на вершину стека
; в начале преобразования
bis.b R14,&P1DIR ; Измерение от датчика или опоры
bis #LPM0,SR ; Ждём прерывания от CCR1
mov &CCR1,R14 ; R14 = TAR (CCR1) в конце
; преобразования
sub @SP+,R14 ; R14 = время разряда
bic.b #Sensor+Ref,&P1DIR ; Отключить датчик и опору
clr.b &CACTL1 ; Отключить компаратор
clr &CCTL1 ; Очистить CCTL1
clr &TACTL ; Отключить таймер timer_A
ret
;------------------------------------------------------------------------------------------
; Вычисление температуры и переход к процедуре отображения
;------------------------------------------------------------------------------------------
Calculate mov RESULT,IROP1
mov #10000,IROP2L
;------------------------------------------------------------------------------------------
; Процедура умножения IROP1 x IROP2L -> IRACM/IRACL
; используются переменные IROP1, IROP2L, IROP2M, IRACL, IRACM, IRBT
;------------------------------------------------------------------------------------------
MPYU clr IRACCL ; 0 -> МЗР результата
clr IRACCH ; 0 -> СЗР результата
MACU clr IROP2H ; 0 -> СЗР множителя
mov #1,IRBIT ; Регистр проверки бит
MPY2 bit IRBIT,IROP1 ; Проверить текущий бит
jz MPY1 ; Если 0 не делать ничего
add IROP2L,IRACCL ; Если 1 добавить множитель к результату
addc IROP2H,IRACCH
MPY1 rla IROP2L ; множитель x 2
rlc IROP2H ;
rla IRBIT ; Проверить следующий бит
jnc MPY2 ; Завершить, если проверили все
mov TEMP,IROP1
mov IRACCL,IROP2L
mov IRACCH,IROP2H
;------------------------------------------------------------------------------------------
; Подпрограмма беззнакового деления 32-бит на 16-бит
; IROP2M|IROP2L : IROP1 -> IRACL остаток в IROP2M
; возврат: carry = 0 = OK carry = 1 = частное> 16 бит
; используются переменные IROP1, IROP2L, IRACL, IRBT, IROP2M
;------------------------------------------------------------------------------------------
DIVIDE clr IRACCL ; Очистить МЗР аккумулятора
mov #17,IRBIT ; Кольцевой счётчик
DIV1 cmp IROP1,IROP2H
jlo DIV2
sub IROP1,IROP2H
DIV2 rlc IRACCL
jc RES2F ; Ошибка, результат > 16 бит
dec IRBIT ; Декремент кольцевого счётчика
jz RES2F ; Если 0, выход без сообщения об ошибке
rla IROP2L
rlc IROP2H
jnc DIV1
sub IROP1,IROP2H
setc
jmp DIV2
;------------------------------------------------------------------------------------------
; Преобразование сопротивления датчика в температуру в градусах Фаренгейта
; Табличный поиск сделан с учётом десятичного вычитания
; В IRACCL значение сопротивления
;------------------------------------------------------------------------------------------
RES2F clr R13 ;Очистить указатель таблицы
; сопротивлений
mov #99h,R14 ; R14 – счётчик
CMPR cmp RES_TAB(R13),IRACCL
; Сравнить табличное значение с
; датчиком
jl Display1 ; если значение датчика меньше
; табличного - переход
incd R13 ; Двойной инкремент указателя
dadd.b #99h,R14 ; Вычесть 1 из счётчика
mov R14,R12 ; Сохранить, чтобы при смене режима
; значение не было утеряно
jmp CMPR
;------------------------------------------------------------------------------------------
; Отображает "F", знак «°»и температуру на ЖКИ. Включает/выключает
; ЖКИ на каждом вызове, если температура ? порога. В R14 – значение температуры
; в формате BCD
;------------------------------------------------------------------------------------------
Display1 mov.b #033h,&LCDM1 ; Отобразить "F" на экране
xor.b #010h,&LCDM1+1 ; Мигающий знак ° (1-й из 2-х байт)
xor.b #013h,&LCDM1+2 ; Мигающий знак ° (2-й из 2-х байт)
mov.b #LCDM1+3,R15 ; В R15 указатель на первую позицию
; ЖКИ
CheckTemp cmp.b SetPnt,R14 ; Значение BCD в R14 ? порога?
jc ToggleLCD ; Да, переход на мигание ЖК
clr.b &P2OUT ; Лог. «0» на P2.5
bis.b #LCDSON,&LCDCTL ; Включить ЖКИ
jmp OutLCD ; переход на отображение температуры
; в R14
ToggleLCD mov.b #20h,&P2OUT ; Лог. «1» на P2.5 означает, что
; температура ? порога
xor.b #LCDSON,&LCDCTL ; Сменить состояние ЖКИ (вкл/выкл)
; при каждом вызове
jmp OutLCD ; переход на отображение температуры
; в R14
;------------------------------------------------------------------------------------------
; Отображает символы "SP" и 2 цифры порога
;------------------------------------------------------------------------------------------
Display2 mov.b #033h,&LCDM1+3 ; Отобразить на экране сегменты S & P
mov.b #011h,&LCDM1+4 ; с использованием 3 ячеек памяти ЖКИ
mov.b #027h,&LCDM1+5 ; т.к. режим 3 mux
mov.b #LCDM1,R15 ; В R15 указатель на первую позицию
; ЖКИ
jmp OutLCD ; переход на отображение порога в R14
;------------------------------------------------------------------------------------------
; Отображает часы, хранящиеся в ячейках ОЗУ MIN, HOUR. Временно используются
; Регистры R15 и R14
;------------------------------------------------------------------------------------------
Dis_Clock mov.b #LCDM1,R15; ; В R15 указатель на первую позицию
; ЖКИ
mov.b MIN,R14 ; Значение минут в формате BCD ? R14
call #OutLCD ; Вызов процедуры отображения минут
inc R15 ; Инкремент на след. позицию ЖКИ
mov.b HOUR,R14 ; Значение часов в формате BCD ? R14
; Переход к отображению часов
;------------------------------------------------------------------------------------------
; Отображает 2 цифры на ЖКИ в режиме 3 mux . Временно используются
; Регистры R15, R14 и R13
;------------------------------------------------------------------------------------------
OutLCD mov.b R14,R13 ; Копировать BCD-значение R14 ? R13
rra.b R13 ; Сдвиг R13 вправо 4 раза
rra.b R13 ; для выделения старшей тетрады
rra.b R13 ;
rra.b R13 ;
and #000Fh,R14 ; В R14 только младшая тетрада
add R14,R14 ; Удвоить R14, т.к. данные 2-байтовые
; поэтому адреса идут через 2 байта
and #000Fh,R13 ; В R13 только старшая тетрада
add R13,R13 ; Удвоить R14, т.к. данные 2-байтовые
; поэтому адреса идут через 2 байта
mov LCD_Tab(R14),LCDTEMP
;16 бит информации о сегментах ?
; LCDTEMP
;LCDTEMP = 0000 0bch 0agd 0yfe
mov.b LCDTEMP,0(R15) ; Сегменты 'dga_ef' младшей цифры
swpb LCDTEMP ; Обменять местами байты в LCDTEMP
bic.b #37h,1(R15) ; Очистить всё, кроме децимальной точки
; таким образом, она может мигать
bis.b LCDTEMP,1(R15) ; Мл. байт LCDTEMP ? ЖКИ , отображает
; сегменты 'bch' младшей цифры
mov LCD_Tab(R13),LCDTEMP
;16 бит информации о сегментах ?
; LCDTEMP
;LCDTEMP = 0000 0bch 0agd 0yfe
rla LCDTEMP ; LCDTEMP = 0000 bch0 agd0 yfe0
rla LCDTEMP ; LCDTEMP = 000b ch0a gd0y fe00
rla LCDTEMP ; LCDTEMP = 00bc h0ag d0yf e000
rla LCDTEMP ; LCDTEMP = 0bch 0agd 0yfe 0000
bis.b LCDTEMP,1(R15) ; Сегменты 'yfe' старшей цифры
swpb LCDTEMP ; LCDTEMP = 0yfe 0000 0bch 0agd
mov.b LCDTEMP,2(R15) ; Сегменты 'bchagd' старшей цифры
incd.b R15 ; Двойной инкремент указателя позиции
; ЖКИ в R15
ret
;------------------------------------------------------------------------------------------
; Инкремент часов реального времени
;------------------------------------------------------------------------------------------
Clock setc ; Вызов раз в секунду
dadc.b SEC ; Инкремент секунд с использованием
; бита carry
cmp.b #060h,SEC ;минута прошла?
jlo Clockend ; нет, выход (C = 0)
clr.b SEC ; да, очищаем счётчик секунд (C = 1)
Clock1 dadc.b MIN ; Увеличиваем счётчик минут если carry=1
cmp.b #060h,MIN ;60 мин. прошло?
jlo Clockend ; нет, завершение процедуры
clr.b MIN ; да, очищаем счётчик минут
dadc.b HOUR ; и увеличиваем счётчик часов
cmp.b #013h,HOUR ;12 часов прошло?
jlo Clockend ; нет, завершение процедуры
mov.b #01h,HOUR ; да, счётчик часов = 1
Clockend ret
;------------------------------------------------------------------------------------------
Setup ;Конфигурация модулей и управляющих регистров
;------------------------------------------------------------------------------------------
StopWDT mov #WDTPW+WDTHOLD,&WDTCTL
; Остановить сторожевой Watchdog Timer
bis.b #WDTIE,IE1 ; Разрешить прерывание от WDT
; т.к. оно используется в подпрограммах
; обработки прерываний
SetupLCD mov.b #055h,&LCDCTL ; 3mux ЖКИ, segs 20-23 = выходы
bis.b #0FCh,&P5SEL ;Установить Rxx и выводы COM для ЖКИ
SetupBT mov.b #BT_ADLY_1000,&BTCTL
; Прерывание от базового таймера Basic
; Timer 1 раз в секунду
bic.b #BTFRFQ1+BTFRFQ0,&BTCTL
;Частота ЖКИ freqLCD = ACLK / 256
mov.b #BTIE,&IE2 ; Разрешить Прерывание от базового
; таймера Basic Timer
SetupFLL2 bis.b #XCAP18PF,&FLL_CTL0
; Установить конденсаторы для кварца
mov #10000,R15
FLL_Wait dec R15 ; Задержка для умножителя частоты FLL
jnz FLL_Wait ; для установления, нужна только при
; первоначальном включении
SetupP1 mov.b #SetSW+ModeSW,&P1IE
; Прерывания от P1 разрешены
bis.b #SetSW+ModeSW,&P1IES
; Прерывание от P1 по перепаду 1? 0
mov.b #083h,&P1DIR ; P1.0,1,7 – выходы
bis.b #Ref,&P1DIR ; Перевести вывод Ref на выход,
; остальные входы при этом
; остаются в лог. «0» - потребление в
; данном случае меньше, чем в
; неподключенном состоянии
clr.b &P1OUT ; Очистить защёлку порта
SetupCA mov.b #P2CA0,&CACTL2 ; Вход «+» компаратора = P1.6
SetupPx mov.b #0FFh,&P2DIR ; порт 2 переключить на вывод
clr.b &P2OUT ; на выходе лог. «0»
mov.b #0FFh,&P3DIR ; порт 3 переключить на вывод
mov.b #0FFh,&P4DIR ; порт 4 переключить на вывод
mov.b #0FFh,P6DIR ; порт 6 переключить на вывод
ClearRAM clr SEC ; обнулить SEC & MIN одной 2-байтовой
; операцией, т.к. они в смежных ячейках
mov #0012h,HOUR ; Очистить FLAG, загрузить 12
; в ячейку часов HOURs
clr Index ; Режим установить в 0
clr.b &P1IFG ; Очистить флаги прерываний порта 1
clr.b &IFG1 ; Очистить регистр флагов прерываний 1
clr.b &IFG2 ; Очистить регистр флагов прерываний 2
eint ; Разрешить прерывания
TestTiming mov.b #4,TestFreq ; Организовать счётчик для измерения
; температуры только 1 раз за 4 сек.
mov.b #10,AutoSW ; Оставаться в режиме часов 10 сек,
; потом автоматически переходить
; в режим термостата
SetupFlash xor #FXKEY+LOCK,&FCTL3
; Отключить защиту флеш-памяти от
; записи
xor #FXKEY+WRT,&FCTL1
; Разрешить запись во флеш
SetPntr mov #1000h,Pointer ; Инициализировать указатель на
; первый адрес в информационной флеш-
; памяти
;;; mov #107Bh,Pointer ; инициализация указателя на 5 байт
;;; ; перед границей сегмента, используйте
;;; ; этот пример для записи и стирания
;;; ; через границу сегмента
;;; ; для «раскомментирования»
;;; ; убрать ";;;" в начале строки
cmp.b #0FFh,0(Pointer) ; Первая ячейка памяти пуста?
jnz InitPntr ; нет, переход к поиску текущей ячейки
mov.b #79h,0(Pointer) ; да, загрузить значение порога по
; умолчанию
jmp InitSP ; Переход к инициализации порога
InitPntr cmp.b #0FFh,1(Pointer) ; Следующая ячейка пуста?
jz InitSP ; да, переход к инициализации порога
inc Pointer ; нет, инкремент указателя
;;; cmp #1082h,Pointer ; Указатель в конце 8 байт ?
;;; ; Используйте этот пример для записи и
;;; ; стирания через границу сегмента
;;; ; для «раскомментирования»
;;; ; убрать ";;;" в начале строки
cmp #10FFh,Pointer ; Указатель на последней ячейке?
jz InitSP ; да, порог в последней ячейке
jmp InitPntr ; Проверка следующей ячейки
InitSP mov.b 0(Pointer),SetPnt ; Инициализация порога
LockFl xor #FXKEY+LOCK,&FCTL3
; Установить защиту флеш памяти
ClearLCD mov #15,R15 ; Очистить 15 байт памяти ЖКИ
Clear1 mov.b #0,LCDM1-1(R15) ; записав «0» в соотв. ячейки ОЗУ
;'-1' для доступа к 0-й ячейке LCDM1(0)
dec R15 ; Вся память ЖКИ очищена?
jnz Clear1 ; нет, чистим остальную
ret
-------------------------------------------------------------------------------------------
; P1 ISR: Выбор входа, смена режима или разрешение интервального счётчика WDT
;------------------------------------------------------------------------------------------
P1x_ISR bit.b #4,&P1IFG ; Кнопка «Режим» нажата?
jnz P12_ISR ; да, переход к подпрограмме выбора
; режима
P13_ISR mov #WDT_ADLY_250+WDTNMIES,&WDTCTL ;
; Интервал таймера WDT 250 ms
clr.b &P1IFG ; Очистить флаги прерываний порта P1
bic.b #SetSW,&P1IE ; Запретить прерывание от P1.3 interrupt
jmp EndISR
P12_ISR mov #WDT_ADLY_250+WDTNMIES,&WDTCTL
; Интервал таймера WDT 250 ms
bis.b #LCDSON,&LCDCTL ; Включить ЖКИ
clr.b &P1IFG ; Очистить флаги прерываний порта P1
incd Index ; Двойной инкремент указателя перехода
cmp #04,Index ; Выход из режима установки порога?
jz StoreSP ; да, переход к сохранению значения
cmp #08,Index ;За границами таблицы переходов?
jl EndISR ; нет, переходим
clr Index ; Очистим указатель = режим термостата
EndISR bic.b #WDTIFG,&IFG1 ; Очистка флага прерывания WDT
reti
;------------------------------------------------------------------------------------------
; Сохраняет порог, при необходимости стирает сегмент флеш-памяти
;------------------------------------------------------------------------------------------
StoreSP xor #FXKEY+LOCK,&FCTL3 ; Снять защиту флеш-памяти
cmp.b SetPnt,0(Pointer) ;Текущий порог = значению по указателю?
jz LockFlash ; да, ничего запоминать не надо
;;; cmp #1082h,Pointer ; Указатель в конце 8 байт ?
;;; ; Используйте этот пример для записи и
;;; ; стирания через границу сегмента
;;; ; для «раскомментирования»
;;; ; убрать ";;;" в начале строки
cmp #10FFh,Pointer ; Указатель на последней ячейке?
jz EraseFlash ; да, перед записью стираем
SaveSP inc Pointer ; Инкремент указателя
mov #FWKEY+WRT,&FCTL1
; Разрешить запись в флеш-память
mov.b SetPnt,0(Pointer) ; Сохранить новый порог
TestBusy1 bit #BUSY,&FCTL3 ; Проверка флага занятости
jnz TestBusy1 ; Ждём, пока освободится
LockFlash xor #FXKEY+LOCK,&FCTL3
; Установить защиту флеш-памяти
jmp EndISR ; Переход на выход прерывания WDT
EraseFlash mov #FWKEY+ERASE,&FCTL1
; Подготовка стирания
clr.b 0(Pointer) ; Фиктивная запись в сегмент
TestBusy2 bit #BUSY,&FCTL3 ; Проверка флага занятости
jnz TestBusy2 ; Ждём, пока освободится
sub #081h,Pointer ; Установим указатель на первый сегмент
mov #FWKEY+ERASE,&FCTL1
; Подготовка стирания
clr.b 0(Pointer) ; Фиктивная запись в сегмент
TestBusy3 bit #BUSY,&FCTL3 ; Проверка флага занятости
jnz TestBusy3 ; Ждём, пока освободится
;;; mov #107Ah,Pointer ; Инициализируем указатель на 6 байт перед
;;; ; границей сегмента, т.к.
;;; ; перед сохранением указатель инкрементируется
;;; ; Используйте этот пример для записи и
;;; ; стирания через границу сегмента
;;; ; для «раскомментирования»
;;; ; убрать ";;;" в начале строки
mov #0FFFh,Pointer ; Уменьшить указатель, т.к.
; перед сохранением указатель
;инкрементируется
jmp SaveSP ; Переход к сохранению порога
;------------------------------------------------------------------------------------------
; Подпрограмма обработки прерывания сторожевого таймера Watchdog
; очистка ЖКИ, проверка кнопок, если нажата кнопка «Установка»,
; инкрементировать временную задержку
;------------------------------------------------------------------------------------------
WDTInt bic #LPM3,0(SP) ; Оставаться в активном режиме
; после возврата из подпрограммы
cmp.b #2,Index ; Режим «Установка температуры»?
jeq ChngSP ; да, переход к смене порога
call #ClearLCD ; Очистить память ЖКИ
cmp.b #4,Index ; Режим «Часы»?
jne ClrSW ; нет, переход к очистке флагов кнопок
SetCLK bit.b #SetSW,&P1IN ; Нажата кнопка «Установка»?
jc ClrSW ; нет, переход к очистке флагов кнопок
Set_2 call #Clock ; Вызов процедуры часов
call #Dis_Clock ; Вызов процедуры отображения часов
mov #0500,R15 ; Программная задержка
Set_1 dec R15 ; Декремент значения задержки
jnz Set_1 ; Цикл задержки
jmp SetCLK ; Повторная проверка кнопки «Установка»
ChngSP bit.b #SetSW,&P1IN ; Нажата кнопка «Установка»?
jc ClrSW ; нет, переход к очистке флагов кнопок
cmp.b #99h,SetPnt ; Установлен максимальный порог?
jc ResetSP ; да, сброс на 32F
dadd #1,SetPnt ; нет, десятичный инкремент на 1
jmp SPdelay ; Пропустить след. инструкцию
ResetSP mov #32h,SetPnt ; Сброс порога на 32F
SPdelay mov SetPnt,R14 ; R14 используется для передачи
; значения
call #Display2 ; Обновить индикацию
mov #40000,R15 ; Программная задержка
Set_3 dec R15 ; Декремент значения задержки
jnz Set_3 ; Цикл задержки
jmp ChngSP ; Переход к повторной проверке кнопки
; «Установка»
ClrSW clr.b &P1IFG ; Очистить флаги прерываний порта 1
; на случай дребезга кнопок
bis.b #SetSW,&P1IE ; Разрешить прерывание от P1.3
Next1 mov #WDTPW+WDTHOLD,&WDTCTL
; Остановить Watchdog Timer
WDTIend reti
;------------------------------------------------------------------------------------------
; Подпрограмма обработки прерываний базового таймера Basic Timer
; BT генерирует прерывания 1 раз в секунду. Биты режима в стеке изменяются,
; поэтому после возврата из прерывания ЦПУ остаётся в активном режиме
;------------------------------------------------------------------------------------------
BT_ISR bic #LPM3,0(SP) ; Очистить биты режимов пониженного
; потребления в статусном регистре SR,
; находящемся вверху стека
call #Clock ; Обновление часов каждую секунду
; даже когда они не отображаются
reti
;------------------------------------------------------------------------------------------
TAX_ISR ; Подпрограмма обработки прерываний регистра CCR1
;------------------------------------------------------------------------------------------
CCR1_ISR bic #LPM0,0(SP) ; Выход из LPM0 по reti
bic #0001h,&CCTL1 ; Очистка флага прерывания CCR1
reti
;------------------------------------------------------------------------------------------
; Таблица символов для 4,5-цифрового 3-мультиплексного ЖКИ модели #VIM-503 4.5
;------------------------------------------------------------------------------------------
f equ 0001h
e equ 0002h
h equ 0004h
a equ 0010h
g equ 0020h
d equ 0040h
b equ 0100h ; Децимальная точка
c equ 0200h
y equ 0400h
EVEN ; Выравнивание по чётному адресу
LCD_Tab DW a+b+c+d+e+f ; Отображается "0"
DW b+c ; Отображается "1"
DW a+b+d+e+g ; Отображается "2"
DW a+b+c+d+g ; Отображается "3"
DW b+c+f+g ; Отображается "4"
DW a+c+d+f+g ; Отображается "5"
DW a+c+d+e+f+g ; Отображается "6"
DW a+b+c ; Отображается "7"
DW a+b+c+d+e+f+g ; Отображается "8"
DW a+b+c+d+f+g ; Отображается "9"
DW g ; Отображается "-"
;------------------------------------------------------------------------------------------
; Таблица сопротивлений, килоОмы ? 99-32 градусов Фаренгейта
;------------------------------------------------------------------------------------------
EVEN ; Выравнивание по чётному адресу
RES_TAB DW 6446 ;99 F
DW 6570
DW 6693
DW 6817
DW 6941 ;95 F
DW 7093
DW 7245
DW 7398
DW 7550
DW 7703 ;90 F
DW 7856
DW 8008
DW 8161
DW 8313
DW 8500 ;85 F
DW 8688
DW 8875
DW 9063
DW 9250
DW 9438 ;80 F
DW 9625
DW 9813
DW 10000
DW 10232
DW 10464 ;75 F
DW 10697
DW 10929
DW 11161
DW 11393
DW 11626 ;70 F
DW 11858
DW 12090
DW 12378
DW 12666
DW 12953 ;65 F
DW 13241
DW 13529
DW 13817
DW 14104
DW 14392 ;60 F
DW 14680
DW 15044
DW 15409
DW 15773
DW 16137 ;55 F
DW 16502
DW 16867
DW 17231
DW 17596
DW 17960 ;50 F
DW 18414
DW 18869
DW 19323
DW 19778
DW 20232 ;45 F
DW 20687
DW 21141
DW 21596
DW 22050
DW 22631 ;40 F
DW 23212
DW 23793
DW 24374
DW 24956
DW 25527 ;35 F
DW 26118
DW 26699
DW 27280 ;32 F
;--------------------------------------------------------------------------------------
; Вектора прерываний 41x
;--------------------------------------------------------------------------------------
RSEG INTVEC
DW BT_ISR ; Базовый таймер Basic Timer
DW RESET ; Порт ввода-вывода 2
DW RESET ; Нет источника
DW RESET ; Нет источника
DW P1x_ISR ; Порт ввода-вывода 1
DW TAX_ISR ; Регистры захвата-сравнения CCIFG1 & 2 таймера Timer A
DW RESET ; Регистр захвата-сравнения CCIFG0 таймера Timer A
DW RESET ; Нет источника
DW RESET ; Нет источника
DW RESET ; Нет источника
DW WDTInt ; Сторожевой таймер Watchdog Timer, режим таймера
DW RESET ; Компаратор Comparator A
DW RESET ; Нет источника
DW RESET ; Нет источника
DW RESET ; NMI, сбой генератора, ACCVIFG
DW RESET ; POR, внешний reset, Watchdog
END
Получить консультации и преобрести компоненты вы сможете у дистибутора фирмы Texas Instruments компании КОМПЭЛ, |
|