Girando su aliexpress ho notato questi piccoli lcd a 3 cifre ... sono pannelli in vetro senza driver con 3 cifre a 7 segmenti
Il microcontrollore RA4M1 (montato a bordo delle UNO R4) contiene al suo interno il modulo SLCDC che permette di gestire direttamente questi lcd senza driver. Purtroppo le UNO R4 non hanno abbastanza pin per collegare questi display, percio' ho sviluppato il progetto su una sua variante, la WeAct RA4M1 sulla quale ho caricato il bootloader della UNO R4 MINIMA, in questo modo Arduino IDE riconosce questa scheda come se fosse una R4 MINIMA con il vantaggio di avere nolti piu' pin disponibili.
L'uso di questi pannelli lcd e' molto utile nell'ottica del risparmio energetico perche' consumano correnti nell'ordine dei uA (microAmpere), percio' schede alimentate a batterie o con pannelli solari ... e poi saper gestire questo tipo di display puo' tornare utile per riciclare lcd di qualche vecchio oggetto che magari dovremmo buttare (radiosveglie, orologi ecc.).
Sul sito Aliexpress ho trovato poche informazioni tecniche riguardo questi pannelli, ho dovuto incrociare queste informazioni con quelle contenute nel datasheet dell'RA4M1 e fare diverse prove prima di vederlo funzionare.
Quado ,successivamente, parlo di datasheet faccio riferimento all'User’s Manual: Hardware. Questo il pinouts dell'lcd:
Ci sono 3 cifre con 7 segmenti ciascuna. Tutte e 3 le cifre hanno in comune 4 pin (COM0, COM1,COM2 e COM3), ogni cifra ha 2 pin dedicati (SEG1,SEG2,SEG3,SEG4,SEG5,SEG6). I segmenti si accendono quando viene creata una differenza di potenziale tra i pin SEG e i pin COM. Il segnale che alimenta i segmenti deve avere una frequenza di almeno 30Hz per evitare lo sfarfallio (dopo varie configurazioni ho optato per i 32Hz) e un ampiezza di 3V.
Come suggerito dal datasheet, nella tabella 45.6 a pag.1265, i pannelli con 4 pin comuni possono essere gestiti sia con 1/3 Bias che con 1/4 Bias... io ho testato 1/3 Bias con ottimi risultati! Ma cosa significa 1/3 Bias? Con i vecchi display a 7 segmenti a led bastava creare una differenza di potenziale pari all'alimentazione di ogni singolo segmento per accenderli, con 1/3 Bias l'alimentazione dei segmenti viene multiplexata ... ci sono 3 livelli di tensione (per i 3V abbiamo 1V, 2V e 3V), a segmento spento l'ampiezza del segnale oscilla tra 1V e 2V, questo permette una notevole velocita' di accensione/spegnimento dei segmenti (pensate al display di un cronometro usato in ambito sportivo!). Per lavorare a 1/3 Bias ci occorre avere questi 3 livelli di tensione sui pin del nostro RA4M1 (considerando che il nostro lcd lavora a 3Volt avremo 1V sul pin VL1 che corrisponde al pin P100, 2V sul pin VL2 il nostro P101 e 3V sul pin VL4 che corrisponde alla porta P103).
Per creare questo segnale ci sono 3 modalita':
- External resistance division method: Dobbiamo portare noi sulla scheda i 3 livelli di tensione con 3 resistenze in serie tra Vcc e GND. NON ho testato al momento questo metodo
- Internal Voltage Boosting Method: da usare su schede con Vcc a 5V ... il nostro processore ha un generatore interno che genera 3Volt e divide i 3 livelli di tensione sui pin P100,P101 e P103 che poi andra' a multiplexare per accendere e spegnere i segmenti (per utilizzare questa modalita' implementata nel programma che allego sotto, utilizzare la
#define INTERNAL_VOLTAGE_BOOSTING) - Capacitor Split Method: Questo e' il metodo che sfrutta il massimo risparmio energetico perchè non usa il generatore interno per generare i 3Volt ma suddivide su 3 livelli la Vcc sempre sui pin P100,P101 e P103 Attenzione ad usare questo metodo SOLTANTO su schede con Vcc a 3.3Volt, altrimenti rischiate di bruciare il pannello lcd! per utilizzare questo metodo, utilizzare la
#define CAPACITOR_SPLIT_METOD
Tra i pin P100, P101, P103 verso GND e a cavallo dei pin P111 e P112, il datasheet prevede 4 condensatori da 0.47uF che fungono da filtri.
Come si accendono i segmenti?
Per accendere i vari segmenti e creare numeri e lettere (nel limite dei 7 segmenti) occorre fare riferimento alla fig. 45.28 del datasheet a pag.1297:
A sinistra abbiamo la combinazione dei 2 segmenti dedicati ad ogni cifra con (a destra) i 4 pin comuni a tutte le cifre ... Se per esempio vogliamo far accendere il numero 1 sulla cifra a destra del nostro display SEG2n corrisponderà a SEG1 e SEG2n+1 a SEG2 ...
|SEG1| SEG2|
|COM0 | 0 | 0 |
|COM1 | 1 | 0 |
|COM2 | 1 | 0 |
|COM3 | 0 | 0 |
il SEG1 sara' 0b0110 (0x06) e SEG0 0b0000 (0x00), percio' scrivendo:
R_SLCDC->SEG[1] = 0x06;
R_SLCDC->SEG[2] = 0x00;
Si accendera' il numero 1 sulla cifra piu' a destra ![]()
Ho testato un programma che visualizza la temperatura della CPU sul dislpay con la funzione lcd_display_3dig(int32_t value); che permette di visualizzare valori tra -99 e 999 ...
#include "analog.h"
// With Capacitor split metod, LCD drive voltage has same level of RA4M1 Vcc (USE IT ONLY IF Vcc of RA4M1 is 3.3V)
// Capacitor split metod not require continuous current flow, and therefore the current consuption can be reduced
//#define CAPACITOR_SPLIT_METOD
// Internal voltage boosting metod allow you to choose LCD drive voltage by VLCD register
// RA4M1 enable internal voltage boost circuit that supply a constant voltage, regardless of changes in Vcc
#define INTERNAL_VOLTAGE_BOOSTING
#define PERIOD 1000
#define SLOPE -0.00365 // Sensibilità del sensore di temperatura V/℃ ((vs - v1) / (24 - 125)) --> Correggere qui eventuale errore di temperatura reale/misurata (con termometro su chip)
#define VREF 1.43 // Tensione interna di riferimento (secondo il datascheet Typ:1.43V Min:1.36V Max:1.50V)
float degC, vCC;
adc_status_t status;
adc_info_t adc_info;
const uint8_t char_number[] = { // Numeri da visualizzare sul display
0x7d, 0x60, 0x3e, 0x7a, 0x63, 0x5b, 0x5f, 0x70, 0x7f, 0x7b /* 0-9 */
};
void setup() {
setupLCD();
Serial.begin(115200);
delay(2000);
}
void loop() {
static uint32_t last = millis();
uint32_t now = millis();
if(now - last >= PERIOD) {
last = now;
degC = readTemp(); // Misurazione della temperatura con sensore integrato nella CPU
lcd_display_3dig((int)degC); // Visualizza la temperatura sul display
Serial.print("Temp:");Serial.print(degC, 2);Serial.println("°C"); // Temperatura in uscita su seriale
}
}
void lcd_display_3dig(int32_t value) { // Visualizza un valore numerico compreso tra -99 e 999
bool negative = false; // flag che indica un valore negativo
if((int)value<0){ // Se il valore e' negativo
value = value * -1; // non considera il segno meno
negative = true; // ma tiene conto del segno meno con il flag "negative"
}
//uint8_t thousands = (uint8_t)((value % 10000) / 1000); // Da usare SOLTANTO su lcd a 4 cifre
uint8_t hundreds = (uint8_t)((value % 1000) / 100); // scompone il valore in centinaia ...
uint8_t tens= (uint8_t)((value % 100) / 10); // decine ...
uint8_t units= (uint8_t)((value % 10) / 1); // e unita' ...
// Ogni cifra sul display è rappresentata da 2 segmenti
R_SLCDC->SEG_b[1].A = char_number[(units)] >> 4; // visualizza le unita' sulla cifra a destra del display
R_SLCDC->SEG_b[2].A = char_number[(units)] & 0x0f; // la cifra a destra del display e' pilotata dai segmenti 1 & 2
if(tens){ // Se il valore ha cifre dedimali le stampa sul display
R_SLCDC->SEG_b[3].A = char_number[(tens)] >> 4; // visualizza le decine' sulla cifra al centro del display
R_SLCDC->SEG_b[4].A = char_number[(tens)] & 0x0f; // la cifra centrale del display e' pilotata dai segmenti 3 & 4
}
if((tens == 0) && (negative == true)){ // Se il valore non ha cifre decimali ma e' negativo, stampa "-" a sinistra delle unita'
R_SLCDC->SEG_b[3].A = 0x00; // "-" e' rappresentato con il valore 0x02
R_SLCDC->SEG_b[4].A = 0x02;
}
if(hundreds){ // Se il valore ha cifre centesimali
R_SLCDC->SEG_b[5].A = char_number[(tens)] >> 4; // visualizza le centinaia sulla cifra a sinistra del display
R_SLCDC->SEG_b[6].A = char_number[(tens)] & 0x0f; // la cifra a sinistra del display e' pilotata dai segmenti 5 & 6
}
if((hundreds == 0) && (negative == true)){ // Se il valore non ha cifre centesimali ma e' negativo, stampa "-" a sinistra delle decine'
R_SLCDC->SEG_b[5].A = 0x00; // "-" e' rappresentato con il valore 0x02
R_SLCDC->SEG_b[6].A = 0x02;
}
}
void setupLCD(){
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_03_PIN_01, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // SEG01
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_03_PIN_02, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // SEG02
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_03_PIN_02, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // SEG02
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_03_PIN_02, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // SEG02
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_03_PIN_03, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // SEG03
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_04_PIN_00, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // SEG04
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_04_PIN_01, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // SEG05
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_04_PIN_02, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // SEG06
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_01_PIN_04, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // COM0
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_01_PIN_05, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // COM1
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_01_PIN_06, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // COM2
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_01_PIN_07, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // COM3
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_01_PIN_11, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // CAPH
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_01_PIN_12, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // CAPL
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_01_PIN_00, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // VL1
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_01_PIN_01, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // VL2
//R_IOPORT_PinCfg(NULL, BSP_IO_PORT_01_PIN_02, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // VL3
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_01_PIN_03, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // VL4
R_MSTP->MSTPCRC_b.MSTPC4 = 0; // Enable SLCDC module
/*8.7.11 Segment LCDC Source Clock (LCDSRCCLK)
The Segment LCDC source clock, LCDSRCCLK, is the operating clock for the SLCDC.
The LCDSRCCLK is specified by the LCDSCKSEL[2:0] bits in SLCDSCKCR.
LCDSRCCLK is output when SLCDSCKCR.LCDSCKEN is set to 1. When changing the value of
SLCDSCKCR.LCDSCKSEL[2:0], make sure that the value of SLCDSCKCR.LCDSCKEN is 0.*/
R_SYSTEM->PRCR = 0xA501;
R_SYSTEM->SLCDSCKCR = 0x80; // Enable LOCO clock as LCD source clock (see 8.2.19 Segment LCD Source Clock Control Register)
R_SYSTEM->PRCR = 0xA501;
#ifdef INTERNAL_VOLTAGE_BOOSTING
R_SLCDC->LCDM1_b.LCDVLM = 0;
R_SLCDC->LCDM0 = 0x4D; //Internal voltage boosting method
R_SLCDC->VLCD = 0x04; // Reference Voltage = 3V
delay(10);
#endif
#ifdef CAPACITOR_SPLIT_METOD
R_SLCDC->LCDM0 = 0x8D; //Capacitor split method
#endif
R_SLCDC->LCDC0 = 0x07; // 128Hz means 32Hz with 1/3 bias
R_SLCDC->LCDM1_b.VLCON = 1; //Enable voltage boosting circuit operation
delay(10);
R_SLCDC->LCDM1_b.SCOC = 1;
R_SLCDC->LCDM1_b.LCDON = 1;
}
void lcd_display_close(){
R_SLCDC->LCDM1 = (uint8_t)(R_SLCDC->LCDM1 &(~(0xC0))); //Stop SLCD output
R_SLCDC->LCDM1_b.VLCON = 0; //Stop voltage boost circuit or capacitor split circuit operation
R_SLCDC->LCDM0_b.MDSET = 0; //Switch to external resistance method to reduce idle power consuption
R_SYSTEM->PRCR = 0xA501;
R_SYSTEM->SLCDSCKCR_b.LCDSCKEN = 0; //Disable lcd clock
R_SYSTEM->PRCR = 0xA501;
R_MSTP->MSTPCRC_b.MSTPC4 = 1; //Enter module-stop state for the SLCDC
}
float readTemp(){
ADC_Container adc(0, NULL);
uint16_t adc_data = 0; // R_ADC0->ADTSDR & 0xFFFF;
float mcu_temp_c = 0;
int16_t v125;
float v1,vs;
vCC = readVcc();
adc.cfg.resolution = ADC_RESOLUTION_12_BIT;
adc.channel_cfg.scan_mask = ADC_MASK_TEMPERATURE; //ADEXICR
analogReference(AR_INTERNAL);
R_ADC_Open(&adc.ctrl, &adc.cfg);
R_ADC_ScanCfg(&adc.ctrl, &adc.channel_cfg);
R_ADC_ScanStart(&adc.ctrl); // ADCSR.ADST
delay(1);
R_ADC_Read (&adc.ctrl, ADC_CHANNEL_TEMPERATURE, &adc_data);
while( ADC_STATE_SCAN_IN_PROGRESS == status.state) {
R_ADC_StatusGet(&adc.ctrl, &status);
}
R_ADC_InfoGet(&adc.ctrl, &adc_info);
v125 = (int16_t) adc_info.calibration_data; // v125 = (R_TSN->TSCDRH << 8) + R_TSN->TSCDRL
v1 = 3.3f * v125 / 4096; // Voltage output by the TNS at 125 degreeC
vs = vCC * adc_data / 4096; // Voltage output by the TNS at the time of measurement of T1 (volt)
//Serial.print("vs: ");Serial.print(vs);Serial.print(" v1: ");Serial.println(v1);
mcu_temp_c = (vs - v1) / SLOPE + 125;
//Serial.println(mcu_temp_c);
R_ADC_Close(&adc.ctrl);
return mcu_temp_c;
}
float readVcc(){
ADC_Container adc(0,NULL);
adc.cfg.resolution = ADC_RESOLUTION_12_BIT;
adc.channel_cfg.scan_mask = ADC_MASK_VOLT;//ADEXICR
adc.cfg_extend.adc_vref_control = ADC_VREF_CONTROL_AVCC0_AVSS0; //ADHVREFCNT
uint16_t adc_data = 0; // R_ADC0->ADOCDR & 0xFFFF;
float vCC;
R_ADC_Open(&adc.ctrl, &adc.cfg);
R_ADC_ScanCfg(&adc.ctrl, &adc.channel_cfg);
R_ADC_ScanStart(&adc.ctrl);// ADCSR.ADST
delay(1);
R_ADC_Read (&adc.ctrl, ADC_CHANNEL_VOLT, &adc_data);
while( ADC_STATE_SCAN_IN_PROGRESS == status.state) {
R_ADC_StatusGet(&adc.ctrl, &status);
}
vCC = (VREF * 4096) / adc_data; //4096 12bit - 16383 14bit
//Serial.print("Vcc: ");Serial.print(vCC);Serial.println("V");
R_ADC_Close(&adc.ctrl);
return vCC;
}
Infine, un saluto con la scritta "CIAO" che scorre sul dislpay...
// With Capacitor split metod, LCD drive voltage has same level of RA4M1 Vcc (USE IT ONLY IF Vcc of RA4M1 is 3.3V)
// Capacitor split metod not require continuous current flow, and therefore the current consuption can be reduced
//#define CAPACITOR_SPLIT_METOD
// Internal voltage boosting metod allow you to choose LCD drive voltage by VLCD register
// RA4M1 enable internal voltage boost circuit that supply a constant voltage, regardless of changes in Vcc
#define INTERNAL_VOLTAGE_BOOSTING
const uint8_t char_number[] = {
0x7d, 0x60, 0x3e, 0x7a, 0x63, 0x5b, 0x5f, 0x70, 0x7f, 0x7b /* 0-9 */
};
const uint8_t char_CIAO[] = {
0x1d, 0x60, 0x77, 0x7d /* C-I-A-O */
};
const uint8_t char_Err[] = {
0x1f, 0x06, 0x06 /* E-r-r */
};
void setup() {
Serial.begin(115200);
delay(2000);
setupLCD();
//lcd_display_3dig(-87);
//display_Err(); // Visualizza la scritta "Err"
display_CIAO(); // Scorre la parola CIAO sul display
}
void loop() {
//display_CIAO();
}
void display_CIAO(){
// Primo screen C
R_SLCDC->SEG_b[1].A = char_CIAO[0] >> 4;
R_SLCDC->SEG_b[2].A = char_CIAO[0] & 0x0f;
delay(500);
// Secondo screen CI
R_SLCDC->SEG_b[3].A = char_CIAO[0] >> 4;
R_SLCDC->SEG_b[4].A = char_CIAO[0] & 0x0f;
R_SLCDC->SEG_b[1].A = char_CIAO[1] >> 4;
R_SLCDC->SEG_b[2].A = char_CIAO[1] & 0x0f;
delay(500);
// Terzo screen CIA
R_SLCDC->SEG_b[5].A = char_CIAO[0] >> 4;
R_SLCDC->SEG_b[6].A = char_CIAO[0] & 0x0f;
R_SLCDC->SEG_b[3].A = char_CIAO[1] >> 4;
R_SLCDC->SEG_b[4].A = char_CIAO[1] & 0x0f;
R_SLCDC->SEG_b[1].A = char_CIAO[2] >> 4;
R_SLCDC->SEG_b[2].A = char_CIAO[2] & 0x0f;
delay(500);
//Quarto screen IAO
R_SLCDC->SEG_b[5].A = char_CIAO[1] >> 4;
R_SLCDC->SEG_b[6].A = char_CIAO[1] & 0x0f;
R_SLCDC->SEG_b[3].A = char_CIAO[2] >> 4;
R_SLCDC->SEG_b[4].A = char_CIAO[2] & 0x0f;
R_SLCDC->SEG_b[1].A = char_CIAO[3] >> 4;
R_SLCDC->SEG_b[2].A = char_CIAO[3] & 0x0f;
delay(500);
// Quinto screen AO
R_SLCDC->SEG_b[5].A = char_CIAO[2] >> 4;
R_SLCDC->SEG_b[6].A = char_CIAO[2] & 0x0f;
R_SLCDC->SEG_b[3].A = char_CIAO[3] >> 4;
R_SLCDC->SEG_b[4].A = char_CIAO[3] & 0x0f;
R_SLCDC->SEG_b[1].A = 0;
R_SLCDC->SEG_b[2].A = 0;
delay(500);
//Sesto screen O
R_SLCDC->SEG_b[5].A = char_CIAO[3] >> 4;
R_SLCDC->SEG_b[6].A = char_CIAO[3] & 0x0f;
R_SLCDC->SEG_b[3].A = 0;
R_SLCDC->SEG_b[4].A = 0;
R_SLCDC->SEG_b[1].A = 0;
R_SLCDC->SEG_b[2].A = 0;
delay(500);
//Settimo screen vuoto
R_SLCDC->SEG_b[5].A = 0;
R_SLCDC->SEG_b[6].A = 0;
R_SLCDC->SEG_b[3].A = 0;
R_SLCDC->SEG_b[4].A = 0;
R_SLCDC->SEG_b[1].A = 0;
R_SLCDC->SEG_b[2].A = 0;
delay(500);
}
void display_Err(){
R_SLCDC->SEG_b[1].A = char_Err[2] >> 4;
R_SLCDC->SEG_b[2].A = char_Err[2] & 0x0f;
R_SLCDC->SEG_b[3].A = char_Err[1] >> 4;
R_SLCDC->SEG_b[4].A = char_Err[1] & 0x0f;
R_SLCDC->SEG_b[5].A = char_Err[0] >> 4;
R_SLCDC->SEG_b[6].A = char_Err[0] & 0x0f;
}
void lcd_display_3dig(int32_t value) { // Visualizza un valore numerico compreso tra -99 e 999
bool negative = false; // flag che indica un valore negativo
if((int)value<0){ // Se il valore e' negativo
value = value * -1; // non considera il segno meno
negative = true; // ma tiene conto del segno meno con il flag "negative"
}
//uint8_t thousands = (uint8_t)((value % 10000) / 1000); // Da usare SOLTANTO su lcd a 4 cifre
uint8_t hundreds = (uint8_t)((value % 1000) / 100); // scompone il valore in centinaia ...
uint8_t tens= (uint8_t)((value % 100) / 10); // decine ...
uint8_t units= (uint8_t)((value % 10) / 1); // e unita' ...
// Ogni cifra sul display è rappresentata da 2 segmenti
R_SLCDC->SEG_b[1].A = char_number[(units)] >> 4; // visualizza le unita' sulla cifra a destra del display
R_SLCDC->SEG_b[2].A = char_number[(units)] & 0x0f; // la cifra a destra del display e' pilotata dai segmenti 1 & 2
if(tens){ // Se il valore ha cifre dedimali le stampa sul display
R_SLCDC->SEG_b[3].A = char_number[(tens)] >> 4; // visualizza le decine' sulla cifra al centro del display
R_SLCDC->SEG_b[4].A = char_number[(tens)] & 0x0f; // la cifra centrale del display e' pilotata dai segmenti 3 & 4
}
if((tens == 0) && (negative == true)){ // Se il valore non ha cifre decimali ma e' negativo, stampa "-" a sinistra delle unita'
R_SLCDC->SEG_b[3].A = 0x00; // "-" e' rappresentato con il valore 0x02
R_SLCDC->SEG_b[4].A = 0x02;
}
if(hundreds){ // Se il valore ha cifre centesimali
R_SLCDC->SEG_b[5].A = char_number[(tens)] >> 4; // visualizza le centinaia sulla cifra a sinistra del display
R_SLCDC->SEG_b[6].A = char_number[(tens)] & 0x0f; // la cifra a sinistra del display e' pilotata dai segmenti 5 & 6
}
if((hundreds == 0) && (negative == true)){ // Se il valore non ha cifre centesimali ma e' negativo, stampa "-" a sinistra delle decine'
R_SLCDC->SEG_b[5].A = 0x00; // "-" e' rappresentato con il valore 0x02
R_SLCDC->SEG_b[6].A = 0x02;
}
}
void setupLCD(){
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_03_PIN_01, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // SEG01
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_03_PIN_02, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // SEG02
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_03_PIN_02, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // SEG02
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_03_PIN_02, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // SEG02
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_03_PIN_03, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // SEG03
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_04_PIN_00, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // SEG04
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_04_PIN_01, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // SEG05
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_04_PIN_02, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // SEG06
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_01_PIN_04, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // COM0
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_01_PIN_05, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // COM1
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_01_PIN_06, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // COM2
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_01_PIN_07, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // COM3
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_01_PIN_11, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // CAPH
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_01_PIN_12, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // CAPL
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_01_PIN_00, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // VL1
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_01_PIN_01, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // VL2
//R_IOPORT_PinCfg(NULL, BSP_IO_PORT_01_PIN_02, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // VL3
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_01_PIN_03, IOPORT_PERIPHERAL_LCDC | IOPORT_CFG_PERIPHERAL_PIN); // VL4
R_MSTP->MSTPCRC_b.MSTPC4 = 0; // Enable SLCDC module
/*8.7.11 Segment LCDC Source Clock (LCDSRCCLK)
The Segment LCDC source clock, LCDSRCCLK, is the operating clock for the SLCDC.
The LCDSRCCLK is specified by the LCDSCKSEL[2:0] bits in SLCDSCKCR.
LCDSRCCLK is output when SLCDSCKCR.LCDSCKEN is set to 1. When changing the value of
SLCDSCKCR.LCDSCKSEL[2:0], make sure that the value of SLCDSCKCR.LCDSCKEN is 0.*/
R_SYSTEM->PRCR = 0xA501;
R_SYSTEM->SLCDSCKCR = 0x80; // Enable LOCO clock as LCD source clock (see 8.2.19 Segment LCD Source Clock Control Register)
R_SYSTEM->PRCR = 0xA501;
#ifdef INTERNAL_VOLTAGE_BOOSTING
R_SLCDC->LCDM1_b.LCDVLM = 0;
R_SLCDC->LCDM0 = 0x4D; //Internal voltage boosting method
R_SLCDC->VLCD = 0x04; // Reference Voltage = 3V
delay(10);
#endif
#ifdef CAPACITOR_SPLIT_METOD
R_SLCDC->LCDM0 = 0x8D; //Capacitor split method
#endif
R_SLCDC->LCDC0 = 0x07; // 128Hz means 32Hz with 1/3 bias
R_SLCDC->LCDM1_b.VLCON = 1; //Enable voltage boosting circuit operation
delay(10);
R_SLCDC->LCDM1_b.SCOC = 1;
R_SLCDC->LCDM1_b.LCDON = 1;
}
void lcd_display_close(){
R_SLCDC->LCDM1 = (uint8_t)(R_SLCDC->LCDM1 &(~(0xC0))); //Stop SLCD output
R_SLCDC->LCDM1_b.VLCON = 0; //Stop voltage boost circuit or capacitor split circuit operation
R_SLCDC->LCDM0_b.MDSET = 0; //Switch to external resistance method to reduce idle power consuption
R_SYSTEM->PRCR = 0xA501;
R_SYSTEM->SLCDSCKCR_b.LCDSCKEN = 0; //Disable lcd clock
R_SYSTEM->PRCR = 0xA501;
R_MSTP->MSTPCRC_b.MSTPC4 = 1; //Enter module-stop state for the SLCDC
}






