Jak ktokolwiek może korzystać z mikrokontrolera, który ma tylko 384 bajty pamięci programu?

67

Na przykład PIC10F200T

Praktycznie każdy kod, który napiszesz, będzie większy niż ten, chyba że jest to układ jednofunkcyjny. Czy jest jakiś sposób, aby załadować więcej pamięci programu z pamięci zewnętrznej lub coś takiego? Jestem tylko ciekawy, nie rozumiem, jak to może być bardzo przydatne ... ale musi być.

koder543
źródło
6
Istnieje wiele aplikacji dla małych mikrokontrolerów, od generatorów sygnałów specjalnego przeznaczenia, do konwerterów protokołów, do „węzłów” w większym systemie sterowania itp. Itp.,
Dave Tweed
13
Program do gry w szachy zajmuje 672 bajty, więc to nie jest dobre. en.wikipedia.org/wiki/1K_ZX_Chess
John Burton
8
Oto kilka przykładów tego, co można zrobić za pomocą małych programów (mniej niż 256 bajtów).
hammar
9
Co masz na myśli, „chyba że jest to układ jednocelowy”? Większość systemów wbudowanych ma jeden cel.
Jeanne Pindar
6
Po studiach zbudowałem w pełni funkcjonalny program do sygnalizacji świetlnej dla komputera 8085/8155 (maks. 256 bajtów), który zmontowałem. Miał przyciski spacerowe i kilka czujników, które symulowałyby obecność pojazdu.
Zoredache

Odpowiedzi:

133

Dzieciaki, zejdźcie z mojego trawnika!

384 bajty to dużo miejsca na stworzenie czegoś dość złożonego w asemblerze.

Jeśli przejrzysz historię, kiedy komputery były wielkości pokoju, znajdziesz naprawdę niesamowite osiągnięcia artystyczne wykonane w <1k.

Na przykład przeczytaj klasyczną historię Mel - prawdziwego programisty . Trzeba przyznać, że ci faceci mieli 4096 słów pamięci do zabawy, dekadenccy niewierni.

Zobacz także niektóre ze starych konkursów demonstracyjnych, w których wyzwaniem było dopasowanie „intro” do bootblocka dyskietki, typowymi celami są 4k lub 40k i zwykle udaje im się włączyć muzykę i animację.

Edytuj, aby dodać : Okazuje się, że możesz zaimplementować pierwszy na świecie kalkulator naukowy o wartości 100 USD w 320 słowach.

Edycja dla najmłodszych:

  • Dyskietka = dyskietka.
  • Bootblock = 1. sektor dyskietki odczytany podczas uruchamiania.
  • Demoscena = konkursy programistyczne między grupami hakerów.
  • Asembler = fantazyjny sposób programowania urządzenia, jeśli jesteś zbyt miękki, aby używać 8 przełączników i przycisku „zapisz”.
John U
źródło
4
Konsola do gier Atari 2600 miała tylko 4KB pamięci we wkładach ROM do gier (choć niektóre gry ominęły to ograniczenie, używając przełączania banków, aby uzyskać dostęp do więcej niż 4K).
Johnny
1
Eony temu zrobiłem całkiem realistyczny ćwierkający ptak (wystarczająco, aby ludzie szukali ptaka, zamiast podejrzewać komputer), którego wnętrzności (ale nie losowy kod, który uniemożliwiał mu wydawanie dokładnie tego samego dźwięku za każdym razem) wstrząsnęłyby około 384 bajtów, a ja miałem dodatkowe ograniczenia braku zapisywalnych adresów, a bajt zerowy nie był dozwolony w pliku binarnym.
Loren Pechtel
2
Muszę wydostać się więcej, pamiętam to z dawnych
John U
7
+1 za „The Story of Mel”. Jedna z najlepszych rzeczy, które czytałem przez cały tydzień.
Justin
1
@JohnU: Pierwsze kilka gier na Atari 2600 to 2K. Wielu deweloperów nigdy nie zaprojektowało gier, które wykraczałyby poza 4K, ponieważ chociaż 8K układów było przystępnych cenowo (a wózki niektórych firm po prostu wykorzystywały połowę układu 4K), dodając przełączanie banków na kartę za pomocą standardowego (aktywny niski wybór chipów) chip zwiększył liczbę chipów pomocniczych z jednego do trzech.
supercat
59

