| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- (*
- Пример для 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;
- SCB_SCR = 0E000ED00H + 10H;
- SLEEPONEXIT = {1};
- SLEEPDEEP = {2};
- SEVONPEND = {4};
- 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;
- PROCEDURE [code] wfi
- 0BF30H; (* wfi *)
- PROCEDURE sleep;
- VAR
- x: SET;
- BEGIN
- REPEAT
- (* настроить режим сна *)
- SYSTEM.GET(SCB_SCR, x);
- SYSTEM.PUT(SCB_SCR, x - SLEEPDEEP);
- (* ждать прерывание *)
- wfi
- UNTIL FALSE
- END sleep;
- BEGIN
- main;
- sleep
- END LCD.
|