ทุกคนสามารถใช้ไมโครคอนโทรลเลอร์ที่มีหน่วยความจำของโปรแกรมเพียง 384 ไบต์ได้อย่างไร


67

ยกตัวอย่างเช่นPIC10F200T

รหัสใด ๆ ที่คุณเขียนจะมีขนาดใหญ่กว่านั้นยกเว้นว่าเป็นชิปวัตถุประสงค์เดียว มีวิธีใดบ้างที่จะโหลดหน่วยความจำโปรแกรมเพิ่มเติมจากที่เก็บข้อมูลภายนอก ฉันแค่อยากรู้อยากเห็นฉันไม่เห็นว่าสิ่งนี้จะมีประโยชน์มาก ... แต่มันต้องเป็น


6
มีแอปพลิเคชั่นมากมายสำหรับไมโครคอนโทรลเลอร์ขนาดเล็กตั้งแต่เครื่องกำเนิดสัญญาณพิเศษไปจนถึงตัวแปลงโปรโตคอลไปจนถึง "โหนด" ในระบบควบคุมขนาดใหญ่ ฯลฯ ฯลฯ
Dave Tweed

13
โปรแกรมเล่นหมากรุกใช้เวลา 672 ไบต์ดังนั้นจึงไม่ดี en.wikipedia.org/wiki/1K_ZX_Chess
John Burton

8
นี่คือตัวอย่างของสิ่งที่สามารถทำได้กับโปรแกรมเล็ก ๆ (น้อยกว่า 256 ไบต์)
hammar

9
คุณหมายถึงอะไร "ถ้าไม่มีชิปตัวเดียว" ระบบฝังตัวส่วนใหญ่มีจุดประสงค์เดียว
Jeanne Pindar

6
ย้อนกลับไปในวิทยาลัยฉันสร้างโปรแกรมสัญญาณไฟจราจรที่ใช้งานได้อย่างสมบูรณ์สำหรับคอมพิวเตอร์ 8085/8155 (สูงสุด 256 ไบต์) ที่ฉันประกอบ มันมีปุ่มเดินและเซ็นเซอร์บางตัวที่จะจำลองการปรากฏตัวของยานพาหนะ
Zoredache

คำตอบ:


133

ลูกคุณออกไปจากสนามหญ้าของฉัน!

384 ไบต์มีพื้นที่มากมายในการสร้างสิ่งที่ค่อนข้างซับซ้อนในแอสเซมเบลอร์

หากคุณขุดลึกลงไปถึงประวัติศาสตร์เมื่อคอมพิวเตอร์มีขนาดเท่ากับห้องคุณจะพบกับงานศิลปะที่น่าทึ่งที่ดำเนินการใน <1k

ยกตัวอย่างเช่นอ่านคลาสสิกเรื่องของเมล - โปรแกรมเมอร์จริง เป็นที่ยอมรับคนเหล่านั้นมี 4096 คำของหน่วยความจำที่จะเล่นกับคนนอกศาสนาเสื่อมโทรม

ดูการแข่งขัน demoscene แบบเก่าที่ความท้าทายคือการใส่ "อินโทร" เข้าไปใน bootblock ของฟลอปปี้เป้าหมายทั่วไปคือ 4k หรือ 40k และมักจะจัดการเพื่อรวมเพลงและภาพเคลื่อนไหว

แก้ไขเพื่อเพิ่ม : ปรากฎว่าคุณสามารถใช้เครื่องคิดเลขวิทยาศาสตร์มูลค่า 100 ดอลลาร์แรกของโลกใน 320 คำ

แก้ไขสำหรับผู้เยาว์ที่ไม่เหมาะสม:

  • ฟลอปปี้ = ฟลอปปี้ดิสก์
  • Bootblock = ส่วนที่ 1 ของฟลอปปี้อ่านเมื่อบูทเครื่อง
  • Demoscene = การแข่งขันการเขียนโปรแกรมระหว่างกลุ่มแฮ็กเกอร์
  • Assembler = วิธีการเขียนโปรแกรมของอุปกรณ์หากคุณอ่อนเกินกว่าจะใช้สวิตช์สลับ 8 ปุ่มและปุ่ม "store"

