Завдяки BadMojoX, який створив plugin Dir (Display & control device, популярна мультимедійна оболонка MediaPortal отримала можливість виводити додаткову інформацію на зовнішній LCD-дисплей, а також апаратно розпізнавати сигнали з пульта дистанційного керування.
Питання щодо роботи plugin можна задавати у спеціальній гілці форуму:Dir (Display & IR) control device
Модифікована версія приставки з інтерфейсом USB на PIC18F14K50.
Для перегляду та прослуховування мультимедіа я спорудив окремий ПК на базі Intel Celeron 1200 Tualatin із встановленою оболонкою Media Portal. Ця оболонка дуже схожа на Windows Media Center, але має більш широкі можливості, безкоштовна та має безліч плагінів.
Пристрій насамперед призначений для відображення на текстовому дисплеї додаткової інформації (тривалість відтворення, ім'я файлу, що відтворюється, MP3 ID теги, активний телеканал і багато іншого, а також приймати сигнали пульта дистанційного керування (декодуванням займається МК) і відправляти декодовані команди плагіну. В режимі очікування я вирішив виводити на дисплей поточний час, дату, день тижня та температуру. Заради інтересу я також влаштував на другому рядку дисплея, інформація для якого знаходиться у встановленій на платі зовнішньої флеш-пам'яті. Тобто, можна попередньо записати з ПК туди якусь інформацію (наприклад, прогноз погоди на тиждень) і вона буде прокручуватись там.
Насамперед наведу зміст оригінального файлу interface.h, в якому описані всі команди, що використовуються при обміні даними між плагіном та приставкою. Власне весь вихідний текст виходить з цього список команд. Зеленим кольором виділено команди, які підтримуються моєю версією приставки. На решту команд приставка відповідає "CMD_UNKNOWN" або робить вигляд, що прийняла її (залежно від команди).
#ifndef INTERFACE_H
#define INTERFACE_H
// each command consists from a
single command byte
// and from
command parameters, which follow the command.
// The count of parameters is command dependent.
// Each command sent from the computer will be aknowledged
by the hardware: CMD_ACCEPTED, Command ID
// If command contains wrong parameter or the command id is
unknown, the hardware answers with: CMD_UNKNOWN,CommandID.
#define NO_CMD 0x00 //
no current command
#define CMD_PING 0x01
// pings board.
// To board: CMD_PING, From board:
CMD_ACCEPTED, CMD_PING = (Aknowledge)
#define
CMD_ACCEPTED 0x02 // reports accepted command
following by the command code
#define CMD_IR_CODE
0x03 // notyfies the computer about a key pressed on
the remote control.
// To board:
-, From board: (Aknowledge), CMD_IR_CODE, KeyCode
#define
CMD_POWERDOWN 0x04 // power down. Notyfies the hardware
that the computer will be switched off.
// To board: CMD_POWERDOWN, From board: (Aknowledge)
#define CMD_SET_ON_STATE 0x05 // followed by the
power on state, used to display different states.
// To board: CMD_SET_ON_STATE, State (1 byte), From board:
(Aknowledge)
// State byte
description:
// DISPLAY_STATE 0 -
use state
// DISPLAY_TIME 1 -
display current time
//
DISPLAY_ALARM 2 - display alarm symbol
// DISPLAY_REC 3 - display rec. symbol
// DISPLAY_DATE1 4 date format to display (00- no date)
// DISPLAY_DATE2 5
// DISPLAY_BRIGHTNESS 6 - display LCD brightness in % (only
offline mode)
#define CMD_SET_OFF_STATE 0x06
// followed by the power on state , used to display
different states
// To board:
CMD_SET_ON_STATE, State (1 byte), From board: (Aknowledge), State byte is the
same
// as for CMD_SET_ON_STATE.
#define CMD_SET_LED 0x07 // followed by the led
state
// To board: CMD_SET_LED,
Led state (0/1) From board: (Aknowledge)
#define CMD_GET_BR_ITEM
0x08 // followed by the position
// To board: CMD_GET_BR_ITEM, Position (0...)
// From board: if the entry exists then
(Aknowledge) and informations
//
From time (Hour, Min) (2 bytes), To time (Hour, Min) (2 bytes), 2 Bytes
brightness (| 0x8000 if the entry is valid and used).
// From board: if the entry does not exist then:
CMD_UNKNOWN, CMD_GET_BR_ITEM = (Failed)
#define CMD_SET_BR_ITEM
0x09 // followed by the position index + from time + to
time + brightness
// To board:
CMD_SET_BR_ITEM, Index, 6 data bytes. From board: (Aknowledge) or (Failed)
#define CMD_GET_ON_STATE 0x0A // get on common state
// To board: CMD_GET_ON_STATE, From board: (Aknowledge),
CMD_GET_ON_STATE, State (1 byte)
#define CMD_GET_OFF_STATE 0x0B
// get off common state
// To board: CMD_GET_OFF_STATE, From board: (Aknowledge),
CMD_GET_OFF_STATE, State (1 byte)
#define CMD_GET_LED 0x0C
// returns led state
// To board: CMD_GET_LED, From board: (Aknowledge),
CMD_LED, State (1 byte)
#define CMD_CHECK_BR_TABLE 0x0D
// reset stored minutes to check the brightness from the
table
// To board:
CMD_CHECK_BR_TABLE, From board: (Aknowledge)
#define CMD_GET_POWER_DELAY 0x0E // returns power change
delay in seconds
// To board:
CMD_GET_POWER_DELAY, From board: (Aknowledge), CMD_GET_POWER_DELAY, Delay (1
byte)
#define CMD_SET_POWER_DELAY 0x0F //
set power delay in seconds
// To
board: CMD_SET_POWER_DELAY, Delay (1 byte), From board: (Aknowledge)
#define CMD_SET_HOUR 0x10 //
set hour
// To board:
CMD_SET_HOUR, Hour (1 byte), From board: (Aknowledge)
#define CMD_SET_MIN 0x11 // set
min
// To board: CMD_SET_MIN, Min
(1 byte), From board: (Aknowledge)
#define
CMD_SET_SEC 0x12 // set sec
// To board: CMD_SET_SEC, Sec (1 byte), From board: (Aknowledge)
#define CMD_SET_DAY 0x13 // set
day
// To board: CMD_SET_DAY, Day
(1 byte), From board: (Aknowledge)
#define
CMD_SET_MON 0x14 // set month
// To board: CMD_SET_MON, Min (1 byte), From board: (Aknowledge)
#define CMD_SET_YEAR 0x15
//21 set year
// To board:
CMD_SET_YEAR, Year (2 bytes), From board: (Aknowledge)
#define CMD_SET_WEEK 0x35 //
set day of week
// To board: CMD_SET_WEEK, week (1 byte), From board: (Aknowledge)
#define
CMD_SET_ALARM 0x16 // set alarm to hour, min, day,
month
// To board: CMD_SET_ALARM,
Hour (1byte), Min (1byte), Day (1byte), Month(1 byte), From board: (Aknowledge)
#define CMD_ALARM_ENABLE 0x17 // enable alarm, 0 -
disable, 1-enable
// To board:
CMD_ALARM_ENABLE, Enable/Disable (1 byte), From board: (Aknowledge)
#define CMD_LCD_CLEAR 0x20 //
lcd clrscr
// To board:
CMD_LCD_CLEAR, From board: (Aknowledge)
#define CMD_LCD_HOME 0x21
// lcd home
// To board: CMD_LCD_HOME, From board: (Aknowledge)
#define CMD_LCD_GOTO 0x22 //
lcd goto
// To board:
CMD_LCD_GOTO, Position (1byte), From board: (Aknowledge)
#define CMD_LCD_TEXT 0x23 //
followed by a string, terminated by 0
// To board: CMD_LCD_TEXT, Text, 0, From board: (Aknowledge)
#define CMD_LCD_CGRAM 0x24 // programm cgram,
address, then the values
#define CMD_LCD_BRIGHT 0x25
// sets the immediate lcd brightness
#define CMD_W_EXT_FLASH 0x30 //
Write data to external EEPROM //To board: CMD_W_EXT_FLASH, Text, 0, From board:
(Aknowledge)
//0 = 48
// To board: CMD_LCD_BRIGHT, Brightness (2 bytes), From
board: (Aknowledge)
#define CMD_GET_BOARD_ID
0x80 //returns command accepted followed by two
bytes 0xAA55
// To board:
CMD_GET_BOARD_ID, From board: (Aknowledge), CMD_GET_BOARD_ID, 0xAA55
#define CMD_GET_BOARD_HW 0x81
//returns command accepted followed by two bytes HW Version
// To board: CMD_GET_BOARD_HW, From board: (Aknowledge),
CMD_GET_BOARD_HW, (HW Version) 2 bytes
#define
CMD_GET_BOARD_SW 0x82 // returns command accepted
followed by two bytes SW Version
// To board: CMD_GET_BOARD_SW, From board: (Aknowledge), CMD_GET_BOARD_SW, (SW
Version) 2 bytes
#define CMD_GET_BOARD_INFO
0x83 // returns command accepted followed by command
id + board information text terminated by 0 character
// To board: CMD_GET_BOARD_INFO, From board: (Acknowledge),
CMD_GET_BOARD_INFO, Text, 0 character
#define
CMD_UNKNOWN 0xFF // unknown command
#define BOARD_ID_LO 0x55
#define BOARD_ID_HI 0xAA
#define BOARD_HW_LO
0x00
#define BOARD_HW_HI 0x01
#define BOARD_SW_LO 0x02
#define
BOARD_SW_HI 0x00
#endif
Робота з плагіном дуже проста. Достатньо правильно відповідати на отримані команди. Як зазначено вище, при отриманні приставкою команди вона має надіслати команду CMD_ACCEPTED і далі переслати отриманий код команди. Наприклад, на команду CMD_PING приставка має відповісти CMD_ACCEPTED CMD_PING.
З огляду на це вдалося отримати досить просту функцію обробки команд, написану мовою Сі:
void fn_CMD_ACCEPTED(unsigned char key)
{
putc(CMD_ACCEPTED);
putc(key);
}
......
if (FIFOsize>0) key=ReadFIFO();
else key=0;
//FIFO - буфер приема UART.
switch(key) {
case NO_CMD : break;
case CMD_PING : fn_CMD_ACCEPTED(CMD_PING); break;
//Ping
case CMD_SET_ON_STATE: putc(CMD_UNKNOWN);
putc(key); StandBy=0; break;
case
CMD_SET_OFF_STATE:fn_CMD_SET_STATE(CMD_SET_OFF_STATE); break;
case CMD_SET_LED : ReadFIFO(); fn_CMD_ACCEPTED(CMD_SET_LED); break;
case CMD_GET_ON_STATE: putc(CMD_UNKNOWN); putc(key); break;
case CMD_SET_HOUR : hour=ReadFIFO(); fn_CMD_ACCEPTED(CMD_SET_HOUR);
AdditionalInfo=RefreshClock=3; break;
case
CMD_SET_MIN : min=ReadFIFO(); fn_CMD_ACCEPTED(CMD_SET_MIN); AdditionalInfo=RefreshClock=3;
break;
case CMD_SET_SEC : sec=ReadFIFO();
fn_CMD_ACCEPTED(CMD_SET_SEC); AdditionalInfo=RefreshClock=3; break;
case CMD_SET_DAY : day=ReadFIFO(); fn_CMD_ACCEPTED(CMD_SET_DAY);
AdditionalInfo=RefreshClock=3; break;
case
CMD_SET_MON : mon=ReadFIFO(); fn_CMD_ACCEPTED(CMD_SET_MON); AdditionalInfo=RefreshClock=3;
break;
case CMD_SET_YEAR : fn_CMD_SET_YEAR();
AdditionalInfo=RefreshClock=3; break;
case
CMD_SET_WEEK : week=ReadFIFO(); fn_CMD_ACCEPTED(CMD_SET_WEEK);
AdditionalInfo=RefreshClock=3; break;
case
CMD_LCD_CLEAR : DisplayClear(); break;
case
CMD_LCD_HOME : LCDGoTo(0); fn_CMD_ACCEPTED(CMD_LCD_HOME); break;
case CMD_LCD_GOTO : LCDGoTo(ReadFIFO()); fn_CMD_ACCEPTED(CMD_LCD_GOTO);
break;
case CMD_LCD_TEXT : LCDTextOut();
fn_CMD_ACCEPTED(CMD_LCD_TEXT); StandBy=0; break;
case CMD_GET_BOARD_ID:fn_CMD_ACCEPTED(CMD_GET_BOARD_ID); putc(CMD_GET_BOARD_ID);
putc(BOARD_ID_LO); putc(BOARD_ID_HI); break;
case CMD_GET_BOARD_HW:fn_CMD_ACCEPTED(CMD_GET_BOARD_HW); putc(CMD_GET_BOARD_HW);
putc(0x01); putc(0x00); break;
case CMD_GET_BOARD_SW:fn_CMD_ACCEPTED(CMD_GET_BOARD_SW); putc(CMD_GET_BOARD_SW);
putc(0x02); putc(0x00); break;
case CMD_GET_BOARD_INFO:fn_CMD_ACCEPTED(CMD_GET_BOARD_INFO); putc(CMD_GET_BOARD_INFO);
putc(0x33); putc(0x34); putc(0x35); putc(0x00); break;
case CMD_W_EXT_FLASH: WriteExternalFlash(); fn_CMD_ACCEPTED(CMD_W_EXT_FLASH);
break;
default : putc(CMD_UNKNOWN); putc(key);
ShowError(key); break;
}
Приставка побудована на базі мікроконтролера PIC16F887 (вдосконалена версія PIC16F877A, корпус DIP40), працює на частоті 4 МГц (кварцевий резонатор). Перетворювач RS232-UART - MAX232CPE, мікросхема годинника (RTC) DS1307 (DIP8, I2C), EEPROM-пам'ять - 24AA32 (DIP8, I2C, 32кбіта, підходить на любий об'єм, прив'язки в прошивці немає. Це для інформації в другому рядку).
Щоб заощадити на батарейках :) я встановив в схему живлення годинника реального часу DS1307 іоністор ємністю 0.1F (5.1V). Заряду впевнено достатньо на кілька тижнів роботи без зовнішнього живлення, більше в мене не було можливості перевірити (жити без приставки не можу :)). Для підзарядки використовується подільник напруги на двох резисторах і захистному діоді, що запобігає розряду через схему.
Після довгих роздумів, як дисплей був обраний BC2002BFNLCH з зеленим інверсним підсвічуванням та висотою символів 9.6 мм.
Щоб зробити приставку компактною, я спроектував друковану плату таких самих розмірів, як і сам дисплей, що дозволило встановити її за ним.
Друкована плата виготовлялася за ЛУТ-технологією:
Плата в форматі SprintLayout 5.0.
У прошивці встановлена швидкість 9600 кбіт/с (без бітів контролю парності, один стоповий біт).
Прошивка: build 31 (04.05.09) Прошивка.hex (PIC16F887)
Файл "DirControlDevicePlugin.DisplayStates.xml" містить оформлення інформації, що виводиться на дисплей. Мій файл розрахований на дисплей 20x2:
Файл "DirControlDevicePlugin.Cyrylic.CharacterTranslations.xml" містить таблицю перетворення кириличних символів з кодування UTF-8 (ну і win-1251) в кириличне кодування зашите в LCD-дисплей на контролері типу HD44780 (KS0066U). У зв'язку з тим, що стандартна таблиця символів контролера HD44780 (KS0066U) не містить українських символів, вони завантажуються програмно після подачі живлення.
Файл "DirControlDevicePlugin.DisplayTypes.xml" містить геометрію Вашого LCD-дисплея (8x1, 16x2, 0x20). Файл легко підправити вручну під дисплей.
Ці файли слід покласти поруч із файлом плагіна.
1.///Версия прошивки:
2.#define
BuildVer "\fDISPLAY v1.0\nbuild 31 (04.05.09)"
3.
4.#include
<16F887.h>
5.#include
"interface.h"
6.
7.#device
*=16
8.#device
adc=8
9.
10.
11.#FUSES
WDT
//Watch Dog Timer
12.#FUSES
XT
//Crystal osc <= 4mhz
13.#FUSES
PUT
//Power Up Timer
14.#FUSES
MCLR
//Master Clear pin enabled
15.#FUSES
NOPROTECT
//Code not protected from reading
16.#FUSES
NOCPD
//No EE protection
17.#FUSES
BROWNOUT
//Reset when brownout detected
18.#FUSES
NOIESO
//Internal External Switch Over mode disabled
19.#FUSES
NOFCMEN
//Fail-safe clock monitor disabled
20.#FUSES
NOLVP
//No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
21.#FUSES
NODEBUG
//No Debug mode for ICD
22.#FUSES
NOWRT
//Program memory not write protected
23.#FUSES
BORV21
//Brownout reset at 2.1V
24.#FUSES
NODEBUG
//No Debug mode for ICD
25.#FUSES
NOLVP
//No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
26.#FUSES
NOWRT
//Program memory not write protected
27.
28.
29.#use
delay(clock=4000000,RESTART_WDT)
30.//#use
rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,errors)
31.//#use
i2c(Master,Slow,sda=PIN_C4,scl=PIN_C3,SMBUS) //,FORCE_HW ,NOFLOAT_HIGH,
32.#use
i2c(Master,Slow,sda=PIN_C4,scl=PIN_C3,force_hw)
33.
34.#use
fast_io(A) // Работа с портами без переключения
35.#use
fast_io(B) // каждый раз регистров TRIS
36.#use
fast_io(C) //
37.#use
fast_io(D) //
38.
39.#byte
PORTA = 0x05
40.#byte
PORTB = 0x06
41.#byte
PORTC = 0x07
42.#byte
PORTD = 0x08
43.#byte
PORTE = 0x09
44.
45.#byte
TRISA = 0x85
46.
47.#byte
RCSTA = 0x18
48.#bit
OERR = RCSTA.1
49.#bit
CREN = RCSTA.4
50.
51.#byte
TMR2 = 0x11
52.
53.#bit
CTS = PORTC.0
54.
55.
56.#bit
IrRXpin = PORTB.0 //Ir RX pin
57.#bit
IrRXLEDpin = PORTA.1 //Ir RX pin
58.
59.#define
use_portd_lcd TRUE
60.#include
<LCD.C>
61.
62.
63.//#bit
RxOverflowBit = RS232_ERRORS.1
64.
65.#define
FIFOsizemax 31
66.#define
TEXTBUFFER 21
67.
68.unsigned
int16 year;
69.unsigned
char
mon,day,hour,min,sec,msec,week;
70.unsigned
char
StandBy;
71.unsigned
char
IrTimeOut;
72.unsigned
char
CustomCode1,CustomCode2,DataCode1,DataCode2,CodeCounter,IrDAclock,PrevCommand,IrRxFlag;
73.unsigned
char
RefreshDisplay, RefreshClock;
74.unsigned
char
FIFOstart,FIFOend,FIFOsize,FIFOover;
75.unsigned
char
FIFObuffer[FIFOsizemax];
76.unsigned
int16 AdditionalInfo;
77.unsigned
int16 UpdateTemperatureCount;
78.
79.//Перечень
функций
80.void
main(void);
81.void
TIMER0_isr(void);
82.void
LCDTextOut(void);
83.void
lcd_VarOut(int16
OutVar);
84.void
LCDGoTo(unsigned
char
Pos);
85.void
lcd_ZeroOut(void);
86.#separate
void ShowCyrTime(void);
87.unsigned
char
RemoteControllRX(void);
88.void
RxDataOut(void);
89.void
ShowInfo(void);
90.void
WriteTestTextToExtEEPROM(void);
91.void
RefreshTime(void);
92.void
WriteExternalFlash(void);
93.void
Read10bytesFlash(void);
94.unsigned
char
ReadFIFO(void);
95.//void
WriteFIFO(unsigned char);
96.//void
InitFIFO(void);
97.
98.//void
ToggleMode(void);
99.//void
ReadCurrent(void);
100.
void
RefreshTemperature(void);
101.
void
UpdateTemperature(void);
102.
103.
//// My One Wire DS18S20
104.
unsigned
char
OneWire_reset(void);
105.
void
OneWire_Write(unsigned
char
WData);
106.
unsigned
char
OneWire_Read(void);
107.
108.
void
SetTime(void);
109.
110.
unsigned
char
RemoteControllRX2(void);
///TEST!!!
111.
112.
#byte PIE1 = 0x8C
113.
#byte PIR1 = 0x0C
114.
115.
//UART
116.
#byte TXSTA = 0x98
117.
#bit CSRC = TXSTA.7
118.
#bit TX9 = TXSTA.6
119.
#bit TXEN = TXSTA.5
120.
#bit SYNC =
TXSTA.4
121.
#bit BRGH = TXSTA.2
122.
#byte RCSTA = 0x18
123.
#bit SPEN = RCSTA.7
124.
#bit RX9 = RCSTA.6
125.
#byte SPBRG = 0x99
126.
#bit TXIE = PIE1.4
127.
#bit RCIE = PIE1.5
128.
#bit TXIF = PIR1.4
129.
#byte TXREG = 0x19
130.
131.
//Список переменных для функции
ShowInfo
132.
#define DISPLAY_COL_MAX 25
133.
unsigned
int16 SI_pointer;
134.
unsigned
char
SI_buffer[DISPLAY_COL_MAX];
135.
unsigned
int16 SI_Refresh;
136.
137.
signed
int8 CyrInTemp,CyrOutTemp;
138.
139.
//Таблица дополнительных
загружаемых символов
140.
unsigned
char
cgram[64]
=
{
141.
0x0E,0x11,0x10,0x1C,0x10,0x11,0x0E,0x00,
// символ 0x00 Є
142.
0x00,0x00,0x0E,0x10,0x1c,0x10,0x0E,0x00,
// символ 0x01 є
143.
0x0A,0x00,0x04,0x04,0x04,0x04,0x0E,0x00,
// символ 0x02 Ї
144.
0x0A,0x00,0x0C,0x04,0x04,0x04,0x0E,0x00,
// символ 0x03 ї
145.
0x02,0x05,0x02,0x00,0x00,0x00,0x00,0x00,
// символ 0x04 градус
146.
0x00,0x00,0x1E,0x08,0x04,0x08,0x1E,0x00,
// символ 0x05
147.
0x1f,0x00,0x1f,0x00,0x1f,0x00,0x1f,0x00,
// символ 0x06
148.
0x1f,0x00,0x1f,0x00,0x1f,0x00,0x1f,0x00
// символ 0x07
149.
};
150.
151.
void
load_cgram(void)
{
152.
unsigned
char
x;
153.
lcd_send_byte(0,0x40);
// вызов записи в регистры ЖКИ
154.
delay_us(45);
155.
for
(x
=
0;
x <
64;
x++)
156.
{
157.
lcd_send_byte(1,cgram[x]);
// вызов записи данных в ЖКИ
158.
delay_us(50);
159.
}
160.
lcd_send_byte(0,0x80);
// вызов записи в
регистры ЖКИ
161.
162.
}
163.
164.
void
putc(unsigned
char
bt)
165.
{
166.
//Проверяем, закончилась ли
предыдущая передача
167.
while(TXIF==0);
//если нет, то ждем.
168.
TXREG=bt;
// Загружаем данные для передачи
169.
}
170.
171.
172.
173.
#int_TIMER0
174.
void
TIMER0_isr(void)
175.
{
176.
if
(OERR==1)
{
lcd_putc("\fOver");
while(1);
}
//Если переполнение буфера приема -
зависаем
177.
if
(FIFOover==1)
{
lcd_putc("\fFIFO");
while(1);
}
178.
179.
mSec++;
180.
if(mSec>15)
//16
181.
{
Sec++;
182.
mSec=0;
183.
if
(Sec>59)
184.
{
Sec=0;
185.
Min++;
186.
187.
if
(Min>59)
188.
{
Hour++;
189.
Min=0;
}
190.
if
(hour>23)
191.
{
day++;
192.
hour=0;
193.
194.
if
((day>28)&(mon==2))
195.
{
day=0;
196.
mon++;
}
197.
if
((day>30)&((mon==4)&(mon==6)&(mon==4)&(mon==9)&(mon==11)))
198.
{
day=0;
199.
mon++;
}
200.
if
(day>31)
201.
{
day=0;
202.
mon++;
}
203.
if
(mon>12)
204.
{
year++;
205.
mon=0;
}
206.
}
207.
}
208.
209.
}
210.
if
(IrDAclock<250)
IrDAclock++;
211.
}
212.
213.
void
LCDTextOut(void)
214.
{
215.
//#include
"codetable.h"
216.
unsigned
char
Ch,i,n;
217.
unsigned
char
buffer[TEXTBUFFER+1];
218.
219.
for
(i=0;i<TEXTBUFFER;i++)
buffer[i]=0;
//Инициализация буфера
220.
221.
Ch=ReadFIFO();
222.
i=0;
223.
while
(Ch!=0)
//Заполнение буфера данными из СОМ порта
224.
{
225.
buffer[i]=Ch;
226.
Ch=ReadFIFO();
227.
i++;
228.
if
(i>TEXTBUFFER)
break;
229.
restart_wdt();
230.
}
231.
232.
for
(n=0;n<i;n++)
233.
{
if
(buffer[n]>0)
234.
{/*
if(buffer[n]>122) Ch=CyrTable[Ch-123];
235.
else
236.
Ch=buffer[n];
237.
if(buffer[n]==92) Ch=47;
238.
*/
239.
240.
lcd_putc(buffer[n]);
241.
}
242.
243.
if
(IrRXpin==0)
//Обрабатываем сигналы с пульта вне
очереди
244.
{
RemoteControllRX();}
245.
restart_wdt();
246.
247.
}
//Вывод содержимого буфера на дисплей
248.
249.
}
250.
251.
void
lcd_VarOut(int16
OutVar)
//Вывод на ЖК числа
252.
{
253.
byte buffer[8]={0,0,0,0,0,0,0,0};
254.
unsigned
char
i;
255.
256.
//sprintf(buffer,"%3.0w",OutVar);
257.
sprintf(buffer,"%lu",OutVar);
258.
i=0;
259.
while(i<8)
260.
{if
(buffer[i]>32)
lcd_putc(buffer[i]);
261.
i++;
262.
restart_wdt();
263.
}
264.
}
265.
266.
void
LCDGoTo(unsigned
char
Pos)
267.
{
268.
unsigned
char
x,y;
269.
if
(Pos<0x40)
{x=Pos;
y=0;}
else
{x=Pos-0x40;
y=1;}
270.
lcd_gotoxy(x+1,y+1);
271.
}
272.
273.
void
lcd_ZeroOut(void)
274.
{
lcd_putc("0");
}
275.
276.
#define InfoScroll 1000
277.
#define InfoScrollDate
InfoScroll/3.0
278.
279.
//#separate
280.
void
ShowCurentTemperature(signed
char
cT)
281.
{
unsigned
char
T;
282.
lcd_putc("єi\xBC
");
283.
284.
285.
// if (cT<0)
286.
// { lcd_putc("-");
T=0xFF-cT+1; }
287.
//
else
288.
T=cT;
289.
lcd_VarOut(T>>1);
290.
lcd_putc(0x04);
291.
lcd_putc(0x20);
lcd_putc(0x20);
292.
// lcd_VarOut(CyrOutTemp);
293.
294.
}
295.
296.
297.
#separate void Day_Monday(void)
298.
{
lcd_putc("Ёo\xBDeгi\xBBoє");
}
//Понеділок
299.
300.
#separate void
Day_Tuesday(void)
301.
{lcd_putc("Biіїopoє");}
302.
303.
#separate void Day_Wednesday(void)
304.
{lcd_putc("Cepeгa");}
305.
306.
#separate void Day_Thursday(void)
307.
{lcd_putc("«eїіep");}
308.
309.
#separate void Day_Friday(void)
310.
{lcd_putc("Ё'ЗїЅёеЗ");}
311.
312.
#separate
313.
void
ShowCyrTime(void)
314.
{
315.
316.
RefreshDisplay++;
317.
if
((FIFOsize==0)&&(StandBy==1)&&(RefreshDisplay>250))
318.
{
319.
{
//Отображение времени
320.
lcd_gotoxy(1,1);
321.
if
(((FIFOsize==0)))
{
if(hour<10)
lcd_ZeroOut();
lcd_VarOut(hour);
}
322.
if
(FIFOsize==0)
lcd_putc(":");
323.
if
(((FIFOsize==0)))
{
if(min<10)
lcd_ZeroOut();
lcd_VarOut(min);
}
324.
325.
AdditionalInfo++;
326.
lcd_gotoxy(7,1);
327.
if
(AdditionalInfo<(InfoScroll*(1.0/3.0)))
328.
{//Отображение
даты
329.
if
(((FIFOsize==0))&&(IrRXpin))
330.
if
(((FIFOsize==0))&&(IrRXpin))
{
if(day<10)
lcd_ZeroOut();
lcd_VarOut(day);
}
331.
if
(((FIFOsize==0))&&(IrRXpin))
lcd_putc(".");
332.
if
(((FIFOsize==0))&&(IrRXpin))
{
if(mon<10)
lcd_ZeroOut();
lcd_VarOut(mon);
}
333.
if
(((FIFOsize==0))&&(IrRXpin))
lcd_putc(".");
334.
if
(((FIFOsize==0))&&(IrRXpin))
{
lcd_VarOut(year);
RefreshDisplay=0;
}
335.
}
336.
//Отображение дня недели
337.
if
((AdditionalInfo>(InfoScroll*(1.0/3.0)))&&(AdditionalInfo<(InfoScroll*(2.0/3.0))))
338.
{
339.
if
(week==2)
Day_Monday();
// Понеділок
340.
if
(week==3)
Day_Tuesday();
341.
if
(week==4)
Day_Wednesday();
342.
if
(week==5)
Day_Thursday();
343.
if
(week==6)
Day_Friday();
344.
if
(week==7)
lcd_putc("CyІoїa");
345.
if
(week==1)
lcd_putc("Heгi»З");
//Неділя
346.
347.
//
lcd_putc(">"); lcd_putc(0x00); lcd_putc(0x01); lcd_putc(0x02); lcd_putc(0x03);
lcd_putc(0x04);
348.
349.
{unsigned
char
fff=0;
350.
while
(fff<5)
351.
{
lcd_putc("
");
fff++;}
352.
}
353.
}
354.
//Отображение температуры
355.
if
((AdditionalInfo>(InfoScroll*(2.0/3.0)))&&(AdditionalInfo<(InfoScroll*(3.0/3.0))))
356.
{
ShowCurentTemperature(CyrInTemp);
357.
}
358.
//Синхронизация часов с DS1307
359.
if
(AdditionalInfo==1)
RefreshTime();
360.
361.
if
(AdditionalInfo>InfoScroll)
AdditionalInfo=0;
362.
}
363.
}
364.
}
365.
366.
367.
void
init_all(void)
368.
{
369.
unsigned
int
i;
370.
371.
year=2008;
372.
mon=day=hour=min=sec=week=0;
373.
StandBy=1;
374.
375.
//UpdateTemperature();
376.
377.
SET_TRIS_A(0b10101111);
378.
SET_TRIS_C(0b10011110);
379.
SET_TRIS_D(0b00000000);
380.
381.
382.
383.
lcd_init();
384.
load_cgram();
//Загрузить спец. символы
385.
386.
setup_adc_ports(NO_ANALOGS);
387.
setup_adc(ADC_OFF);
388.
//setup_psp(PSP_DISABLED);
389.
//setup_spi(FALSE);
390.
setup_wdt(WDT_18MS|WDT_TIMES_128);
391.
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
392.
setup_timer_1(T1_DISABLED);
393.
setup_timer_2(T2_DIV_BY_16,255,12);
394.
setup_comparator(NC_NC_NC_NC);
395.
setup_vref(FALSE);
396.
397.
lcd_putc(BuildVer);
398.
399.
delay_ms(255);
400.
delay_ms(255);
401.
delay_ms(255);
402.
delay_ms(255);
403.
delay_ms(255);
404.
delay_ms(255);
405.
delay_ms(255);
406.
407.
//Инициализация ShowInfo
408.
for(i=0;i<DISPLAY_COL_MAX
;i++)
409.
{
SI_buffer[i]=0;
}
410.
411.
RefreshClock=1;
//Обновить часы побыстрее
412.
413.
414.
//Настройка
UART
415.
SPBRG=25;
//9600=25
416.
SYNC=0;
//TXSTA: асинхронный режим
417.
TX9=0;
//TXSTA: 8ми битный режим
418.
BRGH=1;
//TXSTA: высокоскоростной режим работы
419.
RCIE=1;
420.
RX9=0;
//RCSTA: 8ми битный режим
421.
CREN=1;
//RCSTA: Разрешение приема
422.
SPEN=1;
//RCSTA: включение UART
423.
TXEN=1;
//TXSTA: передача разрешенна
424.
425.
FIFOover=FIFOsize=FIFOstart=FIFOsize=FIFOend=0;
426.
427.
enable_interrupts(INT_TIMER0);
// Прерывания от таймера0
428.
429.
430.
// TestDebug:
431.
IrRxFlag=0;
//Сигналов с пульта не принимали
432.
lcd_putc("\f");
433.
}
434.
#separate
435.
void
fn_CMD_ACCEPTED(unsigned
char
key)
436.
{
437.
putc(CMD_ACCEPTED);
438.
putc(key);
439.
}
440.
441.
//Команда перевода приставки в
активное состояние
442.
//#separate
443.
void
fn_CMD_SET_STATE(unsigned
char
key)
444.
{
unsigned
char
key2;
445.
if
(key==CMD_SET_ON_STATE)
446.
{
StandBy=0;}
447.
if
(key==CMD_SET_OFF_STATE)
448.
{
StandBy=1;}
449.
key2=ReadFIFO();
450.
451.
fn_CMD_ACCEPTED(key);
452.
453.
//putc(key2);
454.
455.
}
456.
#separate
457.
void
ShowError(unsigned
char
key)
458.
{
459.
lcd_putc("\fErr:");
lcd_VarOut(key);
460.
}
461.
#separate
462.
void
DisplayClear()
463.
{lcd_putc("\f");
fn_CMD_ACCEPTED(CMD_LCD_CLEAR);}
464.
465.
#separate
466.
void
fn_CMD_SET_YEAR(void)
467.
{
year=0;
468.
year=(year|((unsigned
int16)(ReadFIFO())));year=year|(((unsigned
int16)(ReadFIFO()))<<8);
469.
fn_CMD_ACCEPTED(CMD_SET_YEAR);
470.
}
471.
472.
void
main(void)
473.
{
474.
unsigned
char
key;
//buffer for rx command
475.
476.
init_all();
477.
restart_wdt();
478.
enable_interrupts(GLOBAL);
// Глобальное разрешение прерываний
479.
//DisplayClear();
480.
while(1)
481.
{
482.
483.
//if
(kbhit()) key = getch(); else key=0;
484.
if
(FIFOsize>0)
key=ReadFIFO();
else
key=0;
485.
486.
switch(key)
{
487.
case
NO_CMD :
break;
488.
case
CMD_PING
:
fn_CMD_ACCEPTED(CMD_PING);
break;
//Ping
489.
case
CMD_SET_ON_STATE:
putc(CMD_UNKNOWN);
putc(key);
StandBy=0;
break;
490.
case
CMD_SET_OFF_STATE:fn_CMD_SET_STATE(CMD_SET_OFF_STATE);
break;
491.
case
CMD_SET_LED :
ReadFIFO();
fn_CMD_ACCEPTED(CMD_SET_LED);
break;
492.
case
CMD_GET_ON_STATE:
putc(CMD_UNKNOWN);
putc(key);
break;
493.
case
CMD_SET_HOUR :
hour=ReadFIFO();
fn_CMD_ACCEPTED(CMD_SET_HOUR);
AdditionalInfo=RefreshClock=3;
break;
494.
case
CMD_SET_MIN :
min=ReadFIFO();
fn_CMD_ACCEPTED(CMD_SET_MIN);
AdditionalInfo=RefreshClock=3;
break;
495.
case
CMD_SET_SEC :
sec=ReadFIFO();
fn_CMD_ACCEPTED(CMD_SET_SEC);
AdditionalInfo=RefreshClock=3;
break;
496.
case
CMD_SET_DAY :
day=ReadFIFO();
fn_CMD_ACCEPTED(CMD_SET_DAY);
AdditionalInfo=RefreshClock=3;
break;
497.
case
CMD_SET_MON :
mon=ReadFIFO();
fn_CMD_ACCEPTED(CMD_SET_MON);
AdditionalInfo=RefreshClock=3;
break;
498.
case
CMD_SET_WEEK :
week=ReadFIFO();
fn_CMD_ACCEPTED(CMD_SET_WEEK);AdditionalInfo=RefreshClock=3;
break;
499.
case
CMD_SET_YEAR :
fn_CMD_SET_YEAR();
AdditionalInfo=RefreshClock=3;
break;
500.
501.
case
CMD_LCD_CLEAR :
DisplayClear();
break;
//Clead Display
502.
case
CMD_LCD_HOME :
LCDGoTo(0);
fn_CMD_ACCEPTED(CMD_LCD_HOME);
break;
503.
case
CMD_LCD_GOTO :
LCDGoTo(ReadFIFO());
fn_CMD_ACCEPTED(CMD_LCD_GOTO);
break;
// GoTo
504.
case
CMD_LCD_TEXT :
LCDTextOut();
fn_CMD_ACCEPTED(CMD_LCD_TEXT);
StandBy=0;
break;
// TextOut
505.
case
CMD_GET_BOARD_ID:fn_CMD_ACCEPTED(CMD_GET_BOARD_ID);
putc(CMD_GET_BOARD_ID);
putc(BOARD_ID_LO);
putc(BOARD_ID_HI);
break;
// lcd_putc("\fID
version");
506.
case
CMD_GET_BOARD_HW:fn_CMD_ACCEPTED(CMD_GET_BOARD_HW);
putc(CMD_GET_BOARD_HW);
putc(0x01);
putc(0x00);
break;
// lcd_putc("\fHW version");
507.
case
CMD_GET_BOARD_SW:fn_CMD_ACCEPTED(CMD_GET_BOARD_SW);
putc(CMD_GET_BOARD_SW);
putc(0x02);
putc(0x00);
break;
// lcd_putc("\fSW version");
508.
case
CMD_GET_BOARD_INFO:fn_CMD_ACCEPTED(CMD_GET_BOARD_INFO);
putc(CMD_GET_BOARD_INFO);
putc(0x33);
putc(0x34);
putc(0x35);
putc(0x00);
break;
509.
510.
case
CMD_W_EXT_FLASH:
WriteExternalFlash();
fn_CMD_ACCEPTED(CMD_W_EXT_FLASH);
break;
511.
// case
CMD_R_EXT_FLASH: Read10bytesFlash(); break;
512.
513.
514.
default
:
putc(CMD_UNKNOWN);
putc(key);
ShowError(key);
break;
//Unknown command
515.
}
516.
517.
///// WriteExternalFlash();
///***********
518.
restart_wdt();
519.
520.
521.
522.
//Если была команда установки года,
то сохраним это все в RTC
523.
if(key==CMD_SET_SEC)
SetTime();
524.
525.
if
(IrRXpin==0)
526.
{
RemoteControllRX();
}
527.
528.
if
((key==NO_CMD)&&(StandBy==1))
529.
{
UpdateTemperature();
//Функция считывания значения температуры
530.
ShowInfo();
//Вывод на дисплей
времени, даты и др.
531.
ShowCyrTime();
532.
restart_wdt();
533.
}
534.
535.
if
((IrRxFlag==1)&&(FIFOsize==0)&&(key==NO_CMD))
536.
{
RxDataOut();
//Отправка в порт принятой команды с ИК
пульта ДУ
537.
IrRxFlag=0;
538.
}
539.
540.
/* if
((IrRxFlag==1)&&(FIFOsize==0)) //???
541.
{
RxDataOut();
542.
IrRxFlag=0;
543.
}
544.
*/
545.
546.
547.
}
548.
}
549.
550.
#define
Min0RxBitTime 58
551.
#define Max0RxBitTime 100
552.
#define Min1RxBitTime 116
553.
#define Max1RxBitTime 174
554.
555.
unsigned
char
IrRXbyteNEC(unsigned
char
RxByte)
556.
{
557.
unsigned
char
IndexByte,BitTime,BitMask,RxByte2;
558.
CTS=0;
559.
IndexByte=0;
560.
RxByte2=0;
561.
//RxByte=10;
562.
while(IndexByte<8)
563.
{
while((IrRXpin==0)&&(IrTimeOut==0))
restart_wdt();
// начало синхроимпульса
564.
while((IrRXpin==1)&&(IrTimeOut==0))
restart_wdt();
// конец синхроимпульса
565.
while((IrRXpin==0)&&(IrTimeOut==0))
restart_wdt();
// начало следующего
бита
566.
BitTime=TMR2;
567.
if
(IrTimeOut>1)
break;
568.
TMR2=IrTimeOut=0;
569.
if
((BitTime<Min0RxBitTime)|(BitTime>Max1RxBitTime))
{
IrTimeOut=1;
break;
}
570.
if
(BitTime<Max0RxBitTime)
BitMask=0;
571.
if
(BitTime>Min1RxBitTime)
572.
{
BitMask=1;
573.
BitMask=BitMask<<IndexByte;
574.
RxByte2|=BitMask;
575.
}
576.
IndexByte++;
577.
}
578.
579.
if
(CodeCounter==1)
CustomCode1=RxByte2;
580.
if
(CodeCounter==2)
CustomCode2=RxByte2;
581.
if
(CodeCounter==3)
DataCode1=RxByte2;
582.
if
(CodeCounter==4)
DataCode2=RxByte2;
583.
RxByte=RxByte2;
584.
585.
if
(IrTimeOut==0)
586.
{
return
1;
}
587.
else
588.
{
return
0;
}
589.
590.
}
591.
592.
unsigned
char
RemoteControllRX2(void)
593.
{
594.
595.
putc(CMD_ACCEPTED);
//Test UART transmit
596.
putc(CMD_ACCEPTED);
597.
putc(CMD_ACCEPTED);
598.
putc(CMD_ACCEPTED);
599.
600.
601.
CustomCode1=0x02;
602.
CustomCode2=0xFD;
603.
DataCode1=0x01;
604.
DataCode2=0xFE;
605.
606.
IrRxFlag=1;
607.
IrRXLEDpin=1;
608.
return
1;
609.
610.
}
611.
612.
613.
unsigned
char
RemoteControllRX(void)
614.
{
615.
unsigned
char
bitIndex;
616.
//Готовим буфер для приема
617.
//IrRXLEDpin=1;
618.
if
(IrRxFlag==1)
goto
RxOK;
//Если уже есть принятая, но
неотправленная команда, то выходим
619.
CustomCode1=CustomCode2=DataCode1=DataCode2=bitIndex=0;
620.
//lcd_putc("\fIrDA");
621.
622.
//Готовим таймер1
623.
setup_timer_2(T2_DIV_BY_4,255,1);
//переполнение каждые 1024 мкс
624.
//setup_timer_2(T2_DIV_BY_16,255,1); //переполнение каждые 4096 мкс
625.
enable_interrupts(INT_TIMER2);
626.
//Ждем окончания стартового бита.
Бит 1.
627.
TMR2=IrTimeOut=0;
628.
//while((IrRXpin==0)&(IrTimeOut<10));
629.
while(1)
630.
{
if
(IrRXpin!=0)
break;
631.
if
(IrTimeOut>10)
break;
632.
restart_wdt();
633.
}
634.
if
(IrTimeOut>10)
GoTo RxTimeOut;
635.
636.
//Пауза на 4 мс
637.
TMR2=IrTimeOut=0;
638.
while(IrTimeOut<3)
restart_wdt();
639.
640.
setup_timer_2(T2_DIV_BY_16,255,1);
//переполнение каждые
4096 мкс
641.
642.
//Ждем появления первого байта
643.
TMR2=IrTimeOut=0;
644.
while((IrRXpin==1)&(IrTimeOut==0))
restart_wdt();
645.
if
(IrTimeOut>0)
GoTo RxTimeOut;
646.
//Прием байта Custom code
647.
TMR2=IrTimeOut=0;
648.
CodeCounter=1;
649.
if
(!IrRXbyteNEC(CustomCode1))
GoTo RxTimeOut;
650.
CodeCounter=2;
651.
if
(!IrRXbyteNEC(CustomCode2))
GoTo RxTimeOut;
652.
CodeCounter=3;
653.
if
(!IrRXbyteNEC(DataCode1))
GoTo RxTimeOut;
654.
CodeCounter=4;
655.
if
(!IrRXbyteNEC(DataCode2))
GoTo RxTimeOut;
656.
657.
disable_interrupts(INT_TIMER2);
658.
//Функция отладки. Логический
анализатор
659.
660.
GoTo RxOK;
661.
662.
663.
RxTimeOut:;
//Метка. Сюда переходим, если были ошибки
приема
664.
IrRxFlag=0;
665.
IrRXLEDpin=0;
666.
return
0;
667.
668.
goto
DataOut;
669.
670.
RxOK:;
671.
IrRxFlag=1;
672.
IrRXLEDpin=1;
673.
return
1;
674.
675.
DataOut:;
//Вывод данных на дисплей
676.
}
677.
678.
679.
void
RxDataOut(void)
680.
{
681.
//lcd_putc("\f");
682.
//Проверяем код устройства:
683.
if
((CustomCode1==0x02)||(CustomCode2==0xFD)||(CustomCode2==0x03)||(CustomCode2==0xFC))
684.
{
//Проверяем принятый байт команды на
правильность
685.
if
(DataCode1==(255-DataCode2))
686.
{
//Если все совпало, то выполняем
антидребезг
687.
if((PrevCommand!=DataCode1)||(IrDAclock>6))
//5
688.
{
putc(CMD_IR_CODE);
//Если следующая команда другая или
прошло больше 1 сек,то передаем команду
689.
if((CustomCode1==0x02)||(CustomCode2==0xFD))
putc(DataCode1);
// Мой пульт использует два кода
оборудования
690.
if((CustomCode1==0x03)||(CustomCode2==0xFC))
putc(DataCode1+0xE0);
// Для дополнительного
кода +0xE0
691.
IrDAclock=0;
//
692.
PrevCommand=DataCode1;
693.
IrRXLEDpin=0;
694.
}
695.
}
696.
}
697.
698.
}
699.
700.
#int_TIMER2
701.
void
TIMER2_isr()
702.
{
703.
IrTimeOut++;//Флаг
переполнения таймера
704.
}
705.
706.
707.
//Появился байт в буфере приема
708.
#byte RCREG = 0x1A
709.
710.
//Считывание байта
из буфера приема в FIFO буфер
711.
#int_RDA
712.
void
RDA_isr(void)
713.
{
714.
unsigned
char
RxByte;
715.
RxByte=RCREG;
716.
if
(FIFOsize<FIFOsizemax)
// Проверяем, есть ли место
717.
{
FIFObuffer[FIFOend]=RxByte;
//Записываем в буфер значение
718.
FIFOend++;
// Увеличиваем показания счетчика позиции
(указатель)
719.
FIFOsize++;
// Увеличиваем значение размера буфера
720.
if
(FIFOend>=FIFOsizemax)
//Проверяем выход за
конец буфера
721.
{
FIFOend=0;}
// и устанавливаем указатель в начало
722.
restart_wdt();
723.
724.
}
else
FIFOover=1;
725.
726.
}
727.
728.
729.
//Чтение из буфера приема
730.
unsigned
char
ReadFIFO(void)
731.
{
unsigned
char
FIFObyte;
732.
while(FIFOsize==0)
restart_wdt();
//Ожидание получения следующего байта
733.
if
(FIFOsize>0)
// Если размер буфера больше нуля
734.
{
FIFObyte=FIFObuffer[FIFOstart];
// Считываем байт из буфера
735.
FIFOsize--;
// Количество байт в
буфере -1
736.
FIFOstart++;
// Указатель на следующий байт
737.
if
(FIFOstart>=FIFOsizemax)
// Если дошли до границы буфера
738.
{FIFOstart=0;}
// переходим в начало
739.
restart_wdt();
740.
}
741.
return
FIFObyte;
742.
}
743.
744.
745.
//Функция для
вывода текстовой информации из внешней памяти во второй строке дисплея
746.
void
ShowInfo(void)
747.
{
748.
unsigned
char
i;
749.
750.
if
(SI_Refresh<8192)
GoTo SI_END;
751.
SI_Refresh=0;
752.
753.
disable_interrupts(GLOBAL);
754.
755.
if
(SI_buffer[0]==0x00)
756.
{
//Буфер пуст. Начинаем загрузку текста с
начала
757.
SI_pointer=0x00;
758.
//Указываем
начальный адресс для чтения данных
759.
}
760.
//if
(SI_pointer!=0x00)
761.
{
// Если указатель указывает не на адресс 0
762.
// то следует сместить данные на 1 байт
763.
i=0;
764.
while(i<(DISPLAY_COL_MAX-1))
765.
{
SI_buffer[i]=SI_buffer[i+1];
766.
i++;
767.
}
768.
SI_buffer[DISPLAY_COL_MAX-1]=0x00;
769.
}
770.
restart_wdt();
771.
772.
//Ищем первую свободную ячейку в
буфере
773.
i=0;
774.
while((SI_buffer[i]!=0x00)&&(i<DISPLAY_COL_MAX))
i++;
775.
776.
777.
778.
if
(i<(DISPLAY_COL_MAX-5))
//Делаем чтение блоками
779.
{
//по 5 байт
780.
delay_us(90);
781.
i2c_start();
// Restart
782.
i2c_write(0xA7);
// Адресс устройства
783.
784.
while(i<DISPLAY_COL_MAX)
785.
{//
Загружаем данные в буфер до его заполнения
786.
delay_us(255);
787.
restart_wdt();
788.
if
(i<DISPLAY_COL_MAX-1)
789.
SI_buffer[i]
=
i2c_read(1);
790.
else
791.
SI_buffer[i]
=
i2c_read(0);
792.
793.
if
(SI_buffer[i]==0x00)
794.
{
// Найден маркер конца сообщения.
795.
// указываем
адресс начала
796.
i2c_read(0);
// Даем сигнал окончания чтения
797.
i2c_stop();
// Посылаем сигнал СТОП
798.
i2c_start();
// Старт
799.
i2c_write(0xA6);
//Режим записи
800.
i2c_write(0x00);
// Адресс ячейки
801.
i2c_write(0x00);
// Адресс ячейки
802.
i2c_start();
// Старт
803.
i2c_write(0xA7);
//Режим чтения
804.
805.
if
(i<DISPLAY_COL_MAX-1)
806.
SI_buffer[i]
=
i2c_read(1);
807.
else
808.
SI_buffer[i]
=
i2c_read(0);
809.
810.
SI_pointer=0;
811.
}
812.
813.
814.
i++;
815.
SI_pointer++;
816.
}
817.
818.
i2c_stop();
819.
i2c_stop();
820.
}
821.
822.
i=0;
823.
lcd_gotoxy(1,2);
824.
while(i<(DISPLAY_COL_MAX-5))
825.
{
//Вывожу текст на экран
826.
if
(SI_buffer[i]>0)
lcd_putc(SI_buffer[i]);
827.
i++;
828.
restart_wdt();
829.
}
830.
enable_interrupts(GLOBAL);
831.
SI_END:;
832.
SI_Refresh++;
833.
}
834.
835.
836.
837.
//Преобразования из двоичной
системы в двоично-десятичную
838.
unsigned
char
rtf_format(unsigned
char
rtc_data)
839.
{
840.
unsigned
char
buf[2],rtc_res_data;
841.
842.
sprintf(buf,"%2d",rtc_data);
843.
if
(buf[0]==0x20)
buf[0]=48;
844.
rtc_res_data=(buf[0]-48)<<4;
845.
rtc_res_data+=(buf[1]-48);
846.
847.
return
rtc_res_data;
848.
}
849.
850.
//Функция
установки текущего времени в часах реального времени DS1307
851.
void
SetTime(void)
852.
{
853.
unsigned
char
rtc_data;
854.
855.
i2c_start();
// Старт
856.
i2c_write(0xD0);
// DS1307.Запись
857.
i2c_write(0);
// Начинаем с минут
858.
859.
//Подготовка значения секунд
860.
rtc_data=rtf_format(sec);
861.
i2c_write(rtc_data);
862.
rtc_data=rtf_format(min);
863.
i2c_write(rtc_data);
864.
rtc_data=rtf_format(hour);
865.
i2c_write(rtc_data);
866.
867.
/* //Тут мы пропускаем регист дня
недели
868.
i2c_start();
// Старт
869.
i2c_write(0xD0); //
DS1307.Запись
870.
i2c_write(0x04); // 4я ячейка. */
871.
872.
i2c_write(week);
// День недели
873.
rtc_data=rtf_format(day);
874.
i2c_write(rtc_data);
875.
rtc_data=rtf_format(mon);
876.
i2c_write(rtc_data);
877.
rtc_data=rtf_format((unsigned
int16)(year-2000));
878.
i2c_write(rtc_data);
879.
rtc_data=0b00000000;
//Байт настроек доп. выхода.
880.
i2c_write(rtc_data);
881.
882.
883.
i2c_stop();
884.
restart_wdt();
885.
}
886.
887.
888.
889.
//Функция чтения текущего времени
из часов реального времени DS1307
890.
void
RefreshTime(void)
891.
{
892.
unsigned
char
rtc_day,rtc_mon,rtc_year,rtc_hour,rtc_min,rtc_sec;
893.
894.
if
(RefreshClock!=1)
GoTo NoRTCfounded;
// Обновляем показания очень редко!
895.
896.
i2c_start();
// Старт
897.
i2c_write(0xD0);
// Адресс устройства
898.
i2c_write(0);
// Адресс ячейки
899.
900.
i2c_start();
// Restart
901.
i2c_write(0xD1);
// Адресс устройства
902.
903.
rtc_sec
=i2c_read(1)&0b01111111;
// Чтение секунд
904.
rtc_min
=i2c_read(1)&0b01111111;
905.
rtc_hour=i2c_read(1)&0b00111111;
906.
week=i2c_read(1)
&0b00000111;
907.
rtc_day=i2c_read(1)
&0b00111111;
908.
rtc_mon=i2c_read(1)
&0b00011111;
909.
rtc_year=i2c_read(0);
910.
911.
i2c_stop();
912.
913.
restart_wdt();
914.
915.
if
(rtc_sec==0x7F)
GoTo
NoRTCfounded;
916.
917.
//sec =(rtc_sec &0b00001111+((rtc_sec &0b01110000)>>4)*0x0A);
918.
sec
=rtc_sec
&
0b00001111;
919.
sec
=(rtc_sec>>4)*0x0A+sec;
920.
921.
922.
//min =(rtc_min &0b00001111+((rtc_min &0b01110000)>>4)*0x0A);
923.
min
=rtc_min
&0b00001111;
924.
min
=(rtc_min>>4)*0x0A
+
min;
925.
//hour=(rtc_hour&0b00001111+((rtc_hour&0b00110000)>>4)*0x0A);
926.
hour=rtc_hour&0b00001111;
927.
hour=(rtc_hour>>4)*0x0A+hour;
928.
929.
//day =(((rtc_day
&0b00110000)>>4)*0x0A+rtc_day &0b00001111);
930.
day
=
rtc_day
&0b00001111;
931.
day
=(rtc_day>>4)*0x0A
+
day;
932.
933.
//mon =(rtc_mon
&0b00001111+((rtc_mon &0b00010000)>>4)*0x0A);
934.
mon
=rtc_mon
&0b00001111;
935.
mon
=(rtc_mon>>4)*0x0A
+
mon;
936.
937.
//year=rtc_year&0b00001111 +((rtc_year&0b11110000)>>4)*0x0A;
938.
year=rtc_year&0b00001111;
939.
year=(rtc_year>>4)*0x0A+year;
940.
year+=2000;
941.
NoRTCfounded:;
942.
RefreshClock++;
943.
if
(RefreshClock>5)
RefreshClock=0;
944.
}
945.
946.
void
WriteExternalFlash(void)
947.
{
948.
unsigned
char
S;
949.
unsigned
int16 adr;
950.
if
(ReadFIFO()==0x31)
951.
{if
(ReadFIFO()==0x39)
//Защита от случайной записи
952.
{
953.
i2c_start();
// Старт
954.
i2c_write(0xA6);
// Адресс устройства
955.
delay_us(50);
956.
i2c_write(0);
// Адресс ячейки
957.
i2c_write(0);
// Адресс ячейки
958.
959.
adr=0;
960.
961.
do
{
i2c_start();
// Старт
962.
delay_us(100);
963.
i2c_write(0xA6);
// Адресс устройства
964.
delay_us(100);
965.
//i2c_write((adr&0b1111111100000000)>>8); // Адресс ячейки
966.
i2c_write(adr>>8);
// Адресс ячейки
967.
delay_us(100);
968.
i2c_write(adr);
// Адресс ячейки
969.
//i2c_write(adr
&0b0000000011111111); // Адресс ячейки
970.
971.
S=ReadFIFO();
972.
i2c_write(S);
973.
974.
if
(S==0x00)
i2c_write(S);
//Записываем подряд два нуля.
975.
delay_us(100);
976.
i2c_stop();
977.
delay_ms(6);
978.
restart_wdt();
979.
adr++;
980.
// if
(S==0x40) break;
981.
}
while
((S!=0x00)&&(S!=0xFF));
982.
}
983.
else
984.
putc(CMD_UNKNOWN);
985.
}
986.
else
987.
putc(CMD_UNKNOWN);
988.
}
989.
990.
void
Read10bytesFlash(void)
991.
{
992.
unsigned
char
i,sec;
993.
994.
i2c_start();
// Старт
995.
i2c_write(0xA7);
// Адресс
устройства
996.
i=1;
997.
while(i<10)
998.
{if
(i<9)
999.
sec
=
i2c_read(1);
1000.
else
1001.
sec
=
i2c_read(0);
1002.
putc(sec);
1003.
i++;
1004.
restart_wdt();
1005.
}
1006.
1007.
i2c_stop();
1008.
}
1009.
1010.
1011.
1012.
//******
1013.
1014.
#bit DS1821_PIN =
PORTA.4
1015.
#define
DS1821_PIN_INPUT TRISA|=0b00010000;
1016.
#define DS1821_PIN_OUTPUT
TRISA&=0b11101111;
1017.
1018.
//Команды OneWire интерфейса
1019.
#define SEARCH_ROM 0xF0
1020.
#define READ_ROM
0x33
1021.
#define MATCH_ROM 0x55
1022.
#define SKIP_ROM 0xCC
1023.
1024.
//Команды DS1821
1025.
#define
DS1821_Start_Convert_T 0xEE
1026.
#define DS1821_Stop_Convert_T
0x22
1027.
#define DS1821_Read_Temperature
0xAA
1028.
1029.
//Команды DS1820
1030.
#define
DS1820_Start_Convert_T 0x44
1031.
#define DS1820_Read_Scratchpad
0xBE
1032.
1033.
//=== Reset ===
1034.
unsigned
char
OneWire_reset(void)
1035.
{
1036.
int1 DeviceOK;
1037.
unsigned
char
wait;
1038.
1039.
//Выдаем "0" в линию
1040.
DS1821_PIN=0;
1041.
DS1821_PIN_OUTPUT
1042.
1043.
//Пауза на 480 мкс
1044.
Delay_us(250);
1045.
Delay_us(230);
1046.
1047.
//Отпускаем линию на 15 мкс
1048.
DS1821_PIN_INPUT
1049.
Delay_us(15);
1050.
1051.
//Ожидаем импульс подтверждения от
ведомых устройств 60 мкс
1052.
wait=DeviceOK=0;
1053.
while(wait<37)
1054.
{
wait++;
1055.
if
(DS1821_PIN==0)
{
DeviceOK=1;
}
1056.
}
1057.
//lcd_VarOut(PORTA);
1058.
restart_wdt();
1059.
return
DeviceOK;
1060.
}
1061.
//#define nop #asm nop; #endasm
1062.
//Функция отправки лог. 0 в линию
1063.
void
OneWire_Send0(void)
1064.
{
// Посылаем 0 в течении 80 мкс
1065.
DS1821_PIN_OUTPUT
1066.
delay_us(80);
1067.
DS1821_PIN_INPUT
1068.
}
1069.
//Функция отправки лог. 1 в линию
1070.
void
OneWire_Send1(void)
1071.
{
// Посылаем 0 в течении 1 мкс
1072.
DS1821_PIN_OUTPUT
//(начало тайм-слота)
1073.
delay_us(1);
1074.
DS1821_PIN_INPUT
1075.
// Посылаем 0 в течении 80 мкс
1076.
delay_us(80);
1077.
}
1078.
1079.
void
OneWire_Write(unsigned
char
WData)
1080.
{
1081.
unsigned
char
i;
1082.
i=0;
1083.
while(i<8)
1084.
{
if
((WData&0b00000001)==1)
1085.
OneWire_Send1();
1086.
else
1087.
OneWire_Send0();
1088.
WData=WData>>1;
1089.
i++;
1090.
}
1091.
restart_wdt();
1092.
}
1093.
//Чтение данных из шины. Таймслот = 60...120 мкс
1094.
unsigned
char
OneWire_Read(void)
1095.
{
1096.
unsigned
char
i,RData;
1097.
#locate Dbit = 0x7F
1098.
//int1 Dbit;
1099.
i=0;
1100.
while(i<8)
1101.
{//Принятый
бит
1102.
Dbit=1;
1103.
//Смещаем
принятые биты
1104.
RData=RData>>1;
1105.
1106.
//Посылаем
тактовый импульс
1107.
DS1821_PIN_OUTPUT
//(начало тайм-слота)
1108.
delay_us(1);
1109.
DS1821_PIN_INPUT
1110.
delay_us(4);
1111.
1112.
if
(DS1821_PIN==0)
Dbit=0;
//15 мкс
1113.
if
(DS1821_PIN==0)
Dbit=0;
//30 мкс
1114.
if
(DS1821_PIN==0)
Dbit=0;
//45
1115.
if
(DS1821_PIN==0)
Dbit=0;
//60
1116.
if
(DS1821_PIN==0)
Dbit=0;
//75
1117.
if
(DS1821_PIN==0)
Dbit=0;
//90
1118.
if
(DS1821_PIN==0)
Dbit=0;
//105
1119.
if
(DS1821_PIN==0)
Dbit=0;
//120
1120.
if
(DS1821_PIN==0)
Dbit=0;
//135
1121.
if
(DS1821_PIN==0)
Dbit=0;
//150
1122.
if
(DS1821_PIN==0)
Dbit=0;
1123.
if
(DS1821_PIN==0)
Dbit=0;
1124.
if
(DS1821_PIN==0)
Dbit=0;
1125.
if
(DS1821_PIN==0)
Dbit=0;
1126.
if
(DS1821_PIN==0)
Dbit=0;
1127.
1128.
if
(Dbit==1)
RData|=0b10000000;
1129.
1130.
//Пауза
в 1 мкс
1131.
delay_us(15);
1132.
i++;
1133.
}
1134.
restart_wdt();
1135.
return
RData;
1136.
}
1137.
1138.
void
UpdateTemperature(void)
1139.
{
1140.
1141.
if
(UpdateTemperatureCount!=0)
GoTo EndUT;
1142.
1143.
disable_interrupts(GLOBAL);
1144.
if
(OneWire_reset()==1)
1145.
{
// Есть сигнал ответа от
ведомого
1146.
// продолжим....
1147.
delay_us(1);
1148.
//Обращаемся
ко всем (или единственному на проводе)
1149.
1150.
//Даем
команду чтения температуры
1151.
OneWire_Write(SKIP_ROM);
1152.
delay_us(100);
1153.
//OneWire_Write(DS1821_Read_Temperature);
//DS1821
1154.
OneWire_Write(DS1820_Read_Scratchpad);
//DS18S20
1155.
1156.
delay_us(100);
1157.
CyrInTemp=OneWire_Read();
1158.
1159.
//
CyrInTemp=OneWire_Read()<<8+CyrInTemp;
1160.
1161.
//Даем
команду на запуск преобразования температуры
1162.
OneWire_reset();
1163.
OneWire_Write(SKIP_ROM);
1164.
delay_us(1);
1165.
//OneWire_Write(Start_Convert_T);
1166.
OneWire_Write(DS1820_Start_Convert_T);
//DS18S20
1167.
1168.
1169.
}
1170.
enable_interrupts(GLOBAL);
1171.
1172.
EndUT:;
1173.
UpdateTemperatureCount++;
1174.
}
Опубліковано
Оновлено 30.11.2023