LCM — CH32V003 Light Control Module
Light Control Module, I2C slave
Loading...
Searching...
No Matches
lcm_led.c
Go to the documentation of this file.
1/********************************** (C) COPYRIGHT *******************************
2 * File Name : lcm_led.c
3 * Description : Индикация LCM на PD4 (красный) и PC0 (зелёный).
4 *
5 * Активный уровень — 0 (светодиод горит при GPIO=0).
6 *
7 * Важно: из I2C ISR (WCH-Interrupt-fast) НЕЛЬЗЯ вызывать
8 * __disable_irq()/__enable_irq() — они трогают биты
9 * MIE и MPIE в mstatus одной маской (0x88). Если такой
10 * вызов не сбалансирован явным __enable_irq() до выхода
11 * из ISR, mret восстановит MIE = MPIE = 0, и глобальные
12 * прерывания погаснут навсегда. Поэтому здесь — только
13 * прямые атомарные записи в GPIO->BSHR/BCR и volatile
14 * флаг (один писатель в ISR, один читатель в Poll).
15 *********************************************************************************/
16
17#include "lcm_led.h"
18#include "debug.h"
19#include "ch32v00x_conf.h"
20
21#define LCM_LED_GREEN_MS 100U
22#define LCM_LED_RED_MIN_MS 100U
23
24#define LCM_LED_RED_PORT GPIOD
25#define LCM_LED_RED_PIN GPIO_Pin_4
26#define LCM_LED_GREEN_PORT GPIOC
27#define LCM_LED_GREEN_PIN GPIO_Pin_0
28
29/*
30 * Сколько мс ещё держать зелёный; уменьшается в LCM_Led_Poll().
31 * Задержки — через Delay_Ms() (debug.c, аппаратный SysTick, откалиброван
32 * по SystemCoreClock). Самодельный цикл NOP использовался раньше и мог
33 * давать неточный интервал (компилятор/wait-states флеша), из-за чего
34 * зелёный не гас через заявленные 100 мс.
35 */
36static volatile uint16_t s_green_ms_left;
37
38/*
39 * Минимальная видимая длительность красного индикатора ошибки.
40 * Без этого: если GET_ERROR приходит сразу после команды с ошибкой,
41 * ErrorOn()/ErrorOff() происходят почти одновременно и вспышка не видна.
42 * ErrorOn() всегда (пере)запускает таймер s_red_ms_left; ErrorOff() гасит
43 * светодиод немедленно, только если таймер уже истёк, иначе выставляет
44 * s_red_off_pending — реальное гашение довершит LCM_Led_Poll().
45 */
46static volatile uint16_t s_red_ms_left;
47static volatile uint8_t s_red_off_pending;
48
49static void LCM_Led_RedSet(uint8_t on)
50{
51 if (on != 0U) {
53 } else {
55 }
56}
57
58static void LCM_Led_GreenSet(uint8_t on)
59{
60 if (on != 0U) {
62 } else {
64 }
65}
66
67static void LCM_Led_ConfigPins(void)
68{
69 GPIO_InitTypeDef gpio = {0};
70
71 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);
72
73 gpio.GPIO_Speed = GPIO_Speed_30MHz;
74 gpio.GPIO_Mode = GPIO_Mode_Out_PP;
75
76 gpio.GPIO_Pin = LCM_LED_GREEN_PIN;
77 GPIO_Init(LCM_LED_GREEN_PORT, &gpio);
78
79 gpio.GPIO_Pin = LCM_LED_RED_PIN;
80 GPIO_Init(LCM_LED_RED_PORT, &gpio);
81}
82
83void LCM_Led_Init(void)
84{
88 s_green_ms_left = 0U;
89 s_red_ms_left = 0U;
91}
92
99
101{
102 if (s_red_ms_left == 0U) {
103 LCM_Led_RedSet(0U);
104 } else {
105 /* Минимальное время показа не истекло — гашение довершит Poll(). */
107 }
108}
109
115
116void LCM_Led_Poll(void)
117{
118 if (s_green_ms_left == 0U && s_red_ms_left == 0U) {
119 return;
120 }
121
122 /* 1 мс за итерацию main (аппаратный SysTick) — не трогает IRQ */
123 Delay_Ms(1U);
124
125 if (s_green_ms_left != 0U) {
127 if (s_green_ms_left == 0U) {
129 }
130 }
131
132 if (s_red_ms_left != 0U) {
134 if (s_red_ms_left == 0U && s_red_off_pending != 0U) {
135 LCM_Led_RedSet(0U);
137 }
138 }
139}
#define LCM_LED_GREEN_PIN
Definition lcm_led.c:27
static volatile uint16_t s_red_ms_left
Definition lcm_led.c:46
#define LCM_LED_RED_PORT
Definition lcm_led.c:24
void LCM_Led_Init(void)
Definition lcm_led.c:83
static void LCM_Led_RedSet(uint8_t on)
Definition lcm_led.c:49
static void LCM_Led_ConfigPins(void)
Definition lcm_led.c:67
static volatile uint16_t s_green_ms_left
Definition lcm_led.c:36
void LCM_Led_ActivityPulse(void)
Definition lcm_led.c:110
void LCM_Led_ErrorOff(void)
Definition lcm_led.c:100
void LCM_Led_ErrorOn(void)
Definition lcm_led.c:93
static void LCM_Led_GreenSet(uint8_t on)
Definition lcm_led.c:58
#define LCM_LED_GREEN_PORT
Definition lcm_led.c:26
static volatile uint8_t s_red_off_pending
Definition lcm_led.c:47
#define LCM_LED_RED_MIN_MS
Definition lcm_led.c:22
#define LCM_LED_RED_PIN
Definition lcm_led.c:25
void LCM_Led_Poll(void)
Definition lcm_led.c:116
#define LCM_LED_GREEN_MS
Definition lcm_led.c:21