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);
}