Mikrokontrolery są na tyle tanie, że często są używane do robienia naprawdę prostych rzeczy, które w przeszłości prawdopodobnie byłyby wykonywane z dyskretną logiką. Naprawdę proste rzeczy. Na przykład, ktoś może chcieć, aby urządzenie włączało wyjście na jedną sekundę co pięć sekund, a dokładniej niż byłby w stanie to zrobić zegar 555.

  movwf OSCCON
mainLp:
  ; Set output low
  clrf  GPIO
  movlw 0xFE
  movwf TRIS
  clrwdt
  call  Wait1Sec
  clrwdt
  call  Wait1Sec
  clrwdt
  call  Wait1Sec
  clrwdt
  call  Wait1Sec
  ; Set output high
  bsf   GPIO,0
  clrwdt
  call  Wait1Sec
  goto  mainLp
Wait1Sec:
  movlw 6
  movwf count2
  movlw 23
  movwf count1
  movlw 17
  movwf count0
waitLp:
  decfsz count0
   goto   waitLp
  decfsz count1
   goto   waitLp
  decfsz count2
   goto   waitLp
  retlw  0

Byłaby to prawdziwa, użyteczna aplikacja, zawierająca mniej niż 32 słowa (48 bajtów) przestrzeni kodu. Można łatwo dodać kilka opcji, aby mieć pewne opcje sterowania czasem styków we / wy i nadal mieć dużo miejsca do stracenia, ale nawet jeśli wszystko, co zrobił, było dokładnie tak, jak pokazano powyżej, może być tańsze i łatwiejsze niż jakakolwiek alternatywa z wykorzystaniem dyskretnych logika. BTW, clrwdtinstrukcje można przenieść do podprogramu, ale uczyni to mniej niezawodnym. Jak napisano, nawet jeśli usterka spowoduje uszkodzenie stosu adresów zwrotnych, watchdog nie zostanie zasilony, dopóki wykonanie nie powróci do głównej pętli. Jeśli tak się nie stanie, organ nadzorczy zresetuje układ po kilku sekundach.

supercat
źródło
9
Szczerze mówiąc, możesz trochę zoptymalizować swój kod, dając zły przykład dzieciom - 5 oddzielnych połączeń, aby czekać 1 sekundę ??? Nicpoń! ;)
John U
9
@JohnU: FYI, kod używa osobnych wywołań, ponieważ jeśli użyje licznika liczenia do zera, a licznik zostanie zakłócony, pętla może działać 255 razy zamiast czterech, jednocześnie karmiąc watchdoga raz na sekundę. Chociaż można by się przed tym zabezpieczyć, sprawdzając w każdej pętli, czy zliczanie było w zakresie, kod do wykonania tego jest bardziej skomplikowany niż pięć wywołań i pięć clrwdtinstrukcji. Nie jest to najbardziej absolutnie bezpieczny sposób przeciwdziałania awariom, ale należy wziąć pod uwagę kwestie bezpieczeństwa (np. Unikanie clrwdtpodprogramu).
supercat
10
@ coder543: W przypadku braku takich rzeczy, jak szum zasilacza, niezbyt. Z drugiej strony, w częściach bez wykrywacza przepalenia, może się zdarzyć wiele szalonych rzeczy, jeśli VDD spadnie do poziomu między minimalnym napięciem roboczym a ziemią, a następnie wróci do normy. Zasadniczo należy starać się zapewnić, aby każdy stan, w którym urządzenie może się znaleźć, powróci do normalnego stanu w rozsądnym czasie. Około dwóch sekund na uruchomienie się przez stróża może być nieuniknione, ale cztery minuty na osiągnięcie zera przez wyskakujący licznik może być trochę dużo.
supercat
10
@ coder543, zdarzają się częściej na ważnej demonstracji, niż chcesz w to uwierzyć. Tego rodzaju myślenie jest również wymagane przy budowaniu głęboko osadzonych rzeczy, które nie mają możliwości wezwania pomocy lub zgłoszenia błędu. Lub są niedostępne (pomyśl o głębokim morzu lub kosmosie), nawet jeśli zauważony zostanie błąd.
RBerteig
6
@JohnU: Zauważyłem to, ale pomyślałem, że wyjaśnienie, dlaczego napisałem ten kod, może być pomocne. Nawiasem mówiąc, próbowałem również pokazać, że małe zadania mogą zmieścić się w małym procesorze, nawet jeśli nie są absolutnie idealnie zoptymalizowane.
supercat
26

