257 lines
6.6 KiB
C
257 lines
6.6 KiB
C
#include "main.h"
|
|
#include "tm1637.h"
|
|
#include "keyboard.h"
|
|
|
|
volatile uint32_t tickCount;
|
|
|
|
|
|
// Режимы отображения
|
|
typedef enum {
|
|
MODE_BIN = 0,
|
|
MODE_DEC = 1,
|
|
MODE_HEX = 2
|
|
} DisplayMode;
|
|
|
|
DisplayMode currentMode = MODE_BIN;
|
|
|
|
// --- SysTick прерывание ---
|
|
|
|
void osSystickHandler(void) {
|
|
tickCount++;
|
|
}
|
|
|
|
// --- Инициализация GPIO ---
|
|
|
|
void initGPIO(void) {
|
|
// Включаем тактирование портов A, B, C
|
|
RCC->AHBENR |= RCC_AHBENR_GPIOAEN
|
|
| RCC_AHBENR_GPIOBEN
|
|
| RCC_AHBENR_GPIOCEN;
|
|
|
|
// PA5 - встроенный LED
|
|
GPIOA->MODER = (GPIOA->MODER & ~(3U << (5 * 2))) | (1U << (5 * 2));
|
|
GPIOA->OTYPER &= ~(1U << 5);
|
|
GPIOA->OSPEEDR |= (1U << (5 * 2));
|
|
|
|
// Светодиоды режимов:
|
|
// BIN - PA15
|
|
// DEC - PA9
|
|
// HEX - PC7
|
|
GPIOA->MODER = (GPIOA->MODER & ~(3U << (15 * 2))) | (1U << (15 * 2));
|
|
GPIOA->OTYPER &= ~(1U << 15);
|
|
GPIOA->OSPEEDR |= (1U << (15 * 2));
|
|
|
|
GPIOA->MODER = (GPIOA->MODER & ~(3U << (9 * 2))) | (1U << (9 * 2));
|
|
GPIOA->OTYPER &= ~(1U << 9);
|
|
GPIOA->OSPEEDR |= (1U << (9 * 2));
|
|
|
|
GPIOC->MODER = (GPIOC->MODER & ~(3U << (7 * 2))) | (1U << (7 * 2));
|
|
GPIOC->OTYPER &= ~(1U << 7);
|
|
GPIOC->OSPEEDR |= (1U << (7 * 2));
|
|
|
|
// Входы от DIP-переключателя (8 каналов):
|
|
// ch0 - PA12, ch1 - PA11, ch2 - PB1, ch3 - PA4,
|
|
// ch4 - PA1, ch5 - PA0, ch6 - PC14, ch7 - PC13
|
|
GPIOA->MODER &= ~(3U << (12 * 2) |
|
|
3U << (11 * 2) |
|
|
3U << (4 * 2) |
|
|
3U << (1 * 2) |
|
|
3U << (0 * 2));
|
|
GPIOB->MODER &= ~(3U << (1 * 2));
|
|
GPIOC->MODER &= ~(3U << (14 * 2) |
|
|
3U << (13 * 2));
|
|
|
|
// Подтяжка вниз (так как верхние выводы DIP сидят на 3V3)
|
|
GPIOA->PUPDR = (GPIOA->PUPDR &
|
|
~(3U << (12 * 2) |
|
|
3U << (11 * 2) |
|
|
3U << (4 * 2) |
|
|
3U << (1 * 2) |
|
|
3U << (0 * 2)))
|
|
| (2U << (12 * 2)) // pull-down
|
|
| (2U << (11 * 2))
|
|
| (2U << (4 * 2))
|
|
| (2U << (1 * 2))
|
|
| (2U << (0 * 2));
|
|
|
|
GPIOB->PUPDR = (GPIOB->PUPDR & ~(3U << (1 * 2)))
|
|
| (2U << (1 * 2));
|
|
|
|
GPIOC->PUPDR = (GPIOC->PUPDR &
|
|
~(3U << (14 * 2) |
|
|
3U << (13 * 2)))
|
|
| (2U << (14 * 2))
|
|
| (2U << (13 * 2));
|
|
}
|
|
|
|
// --- USART2 под printf() ---
|
|
|
|
void initUSART2(void) {
|
|
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
|
|
|
|
// PA2/PA3 - альтернативная функция (AF1)
|
|
GPIOA->MODER = (GPIOA->MODER & ~(0xFU << 4)) | (0xAU << 4);
|
|
GPIOA->AFR[0] = (GPIOA->AFR[0] & ~(0xFFU << 8)) | (1U << 8) | (1U << 12);
|
|
|
|
USART2->BRR = 417; // 48MHz / 115200
|
|
USART2->CR1 = USART_CR1_TE | USART_CR1_UE;
|
|
}
|
|
|
|
int _write(int file, uint8_t *ptr, int len) {
|
|
(void)file;
|
|
for (int i = 0; i < len; i++) {
|
|
while (!(USART2->ISR & USART_ISR_TXE));
|
|
USART2->TDR = ptr[i];
|
|
}
|
|
return len;
|
|
}
|
|
|
|
// --- SysTick 1 мс ---
|
|
|
|
void initSysTick(void) {
|
|
SysTick->LOAD = 47999; // 1 мс при 48 МГц
|
|
SysTick->VAL = 0;
|
|
SysTick->CTRL = (1U << 2) | (1U << 1) | (1U << 0);
|
|
}
|
|
|
|
// --- Отладочное мигание встроенным светодиодом ---
|
|
|
|
void checkTickCount(void) {
|
|
if ((tickCount % 2000U) == 0U) { // раз в 2 секунды
|
|
GPIOA->ODR ^= (1U << 5);
|
|
printf("tickCount = %lu\n", (unsigned long)tickCount);
|
|
}
|
|
}
|
|
|
|
// --- Чтение 8-ми дискретных входов ---
|
|
|
|
static uint8_t readInputs(void) {
|
|
uint8_t value = 0;
|
|
|
|
if (GPIOA->IDR & (1U << 12)) value |= (1U << 0); // ch0
|
|
if (GPIOA->IDR & (1U << 11)) value |= (1U << 1); // ch1
|
|
if (GPIOB->IDR & (1U << 1)) value |= (1U << 2); // ch2
|
|
if (GPIOA->IDR & (1U << 4)) value |= (1U << 3); // ch3
|
|
if (GPIOA->IDR & (1U << 1)) value |= (1U << 4); // ch4
|
|
if (GPIOA->IDR & (1U << 0)) value |= (1U << 5); // ch5
|
|
if (GPIOC->IDR & (1U << 14)) value |= (1U << 6); // ch6
|
|
if (GPIOC->IDR & (1U << 13)) value |= (1U << 7); // ch7
|
|
|
|
return value;
|
|
}
|
|
|
|
// --- Светодиоды режимов ---
|
|
|
|
static void updateModeLEDs(void) {
|
|
// Гасим все
|
|
GPIOA->BRR = (1U << 15) | (1U << 9);
|
|
GPIOC->BRR = (1U << 7);
|
|
|
|
switch (currentMode) {
|
|
case MODE_BIN:
|
|
GPIOA->BSRR = (1U << 15); // BIN
|
|
break;
|
|
case MODE_DEC:
|
|
GPIOA->BSRR = (1U << 9); // DEC
|
|
break;
|
|
case MODE_HEX:
|
|
GPIOC->BSRR = (1U << 7); // HEX
|
|
break;
|
|
}
|
|
}
|
|
|
|
// --- Обработка нажатий клавиш B / D / H ---
|
|
|
|
static void handleKey(char key) {
|
|
switch (key) {
|
|
case 'B':
|
|
currentMode = MODE_BIN;
|
|
printf("Mode: BIN\n");
|
|
break;
|
|
case 'D':
|
|
currentMode = MODE_DEC;
|
|
printf("Mode: DEC\n");
|
|
break;
|
|
case 'H':
|
|
currentMode = MODE_HEX;
|
|
printf("Mode: HEX\n");
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
updateModeLEDs();
|
|
}
|
|
|
|
// реагируем только на изменение lastKey
|
|
static void processKeyboard(void) {
|
|
static char prevKey = '\0';
|
|
|
|
if (lastKey != prevKey) {
|
|
if (lastKey != '\0') {
|
|
handleKey(lastKey);
|
|
}
|
|
prevKey = lastKey;
|
|
}
|
|
}
|
|
|
|
// --- Обновление индикации TM1637 ---
|
|
|
|
static void updateDisplay(void) {
|
|
static uint32_t lastInputScan = 0;
|
|
static uint8_t lastValue = 0;
|
|
static uint8_t currentChannel = 0;
|
|
|
|
// Считываем входы примерно раз в 10 мс
|
|
if ((tickCount - lastInputScan) >= 10U) {
|
|
lastInputScan = tickCount;
|
|
lastValue = readInputs();
|
|
}
|
|
|
|
// Обновляем дисплей
|
|
if ((tickCount - last_display_update) >= 250U) { // 4 Гц
|
|
last_display_update = tickCount;
|
|
|
|
switch (currentMode) {
|
|
case MODE_BIN: {
|
|
uint8_t bit = (lastValue >> currentChannel) & 0x01;
|
|
tm1637_display_channel_state(currentChannel, bit);
|
|
currentChannel = (currentChannel + 1) & 0x07; // 0..7 по кругу
|
|
break;
|
|
}
|
|
case MODE_DEC:
|
|
tm1637_display_number(lastValue); // 0..255
|
|
break;
|
|
|
|
case MODE_HEX:
|
|
tm1637_display_hex(lastValue);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- main() ---
|
|
|
|
int main(void) {
|
|
initGPIO();
|
|
initUSART2();
|
|
initSysTick();
|
|
initKeyboard();
|
|
tm1637_init();
|
|
|
|
printf("Oh shi here we go again\n");
|
|
|
|
// Включаем встроенный LED
|
|
GPIOA->ODR |= (1U << 5);
|
|
|
|
updateModeLEDs(); // по умолчанию BIN
|
|
|
|
while (1) {
|
|
checkTickCount();
|
|
scanKeyboard(); // обновляет lastKey
|
|
processKeyboard(); // переключает режимы
|
|
updateDisplay(); // показывает состояние 8 входов
|
|
}
|
|
|
|
return 0;
|
|
}
|