Câștiguri:
- Abilitatea de a defini cerințele de înregistrare, întrerupere și sincronizare pentru microcontroler cu un prompt clar
- Abilitatea de a verifica codul C/Arduino produs de AI în ceea ce privește setările de registru, depășirea tamponului și constrângerile în timp real
- Abilitatea de a aplica obiceiul de a verifica codul generat prin măsurarea acestuia pe hardware (osciloscop, port serial)
Dezvoltarea sistemelor încorporate este locul în care software-ul și hardware-ul se intersectează: setarea incorect a unui bit de registru, menținerea unei întreruperi prea mult timp sau depășirea unui buffer va cauza eșecuri ciudate, greu de reprodus în teren, chiar dacă codul „compilează” și rulează. AI este cu adevărat un accelerator în acest domeniu; Poate produce schelete inițiale, funcții de abstractizare hardware, mașini de stare și rutine de comunicare. Dar AI nu vede fișa de date a cardului dvs., nu vă cunoaște frecvența ceasului și nu percepe constrângerile dvs. în timp real. În această unitate, vom aborda cum să definiți clar funcționarea microcontrolerului pentru AI, cum să verificați codul C/Arduino generat și de ce ar trebui să măsurați totul în hardware.
Definirea clară a cerinței: înregistrare, tăiere, sincronizare
A spune AI să „aprindă un LED” nu va funcționa; Ce card, ce pin, ce frecvență de ceas, ce sincronizare? Când atribuiți o sarcină încorporată AI, utilizați acest cadru: hardware (familie MCU, ceas, pin), funcție (ce se va întâmpla), constrângere (temporizare, putere, memorie) și interfață (registru, HAL, bibliotecă Arduino).
Solicitare slabă / Solicitare puternică
SLAB: „Produce PWM cu STM32”. (Rezultat: ce temporizator, ce frecvență, ce pin este neclar; general, probabil cod de registru greșit.) PUTERNIC: „Produce 20 kHz, 0-100% PWM cu sarcină reglabilă pe TIM3 CH1 (PA6) pentru STM32F103 (ceas de sistem de 72 MHz). calculul în linia de comentarii - Setați taxa cu un parametru de funcție între 0-100 - Comentați fiecare bit de registru pe care îl utilizați.
Diferența este că promptul puternic face ca modelul să arate calculul și să dezvăluie ipoteza ceasului. Deci, puteți verifica independent valorile prescaler/ARR:
Pentru PWM de 20 kHz (ceas 72 MHz): Timer_clock = 72 MHz Dacă vrem prescaler = 72-1 → ceas contor = 1 MHzARR = (1 MHz / 20 kHz) - 1 = 50 - 1 = 49Verificare: 1e6 / (49+1) = 20 00 00 Hz
Auditarea codului AI: ce să căutați?
Doar pentru că codul generat se compilează nu înseamnă că funcționează corect. Urmați această listă de verificare:
zona de control
Ce să cauți
Setări de înregistrare/biți
Exact compatibil cu fișa de date, masca de biți corectă
Întreruperea (ISR)
Este scurt? Fără întârziere de blocare? Se folosesc volatile?
buffer/matrice
Există control la frontieră? Risc de preaplin?
sincronizare
Cu întârziere sau temporizator? Este îndeplinită limita de timp reală?
Tip și lățime
Overflow 8/16/32 biți, confuzie semnată/nesemnată
putere/câine de pază
Câine de pază pentru hrănire în buclă infinită?
Rutinele serviciului de întrerupere (ISR) sunt cea mai comună sursă de erori. AI pune uneori delay() sau buclă lungă în interiorul ISR. Acest lucru duce la pierderea altor întreruperi și la resetarea watchdog-ului. Regula: ISR ar trebui să fie cât mai scurt posibil; Sarcina principală ar trebui să fie configurarea unui steag și mutarea acestuia în bucla principală.
// SLAB (AI produce uneori asta): Funcția de blocare în ISR void TIM3_IRQHandler(void) { if (TIM3->SR & TIM_SR_UIF) { TIM3->SR &= ~TIM_SR_UIF; citire_senzor(); // poate dura mult timp - BAD CASE_Delay(10); // întârziere în ISR - FOARTE RĂU }}// PUTERNIC: ISR scurt; jobul se mută în bucla principală volatilă uint8_t tick_flag = 0; // volatil CONDITIONvoid TIM3_IRQHandler(void) { if (TIM3->SR & TIM_SR_UIF) { TIM3->SR &= ~TIM_SR_UIF; tick_flag = 1; //doar setați flag }}// în bucla principală:if (tick_flag) { tick_flag = 0; citire_senzor(); }
Atenție: Orice variabilă partajată între întrerupere și bucla principală trebuie să fie volatilă. În caz contrar, compilatorul poate stoca variabila în registru și poate pierde actualizarea. AI uită adesea acest cuvânt cheie; Căutați-l în mod special când citiți codul.
Buffer Overflow și erori de tip
AI poate copia datele din portul serial într-o matrice de dimensiuni fixe fără verificarea limitelor. Într-un sistem încorporat, aceasta înseamnă zdrobirea memoriei contigue și blocări inexplicabile. Asigurați-vă că limita este verificată la fiecare strcpy, index de matrice și buffer DMA. În mod similar, un contor de 8 biți se resetează după 255; AI poate ignora acest lucru și se poate baza pe un cont debordant.
Verificare în hardware: „Funcționează” este măsurat, nu presupus
Într-un sistem încorporat, cea mai fiabilă dovadă este contorul, nu compilatorul. Verificați codul generat în aceste trei moduri:
- Osciloscop/analizor logic: Măsoară frecvența PWM, sincronizarea semnalului și forma de undă de comunicare. Dacă ați vrut 20 kHz, vedeți 20 kHz pe ecran.
- Jurnalul portului serial (UART): tipăriți valorile variabilelor, tranzițiile de stare și contoarele de erori și comparați cu comportamentul așteptat.
- Testare legată și de stres: testați dacă sistemul rezistă la cea mai mare sarcină, cele mai rapide date și cel mai prost timp.
Dacă valoarea măsurată nu este de acord cu calculul, ipoteza ceasului, valoarea prescaler sau setarea registrului sunt incorecte; goana.
Mini carcasă
O echipă de studenți are prin AI un cod de măsurare a distanței cu un senzor ultrasonic HC-SR04. Codul compilează dar distanța dă întotdeauna valori ridicole. Când îl conectează la osciloscop, ei văd că piciorul ecou își calculează timpul în milisecunde în loc de microsecunde; AI a folosit millis() în loc de micros(). Această eroare dintr-un cuvânt a confundat întreaga măsurătoare cu un factor de 1000. Când imprimă timpul brut de eco în jurnalul serial și îl compară cu o riglă reală, găsesc eroarea și o repară. Lecția: codul compilat nu este un cod corect; Măsurarea în hardware dezvăluie eroarea imediat.
Greșeli comune
- Acceptarea numelor de registre și a măștilor de biți fără a le compara cu fișa de date.
- Permite întârzierea blocării sau procesarea lungă în cadrul ISR.
- Uitând de volatile pe variabilele partajate.
- Bypass buffer și verificarea limitelor matricei; nevăzând preaplinul.
- Bazându-se pe frecvența ceasului și ipotezele de sincronizare fără a le verifica.
- Considerând că codul „funcționează” fără a-l măsura cu un osciloscop/jurnal serial.
Pe scurt
- Definiți clar sarcina încorporată în termeni de hardware, funcție, constrângeri și interfață.
- Puneți AI să calculeze valorile de sincronizare, cum ar fi prescaler/ARR și să le verifice independent.
- Păstrați ISR-urile scurte, utilizați volatile pe variabilele partajate.
- Căutați în mod specific erorile de registru, limita de buffer și lățimea tipului.
- „Funcționează” este dovedit cu un osciloscop, un analizor logic și un jurnal serial, nu cu compilatorul.
- Dacă valoarea măsurată nu este de acord cu calculul, urmăriți ipotezele.
Sarcina de aplicare
Cu un microcontroler pe care îl aveți (Arduino, STM32, ESP32), cereți AI-ului PWM sau o sarcină periodică la o anumită frecvență. Înainte de a încărca codul: (1) verificați valorile frecvenței/timpul independent de cont în linia de comentarii, (2) verificați pentru volatilitate și blocare în ISR și variabilele partajate. După încărcare, măsurați frecvența reală cu un osciloscop sau analizor logic și comparați-o cu ținta. Dacă există o abatere, găsiți sursa și corectați-o și notați ceea ce sa presupus greșit.