4
คอนโซลเกมของอาตาริ 2600 มีพื้นที่เก็บข้อมูล 4KB ในคาร์ทริดจ์เกม ROM (แม้ว่าบางเกมจะมีข้อ จำกัด นี้โดยใช้การสลับธนาคารเพื่อเข้าถึงมากกว่า 4K)
จอห์นนี่

1
เมื่อหลายปีก่อนฉันทำเสียงนกร้องเจี๊ยก ๆ จริง ๆ (พอที่ผู้คนมองหานกมากกว่าที่จะสงสัยคอมพิวเตอร์) ความกล้าที่ (แต่ไม่ใช่รหัสการสุ่มที่ทำให้เสียงเหมือนกันทุกครั้ง) จะสั่น ประมาณ 384 ไบต์และฉันมีข้อ จำกัด เพิ่มเติมเกี่ยวกับที่อยู่ที่ไม่สามารถเขียนได้และไม่อนุญาตให้ใช้ศูนย์ไบต์ในไบนารี
Loren Pechtel

2
ฉันต้องออกไปมากขึ้นจดจำเรื่องนี้ย้อนหลังได้ในตอนกลางวัน - ตัวรักษาหน้าจอในขนาด 368 ไบต์: aminet.net/package/util/blank/368blanker
John U

7
+1 สำหรับ "The Story of Mel" หนึ่งในสิ่งที่ยิ่งใหญ่ที่สุดที่ฉันได้อ่านตลอดทั้งสัปดาห์
Justin ᚅᚔᚈᚄᚒᚔ

1
@JohnU: สองสามเกมแรกในอาตาริ 2600 เป็นเกม 2K ทั้งหมด นักพัฒนาหลายคนไม่เคยออกแบบเกมใด ๆ ที่เหนือกว่า 4K เพราะแม้ว่าชิป 8K นั้นมีราคาไม่แพง (และรถเข็นของ บริษัท บางแห่งใช้ชิปครึ่งหนึ่งเพียง 4K) เพิ่มการสลับธนาคารเป็นการ์ดโดยใช้มาตรฐาน (เลือกชิปที่ใช้งานต่ำ) ชิปเพิ่มจำนวนชิปสนับสนุนจากหนึ่งเป็นสาม
supercat

59

ไมโครคอนโทรลเลอร์มีราคาถูกเพียงพอที่พวกเขามักจะใช้ทำสิ่งที่ง่าย ๆ ซึ่งในปีที่ผ่านมามีแนวโน้มที่จะทำด้วยตรรกะที่ไม่ต่อเนื่อง สิ่งที่เรียบง่ายจริงๆ ตัวอย่างเช่นหนึ่งอาจต้องการให้อุปกรณ์เปิดเอาท์พุทเป็นเวลาหนึ่งวินาทีทุก ๆ ห้าวินาทีแม่นยำกว่าตัวจับเวลา 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

นั่นจะเป็นแอปพลิเคชั่นที่ใช้งานได้จริงและมีพื้นที่โค้ดน้อยกว่า 32 คำ (48 ไบต์) เราสามารถเพิ่มตัวเลือกสองสามตัวเลือกเพื่อให้ I / O พินควบคุมตัวเลือกเวลาได้อย่างง่ายดายและยังมีที่ว่างมากมาย แต่ถึงแม้ว่าชิปทั้งหมดนั้นเป็นสิ่งที่แสดงให้เห็นอย่างแม่นยำมันอาจจะถูกกว่าและง่ายกว่าทางเลือกอื่น ๆ ตรรกะ. BTW clrwdtคำแนะนำสามารถย้ายไปที่รูทีนย่อย แต่การทำเช่นนั้นจะทำให้สิ่งต่าง ๆ มีความแข็งแกร่งน้อยลง ตามที่เขียนไว้แม้ว่าความผิดพลาดจะทำให้สแต็กที่อยู่ผู้ส่งคืนได้รับความเสียหาย Watchdog จะไม่ได้รับการป้อนข้อมูลจนกว่าการดำเนินการจะกลับไปที่ลูปหลัก หากไม่เคยเกิดขึ้น watchdog จะรีเซ็ตชิปหลังจากผ่านไปสองสามวินาที


