Keyboard

 

Пример клавиатуры в системе на базе микроконтроллера семейства MCS-51

Микросхема кодера SAA3010 (код RC-5)

 


Довольно часто разработчик микроконтроллерной системы сталкивается с проблемой создания клавиатуры с количеством кнопок более десятка. При этом совсем не хочется увеличивать стоимость системы за счет введения схем обработки клавиатуры или нагружать микроконтроллер задачами по обслуживанию последней.

В таких ситуациях может быть полезна идея использовать широко распространенный кодер SAA3010 фирмы PHILIPS, использующей код для передачи сформированных кодов кнопок под названием RC-5.

Эта микросхема была спроектирована для систем дистанционного управления аудио-видео аппаратурой и используется в пультах дистанционного управления. Однако этот кодер можно с успехом использовать в системах на базе микроконтроллера в качестве контроллера клавиатуры. Подробное описание этой микросхемы я не буду приводить здесь, так как достаточно литературы, ее описывающей, и мест в Интернете, где она подробно рассмотрена.

Остановлюсь на конкретном примере использования этого кодера в системе на базе микроконтроллера семейства MCS-51.

В моем, реально работающем, приборе, SAA3010 подключена к микроконтроллеру T89C51RD2.

SAA3010 в тактируется извне (однако, это может быть и керамический резонатор на частоту 450 КГц, как это описано в документации на микросхему) частотой равной частоте кварцевого резонатора микроконтроллера деленной на 32 (деление происходит в программируемой логической интегральной схеме).

Частота кварцевого резонатора микроконтроллера равна 11.059200 МГц. После деления получаем частоту равную 345600 КГц.

Выход кодера подключен к входу внешнего прерывания микроконтроллера INT0.

Используемые ресурсы микроконтроллера: внешнее прерывание INT0 (старт анализа посылки) и TIMER1 (для сэмплирования битов посылки).

Вот собственно и все аппаратные подключения.

Формат посылки кодера SAA3010 с комментариями приведены на рисунке.

 

 

Текст программы на языке Си приведен ниже.

 

Содержание файла main.h.

 

#define false                      0
           
#define true                       1

#define HighB(value)         (value >> 8)
           
#define LowB(value)         (value)

#define RELOAD1           0xf600
           
#define RELOAD             0xf800
           
#define KEYBOARD       P3_2
 

Содержание файла main.с.

 

///////////////////////////////////////////////////
            // Проект Keyboard                 //
            // Кодер SAA3010                  //
            //////////////////////////////////////////////////

            //////////////////////////////////////////////////
            // Design SoftWare:                  //
            // Keil Software, Inc.                //
            // C compiler V7.10                 //
            // Assembler V7.09                  //
            // Linker/Locator LX51 V3.63 //
            //////////////////////////////////////////////////


           
// Заголовочные файлы


           
#include <89c51rd2.h>
           
#include "main.h"

           
// Битовые переменные


            bit sound
;
            bit startBit
, toggleBit;
            bit key
;

           
// Глобальные переменные


            unsigned char data addressCode
, commandCode;
            unsigned char data qPulses
;
            unsigned char data delay0
, delay1;
           

// Обработка прерывания от кодера SAA3010


            void Keyboard
(void) interrupt 0
            
{

   // Запретить прерывание до анализа кода кнопки
               EX0 =
0;

   // Засинхронизироваться на середину первого стартового бита
               while
(!KEYBOARD);

   // Загрузить таймер 1
               TH1 = HighB
(RELOAD1);
               TL1 = LowB
(RELOAD1);

   // Запустить таймер 1
               TR1 =
1;

   // Инициализировать счетчик битов на ноль
               qPulses =
0;

   addressCode = 0;

   commandCode = 0;
            
}
           

// Системный тайминг


            void Timer0
(void) interrupt 1
            