„TYLKO” 384 bajty?

Dawno temu miałem za zadanie napisać (samodzielnie) cały system operacyjny dla specjalistycznego komputera obsługującego przemysł zarządzania statkami, rurociągami i rafineriami. Pierwszy taki produkt firmy był oparty na 6800 i był aktualizowany do 6809, i chcieli, aby nowy system operacyjny współpracował z 6809, aby mogli wyeliminować koszty licencji oryginalnego systemu operacyjnego. Zwiększali także rozmiar romu rozruchowego do 64 bajtów, w porównaniu z 32. Jeśli dobrze pamiętam, to BYŁO około 33 lat temu! - Przekonałem inżynierów, aby podali mi 128 bajtów, abym mógł umieścić sterowniki ROM całego systemu operacyjnego na ROMie, dzięki czemu całe urządzenie będzie bardziej niezawodne i wszechstronne. Obejmowało to:

  • Sterownik klawiatury z kluczem debounce
  • Sterownik wideo
  • Sterownik napędu dyskowego i podstawowy system plików („format abloadera” Motoroli, IIRC), z wbudowaną możliwością traktowania „bankowanej” pamięci tak, jakby to była naprawdę szybka przestrzeń dyskowa.
  • Sterownik modemu (dostali FSK do tyłu, więc te modemy tylko ze sobą rozmawiały)

Tak, wszystkie z nich były tak proste, jak to tylko możliwe, i zoptymalizowane ręcznie, aby usunąć każdy obcy cykl, ale doskonale sprawne i niezawodne. Tak, podłączyłem to wszystko do dostępnych bajtów - och, skonfigurowałem również obsługę przerwań, różne stosy i zainicjowałem system operacyjny w czasie rzeczywistym / wielozadaniowość, poprosiłem użytkownika o opcje rozruchu i uruchomiłem system.

Mój przyjaciel, który jest nadal związany z firmą (jej następcą), powiedział mi kilka lat temu, że mój kod wciąż działa!

Możesz zrobić dużo z 384 bajtami ...

Richard T.
źródło
2
mówisz boot rom i wspominasz o przeniesieniu sterowników na boot rom ... to wskazuje mi, że był dostępny drugi nośnik pamięci. W tej dyskusji ustaliliśmy już, że nie można załadować kodu z pamięci zewnętrznej na ten PIC.
koder543
5
@ coder543 To nie trafia w sedno: 384 bajty wystarczy, by zrobić całkiem sporo! Pierwotne pytanie brzmiało jak skarga, że ​​384 nie wystarczyło, aby zrobić coś pożytecznego - było więcej, niż potrzebowałem - dużo więcej - aby zapewnić wszystkie podstawowe elementy wielozadaniowego systemu operacyjnego w czasie rzeczywistym ...
Richard T
21

Możesz użyć tego do bardzo małych aplikacji (np. Opóźnionego startu zasilacza , wymiany timera 555 , sterowania opartego na triaku , migania diody LED itp.) O mniejszej powierzchni, niż potrzebujesz z bramkami logicznymi lub timerem 555.

Renan
źródło
3
Właśnie zauważyłem, że te dwa pierwsze przykłady pochodziły od samego Stack! dobrze rozegrane.
coder543
9
+1 za wzmiankę o powierzchni. Czasami rozmiar jest wszystkim.
embedded.kyle
17