9
สุจริตคุณสามารถเพิ่มประสิทธิภาพรหัสของคุณบิตการตั้งค่าตัวอย่างที่ไม่ดีให้กับเด็ก ๆ - 5 สายที่แยกต่างหากเพื่อรอ 1sec ??? ขยะ! ;)
John U

9
@JohnU: FYI รหัสใช้การโทรแยกกันเพราะหากใช้ตัวนับนับเป็นศูนย์และการนับมีความผิดพลาดลูปอาจทำงาน 255 ครั้งแทนที่จะเป็นสี่ครั้งในขณะที่ป้อนสุนัขเฝ้าบ้านหนึ่งครั้งต่อวินาที ในขณะที่มันจะเป็นไปได้ที่จะป้องกันโดยการตรวจสอบว่าแต่ละวงอยู่ในช่วงการนับรหัสการทำที่ซับซ้อนกว่าการโทรห้าสายและห้าclrwdtคำแนะนำ นี่ไม่ใช่การจัดเรียงตัวนับที่ไม่ปลอดภัยที่สุดที่เป็นไปได้ แต่มีการพิจารณาบางอย่างเกี่ยวกับปัญหาด้านความปลอดภัย (เช่นการหลีกเลี่ยงclrwdtภายในรูทีนย่อย)
supercat

10
@ coder543: ในกรณีที่ไม่มีเสียงเช่นแหล่งจ่ายไฟไม่มาก ในทางตรงกันข้ามชิ้นส่วนที่ไม่มีตัวตรวจจับแบบไร้สายนั้นเป็นไปได้ที่สิ่งบ้าทุกประเภทจะเกิดขึ้นหาก VDD ตกอยู่ในระดับระหว่างแรงดันไฟฟ้าขั้นต่ำและแรงดันต่ำจากนั้นจึงกลับมาเป็นปกติ โดยทั่วไปเราควรพยายามตรวจสอบให้แน่ใจว่าสถานะใด ๆ ที่อุปกรณ์อาจพบว่าตัวเองจะกลับมาเป็นปกติในช่วงเวลาที่เหมาะสม สองวินาทีหรือมากกว่านั้นสำหรับสุนัขเฝ้าบ้านที่จะเตะอาจจะหลีกเลี่ยงไม่ได้ แต่สี่นาทีสำหรับเคาน์เตอร์ที่ผิดพลาดที่จะไปถึงศูนย์อาจจะค่อนข้างมาก
supercat

10
@ coder543 พวกเขาเกิดขึ้นบ่อยครั้งในการสาธิตที่สำคัญกว่าที่คุณต้องการเชื่อ ต้องใช้ความคิดเช่นนี้เมื่อสร้างสิ่งที่ฝังลึกซึ่งไม่มีวิธีเรียกร้องความช่วยเหลือหรือรายงานข้อผิดพลาด หรือไม่สามารถเข้าถึงได้ (คิดว่าท้องทะเลลึกหรือนอกโลก) แม้ว่าจะสังเกตเห็นข้อผิดพลาดก็ตาม
RBerteig

6
@JohnU: ฉันสังเกตเห็นแล้ว แต่คิดว่าจะอธิบายว่าทำไมฉันจึงเขียนรหัสเพราะฉันอาจมีประโยชน์ บังเอิญฉันพยายามแสดงให้เห็นว่างานเล็ก ๆ สามารถพอดีกับโปรเซสเซอร์ขนาดเล็กแม้ว่าพวกเขาจะไม่ได้รับการปรับให้เหมาะสมอย่างสมบูรณ์แบบ
supercat

