kolibrios/programs/develop/oberon07/Samples/STM32CM3/LCD.ob07

366 lines
8.8 KiB
Plaintext
Raw Normal View History

(*
Пример для 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.