Zaprojektowałem czujnik wilgotności dla roślin, który śledzi ilość wody w roślinie i miga diodą LED, jeśli roślina potrzebuje wody. Możesz sprawić, by czujnik nauczył się rodzaju rośliny, a tym samym zmienił jej ustawienia podczas pracy. Wykrywa niskie napięcie na akumulatorze. Skończyło mi się flashowanie i RAM, ale byłem w stanie napisać wszystko w kodzie C, aby ten produkt działał bezbłędnie.

Użyłem wspomnianego pic10f.


Oto kod, który stworzyłem dla mojego czujnika wody w zakładzie. Użyłem pic10f220, ponieważ ma moduł ADC, ma taką samą pamięć jak pic10f200, postaram się znaleźć schemat jutro.

Kod jest w języku hiszpańskim, ale jest bardzo prosty i należy go łatwo zrozumieć. Kiedy Pic10F budzi się z trybu uśpienia, zresetuje się, więc musisz sprawdzić, czy to był PowerUp, czy zresetować i odpowiednio postępować. Ustawienie rośliny jest utrzymywane w pamięci ram, ponieważ nigdy tak naprawdę nie wyłącza się.

MAIN.C

/*
Author: woziX (AML)

Feel free to use the code as you wish. 
*/

#include "main.h"

void main(void) 
{  
    unsigned char Humedad_Ref;
    unsigned char Ciclos;
    unsigned char Bateria_Baja;
    unsigned char Humedad_Ref_Bkp;

    OSCCAL &= 0xfe;             //Solo borramos el primer bit
    WDT_POST64();                   //1s
    ADCON0 = 0b01000000;
    LEDOFF();
    TRIS_LEDOFF(); 

    for(;;) 
    {  
        //Se checa si es la primera vez que arranca
        if(FIRST_RUN())
        {
            Ciclos = 0;
            Humedad_Ref = 0;
            Bateria_Baja = 0;
        }

        //Checamos el nivel de la bateria cuando arranca por primera vez y cada 255 ciclos.
        if(Ciclos == 0)
        {
            if(Bateria_Baja)
            {
                Bateria_Baja--;
                Blink(2);
                WDT_POST128();
                SLEEP();
            }       

            if(BateriaBaja())
            {
                Bateria_Baja = 100;     //Vamos a parpadear doble por 100 ciclos de 2 segundos
                SLEEP();
            }
            Ciclos = 255;
        }   

        //Checamos si el boton esta picado
        if(Boton_Picado)
        {
            WDT_POST128();
            CLRWDT();
            TRIS_LEDON(); 
            LEDON();
            __delay_ms(1000);   
            TRIS_ADOFF();
            Humedad_Ref = Humedad();
            Humedad_Ref_Bkp = Humedad_Ref;
        }   

        //Checamos si esta calibrado. Esta calibrado si Humedad_Ref es mayor a cero
        if( (!Humedad_Ref) || (Humedad_Ref != Humedad_Ref_Bkp) )
        {
            //No esta calibrado, hacer blink y dormir
            Blink(3);
            SLEEP();
        }   

        //Checamos que Humedad_Ref sea mayor o igual a 4 antes de restarle 
        if(Humedad_Ref <= (255 - Offset_Muy_Seca))
        {
            if(Humedad() > (Humedad_Ref + Offset_Muy_Seca)) //planta casi seca
            {
                Blink(1);
                WDT_POST32();
                SLEEP();    
            }       
        }

        if(Humedad() >= (Humedad_Ref))  //planta seca
        {
            Blink(1);
            WDT_POST64();
            SLEEP();    
        }   

        if(Humedad_Ref >= Offset_Casi_Seca )
        {
            //Si Humedad_Ref es menor a Humedad, entonces la tierra esta seca. 
            if(Humedad() > (Humedad_Ref - Offset_Casi_Seca))  //Planta muy seca
            {
                Blink(1);
                WDT_POST128();
                SLEEP();    
            }
        }

        SLEEP();
    }  
} 