26

"เท่านั้น" 384 ไบต์?

ย้อนกลับไปในวันนั้นฉันมีงานเขียนระบบปฏิบัติการทั้งหมด (ด้วยตัวเอง) สำหรับคอมพิวเตอร์เฉพาะทางที่ให้บริการเรือท่อและอุตสาหกรรมการจัดการโรงกลั่น ผลิตภัณฑ์ตัวแรกของ บริษัท คือ 6800 และได้รับการอัพเกรดเป็น 6809 และพวกเขาต้องการให้ระบบปฏิบัติการใหม่สอดคล้องกับ 6809 เพื่อให้พวกเขาสามารถลดค่าใช้จ่ายใบอนุญาตของระบบปฏิบัติการดั้งเดิม พวกเขายังเพิ่มขนาดบู๊ต ROM เป็น 64 ไบต์เพิ่มขึ้นจาก 32 หากฉันจำได้ถูกต้อง - มันก็ประมาณ 33 ปีที่แล้ว! - ฉันโน้มน้าววิศวกรให้ 128 ไบต์เพื่อให้ฉันสามารถใส่ไดรเวอร์อุปกรณ์ของระบบปฏิบัติการทั้งหมดในรอมและทำให้อุปกรณ์ทั้งหมดน่าเชื่อถือและใช้งานได้หลากหลาย รวมถึง:

  • ไดรเวอร์แป้นพิมพ์พร้อมการ debounce ที่สำคัญ
  • ไดรเวอร์วิดีโอ
  • ดิสก์ไดร์ฟเวอร์และระบบไฟล์พื้นฐาน (โมโตโรล่า "abloader ฟอร์แมต", IIRC) พร้อมความสามารถในการจัดการหน่วยความจำ "แบงค์" ราวกับว่ามันเป็นพื้นที่ดิสก์ที่รวดเร็วมาก
  • ไดรเวอร์โมเด็ม (มี FSK ไว้ด้านหลังดังนั้นโมเด็มเหล่านี้จะคุยกันเท่านั้น)

ใช่สิ่งเหล่านี้เป็นเหมือนกระดูกเปลือยที่ได้รับและได้รับการปรับปรุงด้วยมือเพื่อกำจัดทุกรอบนอก แต่ให้บริการได้อย่างสมบูรณ์และเชื่อถือได้ ใช่ฉันสวมใส่ทั้งหมดที่มีอยู่ในไบต์ - โอ้มันตั้งค่าการจัดการขัดจังหวะกองต่าง ๆ และเริ่มต้นระบบปฏิบัติการเรียลไทม์ / มัลติทาสกิ้งได้รับแจ้งผู้ใช้เกี่ยวกับตัวเลือกการบูตและบูตระบบ

เพื่อนของฉันผู้ซึ่งยังคงเป็นพันธมิตรกับ บริษัท (ผู้สืบทอด) บอกฉันเมื่อสองสามปีก่อนว่ารหัสของฉันยังคงใช้งานได้!

คุณสามารถทำอะไรได้มากด้วย 384 ไบต์ ...


2
คุณพูด boot rom และคุณพูดถึงการย้ายไดรเวอร์ไปยัง boot rom ... สิ่งนี้บ่งบอกว่ามีสื่อบันทึกข้อมูลสำรองอยู่ ในการสนทนานี้เราได้พิจารณาแล้วว่าคุณไม่สามารถโหลดรหัสจากที่จัดเก็บข้อมูลภายนอกใน PIC นี้
coder543

5
@ coder543 นั่นพลาดจุด: 384 ไบต์เพียงพอที่จะทำค่อนข้างมาก! คำถามเดิมอ่านเหมือนคำร้องเรียนที่ 384 ไม่เพียงพอที่จะทำสิ่งที่มีประโยชน์ - มันมากกว่าที่ฉันต้องการ - มากขึ้น - เพื่อให้ส่วนประกอบพื้นฐานทั้งหมดของระบบปฏิบัติการแบบเรียลไทม์และแบบมัลติทาสกิ้ง ...
Richard T

