drive backlight using PWM

This commit is contained in:
King Kévin 2022-06-23 10:06:16 +02:00
parent 1e446cbb0b
commit d37edd9e9d
1 changed files with 21 additions and 20 deletions

41
main.c
View File

@ -1,5 +1,5 @@
/* firmware to control LCD using HD44780 driver over I²C
* Copyright (C) 2019-2020 King Kévin <kingkevin@cuvoodoo.info>
* Copyright (C) 2019-2022 King Kévin <kingkevin@cuvoodoo.info>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include <stdint.h>
@ -7,12 +7,9 @@
#include "stm8s.h"
#include "main.h"
// on-board LED pin in on PB5 (use as sink), same as SDA
#define LED_PORT GPIO_PA
#define LED_PIN PA3
#define led_on() {LED_PORT->ODR.reg &= ~LED_PIN;}
#define led_off() {LED_PORT->ODR.reg |= LED_PIN;}
#define led_toggle() {LED_PORT->ODR.reg ^= LED_PIN;}
// nMOS gate to drive backlight LED
#define BL_PORT GPIO_PA
#define BL_PIN PA3
/* usual HD44780 pinout:
* - 1 GND: ground
@ -201,14 +198,9 @@ void main(void)
while (!(CLK_ICKR & CLK_ICKR_HSIRDY)); // wait for internal oscillator to be ready
// save power by disabling unused peripheral
CLK_PCKENR1 = CLK_PCKENR1_I2C; // only keep I²C
CLK_PCKENR1 = CLK_PCKENR1_I2C | CLK_PCKENR1_TIM25; // only keep I²C and timer 2
CLK_PCKENR2 = CLK_PCKENR2_AWU; // only keep AWU
// configure LED
LED_PORT->DDR.reg |= LED_PIN; // switch pin to output
LED_PORT->CR1.reg &= ~LED_PIN; // use in open-drain mode
led_off(); // start with LED off
// configure independent watchdog (very loose, just it case the firmware hangs)
IWDG_KR = IWDG_KR_KEY_REFRESH; // reset watchdog
IWDG_KR = IWDG_KR_KEY_ENABLE; // start watchdog
@ -270,6 +262,21 @@ void main(void)
AWU->APR.fields.APR = 0x3e; // set time to 256 ms
AWU_CSR |= AWU_CSR_AWUEN; // enable AWU (start only when entering wait or active halt mode)
// configure PWM output for backlight
BL_PORT->DDR.reg |= BL_PIN; // switch pin to output
BL_PORT->CR1.reg |= BL_PIN; // use in push-pull mode
TIM2->CCMR3.output_fields.OC3M = 6; // PWM mode 1
TIM2->CCMR3.output_fields.CC3S = 0; // configure channel as output
TIM2->CCER2.fields.CC3P = 0; // active high
TIM2->CCER2.fields.CC3E = 1; // output enable
TIM2->ARRH.fields.ARR15_8 = 0; // set reload to 0xff
TIM2->ARRL.fields.ARR7_0 = 0xfe; // set reload to 0xff
TIM2->PSCR.fields.PSC = 6; // set frequency to 1 kHz
TIM2->CCR3H.fields.CCR3 = 0; // start with PWM off
TIM2->CCR3L.fields.CCR3 = 0; // start with PWM off
TIM2->EGR.fields.UG = 1; // force reload of values
TIM2->CR1.fields.CEN = 1; // enable timer
// configure display (as per datasheet)
IWDG_KR = IWDG_KR_KEY_REFRESH; // reset watchdog
HD44780_RS_PORT->ODR.reg &= ~HD44780_RS_PIN; // set low for instruction
@ -292,10 +299,8 @@ void main(void)
rim(); // re-enable interrupts
led_on();
while (true) {
IWDG_KR = IWDG_KR_KEY_REFRESH; // reset watchdog
//led_toggle(); // indicate we re running
while (i2c_input_used) { // I²C data is available
sim(); // disable interrupt while reading buffer to not corrupt indexes
uint8_t input_data = i2c_input_buffer[i2c_input_i]; // get start buffered data
@ -356,11 +361,7 @@ void main(void)
hd44780_write_instruction(0x80 | (input_data & 0x3f));
break;
case MODE_BRIGHTNESS:
if (input_data) {
led_on();
} else {
led_off();
}
TIM2->CCR3L.fields.CCR3 = input_data; // set duty cycle
break;
default: // read values do not make sense
break;