Simülasyon + gerçek kartBitirme
Bitirme projesi: PWM motor sürücü + UART komut arayüzü
Bir DC motoru 20 kHz PWM ile süren, bilgisayardan seri komutlarla (PWM, DIR, FREQ, START, STOP, STATUS) yönetilen, acil dur butonu ve aşırı akım korumalı bir STM32 sürücü kartı yazılımı.
Senaryo
Bir laboratuvar test düzeneğinde motor, Nucleo kartı ve TB6612FNG sürücüsüyle çalışır. Operatör bilgisayarda seri terminal açar: "PWM 40" yazınca motor %40 görevle döner, "STATUS" durumu bildirir. Dönerken yön değiştirme komutu reddedilir. Acil dur butonuna basılınca ya da ölçülen akım eşiği aşınca motor 1 ms içinde durur ve hata kodu gönderilir. 2 s komut gelmezse (bilgisayar bağlantısı koptu) motor yavaşlayarak durur.
Sistemi simülasyonda dene
3B STM32 geliştirme kartı
Nucleo benzeri kart 3B masada: GPIOA saatini aç, PA5'i MODER ile çıkış yap ve BSRR yaz; başlık pinleri ve LD2 anında değişir. TIM3 PWM'i açınca motor görev oranına göre döner, kartın üstünde zamanlayıcı dalgası görünür. Sürükleyerek döndür, iki parmakla yakınlaştır. Durum testli saf mantıktan gelir.
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; GPIOA->MODER = (GPIOA->MODER & ~(3U << (5 * 2))) | (0U << (5 * 2)); GPIOA->PUPDR = (GPIOA->PUPDR & ~(3U << (5 * 2))) | (0U << (5 * 2)); uint32_t level = (GPIOA->IDR >> 5) & 1U;
UART çerçeve görselleştirici ve BRR
Bir metin yaz: her karakter start biti, LSB önce 8 veri biti, isteğe bağlı parite ve stop bitine dönüşür. Baud, parite ve stop bitini değiştir, bir biti boz ve alıcının çerçeve (FE) ya da parite (PE) hatasını gör. BRR ve baud hatası hesaplanır.
Gereksinimler (test edilebilir)
- G1: PWM frekansı 20 kHz ± %1, görev oranı %0–100 arasında %1 adımla (mantık analizörüyle ölçülür).
- G2: Her komut 10 ms içinde tek satır yanıt alır; hatalı komut ERR ile başlar ve durumu değiştirmez.
- G3: Dönerken DIR komutu reddedilir; yön yalnız motor dururken değişir.
- G4: Acil dur butonu (EXTI) motoru 1 ms içinde durdurur.
- G5: Motor akımı eşik değeri 50 ms boyunca aşarsa motor durur ve "ERR overcurrent" gönderilir.
- G6: 2 s komut gelmezse motor rampa ile durur (yazılım bekçisi).
- G7: Firmware 64 KB Flash ve 16 KB RAM bütçesine sığar (CI size denetimi).
Mimari
- bsp/: saat (84 MHz), GPIO, TIM3 PWM, USART2, ADC1 + DMA, EXTI; donanıma özgü tek katman.
- app/command.c: saf komut çözümleyici; HAL yok, bilgisayarda test edilir.
- app/motor.c: durum (duty, dir, running), rampa ve güvenlik kuralları; saf mantık.
- ISR'ler yalnız bayrak ve halka tampon doldurur; iş ana döngüde ya da görevlerde yapılır.
- İsteğe bağlı FreeRTOS: motor görevi (öncelik 3, 5 ms), komut görevi (2, kuyrukla), izleme görevi (1, 100 ms).
Doğrulama
- Birim (native): command() için her komut, sınır değerleri, bilinmeyen komut, uzun satır; motor.c rampa ve güvenlik kuralları.
- Benzetim: bu dersteki PWM, UART (Komut sekmesi), NVIC, DMA ve RTOS simülasyonlarında senaryolar.
- Donanımda: mantık analizörüyle G1 ve G4 ölçümü; seri terminal betiğiyle G2, G3, G6.
- CI: her işlemede derleme, native testler ve size bütçesi (G7).
Demo akışı
- Seri terminalden PWM 0 → 100 taraması ve STATUS.
- Dönerken DIR R (reddedilir), STOP sonra DIR R.
- Acil dur butonu ve mantık analizöründe gecikme ölçümü.
- Bağlantıyı kes: bekçi rampası.
Başlangıç kodu
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct { int duty; char dir; int freq; int running; } motor_t;
/* Donanımdan bağımsız: HAL yok. pio test -e native ile çalışır. */
int command(motor_t *m, char *line, char *reply, size_t n) {
for (char *p = line; *p; p++) *p = (char)toupper((unsigned char)*p);
char *cmd = strtok(line, " "), *arg = strtok(NULL, " ");
if (!cmd) { reply[0] = 0; return 0; }
if (!strcmp(cmd, "PWM")) {
char *end; long d = arg ? strtol(arg, &end, 10) : -1;
if (!arg || *end || d < 0 || d > 100) return snprintf(reply, n, "ERR PWM expects 0-100"), -1;
m->duty = (int)d; return snprintf(reply, n, "OK PWM %d", m->duty), 0;
}
if (!strcmp(cmd, "DIR")) {
if (!arg || (strcmp(arg, "F") && strcmp(arg, "R"))) return snprintf(reply, n, "ERR DIR expects F or R"), -1;
if (m->running && m->duty > 0 && arg[0] != m->dir) return snprintf(reply, n, "ERR stop before reversing"), -1;
m->dir = arg[0]; return snprintf(reply, n, "OK DIR %c", m->dir), 0;
}
if (!strcmp(cmd, "START")) { m->running = 1; return snprintf(reply, n, "OK START"), 0; }
if (!strcmp(cmd, "STOP")) { m->running = 0; return snprintf(reply, n, "OK STOP"), 0; }
if (!strcmp(cmd, "STATUS"))
return snprintf(reply, n, "OK %s PWM %d DIR %c FREQ %d", m->running ? "RUN" : "IDLE", m->duty, m->dir, m->freq), 0;
return snprintf(reply, n, "ERR unknown command %s", cmd), -1;
}#include <unity.h>
#include "command.h"
void test_pwm_range(void) {
motor_t m = {0, 'F', 20000, 0}; char r[48], l1[] = "pwm 150", l2[] = "PWM 40";
TEST_ASSERT_EQUAL(-1, command(&m, l1, r, sizeof r)); /* aralık dışı reddedilir */
TEST_ASSERT_EQUAL(0, command(&m, l2, r, sizeof r));
TEST_ASSERT_EQUAL(40, m.duty);
TEST_ASSERT_EQUAL_STRING("OK PWM 40", r);
}
int main(void) { UNITY_BEGIN(); RUN_TEST(test_pwm_range); return UNITY_END(); }Teslimler
- 2. üniteden sonraÖneri ve araç zinciri
Gereksinimler (G1–G7), protokol tablosu taslağı; boş projenin CI'da derlenmesi ve size çıktısı.
Araç zinciri: derleme, bağlama, yükleme, hata ayıklama - 5. üniteden sonraPWM katmanı
pwm_set_percent(), frekans ayarı ve yön pinleri; mantık analizörüyle ölçülmüş frekans ve görev oranı tablosu.
Zamanlayıcılar ve PWM - 7. üniteden sonraUART komut arayüzü
Kesmeyle satır okuma ve command() çözümleyici; PlatformIO native ortamında Unity testleri.
UART: seri iletişim ve komut satırı - 8. üniteden sonraÖlçüm ve güvenlik
ADC + DMA ile motor akımı (ya da potansiyometre) ölçümü, aşırı akımda durdurma, buton ile acil dur (EXTI).
ADC ve DMA - 11. üniteden sonraSistem ve demo
FreeRTOS görevleri (motor, komut, izleme) ya da gerekçeli süper döngü; demo videosu ve rapor.
FreeRTOS: görevler, zamanlayıcı ve senkronizasyon