21

คุณสามารถใช้สิ่งนี้สำหรับแอปพลิเคชันที่มีขนาดเล็กมาก (เช่นการเริ่ม PSU ล่าช้า , การแทนที่ตัวจับเวลา 555 , การควบคุมแบบ triac , การกะพริบ LED ฯลฯ ... ) ที่มีขนาดเล็กกว่าที่คุณต้องการด้วยประตูตรรกะหรือตัวจับเวลา 555


3
ฉันเพิ่งสังเกตเห็นว่าสองตัวอย่างแรกนั้นมาจาก Stack! เล่นดี.
coder543

9
+1 สำหรับการกล่าวถึงรอยเท้า บางครั้งขนาดก็เป็นทุกอย่าง
embedded.kyle

17

ฉันออกแบบเซ็นเซอร์ความชื้นสำหรับพืชที่ติดตามปริมาณน้ำที่พืชมีและกระพริบไฟ LED ถ้าพืชต้องการน้ำ คุณสามารถทำให้เซ็นเซอร์เรียนรู้ชนิดของพืชและทำให้การเปลี่ยนแปลงการตั้งค่าในขณะที่ทำงาน ตรวจจับแรงดันไฟฟ้าต่ำในแบตเตอรี่ ฉันหมดแฟลชและแรม แต่ก็สามารถเขียนทุกอย่างในรหัส C เพื่อให้ผลิตภัณฑ์นี้ทำงานได้อย่างไร้ที่ติ

ฉันใช้ pic10f ที่คุณพูดถึง


นี่คือรหัสที่ฉันทำสำหรับเซ็นเซอร์น้ำในพืช ฉันใช้pic10f220เพราะมันมีโมดูล ADC มันมีหน่วยความจำเช่นเดียวกับ pic10f200 ฉันจะพยายามหา Schematic ในวันพรุ่งนี้

รหัสเป็นภาษาสเปน แต่ง่ายมากและควรเข้าใจได้ง่าย เมื่อ Pic10F ตื่นจากโหมดสลีปมันจะรีเซ็ตดังนั้นคุณต้องตรวจสอบว่าเป็น PowerUp หรือรีเซ็ตและดำเนินการตามนั้น การตั้งค่าพืชจะถูกเก็บไว้ในหน่วยความจำเนื่องจากมันไม่เคยลงจริงๆ

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

แจ้งให้เราทราบหากคุณมีคำถามฉันจะพยายามตอบตามสิ่งที่ฉันจำได้ ฉันเขียนโค้ดเมื่อหลายปีก่อนดังนั้นอย่าตรวจสอบทักษะการเขียนรหัสของฉันเลยพวกเขาได้ปรับปรุง :)

หมายเหตุสุดท้าย ฉันใช้คอมไพเลอร์ Hi-Tech C


3
ฉันน่าสนใจจริง ๆ ในการอ่านวิธีที่คุณทำ คุณจดบันทึกใด ๆ ในขณะที่คุณทำมันโดยที่คุณไม่รังเกียจที่จะแบ่งปันบนเว็บหรือไม่?
RhysW

1
สวัสดี RhysW ฉันเชื่อว่าฉันยังมีรหัส มันง่ายจริงๆจริง ๆ ฉันสามารถส่งรหัสของฉันถ้าคุณมีความสนใจ แจ้งให้เราทราบ วงจรที่ฉันออกแบบนั้นเรียบง่ายและยอดเยี่ยมมีเพียงตัวต้านทาน 3 ตัวมอสเฟต p-channel หนึ่งตัว (สำหรับการป้องกันแบตเตอรี่กลับ) ฝาปิด 100nF และ LED ฉันใช้และไดโอดภายในใน pic10f เพื่อใช้เป็นข้อมูลอ้างอิงสำหรับการวัดแบตเตอรี่และเพื่อให้การอ่านค่า ADC คงที่
scrafy