unsigned char Humedad (void)
{
    LEDOFF();
    TRIS_ADON();
    ADON();
    ADCON0_CH0_ADON();
    __delay_us(12); 
    GO_nDONE = 1;
    while(GO_nDONE);
    TRIS_ADOFF();
    ADCON0_CH0_ADOFF();
    return ADRES;
}   

//Regresa 1 si la bateria esta baja (fijado por el define LOWBAT)
//Regresa 0 si la bateria no esta baja
unsigned char BateriaBaja (void)
{
    LEDON();                
    TRIS_ADLEDON();
    ADON();
    ADCON0_ABSREF_ADON();
    __delay_us(150);        //Delay largo para que se baje el voltaje de la bateria 
    GO_nDONE = 1;
    while(GO_nDONE);
    TRIS_ADOFF();
    LEDOFF();
    ADCON0_ABSREF_ADOFF();  
    return (ADRES > LOWBAT ? 1 : 0);
}   

void Blink(unsigned char veces)
{
    while(veces)
    {
        veces--;
        WDT_POST64();
        TRIS_LEDON(); 
        CLRWDT();
        LEDON();
        __delay_ms(18); 
        LEDOFF();
        TRIS_ADOFF();
        if(veces)__delay_ms(320);   
    }   
}   

MAIN.H

/*
Author: woziX (AML)

Feel free to use the code as you wish. 
*/

#ifndef MAIN_H
#define MAIN_H

#include <htc.h>
#include <pic.h>

 __CONFIG (MCPU_OFF  & WDTE_ON & CP_OFF & MCLRE_OFF & IOSCFS_4MHZ ); 

#define _XTAL_FREQ              4000000
#define TRIS_ADON()             TRIS = 0b1101
#define TRIS_ADOFF()            TRIS = 0b1111
#define TRIS_LEDON()            TRIS = 0b1011
#define TRIS_LEDOFF()           TRIS = 0b1111
#define TRIS_ADLEDON()          TRIS = 0b1001


#define ADCON0_CH0_ADON()          ADCON0 = 0b01000001;     // Canal 0 sin ADON
#define ADCON0_CH0_ADOFF()       ADCON0 = 0b01000000;       // Canal 0 con adON
#define ADCON0_ABSREF_ADOFF()    ADCON0 = 0b01001100;       //Referencia interna absoluta sin ADON
#define ADCON0_ABSREF_ADON()     ADCON0 = 0b01001101;       //referencia interna absoluta con ADON

//Llamar a WDT_POST() tambien cambia las otras configuracion de OPTION
#define WDT_POST1()   OPTION = 0b11001000
#define WDT_POST2()   OPTION = 0b11001001
#define WDT_POST4()   OPTION = 0b11001010
#define WDT_POST8()   OPTION = 0b11001011
#define WDT_POST16()  OPTION = 0b11001100
#define WDT_POST32()  OPTION = 0b11001101
#define WDT_POST64()  OPTION = 0b11001110
#define WDT_POST128() OPTION = 0b11001111

#define Boton_Picado    !GP3
#define FIRST_RUN()     (STATUS & 0x10) //Solo tomamos el bit TO

//Offsets
#define Offset_Casi_Seca  5
#define Offset_Muy_Seca   5

 //Low Bat Threshold
#define LOWBAT                    73
/*
Los siguientes valores son aproximados
LOWBAT  VDD
50      3.07
51      3.01
52      2.95
53      2.90
54      2.84
55      2.79
56      2.74
57      2.69
58      2.65
59      2.60
60      2.56
61      2.52
62      2.48
63      2.44
64      2.40
65      2.36
66      2.33
67      2.29
68      2.26
69      2.23
70      2.19
71      2.16
72      2.13
73      2.10
74      2.08
75      2.05
76      2.02
77      1.99
78      1.97
*/


