stm32/l1: lcd: example using the LCD
This commit is contained in:
committed by
Karl Palsson
parent
2ba1619889
commit
2372d8b59f
25
examples/stm32/l1/stm32l-discovery/lcd-display/Makefile
Normal file
25
examples/stm32/l1/stm32l-discovery/lcd-display/Makefile
Normal file
@@ -0,0 +1,25 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2014 Nikolay Merinov <nikolay.merinov@member.fsf.org>
|
||||
##
|
||||
## This library is free software: you can redistribute it and/or modify
|
||||
## it under the terms of the GNU Lesser General Public License as published by
|
||||
## the Free Software Foundation, either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This library is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU Lesser General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU Lesser General Public License
|
||||
## along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
BINARY = lcd-hello
|
||||
|
||||
LDSCRIPT = $(OPENCM3_DIR)/lib/stm32/l1/stm32l15xxb.ld
|
||||
|
||||
include ../../Makefile.include
|
||||
|
||||
7
examples/stm32/l1/stm32l-discovery/lcd-display/README
Normal file
7
examples/stm32/l1/stm32l-discovery/lcd-display/README
Normal file
@@ -0,0 +1,7 @@
|
||||
------------------------------------------------------------------------------
|
||||
README
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
This example program display word *HELLO on default LCD screen of
|
||||
STM32L-DISCOVERY board.
|
||||
|
||||
201
examples/stm32/l1/stm32l-discovery/lcd-display/lcd-hello.c
Normal file
201
examples/stm32/l1/stm32l-discovery/lcd-display/lcd-hello.c
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2014 Nikolay Merinov <nikolay.merinov@member.fsf.org>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/l1/lcd.h>
|
||||
|
||||
static void lcd_init(void)
|
||||
{
|
||||
/* Move all needed GPIO pins to LCD alternative mode */
|
||||
rcc_peripheral_enable_clock (&RCC_AHBENR, RCC_AHBENR_GPIOAEN
|
||||
| RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN);
|
||||
rcc_peripheral_enable_clock (&RCC_AHBLPENR, RCC_AHBLPENR_GPIOALPEN
|
||||
| RCC_AHBLPENR_GPIOBLPEN | RCC_AHBLPENR_GPIOCLPEN);
|
||||
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO1 | GPIO2
|
||||
| GPIO3 | GPIO8 | GPIO9 | GPIO10 | GPIO15);
|
||||
gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE,
|
||||
GPIO3 | GPIO4 | GPIO5 | GPIO8 | GPIO9 | GPIO10 | GPIO11
|
||||
| GPIO12 | GPIO13 | GPIO14 | GPIO15);
|
||||
gpio_mode_setup(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO0 | GPIO1
|
||||
| GPIO2 | GPIO3 | GPIO6 | GPIO7 | GPIO8 | GPIO9
|
||||
| GPIO10 | GPIO11);
|
||||
|
||||
gpio_set_af (GPIOA, GPIO_AF11, GPIO1 | GPIO2 | GPIO3 | GPIO8 | GPIO9
|
||||
| GPIO10 | GPIO15);
|
||||
gpio_set_af (GPIOB, GPIO_AF11, GPIO3 | GPIO4 | GPIO5 | GPIO8 | GPIO9
|
||||
| GPIO10 | GPIO11 | GPIO12 | GPIO13 | GPIO14 | GPIO15);
|
||||
gpio_set_af (GPIOC, GPIO_AF11, GPIO0 | GPIO1 | GPIO2 | GPIO3 | GPIO6
|
||||
| GPIO7 | GPIO8 | GPIO9 | GPIO10 | GPIO11);
|
||||
|
||||
/* Enable LCD and use LSE clock as RTC/LCD clock. */
|
||||
rcc_peripheral_enable_clock (&RCC_APB1ENR, RCC_APB1ENR_PWREN | RCC_APB1ENR_LCDEN);
|
||||
pwr_disable_backup_domain_write_protect ();
|
||||
rcc_osc_on (LSE);
|
||||
rcc_wait_for_osc_ready (LSE);
|
||||
rcc_rtc_select_clock (RCC_CSR_RTCSEL_LSE);
|
||||
RCC_CSR |= RCC_CSR_RTCEN; /* Enable RTC clock */
|
||||
pwr_enable_backup_domain_write_protect ();
|
||||
|
||||
/* Map SEG[43:40] to SEG[31:28], use 4 LCD commons, use 3 voltage levels
|
||||
when driving LCD display */
|
||||
lcd_enable_segment_multiplexing ();
|
||||
lcd_set_duty (LCD_CR_DUTY_1_4);
|
||||
lcd_set_bias (LCD_CR_BIAS_1_3);
|
||||
|
||||
/* Set screen redraw frequency to 100Hz */
|
||||
lcd_set_refresh_frequency (100);
|
||||
/* And increase contrast */
|
||||
lcd_set_contrast (LCD_FCR_CC_5);
|
||||
|
||||
lcd_enable ();
|
||||
do {} while (!lcd_is_enabled ());
|
||||
do {} while (!lcd_is_step_up_ready ());
|
||||
}
|
||||
|
||||
static void clear_lcd_ram(void)
|
||||
{
|
||||
LCD_RAM_COM0 = 0;
|
||||
LCD_RAM_COM1 = 0;
|
||||
LCD_RAM_COM2 = 0;
|
||||
LCD_RAM_COM3 = 0;
|
||||
}
|
||||
|
||||
/* LCD MAPPING:
|
||||
A
|
||||
_ ----------
|
||||
COL |_| |\ |J /|
|
||||
F| H | K |B
|
||||
_ | \ | / |
|
||||
COL |_| --G-- --M--
|
||||
| /| \ |
|
||||
E| Q | N |C
|
||||
_ | / |P \|
|
||||
DP |_| -----------
|
||||
D
|
||||
|
||||
`mask' corresponds to bits in lexicographic order: mask & 1 == A, mask & 2 == B,
|
||||
and so on.
|
||||
*/
|
||||
static void write_mask_to_lcd_ram (int position, uint16_t mask, int clear_before)
|
||||
{
|
||||
/* Every pixel of character at position can be accessed
|
||||
as LCD_RAM_COMx & (1 << Px) */
|
||||
int P1,P2,P3,P4;
|
||||
if (position < 2) P1 = 2*position;
|
||||
else P1 = 2*position+4;
|
||||
|
||||
if (position == 1) P2 = P1+5;
|
||||
else P2 = P1+1;
|
||||
|
||||
if (position < 3) P3 = (23-2*position)+6;
|
||||
else P3 = (23-2*position)+4;
|
||||
|
||||
if (position == 5) {
|
||||
P4 = P3;
|
||||
P3 -= 1;
|
||||
} else {
|
||||
P4 = P3 - 1;
|
||||
}
|
||||
|
||||
uint32_t COM0,COM1,COM2,COM3;
|
||||
COM0 = LCD_RAM_COM0;
|
||||
COM1 = LCD_RAM_COM1;
|
||||
COM2 = LCD_RAM_COM2;
|
||||
COM3 = LCD_RAM_COM3;
|
||||
|
||||
if (clear_before) {
|
||||
COM0&= ~(1<<P1 | 1<<P2 | 1<<P3 | 1<<P4);
|
||||
COM1&= ~(1<<P1 | 1<<P2 | 1<<P3 | 1<<P4);
|
||||
COM2&= ~(1<<P1 | 1<<P2 | 1<<P3 | 1<<P4);
|
||||
COM3&= ~(1<<P1 | 1<<P2 | 1<<P3 | 1<<P4);
|
||||
}
|
||||
|
||||
COM0 |= ((mask >> 0x1) & 1) << P4 | ((mask >> 0x4) & 1) << P1
|
||||
| ((mask >> 0x6) & 1) << P3 | ((mask >> 0xA) & 1) << P2;
|
||||
COM1 |= ((mask >> 0x0) & 1) << P4 | ((mask >> 0x2) & 1) << P2
|
||||
| ((mask >> 0x3) & 1) << P1 | ((mask >> 0x5) & 1) << P3;
|
||||
COM3 |= ((mask >> 0x7) & 1) << P3 | ((mask >> 0x8) & 1) << P4
|
||||
| ((mask >> 0xB) & 1) << P1 | ((mask >> 0xE) & 1) << P2;
|
||||
COM2 |= ((mask >> 0x9) & 1) << P4 | ((mask >> 0xC) & 1) << P1
|
||||
| ((mask >> 0xD) & 1) << P3 | ((mask >> 0xF) & 1) << P2;
|
||||
|
||||
LCD_RAM_COM0 = COM0;
|
||||
LCD_RAM_COM1 = COM1;
|
||||
LCD_RAM_COM2 = COM2;
|
||||
LCD_RAM_COM3 = COM3;
|
||||
}
|
||||
|
||||
static void write_char_to_lcd_ram (int position, uint8_t symbol, bool clear_before)
|
||||
{
|
||||
uint16_t from_ascii[0x60] = {
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* ! " # $ % & ' */
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* ( ) * + , - . / */
|
||||
0x0000, 0x0000, 0x3FC0, 0x1540, 0x0000, 0x0440, 0x4000, 0x2200,
|
||||
/* 0 1 2 3 4 5 6 7 */
|
||||
0x003F, 0x0006, 0x045B, 0x044F, 0x0466, 0x046D, 0x047D, 0x2201,
|
||||
/* 8 9 : ; < = > ? */
|
||||
0x047F, 0x046F, 0x8000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
/* @ A B C D E F G */
|
||||
0x0000, 0x0477, 0x047C, 0x0039, 0x045E, 0x0479, 0x0471, 0x043D,
|
||||
/* H I J K L M N O */
|
||||
0x0476, 0x1109, 0x001E, 0x1B00, 0x0038, 0x02B6, 0x08B6, 0x003F,
|
||||
/* P Q R S T U V W */
|
||||
0x0473, 0x0467, 0x0C73, 0x046D, 0x1101, 0x003E, 0x0886, 0x2836,
|
||||
/* X Y Z [ \ ] ^ _ */
|
||||
0x2A80, 0x1280, 0x2209, 0x0000, 0x0880, 0x0000, 0x0000, 0x0008
|
||||
};
|
||||
if (symbol > 0x60) return; // masks not defined. Nothing to display
|
||||
|
||||
write_mask_to_lcd_ram (position, from_ascii[symbol], clear_before);
|
||||
}
|
||||
|
||||
|
||||
static void lcd_display_hello (void)
|
||||
{
|
||||
do {} while (!lcd_is_for_update_ready ());
|
||||
clear_lcd_ram (); /* all segments off */
|
||||
write_char_to_lcd_ram (0, '*', true);
|
||||
write_char_to_lcd_ram (1, 'H', true);
|
||||
write_char_to_lcd_ram (2, 'E', true);
|
||||
write_char_to_lcd_ram (3, 'L', true);
|
||||
write_char_to_lcd_ram (4, 'L', true);
|
||||
write_char_to_lcd_ram (5, 'O', true);
|
||||
|
||||
lcd_update ();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i;
|
||||
lcd_init ();
|
||||
|
||||
lcd_display_hello ();
|
||||
|
||||
for (i = 0; i < 1000000; i++) { /* Wait a bit. */
|
||||
__asm__("nop");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user