1
ฟังดูเหมือนเป็นโครงการที่เรียบร้อย มีโอกาสใดบ้างที่คุณสามารถโพสต์รายละเอียดที่นี่ (หรืออย่างน้อยโพสต์ไว้ที่ใดที่หนึ่งและเชื่อมโยงไปยังพวกเขา)?
Ilmari Karonen

1
สวัสดี Scrafy! กรุณาถ้าคุณมีสิ่งที่จะเพิ่มในคำตอบให้ใช้ลิงค์ "แก้ไข" แทนที่จะโพสต์คำตอบใหม่เนื่องจากเว็บไซต์นี้ใช้การลงคะแนนและไม่ทำงานเหมือนฟอรัม
clabacchio

16

สิ่งหนึ่งที่ฉันไม่ได้เห็นกล่าวถึง: ไมโครคอนโทรลเลอร์ที่คุณกล่าวถึงมีราคาเพียง $ 0.34 ต่อคนในปริมาณ 100 ดังนั้นสำหรับสินค้าราคาถูกที่ผลิตเป็นจำนวนมาก เช่นเดียวกันอาจนำไปใช้กับขนาดหรือการใช้พลังงาน


2
นั่นเป็นความคิดแรกของฉัน นอกจากนี้: หากฉันจะเริ่มต้นด้วยความคิดที่เรียบร้อย แต่มีเพียงไม่กี่ร้อยเหรียญที่หลวมสิ่งเช่นนี้อาจหมายถึงความแตกต่างระหว่างการกลับไปสู่งานประจำวันและออกจากงานประจำวัน
phresnel

14

ตอนที่ฉันอยู่มัธยมฉันมีครูคนหนึ่งที่ยืนยันว่าการหรี่แสงนั้นเป็นงานยากสำหรับนักเรียนเช่นฉันจะเล่นงาน

ดังนั้นฉันจึงใช้เวลาเรียนรู้และทำความเข้าใจกับการหรี่แสงตามเฟสโดยใช้ triacs และการเขียนโปรแกรม 16C84 จากไมโครชิพเพื่อทำเพลงนี้ ฉันลงเอยด้วยรหัสแอสเซมบลีนี้:

'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

แน่นอนว่าคุณต้องแก้ไขสิ่งนี้สำหรับชิปที่คุณพูดถึงและอาจเพิ่มชุดคำสั่งแบบอนุกรมราคาถูกสำหรับการป้อนข้อมูลเนื่องจากชิปของคุณไม่มีพอร์ตแบบกว้าง 8 บิตเพื่อฟัง แต่แนวคิดก็คืองานที่ซับซ้อนดูเหมือนจะสามารถ จะทำในรหัสน้อยมาก - คุณสามารถใส่สิบชุดของโปรแกรมข้างต้นลงใน 10F200

คุณสามารถค้นหาข้อมูลโครงการเพิ่มเติมได้ในหน้าLight Dimmingของฉัน บังเอิญฉันไม่ได้แสดงสิ่งนี้กับครูของฉัน แต่จบลงด้วยการทำแท่นขุดเจาะแสงจำนวนมากสำหรับเพื่อนดีเจของฉัน


12

เมื่อหลายปีก่อนฉันเขียนตัวควบคุมอุณหภูมิด้วย I / O แบบอนุกรม (การต่อบิต I / O แบบอนุกรมเนื่องจาก MCU ไม่มี UART) และตัวแปลคำสั่งง่าย ๆ เพื่อพูดคุยกับคอนโทรลเลอร์ MCU เป็นโมโตโรล่า (ปัจจุบันคือฟรีสโคป) MC68HC705K1 ซึ่งมีหน่วยความจำของโปรแกรม (OTPROM) 504 ไบต์และ RAM ประมาณ 32 ไบต์ ไม่น้อยกับ PIC ที่คุณอ้างอิง แต่ฉันจำได้ว่ามี ROM เหลืออยู่ ฉันยังเหลือหน่วยประกอบอีกไม่กี่ 17 ปีต่อมา; ต้องการซื้อหรือไม่

