366 lines
8.8 KiB
Plaintext
366 lines
8.8 KiB
Plaintext
|
(*
|
|||
|
Пример для STM32L152C-DISCO
|
|||
|
|
|||
|
Работа со встроенным ЖКИ.
|
|||
|
|
|||
|
использовано:
|
|||
|
https://habr.com/ru/post/173709/
|
|||
|
*)
|
|||
|
|
|||
|
MODULE LCD;
|
|||
|
|
|||
|
IMPORT SYSTEM;
|
|||
|
|
|||
|
|
|||
|
CONST
|
|||
|
|
|||
|
GPIOA = 40020000H;
|
|||
|
GPIOAMODER = GPIOA;
|
|||
|
GPIOAOTYPER = GPIOA + 04H;
|
|||
|
GPIOAOSPEEDR = GPIOA + 08H;
|
|||
|
GPIOAPUPDR = GPIOA + 0CH;
|
|||
|
GPIOAIDR = GPIOA + 10H;
|
|||
|
GPIOAODR = GPIOA + 14H;
|
|||
|
GPIOABSRR = GPIOA + 18H;
|
|||
|
GPIOALCKR = GPIOA + 1CH;
|
|||
|
GPIOAAFRL = GPIOA + 20H;
|
|||
|
GPIOAAFRH = GPIOA + 24H;
|
|||
|
GPIOABRR = GPIOA + 28H;
|
|||
|
|
|||
|
|
|||
|
GPIOB = 40020400H;
|
|||
|
GPIOBMODER = GPIOB;
|
|||
|
GPIOBOTYPER = GPIOB + 04H;
|
|||
|
GPIOBOSPEEDR = GPIOB + 08H;
|
|||
|
GPIOBPUPDR = GPIOB + 0CH;
|
|||
|
GPIOBIDR = GPIOB + 10H;
|
|||
|
GPIOBODR = GPIOB + 14H;
|
|||
|
GPIOBBSRR = GPIOB + 18H;
|
|||
|
GPIOBLCKR = GPIOB + 1CH;
|
|||
|
GPIOBAFRL = GPIOB + 20H;
|
|||
|
GPIOBAFRH = GPIOB + 24H;
|
|||
|
GPIOBBRR = GPIOB + 28H;
|
|||
|
|
|||
|
|
|||
|
GPIOC = 40020800H;
|
|||
|
GPIOCMODER = GPIOC;
|
|||
|
GPIOCOTYPER = GPIOC + 04H;
|
|||
|
GPIOCOSPEEDR = GPIOC + 08H;
|
|||
|
GPIOCPUPDR = GPIOC + 0CH;
|
|||
|
GPIOCIDR = GPIOC + 10H;
|
|||
|
GPIOCODR = GPIOC + 14H;
|
|||
|
GPIOCBSRR = GPIOC + 18H;
|
|||
|
GPIOCLCKR = GPIOC + 1CH;
|
|||
|
GPIOCAFRL = GPIOC + 20H;
|
|||
|
GPIOCAFRH = GPIOC + 24H;
|
|||
|
GPIOCBRR = GPIOC + 28H;
|
|||
|
|
|||
|
|
|||
|
RCC = 40023800H;
|
|||
|
RCC_CR = RCC;
|
|||
|
RCC_AHBENR = RCC + 1CH;
|
|||
|
RCC_APB2ENR = RCC + 20H;
|
|||
|
RCC_APB1ENR = RCC + 24H;
|
|||
|
RCC_CSR = RCC + 34H;
|
|||
|
|
|||
|
|
|||
|
PWR = 40007000H;
|
|||
|
PWR_CR = PWR;
|
|||
|
|
|||
|
|
|||
|
LCD = 40002400H;
|
|||
|
LCD_CR = LCD;
|
|||
|
LCD_FCR = LCD + 04H;
|
|||
|
LCD_SR = LCD + 08H;
|
|||
|
LCD_RAM = LCD + 14H;
|
|||
|
|
|||
|
|
|||
|
AFM = 2;
|
|||
|
|
|||
|
AF11 = 11;
|
|||
|
|
|||
|
PinsA = {1..3, 8..10, 15};
|
|||
|
PinsB = {3..5, 8..15};
|
|||
|
PinsC = {0..3, 6..11};
|
|||
|
|
|||
|
A = 0; H = 7;
|
|||
|
B = 1; J = 8;
|
|||
|
C = 2; K = 9;
|
|||
|
D = 3; M = 10;
|
|||
|
E = 4; N = 11;
|
|||
|
F = 5; P = 12;
|
|||
|
G = 6; Q = 13;
|
|||
|
|
|||
|
DP = 14; COLON = 15; BAR = 16;
|
|||
|
|
|||
|
|
|||
|
VAR
|
|||
|
display: ARRAY 6, 17 OF INTEGER;
|
|||
|
|
|||
|
digits: ARRAY 10 OF SET;
|
|||
|
|
|||
|
|
|||
|
PROCEDURE SetPinsMode (reg: INTEGER; pins: SET; mode: INTEGER);
|
|||
|
VAR
|
|||
|
x: SET;
|
|||
|
pin: INTEGER;
|
|||
|
|
|||
|
BEGIN
|
|||
|
mode := mode MOD 4;
|
|||
|
SYSTEM.GET(reg, x);
|
|||
|
FOR pin := 0 TO 30 BY 2 DO
|
|||
|
IF (pin DIV 2) IN pins THEN
|
|||
|
x := x - {pin, pin + 1} + BITS(LSL(mode, pin))
|
|||
|
END
|
|||
|
END;
|
|||
|
SYSTEM.PUT(reg, x)
|
|||
|
END SetPinsMode;
|
|||
|
|
|||
|
|
|||
|
PROCEDURE SRBits (adr: INTEGER; setbits, resetbits: SET);
|
|||
|
VAR
|
|||
|
x: SET;
|
|||
|
|
|||
|
BEGIN
|
|||
|
SYSTEM.GET(adr, x);
|
|||
|
SYSTEM.PUT(adr, x - resetbits + setbits)
|
|||
|
END SRBits;
|
|||
|
|
|||
|
|
|||
|
PROCEDURE SetBits (adr: INTEGER; bits: SET);
|
|||
|
VAR
|
|||
|
x: SET;
|
|||
|
|
|||
|
BEGIN
|
|||
|
SYSTEM.GET(adr, x);
|
|||
|
SYSTEM.PUT(adr, x + bits)
|
|||
|
END SetBits;
|
|||
|
|
|||
|
|
|||
|
PROCEDURE ResetBits (adr: INTEGER; bits: SET);
|
|||
|
VAR
|
|||
|
x: SET;
|
|||
|
|
|||
|
BEGIN
|
|||
|
SYSTEM.GET(adr, x);
|
|||
|
SYSTEM.PUT(adr, x - bits)
|
|||
|
END ResetBits;
|
|||
|
|
|||
|
|
|||
|
PROCEDURE TestBits (adr: INTEGER; bits: SET): BOOLEAN;
|
|||
|
VAR
|
|||
|
x: SET;
|
|||
|
|
|||
|
BEGIN
|
|||
|
SYSTEM.GET(adr, x);
|
|||
|
RETURN x * bits = bits
|
|||
|
END TestBits;
|
|||
|
|
|||
|
|
|||
|
PROCEDURE Init;
|
|||
|
VAR
|
|||
|
i, j: INTEGER;
|
|||
|
seg: ARRAY 30 OF INTEGER;
|
|||
|
|
|||
|
BEGIN
|
|||
|
FOR i := 0 TO 29 DO
|
|||
|
seg[i] := i
|
|||
|
END;
|
|||
|
|
|||
|
FOR i := 3 TO 11 DO
|
|||
|
seg[i] := i + 4
|
|||
|
END;
|
|||
|
|
|||
|
seg[18] := 17;
|
|||
|
seg[19] := 16;
|
|||
|
|
|||
|
FOR i := 20 TO 23 DO
|
|||
|
seg[i] := i - 2
|
|||
|
END;
|
|||
|
|
|||
|
j := 0;
|
|||
|
FOR i := 0 TO 5 DO
|
|||
|
display[i, A] := 256 + seg[28 - j];
|
|||
|
display[i, B] := 0 + seg[28 - j];
|
|||
|
display[i, C] := 256 + seg[j + 1];
|
|||
|
display[i, D] := 256 + seg[j];
|
|||
|
display[i, E] := 0 + seg[j];
|
|||
|
display[i, F] := 256 + seg[29 - j];
|
|||
|
display[i, G] := 0 + seg[29 - j];
|
|||
|
display[i, H] := 768 + seg[29 - j];
|
|||
|
display[i, J] := 768 + seg[28 - j];
|
|||
|
display[i, K] := 512 + seg[28 - j];
|
|||
|
display[i, M] := 0 + seg[j + 1];
|
|||
|
display[i, N] := 768 + seg[j];
|
|||
|
display[i, P] := 512 + seg[j];
|
|||
|
display[i, Q] := 512 + seg[29 - j];
|
|||
|
INC(j, 2)
|
|||
|
END;
|
|||
|
|
|||
|
display[0, DP] := 768 + 1;
|
|||
|
display[1, DP] := 768 + 7;
|
|||
|
display[2, DP] := 768 + 9;
|
|||
|
display[3, DP] := 768 + 11;
|
|||
|
|
|||
|
display[0, COLON] := 512 + 1;
|
|||
|
display[1, COLON] := 512 + 7;
|
|||
|
display[2, COLON] := 512 + 9;
|
|||
|
display[3, COLON] := 512 + 11;
|
|||
|
|
|||
|
display[0, BAR] := 768 + 15;
|
|||
|
display[1, BAR] := 512 + 15;
|
|||
|
display[2, BAR] := 768 + 13;
|
|||
|
display[3, BAR] := 512 + 13;
|
|||
|
|
|||
|
digits[0] := {A, B, C, D, E, F};
|
|||
|
digits[1] := {B, C};
|
|||
|
digits[2] := {A, B, M, G, E, D};
|
|||
|
digits[3] := {A, B, M, G, C, D};
|
|||
|
digits[4] := {F, G, M, B, C};
|
|||
|
digits[5] := {A, F, G, M, C, D};
|
|||
|
digits[6] := {A, F, G, M, C, D, E};
|
|||
|
digits[7] := {F, A, B, C};
|
|||
|
digits[8] := {A, B, C, D, E, F, G, M};
|
|||
|
digits[9] := {A, B, C, D, F, G, M};
|
|||
|
END Init;
|
|||
|
|
|||
|
|
|||
|
PROCEDURE ResetSeg (seg: INTEGER);
|
|||
|
BEGIN
|
|||
|
ResetBits(LCD_RAM + (seg DIV 256) * 2 * 4, {seg MOD 256})
|
|||
|
END ResetSeg;
|
|||
|
|
|||
|
|
|||
|
PROCEDURE SetSeg (seg: INTEGER);
|
|||
|
BEGIN
|
|||
|
SetBits(LCD_RAM + (seg DIV 256) * 2 * 4, {seg MOD 256})
|
|||
|
END SetSeg;
|
|||
|
|
|||
|
|
|||
|
PROCEDURE Digit (pos, dgt: INTEGER);
|
|||
|
VAR
|
|||
|
s: SET;
|
|||
|
i: INTEGER;
|
|||
|
|
|||
|
BEGIN
|
|||
|
s := digits[dgt];
|
|||
|
FOR i := 0 TO 13 DO
|
|||
|
IF i IN s THEN
|
|||
|
SetSeg(display[pos, i])
|
|||
|
ELSE
|
|||
|
ResetSeg(display[pos, i])
|
|||
|
END
|
|||
|
END
|
|||
|
END Digit;
|
|||
|
|
|||
|
|
|||
|
PROCEDURE WhileBits (adr: INTEGER; bits: SET);
|
|||
|
BEGIN
|
|||
|
WHILE TestBits(adr, bits) DO END
|
|||
|
END WhileBits;
|
|||
|
|
|||
|
|
|||
|
PROCEDURE UntilBits (adr: INTEGER; bits: SET);
|
|||
|
BEGIN
|
|||
|
REPEAT UNTIL TestBits(adr, bits)
|
|||
|
END UntilBits;
|
|||
|
|
|||
|
|
|||
|
PROCEDURE main;
|
|||
|
VAR
|
|||
|
i: INTEGER;
|
|||
|
|
|||
|
BEGIN
|
|||
|
Init;
|
|||
|
|
|||
|
(* подключить GPIOA, GPIOB, GPIOC *)
|
|||
|
SetBits(RCC_AHBENR, {0, 1, 2});
|
|||
|
|
|||
|
(* настроить на режим альтернативной функции *)
|
|||
|
SetPinsMode(GPIOAMODER, PinsA, AFM);
|
|||
|
|
|||
|
(* 400 кГц *)
|
|||
|
SetPinsMode(GPIOAOSPEEDR, PinsA, 0);
|
|||
|
|
|||
|
(* без подтягивающих резисторов *)
|
|||
|
SetPinsMode(GPIOAPUPDR, PinsA, 0);
|
|||
|
|
|||
|
(* режим push-pull *)
|
|||
|
ResetBits(GPIOAOTYPER, PinsA);
|
|||
|
|
|||
|
(* альтернативная функция AF11 = 0BH *)
|
|||
|
SYSTEM.PUT(GPIOAAFRL, 0BBB0H);
|
|||
|
SYSTEM.PUT(GPIOAAFRH, 0B0000BBBH);
|
|||
|
|
|||
|
(* аналогично для GPIOB *)
|
|||
|
SetPinsMode(GPIOBMODER, PinsB, AFM);
|
|||
|
SetPinsMode(GPIOBOSPEEDR, PinsB, 0);
|
|||
|
SetPinsMode(GPIOBPUPDR, PinsB, 0);
|
|||
|
ResetBits(GPIOBOTYPER, PinsB);
|
|||
|
SYSTEM.PUT(GPIOBAFRL, 000BBB000H);
|
|||
|
SYSTEM.PUT(GPIOBAFRH, 0BBBBBBBBH);
|
|||
|
|
|||
|
(* аналогично для GPIOC *)
|
|||
|
SetPinsMode(GPIOCMODER, PinsC, AFM);
|
|||
|
SetPinsMode(GPIOCOSPEEDR, PinsC, 0);
|
|||
|
SetPinsMode(GPIOCPUPDR, PinsC, 0);
|
|||
|
ResetBits(GPIOCOTYPER, PinsC);
|
|||
|
SYSTEM.PUT(GPIOCAFRL, 0BB00BBBBH);
|
|||
|
SYSTEM.PUT(GPIOCAFRH, 00000BBBBH);
|
|||
|
|
|||
|
(* подключить контроллер ЖКИ *)
|
|||
|
SetBits(RCC_APB1ENR, {9, 28}); (* LCDEN = {9}; PWREN = {28} *)
|
|||
|
|
|||
|
(* разрешить запись в регистр RCC_CSR *)
|
|||
|
SetBits(PWR_CR, {8}); (* DBP = {8} *)
|
|||
|
|
|||
|
(* сбросить источник тактирования *)
|
|||
|
SetBits(RCC_CSR, {23}); (* RTCRST = {23} *)
|
|||
|
|
|||
|
(* выбрать новый источник *)
|
|||
|
ResetBits(RCC_CSR, {23}); (* RTCRST = {23} *)
|
|||
|
|
|||
|
(* включить НЧ генератор *)
|
|||
|
SetBits(RCC_CSR, {8}); (* LSEON = {8} *)
|
|||
|
|
|||
|
(* ждать готовность НЧ генератора *)
|
|||
|
UntilBits(RCC_CSR, {9}); (* LSERDY = {9} *)
|
|||
|
|
|||
|
(* выбрать НЧ генератор как источник тактирования *)
|
|||
|
SRBits(RCC_CSR, {16}, {17}); (* RCC_CSR[17:16] := 01b *)
|
|||
|
|
|||
|
(* настроить контроллер ЖКИ *)
|
|||
|
SRBits(LCD_CR, {2, 3, 6, 7}, {4, 5}); (* MUX_SEG = {7}; BIAS1 = {6}; BIAS0 = {5}; DUTY2 = {4}; DUTY1 = {3}; DUTY0 = {2} *)
|
|||
|
|
|||
|
(* Установить значения коэффициентов деления частоты тактового сигнала LCDCLK *)
|
|||
|
SRBits(LCD_FCR, {11, 18, 24}, {10..12, 18..25}); (* LCD_FCR[12:10] := 010b; LCD_FCR[21:18] := 0001b; LCD_FCR[25:22] := 0100b *)
|
|||
|
|
|||
|
(* ждать синхронизацию регистра LCD_FCR *)
|
|||
|
UntilBits(LCD_SR, {5}); (* FCRSF = {5} *)
|
|||
|
|
|||
|
(* выбрать внутренний источник напряжения для ЖКИ и разрешить его работу *)
|
|||
|
SRBits(LCD_CR, {0}, {1}); (* LCD_CR_VSEL = {1}; LCD_CR_LCDEN = {0} *)
|
|||
|
|
|||
|
(* ждать готовность контроллера ЖКИ *)
|
|||
|
UntilBits(LCD_SR, {0, 4}); (* LCD_SR_RDY = {4}; LCD_SR_ENS = {0} *)
|
|||
|
|
|||
|
(* ждать завершение предыдущей записи *)
|
|||
|
WhileBits(LCD_SR, {2}); (* LCD_SR_UDR = {2} *)
|
|||
|
|
|||
|
(* начать запись *)
|
|||
|
FOR i := 0 TO 5 DO
|
|||
|
Digit(i, i + 1) (* 123456 *)
|
|||
|
END;
|
|||
|
|
|||
|
SetSeg(display[1, DP]); (* 12.3456 *)
|
|||
|
SetSeg(display[3, COLON]); (* 12.34:56 *)
|
|||
|
SetSeg(display[0, BAR]); (* 12.34:56_ *)
|
|||
|
|
|||
|
(* завершить запись *)
|
|||
|
SetBits(LCD_SR, {2}) (* LCD_SR_UDR = {2} *)
|
|||
|
END main;
|
|||
|
|
|||
|
|
|||
|
BEGIN
|
|||
|
main
|
|||
|
END LCD.
|