#define LEDON()                 GP2 = 0; //GPIO = GPIO & 0b1011
#define LEDOFF()                GP2 = 1; //GPIO = GPIO | 0b0100
#define ADON()                  GP1 = 0; //GPIO = GPIO & 0b1101
#define ADOFF()                 GP1 = 1; //GPIO = GPIO | 0b0010

unsigned char Humedad (void);
unsigned char BateriaBaja (void);
void Delay_Parpadeo(void);
void Blink(unsigned char veces);

#endif

Daj mi znać, jeśli masz pytania, postaram się odpowiedzieć na podstawie tego, co pamiętam. Kodowałem to kilka lat temu, więc nie sprawdzaj moich umiejętności kodowania, poprawiły się :).

Ostatnia uwaga. Użyłem kompilatora Hi-Tech C.

szorstki
źródło
3
Byłbym naprawdę ciekawy czytając, jak to zrobiłeś. Czy robiłeś w ogóle jakieś notatki, których nie miałbyś nic przeciwko udostępnianiu w sieci?
RhysW
1
Witaj RhysW, wierzę, że wciąż mam kod. To było naprawdę proste. Mogę przesłać Ci mój kod, jeśli jesteś zainteresowany. Daj mi znać. Obwód, który zaprojektowałem, jest bardzo prosty i fajny, tylko 3 rezystory, jeden p-kanałowy mosfet (do ochrony przed odwróceniem akumulatora), pokrywa 100nF i dioda LED. Używam i wewnętrznej diody w pic10f, aby wykorzystać ją jako odniesienie do pomiaru baterii i utrzymać stałe odczyty ADC.
scrafy
1
Brzmi jak porządny projekt. Czy jest jakaś szansa, że ​​możesz opublikować szczegóły tutaj (lub przynajmniej zamieścić je gdzieś i link do nich)?
Ilmari Karonen
1
Cześć scrafy! Jeśli masz coś do dodania do odpowiedzi, użyj linku „edytuj” zamiast publikować nową odpowiedź, ponieważ ta strona korzysta z głosowania i nie działa jak forum.
clabacchio
16

Jedna rzecz, o której nie widziałem: mikrokontroler, o którym wspomniałeś, kosztuje tylko 0,34 USD w ilości 100 sztuk. Tak więc w przypadku tanich, produkowanych masowo produktów sensowne jest przejście na dodatkowe problemy z kodowaniem narzucone przez tak ograniczoną jednostkę. To samo może dotyczyć wielkości lub zużycia energii.

Mark Harrison
źródło
2
To była dokładnie moja pierwsza myśl. Ponadto: gdybym był startupem z ciekawym pomysłem, ale straciłby tylko kilkaset dolarów, takie rzeczy mogą oznaczać różnicę między powrotem do codziennej pracy a pracą na koniec dnia.
fresnel
14

Kiedy byłem w szkole średniej, miałem nauczyciela, który nalegał, aby ściemnianie światła było zbyt trudnym zadaniem dla takiego ucznia jak ja.

Tak rzucone wyzwanie poświęciłem sporo czasu na naukę i rozumienie ściemniania fazowego za pomocą triaków i programowanie 16C84 z mikroczipu, aby wykonać ten wyczyn. Skończyło się z tym kodem asemblera:

'Timing info:
'There are 120 half-cycles in a 60Hz AC waveform
'We want to be able to trigger a triac at any of 256 
'points inside each half-cycle.  So:
'1 Half cycle takes 8 1/3 mS
'1/256 of one half cycle takes about 32.6uS
'The Pause function here waits (34 * 0xD)uS, plus 3uS overhead
'Overhead includes CALL PAUSE.
'This was originally assembled using Parallax's "8051 style" 
'assembler, and was not optimized any further.  I suppose
'it could be modified to be closer to 32 or 33uS, but it is
'sufficient for my testing purposes.

list 16c84

    movlw   0xFD     '11111101
    tris    0x5      'Port A
    movlw   0xFF     '11111111
    tris    0x6      'Port B
WaitLow:             'Wait for zero-crossing start
    btfss   0x5,0x0  'Port A, Bit 1
    goto    WaitLow  'If high, goto WaitLow
