STM32, C++ и FreeRTOS. Разработка с нуля. Часть 3 (LCD и Экраны)

#include "lcddriver.h"       // Определение класса 
#include         //Регистры STM32
#include "susuassert.h"       //для ASSERT
#include "types.h"            //для типов tPort, tU16, tU8
#include "bitutil.h"          //для макросов работы с битами SETBIT, CLRBIT
#include            //для NULL   
#define BIG_SYMBOLS_COUNT 7  //количество символов в нижней(большой) строке 
// Используем BitBanding см. стр 49. CD00240194.pdf
// доп инфа тут: https://plus.google.com/115316880241890152471/posts/M7tzhpQiC9M
#define SEG_MASK(seg)    (seg & (32-1))
#define SEG_EL(seg,com)  (volatile tU32 *)(PERIPH_BASE + 0x2000000 + ((0x2400 + 0x14 + ((com*2) + ((seg<32)?0:1))*4)*32) + (SEG_MASK(seg)*4))
#define SEG_A ((tU32)1<<0)
#define SEG_B ((tU32)1<<1)
#define SEG_C ((tU32)1<<2)
#define SEG_D ((tU32)1<<3)
#define SEG_E ((tU32)1<<4)
#define SEG_F ((tU32)1<<5)
#define SEG_G ((tU32)1<<6)
#define SEG_H ((tU32)1<<7)
#define SEG_J ((tU32)1<<8)
#define SEG_K ((tU32)1<<9)
#define SEG_M ((tU32)1<<10)
#define SEG_N ((tU32)1<<11)
#define SEG_P ((tU32)1<<12)
#define SEG_Q ((tU32)1<<13)
#define SEG_DP ((tU32)1<<14)
#define SEG_COL ((tU32)1<<15)
// Сегменты больших символов на нижней(Большой) строке               
//       _______a_______
//      |\      |      /|   
//      f  h    j    k  b    |col
//      |    \  |  /    |
//      |___g__\ /__m___|      
//      |      / \      |    | 
//      e    q  p  n    c
//      |  /    |    \  |
//      |/______d______\|    |dp
#define Symbol_20  (tU32)0
#define Symbol_21  (tU32)0
#define Symbol_22  (tU32)0
#define Symbol_23  (tU32)0
#define Symbol_24  (tU32)0
#define Symbol_25  (tU32)0
#define Symbol_26  (tU32)0
#define Symbol_27  (tU32)0
#define Symbol_28  (tU32)0
#define Symbol_29  (tU32)0
#define Symbol_2A  (tU32)0
#define Symbol_2B (SEG_J | SEG_M | SEG_P | SEG_G) //символ '+'
#define Symbol_2C (SEG_DP) //символ ','
#define Symbol_2D (SEG_J | SEG_M) //символ '-'
#define Symbol_2E (SEG_DP) //символ '.'
#define Symbol_2F (SEG_K | SEG_Q) //символ '/'
#define Digit_0 (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_H | SEG_N)
#define Digit_1 (SEG_B | SEG_C)
#define Digit_2 (SEG_A | SEG_B | SEG_G | SEG_E | SEG_D | SEG_M)
#define Digit_3 (SEG_A | SEG_B | SEG_C | SEG_D | SEG_G | SEG_M)
#define Digit_4 (SEG_F | SEG_B | SEG_C | SEG_G | SEG_M)
#define Digit_5 (SEG_A | SEG_F | SEG_G | SEG_C | SEG_D | SEG_M)
#define Digit_6 (SEG_A | SEG_F | SEG_G | SEG_C | SEG_D | SEG_E | SEG_M)
#define Digit_7 (SEG_A | SEG_B | SEG_C)
#define Digit_8 (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G | SEG_M)
#define Digit_9 (SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G | SEG_M)
#define Symbol_3A (SEG_DP) // символ ':'
#define Symbol_3B (SEG_COL) // символ ';'
#define Symbol_3C (SEG_K | SEG_N) // символ '<'
#define Symbol_3D (SEG_A | SEG_G | SEG_M) //символ '='
#define Symbol_3E (SEG_H | SEG_Q) //символ '>'
#define Symbol_3F  (tU32)0 //символ '?' будет у нас пробелом :)
#define Symbol_40 (SEG_D | SEG_E | SEG_F | SEG_A | SEG_B | SEG_M| SEG_J) // '@'
#define Symbol_A  (SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G | SEG_M)
#define Symbol_B  (SEG_A | SEG_K | SEG_N | SEG_D | SEG_E | SEG_G | SEG_F)
#define Symbol_C  (SEG_A | SEG_D | SEG_E | SEG_F)
#define Symbol_D  (SEG_A | SEG_B | SEG_C | SEG_D | SEG_J | SEG_P) 
#define Symbol_E  (SEG_A | SEG_G | SEG_M | SEG_D | SEG_E | SEG_F)
#define Symbol_F  (SEG_A | SEG_G | SEG_M | SEG_E | SEG_F)
#define Symbol_G  (SEG_A | SEG_N | SEG_D | SEG_E | SEG_F)
#define Symbol_H  (SEG_F | SEG_E | SEG_G | SEG_M | SEG_B | SEG_C)
#define Symbol_I  (SEG_G | SEG_P)
#define Symbol_J  (SEG_B | SEG_C | SEG_D)
#define Symbol_K  (SEG_F | SEG_E | SEG_G | SEG_K | SEG_N)
#define Symbol_L  (SEG_F | SEG_E | SEG_D)
#define Symbol_M  (SEG_E | SEG_F | SEG_H | SEG_K | SEG_B | SEG_C)
#define Symbol_N  (SEG_E | SEG_F | SEG_H | SEG_N | SEG_B | SEG_C)
#define Symbol_O   Symbol_D
#define Symbol_P  (SEG_E | SEG_F | SEG_A | SEG_B | SEG_M | SEG_G)
#define Symbol_Q  (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_N)
#define Symbol_R  (SEG_A | SEG_B | SEG_M | SEG_N | SEG_G | SEG_E | SEG_F)
#define Symbol_S  (SEG_A | SEG_F | SEG_G | SEG_M | SEG_C | SEG_D)
#define Symbol_T  (SEG_A | SEG_J | SEG_P)
#define Symbol_U  (SEG_F | SEG_E | SEG_D | SEG_C | SEG_B)
#define Symbol_V  (SEG_H | SEG_N | SEG_C | SEG_B)
#define Symbol_W  (SEG_F | SEG_E | SEG_Q | SEG_N | SEG_C | SEG_B)
#define Symbol_X  (SEG_H | SEG_Q | SEG_N | SEG_K)
#define Symbol_Y  (SEG_H | SEG_K | SEG_P)
#define Symbol_Z  (SEG_A | SEG_K | SEG_Q | SEG_D)
#define BIG_SYMBOL_SIZE (16)  //1 символ 16 сегментов,включая двоеточие и точку
// 1 символ начинается со смещения 2 (+ и - пропускается), дальше см таблицу pTableSegs
#define Big_Digit_0_offset  (tU32)2  
#define Big_Digit_1_offset  (tU32)18 
#define Big_Digit_2_offset  (tU32)34
#define Big_Digit_3_offset  (tU32)50
#define Big_Digit_4_offset  (tU32)66
#define Big_Digit_5_offset  (tU32)82
#define Big_Digit_6_offset  (tU32)97
// У нас 7 цифр на дисплее, это массив для сдвига в количестве сегментов для каждой из цифр. 
const tU32 cLcdDriver::bigDigitOffset[] = 
{
  Big_Digit_0_offset, Big_Digit_1_offset, 
  Big_Digit_2_offset, Big_Digit_3_offset,
  Big_Digit_4_offset, Big_Digit_5_offset,
  Big_Digit_6_offset  
};

