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