// ПР8. USART: ВЕДУЩИЙ микроконтроллер (формирование команд)
// Плата: NUCLEO-C031C6, Wokwi + STM32duino
// Автор: Алексеев Ф.В., ЭФБО-08-23
//
// Линия связи: USART1, TX = PB6 (D1) -> RX ведомого, RX = PB7 (D0) <- TX ведомого,
// 115200 бод, 8N1, общая земля
// Кнопки: SERV (D7) — угол сервопривода с потенциометра A0, FWD (D5) — 200 шагов вперёд,
// REV (D4) — 100 шагов назад, STATUS (D2) — запрос состояния
// Индикация: D13 — ожидание ответа, D12 — OK, D11 — ERROR / нет ответа (тайм-аут)
HardwareSerial Link(PB7, PB6); // USART1
#define LED_WAIT D13
#define LED_OK D12
#define LED_ERR D11
#define POT A0
const uint8_t BTN[4] = { D7, D5, D4, D2 };
char rx[40]; uint8_t rxLen = 0;
bool waiting = false;
uint32_t tSent = 0, timeout = 0;
void leds(bool w, bool ok, bool err) {
digitalWrite(LED_WAIT, w); digitalWrite(LED_OK, ok); digitalWrite(LED_ERR, err);
}
// Отправка команды и запуск ожидания ответа
void sendCmd(const char *cmd, uint32_t tmo) {
Link.print(cmd);
waiting = true; tSent = millis(); timeout = tmo;
leds(1, 0, 0);
}
// Обработка принятой строки ответа
void handleReply(const char *s) {
if (!waiting) return;
waiting = false;
if (strncmp(s, "OK", 2) == 0 || strncmp(s, "STATUS", 6) == 0) leds(0, 1, 0);
else leds(0, 0, 1); // ERROR:... или неизвестный ответ
}
bool pressed(uint8_t i) {
static bool st[4] = {1, 1, 1, 1}, last[4] = {1, 1, 1, 1};
static uint32_t t[4];
bool raw = digitalRead(BTN[i]);
if (raw != last[i]) { last[i] = raw; t[i] = millis(); }
if (millis() - t[i] > 25 && raw != st[i]) { st[i] = raw; return raw == LOW; }
return false;
}
void setup() {
Link.begin(115200, SERIAL_8N1);
analogReadResolution(12);
pinMode(LED_WAIT, OUTPUT); pinMode(LED_OK, OUTPUT); pinMode(LED_ERR, OUTPUT);
for (uint8_t i = 0; i < 4; i++) pinMode(BTN[i], INPUT_PULLUP);
leds(0, 0, 0);
}
void loop() {
// ---- кнопки -> команды ----
if (!waiting) {
if (pressed(0)) {
char cmd[16];
int angle = map(analogRead(POT), 0, 4095, 0, 180);
snprintf(cmd, sizeof(cmd), "SERV:%03d;", angle);
sendCmd(cmd, 2000);
}
if (pressed(1)) sendCmd("STEP:FWD,200;", 3000); // шаги: до 3 с
if (pressed(2)) sendCmd("STEP:REV,100;", 3000);
if (pressed(3)) sendCmd("STATUS?", 2000);
}
// ---- приём ответа построчно (переменная длина, конец строки '\n') ----
while (Link.available()) {
char c = Link.read();
if (c == '\r') continue;
if (c == '\n') { rx[rxLen] = 0; if (rxLen) handleReply(rx); rxLen = 0; }
else if (rxLen < sizeof(rx) - 1) rx[rxLen++] = c;
}
// ---- тайм-аут ответа ----
if (waiting && millis() - tSent > timeout) { waiting = false; leds(0, 0, 1); }
}
Loading
st-nucleo-c031c6
st-nucleo-c031c6