ดังนั้นใช่มันสามารถทำได้อย่างน้อยในการชุมนุม

ไม่ว่าในกรณีใดฉันได้เขียนโปรแกรม C อย่างง่ายเมื่อเร็ว ๆ นี้ซึ่งอาจมีขนาดไม่เกิน 384 ไบต์เมื่อปรับให้เหมาะสม ไม่ใช่ทุกสิ่งที่ต้องการซอฟต์แวร์ที่มีขนาดใหญ่และซับซ้อน


5

คุณสามารถเขียน LED ที่มีหน่วยความจำโปรแกรมขนาด 384 ไบต์และอื่น ๆ อีกมากมาย

เท่าที่ฉันรู้มันเป็นไปไม่ได้ที่จะขยายหน่วยความจำของโปรแกรมด้วยชิปภายนอก (เว้นแต่ว่าคุณกำลังสร้างล่าม ASM แบบเต็มใน 384 ไบต์ซึ่งจะช้า) เป็นไปได้ที่จะขยายหน่วยความจำข้อมูลด้วยชิปภายนอก (EEPROM, SRAM)


1
มันจะไม่เป็นอย่างหนักเพื่อสร้างจำลองเครื่องทัวริงใน 384 ไบต์ ...
คริสแตรทตัน

@ChrisStratton ฉันหมายถึงล่ามเต็มรูปแบบดังนั้น 'หน่วยความจำของโปรแกรมที่ขยาย' จะมีคุณสมบัติเหมือนปกติ

ใช่นั่นคือสิ่งที่ฉันแนะนำวิธีการใช้งานอย่างแน่นหนา ส่วนที่เหลือเป็นเพียงการออกแบบคอมไพเลอร์ ...
คริสแตรทตัน

7
หากต้องการให้โปรแกรมตรรกะถูกเก็บไว้ใน EEPROM ภายนอกการพยายามเลียนแบบชุดคำสั่ง PIC จะไม่เป็นไปได้ แนวทางที่ดีกว่าคือการออกแบบชุดคำสั่งที่ปรับให้เหมาะสมสำหรับการใช้งานกับเครื่องเสมือน จริง ๆ แล้วนั่นคือวิธีการที่ Parallax ใช้กับ "Basic STAMP" ในปี 1990 มันเป็น PIC ที่มีพื้นที่โค้ด 3072 ไบต์จับคู่กับชิป EEPROM อนุกรม
supercat

3
BTW บันทึกเพิ่มเติมเกี่ยวกับตราประทับพื้นฐาน: มันถูกนำมาใช้ในเวลาที่ไมโครคอนโทรลเลอร์ที่ใช้แฟลชหรือ EEPROM ซึ่งหาได้ยาก แต่ชิป EEPROM อนุกรมค่อนข้างราคาถูก สำหรับแอปพลิเคชั่นที่ไม่ต้องการความเร็วมากไมโครโค้ดคงที่ที่มีส่วน EEPROM อนุกรมจะราคาถูกกว่าไมโคร EEPROM ที่มีขนาดเท่ากันหรือใช้แฟลช วันนี้การออกแบบของ BASIC Stamp ไม่เข้าท่า แต่มันค่อนข้างเป็นจริงเมื่อนำมาใช้
supercat

4

มันเลวร้ายยิ่งกว่าที่คุณคิด เพจ Mouser ที่เชื่อมโยงของคุณสับสนเรื่องเมื่อระบุโปรเซสเซอร์นี้ว่ามีหน่วยความจำโปรแกรม 384 ไบต์ PIC10F200 จริงมี 256 12 บิตคำพูดของหน่วยความจำโปรแกรม