WaitHigh:            'Wait for end of Zero Crossing
    btfsc   0x5,0x0  'Port A, Bit 1
    goto    WaitHigh 'If low, goto waitHigh
    call    Pause    'Wait for 0xD * 34 + 3 uS
    bcf     0x5,0x1  'Put Low on port A, Bit 1
    movlw   0x3      'Put 3 into W
    movwf   0xD      'Put W into 0xD
    call    Pause    'Call Pause, 105 uS
    bsf     0x5,0x1  'Put High on Port A, Bit 1
    decf    0xE      'Decrement E
    movf    0x6,W    'Copy Port B to W
    movwf   0xD      'Copy W to 0xD
    goto    Start    'Wait for zero Crossing
Pause:               'This pauses for 0xD * 34 + 3 Micro Seconds
                     'Our goal is approx. 32 uS per 0xD
                     'But this is close enough for testing
    movlw   0xA      'Move 10 to W
    movwf   0xC      'Move W to 0xC
Label1:
    decfsz  0xC      'Decrement C
    goto    Label1   'If C is not zero, goto Label1
    decfsz  0xD      'Decrement D
    goto    Pause    'If D is not zero, goto Pause
    return           'Return

Oczywiście musisz zmodyfikować to dla wspomnianego układu i dodać tani program szeregowy do wprowadzania danych, ponieważ twój układ nie ma 8-bitowego portu do słuchania, ale chodzi o to, że pozornie złożone zadanie może zrobić w bardzo małym kodzie - w 10F200 można zmieścić dziesięć kopii powyższego programu.

Więcej informacji o projekcie można znaleźć na mojej stronie Light Dimming . Nawiasem mówiąc, nigdy nie pokazałem tego mojemu nauczycielowi, ale skończyło się na zrobieniu wielu przyponów oświetleniowych dla mojego przyjaciela DJ-a.

Adam Davis
źródło
12

Cóż, lata temu napisałem kontroler temperatury z szeregowym we / wy (bit-bangowanie szeregowego we / wy, ponieważ MCU nie miało UART) i prosty interpreter poleceń do rozmowy ze sterownikiem. MCU to Motorola (obecnie Freescale) MC68HC705K1, który miał aż 504 bajty pamięci programu (OTPROM) i około 32 bajtów pamięci RAM. Nie tak mały jak PIC, o którym wspominasz, ale pamiętam, że zostało trochę pamięci ROM. Wciąż mam jeszcze kilka zmontowanych jednostek, 17 lat później; chcesz kupić?

Tak, można to zrobić, przynajmniej podczas montażu.

W każdym razie, ostatnio napisałem bardzo proste programy w C, które po zoptymalizowaniu prawdopodobnie zmieściłyby się w 384 bajtach. Nie wszystko wymaga dużego, złożonego oprogramowania.

Lyndon
źródło
5

Możesz napisać mrugnięcie diodą LED z pamięcią programu o długości 384 bajtów, a nawet więcej.

O ile mi wiadomo, nie jest możliwe rozszerzenie pamięci programu za pomocą zewnętrznego układu scalonego (chyba że budujesz pełny interpreter ASM w 384 bajtach , co byłoby wolne). Możliwe jest jednak rozszerzenie pamięci danych za pomocą zewnętrznego układu (EEPROM, SRAM).