//таблица конвертации (ASCI кода буквы - ASCI код ' '(пробела)) в значение на сегментах индикатора
const tU32 cLcdDriver::charToLcdSymbol[] = 
{
  Symbol_20,
  Symbol_21, Symbol_22, Symbol_23, Symbol_24, Symbol_25,
  Symbol_27, Symbol_27, Symbol_28, Symbol_29, Symbol_2A,
  Symbol_2B, Symbol_2C, Symbol_2D, Symbol_2E, Symbol_2F,
  Digit_0, Digit_1, Digit_2, Digit_3, Digit_4,
  Digit_5, Digit_6, Digit_7, Digit_8, Digit_9,
  Symbol_3A, Symbol_3B, Symbol_3C, Symbol_3D,
  Symbol_3D, Symbol_3F, Symbol_40, Symbol_A,
  Symbol_B, Symbol_C, Symbol_D, Symbol_E, Symbol_F,
  Symbol_G, Symbol_H, Symbol_I, Symbol_J, Symbol_K,
  Symbol_L, Symbol_M, Symbol_N, Symbol_O, Symbol_P,
  Symbol_Q, Symbol_R, Symbol_S, Symbol_T, Symbol_U,
  Symbol_V, Symbol_W, Symbol_X, Symbol_Y, Symbol_Z  
};
//таблица с адресами для bitBandinga для каждого сегмента
volatile tU32* cLcdDriver::pTableSegs[] =
{
  SEG_EL(39,3), // +    0
  SEG_EL(39,0), // -    1
  SEG_EL(37,3), // 1A   2
  SEG_EL(37,2), // 1B   3
  SEG_EL(37,1), // 1C   4
  SEG_EL(37,0), // 1D   5
  SEG_EL(39,1), // 1E   6
  SEG_EL(39,2), // 1F   7
  SEG_EL(38,2), // 1G   8
  SEG_EL(38,3), // 1H   9
  SEG_EL(36,3), // 1J   10
  SEG_EL(36,2), // 1K   11
  SEG_EL(36,1), // 1M   12
  SEG_EL(36,0), // 1N   13
  SEG_EL(38,0), // 1P   14
  SEG_EL(38,1), // 1Q   15
  SEG_EL(35,0), // 1DP  16
  SEG_EL(35,3), // 2COL 17

  SEG_EL(33,3), // 2A   18
  SEG_EL(33,2), // 2B   19
  SEG_EL(33,1), // 2C   20
  SEG_EL(33,0), // 2D   21
  SEG_EL(35,1), // 2E   22
  SEG_EL(35,2), // 2F   23
  SEG_EL(34,2), // 2G   24
  SEG_EL(34,3), // 2H   25
  SEG_EL(32,3), // 2J   26
  SEG_EL(32,2), // 2K   27
  SEG_EL(32,1), // 2M   28
  SEG_EL(32,0), // 2N   29
  SEG_EL(34,0), // 2P   30
  SEG_EL(34,1), // 2Q   31
  SEG_EL(31,0), // 2DP  32
  SEG_EL(31,3), // 3COL 33

  SEG_EL(29,3), // 3A   34
  SEG_EL(29,2), // 3B   35
  SEG_EL(29,1), // 3C   36
  SEG_EL(29,0), // 3D   37
  SEG_EL(31,1), // 3E   38
  SEG_EL(31,2), // 3F   39
  SEG_EL(30,2), // 3G   40
  SEG_EL(30,3), // 3H   41
  SEG_EL(28,3), // 3J   42
  SEG_EL(28,2), // 3K   43
  SEG_EL(28,1), // 3M   44
  SEG_EL(28,0), // 3N   45
  SEG_EL(30,0), // 3P   46
  SEG_EL(30,1), // 3Q   47
  SEG_EL(27,0), // 3DP  48
  SEG_EL(27,3), // 4COL 49

  SEG_EL(25,3), // 4A   50
  SEG_EL(25,2), // 4B   51
  SEG_EL(25,1), // 4C   52
  SEG_EL(25,0), // 4D   53
  SEG_EL(27,1), // 4E   54
  SEG_EL(27,2), // 4F   55
  SEG_EL(26,2), // 4G   56
  SEG_EL(26,3), // 4H   57
  SEG_EL(24,3), // 4J   58
  SEG_EL(24,2), // 4K   59
  SEG_EL(24,1), // 4M   60
  SEG_EL(24,0), // 4N   61
  SEG_EL(26,0), // 4P   62
  SEG_EL(26,1), // 4Q   63
  SEG_EL(23,0), // 4DP  64
  SEG_EL(23,3), // 5COL 65

  SEG_EL(21,3), // 5A   66
  SEG_EL(21,2), // 5B   67
  SEG_EL(21,1), // 5C   68
  SEG_EL(21,0), // 5D   69
  SEG_EL(23,1), // 5E   70
  SEG_EL(23,2), // 5F   71
  SEG_EL(22,2), // 5G   72
  SEG_EL(22,3), // 5H   73
  SEG_EL(20,3), // 5J   74
  SEG_EL(20,2), // 5K   75
  SEG_EL(20,1), // 5M   76
  SEG_EL(20,0), // 5N   77
  SEG_EL(22,0), // 5P   78
  SEG_EL(22,1), // 5Q   79
  SEG_EL(19,0), // 5DP  80
  SEG_EL(19,3), // 6COL 81

  SEG_EL(17,3), // 6A   82
  SEG_EL(17,2), // 6B   83
  SEG_EL(17,1), // 6C   84
  SEG_EL(17,0), // 6D   85
  SEG_EL(19,1), // 6E   86
  SEG_EL(19,2), // 6F   87
  SEG_EL(18,2), // 6G   88
  SEG_EL(18,3), // 6H   89
  SEG_EL(16,3), // 6J   90
  SEG_EL(16,2), // 6K   91
  SEG_EL(16,1), // 6M   92
  SEG_EL(16,0), // 6N   93
  SEG_EL(18,0), // 6P   94
  SEG_EL(18,1), // 6Q   95
  SEG_EL(15,0), // 6DP  96

  SEG_EL(13,3), // 7A   97
  SEG_EL(13,2), // 7B   98
  SEG_EL(13,1), // 7C   99
  SEG_EL(13,0), // 7D   100
  SEG_EL(15,1), // 7E   101
  SEG_EL(15,2), // 7F   102
  SEG_EL(14,2), // 7G   103
  SEG_EL(14,3), // 7H   104
  SEG_EL(12,3), // 7J   105
  SEG_EL(12,2), // 7K   106
  SEG_EL(12,1), // 7M   107
  SEG_EL(12,0), // 7N   108
  SEG_EL(14,0), // 7P   109
  SEG_EL(14,1), // 7Q   110

  SEG_EL(1 ,3), // A1   111
  SEG_EL(1 ,2), // A2   112
  SEG_EL(1 ,1), // A3   113
  SEG_EL(1 ,0), // A4   114

  SEG_EL(2 ,0), // BRBL 115
  SEG_EL(2 ,3), // B0   116
  SEG_EL(2 ,2), // B1   117
  SEG_EL(2 ,1), // B2   118

  SEG_EL(0 ,3), // PL   119
  SEG_EL(0 ,2), // P0   120
  SEG_EL(0 ,1), // P1   121
  SEG_EL(0 ,0), // P2   122
  SEG_EL(43,0), // P3   123
  SEG_EL(43,1), // P4   124
  SEG_EL(43,2), // P5   125
  SEG_EL(43,3), // P6   126
  SEG_EL(42,3), // P7   127
  SEG_EL(42,2), // P8   128
  SEG_EL(42,1), // P9   129
  SEG_EL(42,0), // PR   130

  SEG_EL(3 ,0), // AL   131
  SEG_EL(3 ,1), // AU   132
  SEG_EL(3 ,2), // AR   133
  SEG_EL(3 ,3), // AD   134

  SEG_EL(15,3), // SB   135

  SEG_EL(10,0), // 8A   136
  SEG_EL(10,1), // 8B   137
  SEG_EL(10,2), // 8C   138
  SEG_EL(11,3), // 8D   139
  SEG_EL(11,2), // 8E   140
  SEG_EL(11,0), // 8F   141
  SEG_EL(11,1), // 8G   142
  SEG_EL(10,3), // 8P   143

  SEG_EL(8 ,0), // 9A   144
  SEG_EL(8 ,1), // 9B   145
  SEG_EL(8 ,2), // 9C   146
  SEG_EL(9 ,3), // 9D   147
  SEG_EL(9 ,2), // 9E   148
  SEG_EL(9 ,0), // 9F   149
  SEG_EL(9 ,1), // 9G   150
  SEG_EL(8 ,3), // 10P  151
  SEG_EL(7 ,3), // 10COLON  152

  SEG_EL(7 ,0), // 10A  153
  SEG_EL(6 ,0), // 10B  154
  SEG_EL(6 ,2), // 10C  155
  SEG_EL(6 ,3), // 10D  156
  SEG_EL(7 ,2), // 10E  157
  SEG_EL(7 ,1), // 10F  158
  SEG_EL(6 ,1), // 10G  159

  SEG_EL(5 ,0), // 11A  160
  SEG_EL(4 ,0), // 11B  161
  SEG_EL(4 ,2), // 11C  162
  SEG_EL(4 ,3), // 11D  163
  SEG_EL(5 ,2), // 11E  164
  SEG_EL(5 ,1), // 11F  165
  SEG_EL(4 ,1), // 11G  166
};
/*******************************************************************************
* Function:  constructor
* Description: 
******************************************************************************/
cLcdDriver::cLcdDriver(void) 
{
  this->updateDisplay();
}
/*******************************************************************************
* Function:  showBigString
* Description: Выводит информацию в нижнюю(большую)строку на индикаторе. 
******************************************************************************/
void cLcdDriver::showBigString(const char* pStr)
{
  tU32 digitPlace = 0;
  tBoolean bDot = FALSE;   //флаг установки точки
  const char *pNextChar = pStr;
  pNextChar++;
  //заполняем регистры RAM индиактора новыми данными
  //проверяем следующий символ, если он равено точке или запятой
  //ставим флаг необходимости установки сегмента точки в TRUE
  //Пустые символы заполняются пробелами
  while (digitPlace < BIG_SYMBOLS_COUNT)
  {
    if (( *pNextChar == '.' ) || (*pNextChar == ','))
    {
      bDot = TRUE;
    }
    if ((*pStr != '.') && (*pStr != ','))
    {
      if (*pStr != NULL)
      {
        this->showBigSymbol(digitPlace, *pStr, bDot);
      }
      else
      {
        this->showBigSymbol(digitPlace, ' ', FALSE);
      }       
      digitPlace++;
    }
    pStr++;
    pNextChar++;
    bDot = FALSE;
  }
  //Запрашиваем обновления дисплея
  this->updateDisplay();
}
/*******************************************************************************
* Function:  showBigSymbol
* Description: Записывает большой(нижней строки) символ в память индикатора, 
*              но не выводит его индикатор
******************************************************************************/
void cLcdDriver::showBigSymbol(const tU32 digitPlace, 
                               const char character, const tBoolean bDot)
{
  ASSERT(character > 0);
  ASSERT(character < 61);
  volatile tU32 **p_data = &this->pTableSegs[this->bigDigitOffset[digitPlace]];
  tU32 mask = charToLcdSymbol[character - ' '];
  //Если надо установить точку, устанавливаем доп сегмент точки
  if (bDot == TRUE) 
  {
    mask |= SEG_DP;
  }
  // устанавливаем биты в регистрах памяти LCD->RAM через битБендинг
  for(tU32 i = 0, j = 1; i < BIG_SYMBOL_SIZE; i++, j <<= 1)
  {
    if(mask & j)
    {
      **p_data = 1;
    }
    else
    {
      **p_data = 0;
    }
    ++p_data;
  } 
}
/*******************************************************************************
* Function:  isReady
* Description: Проверяем готовность индикатора
******************************************************************************/
tBoolean cLcdDriver::isReady(void)
{
  tBoolean result = FALSE; 
  if (!CHECK_BITS_SET(LCD->SR,LCD_SR_UDR))  
  {
    result = TRUE;
  }
  return result;
}
/*******************************************************************************
* Function:  updateDisplay
* Description: Выполняет запрос на обновление дисплея, вызвывается каждый раз
*              после обновления памяти LCD
******************************************************************************/
void cLcdDriver::updateDisplay(void)
{
  SETBIT(LCD->SR, LCD_SR_UDR);
}


© Habrahabr.ru