ดังนั้นคุณจะทำอย่างไรกับสิ่งนั้น 12 บิต PIC คำแนะนำชุดใช้โดย PIC10F20 xอุปกรณ์ทุกคำแนะนำคำเดียวดังนั้นหลังจากที่คุณลบคำแนะนำไม่กี่สำหรับการติดตั้งหน่วยประมวลผล, คุณเหลือพื้นที่มากพอสำหรับโปรแกรมประมาณ 250 ขั้นตอน เพียงพอสำหรับแอปพลิเคชันจำนวนมาก ฉันอาจจะเขียนคอนโทรลเลอร์ของเครื่องซักผ้าในพื้นที่นั้นได้

ฉันเพิ่งดูคอมไพเลอร์ PIC C ที่มีอยู่และดูเหมือนว่าครึ่งหนึ่งของพวกเขาจะไม่พยายามแม้แต่จะเปล่งรหัสสำหรับ PIC10F200 ผู้ที่อาจวางโค้ดสำเร็จรูปจำนวนมากที่คุณอาจจะสามารถเขียนกะพริบ LED ในพื้นที่ที่เหลือ คุณต้องการใช้ภาษาแอสเซมบลีกับตัวประมวลผลเช่นนั้นจริง ๆ


คุณพูดถูกต้อง 256 คำ ที่จริงแล้วหนึ่งในนั้นมีค่าคงตัวการปรับเทียบ oscillator ดังนั้นคุณจะได้รับคำแนะนำที่ใช้งานได้ 255 คำ นอกจากนี้ 10F200 ไม่ได้ใช้ชุดคำสั่ง PIC 16 14 บิตปกติ ใช้ชุดคำสั่ง PIC 12 12 บิต อย่างไรก็ตามฉันเห็นด้วยกับสถานที่พื้นฐานของคุณ ฉันทำสิ่งที่มีประโยชน์มากมายด้วย PIC 10F200 +1
Olin Lathrop

@OlinLathrop: ฉันได้ชี้แจงคำตอบแล้ว ฉันได้รับคำศัพท์ PIC16 จากหน้า 51 ของชุดข้อมูลแต่ฉันคิดว่ามันชัดเจนกว่าที่จะอ้างถึง "ชุดคำสั่ง 12 บิต" ส่วนนำหน้านั้นไม่ใช่คู่มือที่เชื่อถือได้สำหรับชุดคำสั่งที่ใช้
Warren Young

0

โบกไม้เท้าในวันที่เราต้องแกะชิ้นส่วนของเราเองออกมาจากทราย!

ในปี 1976 (หรือราวนั้น) ระบบอาตาริ 2600 VCS เป็นหนึ่งใน "แพลตฟอร์มวิดีโอเกม" ที่ได้รับความนิยมมากที่สุดแห่งหนึ่งในขณะนั้น ในนั้นไมโครโปรเซสเซอร์ (MOSTEK 6507) วิ่งด้วยความสว่างจ้า ~ 1 MHz และมี RAM ขนาด 128 * ** **

ตัวอย่างที่สองที่ฉันจำได้จากไมโครคอนโทรลเลอร์ที่มี RAM ที่ จำกัด มาก(~ 128 ไบต์)คือ PIC12F ที่ใช้กับตัวแปลง DC-DC ไมโครนี้ยังต้องใช้ภาษาแอสเซมบลีเพื่อเรียกใช้เลย


4
OP ไม่ได้พูดถึง RAM เขากำลังพูดถึงพื้นที่ของโปรแกรม พื้นที่โครงการในอาตาริ 2600 อยู่ในตลับหมึกที่ไม่ได้อยู่ในชิป RIOT รอมโปรแกรมที่รองรับ 2,600 ได้สูงสุด 4 kiB โดยไม่มีการสลับธนาคาร (และบางตลับเชิงพาณิชย์ไม่ ! ทำสลับธนาคาร) ในฐานะที่เป็นเช่น PIC12F ของ OP ที่มีคุณชนะ: อุปกรณ์ชุด PIC10F20x มี 16 หรือ 24 ไบต์ของ SRAM
Warren Young
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.