Благодаря BadMojoX, который создал plugin Dir (Display & control device, популярная мультимедийная оболочка MediaPortal обрела возможность выводить дополнительную информацию на внешний ЖК дисплей, а также аппаратно распознавать сигналы с пульта ДУ.
Вопросы касательно работы плугина можно задавать в специальной ветке форума:Dir (Display & IR) control device
Модифицировання версия приставки с интерфейсом USB на PIC18F14K50 здесь.
Для просмотра и прослушивания мультимедиа я соорудил отдельный ПК на базе Intel Celeron 1200 Tualatin с установленной оболочкой Media Portal. Эта оболочка очень похожа на Windows Media Center, но обладает гораздо более широкими возможностями, бесплатная и имеет множество плагинов.
Устройство прежде всего предназначено для отображения на текстовом дисплее дополнительной информации (длительность воспроизведения, имя воспроизводимого файла, MP3 ID тэги, активный телеканал и много другое, а также принимать сигналы пульта ДУ (декодированием занимается МК) и отправлять декодированные команды плагину. В режиме ожидания я решил выводить на дисплей текущее время, дату, день недели и температуру. Ради интереса я также устроил бегущую строку во второй строке дисплея, информация для которой находится в установленной на плате внешней флэш-памяти.
Прежде всего приведу содержание оригинального файла interface.h, в котором описаны все команды используемые при обмене данными между плагином и приставкой. Собственно весь исходный текст базируется на этом списке команд. Зеленым цветом выделены команды, которые поддерживаются моей версией приставки. На остальные команды приставка отвечает "неизвестная команда" или делает вид, что приняла ее (в зависимости от команды).
#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 МГц (кварцевый резонатор). Преобразователь интерфейсов - MAX232CPE, часы реального времени - DS1307 (DIP8, I2C), flash-память - 24AA32 (DIP8, I2C, 32кбита, подходит на любой объем, привязки в прошивке нет).
Чтобы сэкономить на батарейке :) я установил в схему питания часов реального времени DS1307 ионистор емкостью 0,1Ф (5,1В). Заряда уверенно достаточно на сутки работы без питания, больше у меня не было возможности проверить (жить без приставки не могу :) ). Для подзарядки используется простой делитесь напряжения на двух резисторах и защитный диод, предотвращающий разряд через схему.
После долгих раздумий, в качестве дисплея был выбран BC2002BFNLCH c зеленой инверсной подсветкой и высотой символов почти 10 мм.
Чтобы сделать приставку компактной я спроектировал печатную плату таких же размеров, как и сам дисплей, что позволило установить ее за ним. Я долго искал корпус для приставки, но по-прежнему все установлено так как на фото.
Печатная плата изготавливалась по ЛУТ-технологии:
Печатная
плата в формате SprintLayout 5.0.
В прошивке установлена скорость 9600 кбит/с (без битов
контроли четности, один стоповый бит). При программировании (прошивке микроконтроллера) желательно
включить WDT. Прошивка: 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" содержит геометрию Вашего ЖКИ дисплея (8x1, 16x2, 0x20). Файл легко подправить под Ваш дисплей вручную.
GeSHi © 2004-2007 Nigel McNie, 2007-2009 Benny Baumann, 2008-2009 Milian Wolff
05.01.2010
Вспомогательные материалы
Эти файлы следует положить рядом с файлом плагина.
Демонстрация работы плагина и приставки
Исходный код
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.
}