{

 

   // Перезагрузка таймера 0 для интервала 2 мс. при частоте кварца 11.059200 МГц
               TH0 =
0xf8;
               TL0 =
0xcd;


              
// Сформировать длительность звукового импульса длительностью 100 мс.

   if(sound)
              
{

     // Включить зуммер
                 P1_0 =
0;
                 delay0
--;
                 if
(!delay0)
                 
{
                   delay0 =
50;

       // Выключить зуммер
                   P1_0 =
1;
                   sound = false
;
              
    }
               }
 

   // Определение отпускания кнопки


               if
(key)
               
{
                 if
(KEYBOARD)
                 
{
                    delay1
--;
                    if
(!delay1)
                    
{
                       EX0 =
1;
                       delay1 =
50;
                       key = false
;
                    
}
                 
}
                  else delay1 =
50;
              
 }


             
}    


           
// Анализ битов посылки кодера SAA3010


            void Timer1
(void) interrupt 3
            
{
               bit bLevel
;


              
// Определение состояния выхода кодера SAA3010
               bLevel = KEYBOARD
;


              
// Перезагрузка таймера 1 для анализа следующего бита
               TH1 = HighB
(RELOAD);
               TL1 = LowB
(RELOAD);

               switch
(qPulses)
               
{
                  case
0:
                  
// Определение стартового бита 2
                   startBit = false
;
                   if
(bLevel) startBit = true;
                   break
;
                  case
1:
                  
// Определение toggle бита
                   toggleBit = false
;
                   if
(bLevel) toggleBit = true;
                   break
;
                  case
2:
                  case
3:
                  case
4:
                  case
5:

      case 6:
                  
// Определение 5, 4, 3, 2 и 1-го бита адреса
                   if
(bLevel) addressCode |= 0x01;
                    else addressCode
&= 0xfe;
                  if
(qPulses != 6) addressCode = addressCode << 1;

       break;
                  case
7:
                  case
8:
                  case
9:
                  case
10:
                  case
11:

      case 12:
                  
// Определение 6, 5, 4, 3, 2 и 1-го бита команды
                   if
(bLevel) commandCode |= 0x01;
                    else commandCode
&= 0xfe;
                   if
(qPulses != 12)

        {

          commandCode = commandCode << 1;

          break;

        }

 

       // Все тринадцать анализов битов сделаны

       // Теперь определение действий по коду commandCode


                   TR1 =
0;

       key = true;

 

       // Для предотвращения сбоев, определение действий по коду commandCode

       // делается только при наличии второго стартового бита и, например, при addressCode равном нулю


                   if
(startBit && !addressCode)
                   
{
                      switch
(commandCode)
                      
{
                         case 
:

                .

                .

                .

              break;

                .

                .

                .
                       }

        break;

    }

   // Следующий бит
               qPulses
++;
           
}

 

// Основной цикл программы

 

void main(void)
           
{

  CKCON = 0x7f;
              AUXR = 0x2d;

              delay0 = 50;
              delay1 =
50;

             
// Режимы прерываний:
              // внешнее прерывание 1 (клавиатура) - по уровню

              IT0 =
0;


             
// Приоритеты прерываний:
              // 1 - клавиатура
              // 2 - таймер 0 (системный тайминг)

              PX0 =
1;
              PT0 =
1;


             
// Режимы таймеров:
              //
              // таймер 0 (тайминг) - 1
              // таймер 1 (декодер клавиатуры) - 1

           

  TMOD = 0x11;

  // Константа перезагрузки таймера 0, для получения времени 2 мс.
              TH0 =
0xf8;
              TL0 =
0xcd;
           
             
// Разрешить прерывания от клавиатуры
              EX0 =
1;
             
// Разрешить прерывания от таймера 0
              ET0 =
1;

  // Разрешить прерывания от таймера 1
              ET1 =
1;
             
// Глобальное разрешение прерываний
              EA =
1;
             
// Запустить системный тайминг
              TR0 =
1;
             
// Сгенерировать звуковой сигнал
              sound = true
;

  // Бесконечный цикл
              while
(true);
          
  }