Дисплей - приставка к ПК


Благодаря 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кбита, подходит на любой объем, привязки в прошивке нет).

Схема приставки к ПК. Тектовый ЖК-дисплей, приемник ИК сигналов пульта ДУ
Схема, в формате sPlan 5.

Чтобы сэкономить на батарейке :) я установил в схему питания часов реального времени DS1307  ионистор емкостью 0,1Ф (5,1В). Заряда уверенно достаточно на сутки работы без питания, больше у меня не было возможности проверить (жить без приставки не могу :) ). Для подзарядки используется простой делитесь напряжения на двух резисторах и защитный диод, предотвращающий разряд через схему.

После долгих раздумий, в качестве дисплея был выбран BC2002BFNLCH c зеленой инверсной подсветкой и высотой символов почти 10 мм.

Чтобы сделать приставку компактной я спроектировал печатную плату таких же размеров, как и сам дисплей, что позволило установить ее за ним. Я долго искал корпус для приставки, но по-прежнему все установлено так как на фото.

Внешний вид приставки-дисплея на базе LCD BC2002B PIC16F887 (PIC16F877A)

Печатная плата изготавливалась по ЛУТ-технологии:

Плата
Плата

Печатная плата в формате SprintLayout 5.0.

Обратная сторона

BC2002B

В прошивке установлена скорость 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
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.     }

05.01.2010