źródło
1
Nie byłoby trudno zbudować symulator maszyny Turinga w 384 bajtach ...
Chris Stratton
@ChrisStratton Miałem na myśli pełnego tłumacza, aby „rozszerzona pamięć programu” miała te same funkcje, co normalnie.
Tak, to właśnie zasugerowałem sposób ścisłego wdrożenia. Reszta to projekt kompilatora ...
Chris Stratton
7
Jeśli ktoś chciałby przechowywać logikę programu w zewnętrznej pamięci EEPROM, próba emulacji zestawu instrukcji PIC nie byłaby dobrym rozwiązaniem. Lepszym rozwiązaniem byłoby zaprojektowanie zestawu instrukcji zoptymalizowanego do użycia z maszyną wirtualną; w rzeczywistości takie podejście przyjęła Parallax ze swoim „Basic STAMP” w latach 90. Był to PIC z 3072 bajtami miejsca na kod, połączony z szeregowym układem EEPROM.
supercat
3
BTW, dodatkowa uwaga na temat stempla BASIC: został wprowadzony w czasie, gdy mikrokontrolery oparte na pamięci flash lub EEPROM były stosunkowo rzadkie, ale szeregowe układy EEPROM były dość tanie. W aplikacjach, które nie wymagały dużej prędkości, mikro-kod o stałym kodzie z seryjną częścią EEPROM byłby tańszy niż porównywalna wielkość EEPROM lub micro-flash. Projekt stempla BASIC nie miałby dziś sensu, ale był całkiem praktyczny, kiedy został wprowadzony.
supercat
4

To jest naprawdę gorsze niż myślisz. Połączona strona Mouser jest myląca, gdy określa ten procesor jako mający 384 bajty pamięci programu. PIC10F200 ma w rzeczywistości 256 12-bitowych słów pamięci programu.

Co możesz z tym zrobić? 12-bitowy zestaw instrukcji PIC wykorzystywane przez PIC10F20 x urządzeń są wszystkie instrukcje pojedynczych słów, więc po odjąć kilka instrukcji konfiguracji procesora, jesteś w lewo z wystarczająco dużo miejsca dla programu około 250 kroków. To wystarcza do wielu aplikacji. Na przykład prawdopodobnie mógłbym napisać kontroler pralki w takiej przestrzeni.

Właśnie przejrzałem dostępne kompilatory PIC C i wygląda na to, że około połowa z nich nawet nie spróbuje wyemitować kodu dla PIC10F200. Te, które prawdopodobnie wypuszczają tak dużo kodu, że możesz tylko napisać diodę LED w pozostałej przestrzeni. Naprawdę chcesz używać języka asemblera z takim procesorem.

Warren Young
źródło
Masz rację co do 256 słów instrukcji. W rzeczywistości jeden z nich jest zajęty stałą kalibracji oscylatora, więc otrzymujesz 255 użytecznych instrukcji. Ponadto 10F200 nie używa zwykłego 14-bitowego zestawu instrukcji PIC 16. Wykorzystuje 12-bitowy zestaw instrukcji PIC 12. Zgadzam się jednak z podstawowymi przesłankami. Zrobiłem wiele przydatnych rzeczy z PIC 10F200. +1
Olin Lathrop
@OlinLathrop: Wyjaśniłem odpowiedź. Mam pojęcie PIC16 ze strony 51 arkusza danych , ale zdecydowałem, że łatwiej jest po prostu odnieść się do „12-bitowego zestawu instrukcji”. Prefiks części nie jest niezawodnym przewodnikiem po używanym zestawie instrukcji.
Warren Young,
0

machając laską za dnia, musieliśmy wytrawić własne kawałki z piasku!

W 1976 roku (lub później) system Atari 2600 VCS był jedną z najpopularniejszych „platform gier wideo” tamtych czasów. Mikroprocesor (MOSTEK 6507) działał w nim z oszałamiającym ~ 1 MHz i miał **** 128 bajtów RAM **.

Drugim przykładem, który pamiętam z mikrokontrolera z bardzo ograniczoną pamięcią RAM (~ 128 bajtów) był PIC12F zastosowany na przetwornicy DC-DC. Mikro musiało także używać języka asemblera, aby w ogóle działać.

cowboydan
źródło
4
OP nie mówi o pamięci RAM, mówi o przestrzeni programowej. Przestrzeń programu w Atari 2600 znajduje się we wkładce, a nie w układzie RIOT . 2600 obsługiwanych pamięci ROM programów do 4 kiB bez przełączania banków. (I niektóre komercyjne kasety dokonały przełączania banków!) Jeśli chodzi o twój przykład PIC12F, OP pokonał cię: urządzenia z serii PIC10F20x mają 16 lub 24 bajty SRAM.
Warren Young,