ยกตัวอย่างเช่นPIC10F200T
รหัสใด ๆ ที่คุณเขียนจะมีขนาดใหญ่กว่านั้นยกเว้นว่าเป็นชิปวัตถุประสงค์เดียว มีวิธีใดบ้างที่จะโหลดหน่วยความจำโปรแกรมเพิ่มเติมจากที่เก็บข้อมูลภายนอก ฉันแค่อยากรู้อยากเห็นฉันไม่เห็นว่าสิ่งนี้จะมีประโยชน์มาก ... แต่มันต้องเป็น
ยกตัวอย่างเช่นPIC10F200T
รหัสใด ๆ ที่คุณเขียนจะมีขนาดใหญ่กว่านั้นยกเว้นว่าเป็นชิปวัตถุประสงค์เดียว มีวิธีใดบ้างที่จะโหลดหน่วยความจำโปรแกรมเพิ่มเติมจากที่เก็บข้อมูลภายนอก ฉันแค่อยากรู้อยากเห็นฉันไม่เห็นว่าสิ่งนี้จะมีประโยชน์มาก ... แต่มันต้องเป็น
คำตอบ:
ลูกคุณออกไปจากสนามหญ้าของฉัน!
384 ไบต์มีพื้นที่มากมายในการสร้างสิ่งที่ค่อนข้างซับซ้อนในแอสเซมเบลอร์
หากคุณขุดลึกลงไปถึงประวัติศาสตร์เมื่อคอมพิวเตอร์มีขนาดเท่ากับห้องคุณจะพบกับงานศิลปะที่น่าทึ่งที่ดำเนินการใน <1k
ยกตัวอย่างเช่นอ่านคลาสสิกเรื่องของเมล - โปรแกรมเมอร์จริง เป็นที่ยอมรับคนเหล่านั้นมี 4096 คำของหน่วยความจำที่จะเล่นกับคนนอกศาสนาเสื่อมโทรม
ดูการแข่งขัน demoscene แบบเก่าที่ความท้าทายคือการใส่ "อินโทร" เข้าไปใน bootblock ของฟลอปปี้เป้าหมายทั่วไปคือ 4k หรือ 40k และมักจะจัดการเพื่อรวมเพลงและภาพเคลื่อนไหว
แก้ไขเพื่อเพิ่ม : ปรากฎว่าคุณสามารถใช้เครื่องคิดเลขวิทยาศาสตร์มูลค่า 100 ดอลลาร์แรกของโลกใน 320 คำ
แก้ไขสำหรับผู้เยาว์ที่ไม่เหมาะสม:
ไมโครคอนโทรลเลอร์มีราคาถูกเพียงพอที่พวกเขามักจะใช้ทำสิ่งที่ง่าย ๆ ซึ่งในปีที่ผ่านมามีแนวโน้มที่จะทำด้วยตรรกะที่ไม่ต่อเนื่อง สิ่งที่เรียบง่ายจริงๆ ตัวอย่างเช่นหนึ่งอาจต้องการให้อุปกรณ์เปิดเอาท์พุทเป็นเวลาหนึ่งวินาทีทุก ๆ ห้าวินาทีแม่นยำกว่าตัวจับเวลา 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 จะรีเซ็ตชิปหลังจากผ่านไปสองสามวินาที
clrwdt
คำแนะนำ นี่ไม่ใช่การจัดเรียงตัวนับที่ไม่ปลอดภัยที่สุดที่เป็นไปได้ แต่มีการพิจารณาบางอย่างเกี่ยวกับปัญหาด้านความปลอดภัย (เช่นการหลีกเลี่ยงclrwdt
ภายในรูทีนย่อย)
"เท่านั้น" 384 ไบต์?
ย้อนกลับไปในวันนั้นฉันมีงานเขียนระบบปฏิบัติการทั้งหมด (ด้วยตัวเอง) สำหรับคอมพิวเตอร์เฉพาะทางที่ให้บริการเรือท่อและอุตสาหกรรมการจัดการโรงกลั่น ผลิตภัณฑ์ตัวแรกของ บริษัท คือ 6800 และได้รับการอัพเกรดเป็น 6809 และพวกเขาต้องการให้ระบบปฏิบัติการใหม่สอดคล้องกับ 6809 เพื่อให้พวกเขาสามารถลดค่าใช้จ่ายใบอนุญาตของระบบปฏิบัติการดั้งเดิม พวกเขายังเพิ่มขนาดบู๊ต ROM เป็น 64 ไบต์เพิ่มขึ้นจาก 32 หากฉันจำได้ถูกต้อง - มันก็ประมาณ 33 ปีที่แล้ว! - ฉันโน้มน้าววิศวกรให้ 128 ไบต์เพื่อให้ฉันสามารถใส่ไดรเวอร์อุปกรณ์ของระบบปฏิบัติการทั้งหมดในรอมและทำให้อุปกรณ์ทั้งหมดน่าเชื่อถือและใช้งานได้หลากหลาย รวมถึง:
ใช่สิ่งเหล่านี้เป็นเหมือนกระดูกเปลือยที่ได้รับและได้รับการปรับปรุงด้วยมือเพื่อกำจัดทุกรอบนอก แต่ให้บริการได้อย่างสมบูรณ์และเชื่อถือได้ ใช่ฉันสวมใส่ทั้งหมดที่มีอยู่ในไบต์ - โอ้มันตั้งค่าการจัดการขัดจังหวะกองต่าง ๆ และเริ่มต้นระบบปฏิบัติการเรียลไทม์ / มัลติทาสกิ้งได้รับแจ้งผู้ใช้เกี่ยวกับตัวเลือกการบูตและบูตระบบ
เพื่อนของฉันผู้ซึ่งยังคงเป็นพันธมิตรกับ บริษัท (ผู้สืบทอด) บอกฉันเมื่อสองสามปีก่อนว่ารหัสของฉันยังคงใช้งานได้!
คุณสามารถทำอะไรได้มากด้วย 384 ไบต์ ...
คุณสามารถใช้สิ่งนี้สำหรับแอปพลิเคชันที่มีขนาดเล็กมาก (เช่นการเริ่ม PSU ล่าช้า , การแทนที่ตัวจับเวลา 555 , การควบคุมแบบ triac , การกะพริบ LED ฯลฯ ... ) ที่มีขนาดเล็กกว่าที่คุณต้องการด้วยประตูตรรกะหรือตัวจับเวลา 555
ฉันออกแบบเซ็นเซอร์ความชื้นสำหรับพืชที่ติดตามปริมาณน้ำที่พืชมีและกระพริบไฟ 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
สิ่งหนึ่งที่ฉันไม่ได้เห็นกล่าวถึง: ไมโครคอนโทรลเลอร์ที่คุณกล่าวถึงมีราคาเพียง $ 0.34 ต่อคนในปริมาณ 100 ดังนั้นสำหรับสินค้าราคาถูกที่ผลิตเป็นจำนวนมาก เช่นเดียวกันอาจนำไปใช้กับขนาดหรือการใช้พลังงาน
ตอนที่ฉันอยู่มัธยมฉันมีครูคนหนึ่งที่ยืนยันว่าการหรี่แสงนั้นเป็นงานยากสำหรับนักเรียนเช่นฉันจะเล่นงาน
ดังนั้นฉันจึงใช้เวลาเรียนรู้และทำความเข้าใจกับการหรี่แสงตามเฟสโดยใช้ 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ของฉัน บังเอิญฉันไม่ได้แสดงสิ่งนี้กับครูของฉัน แต่จบลงด้วยการทำแท่นขุดเจาะแสงจำนวนมากสำหรับเพื่อนดีเจของฉัน
เมื่อหลายปีก่อนฉันเขียนตัวควบคุมอุณหภูมิด้วย I / O แบบอนุกรม (การต่อบิต I / O แบบอนุกรมเนื่องจาก MCU ไม่มี UART) และตัวแปลคำสั่งง่าย ๆ เพื่อพูดคุยกับคอนโทรลเลอร์ MCU เป็นโมโตโรล่า (ปัจจุบันคือฟรีสโคป) MC68HC705K1 ซึ่งมีหน่วยความจำของโปรแกรม (OTPROM) 504 ไบต์และ RAM ประมาณ 32 ไบต์ ไม่น้อยกับ PIC ที่คุณอ้างอิง แต่ฉันจำได้ว่ามี ROM เหลืออยู่ ฉันยังเหลือหน่วยประกอบอีกไม่กี่ 17 ปีต่อมา; ต้องการซื้อหรือไม่
ดังนั้นใช่มันสามารถทำได้อย่างน้อยในการชุมนุม
ไม่ว่าในกรณีใดฉันได้เขียนโปรแกรม C อย่างง่ายเมื่อเร็ว ๆ นี้ซึ่งอาจมีขนาดไม่เกิน 384 ไบต์เมื่อปรับให้เหมาะสม ไม่ใช่ทุกสิ่งที่ต้องการซอฟต์แวร์ที่มีขนาดใหญ่และซับซ้อน
คุณสามารถเขียน LED ที่มีหน่วยความจำโปรแกรมขนาด 384 ไบต์และอื่น ๆ อีกมากมาย
เท่าที่ฉันรู้มันเป็นไปไม่ได้ที่จะขยายหน่วยความจำของโปรแกรมด้วยชิปภายนอก (เว้นแต่ว่าคุณกำลังสร้างล่าม ASM แบบเต็มใน 384 ไบต์ซึ่งจะช้า) เป็นไปได้ที่จะขยายหน่วยความจำข้อมูลด้วยชิปภายนอก (EEPROM, SRAM)
มันเลวร้ายยิ่งกว่าที่คุณคิด เพจ Mouser ที่เชื่อมโยงของคุณสับสนเรื่องเมื่อระบุโปรเซสเซอร์นี้ว่ามีหน่วยความจำโปรแกรม 384 ไบต์ PIC10F200 จริงมี 256 12 บิตคำพูดของหน่วยความจำโปรแกรม
ดังนั้นคุณจะทำอย่างไรกับสิ่งนั้น 12 บิต PIC คำแนะนำชุดใช้โดย PIC10F20 xอุปกรณ์ทุกคำแนะนำคำเดียวดังนั้นหลังจากที่คุณลบคำแนะนำไม่กี่สำหรับการติดตั้งหน่วยประมวลผล, คุณเหลือพื้นที่มากพอสำหรับโปรแกรมประมาณ 250 ขั้นตอน เพียงพอสำหรับแอปพลิเคชันจำนวนมาก ฉันอาจจะเขียนคอนโทรลเลอร์ของเครื่องซักผ้าในพื้นที่นั้นได้
ฉันเพิ่งดูคอมไพเลอร์ PIC C ที่มีอยู่และดูเหมือนว่าครึ่งหนึ่งของพวกเขาจะไม่พยายามแม้แต่จะเปล่งรหัสสำหรับ PIC10F200 ผู้ที่อาจวางโค้ดสำเร็จรูปจำนวนมากที่คุณอาจจะสามารถเขียนกะพริบ LED ในพื้นที่ที่เหลือ คุณต้องการใช้ภาษาแอสเซมบลีกับตัวประมวลผลเช่นนั้นจริง ๆ
โบกไม้เท้าในวันที่เราต้องแกะชิ้นส่วนของเราเองออกมาจากทราย!
ในปี 1976 (หรือราวนั้น) ระบบอาตาริ 2600 VCS เป็นหนึ่งใน "แพลตฟอร์มวิดีโอเกม" ที่ได้รับความนิยมมากที่สุดแห่งหนึ่งในขณะนั้น ในนั้นไมโครโปรเซสเซอร์ (MOSTEK 6507) วิ่งด้วยความสว่างจ้า ~ 1 MHz และมี RAM ขนาด 128 * ** **
ตัวอย่างที่สองที่ฉันจำได้จากไมโครคอนโทรลเลอร์ที่มี RAM ที่ จำกัด มาก(~ 128 ไบต์)คือ PIC12F ที่ใช้กับตัวแปลง DC-DC ไมโครนี้ยังต้องใช้ภาษาแอสเซมบลีเพื่อเรียกใช้เลย