예를 들어 PIC10F200T
단일 목적 칩이 아니라면 실제로 작성하는 모든 코드는이 코드보다 큽니다. 외부 저장소 또는 다른 것에서 더 많은 프로그램 메모리를로드 할 수있는 방법이 있습니까? 궁금해서 궁금합니다. 이것이 어떻게 유용한 지 모르겠지만 ... 그래야합니다.
예를 들어 PIC10F200T
단일 목적 칩이 아니라면 실제로 작성하는 모든 코드는이 코드보다 큽니다. 외부 저장소 또는 다른 것에서 더 많은 프로그램 메모리를로드 할 수있는 방법이 있습니까? 궁금해서 궁금합니다. 이것이 어떻게 유용한 지 모르겠지만 ... 그래야합니다.
답변:
애들 아 내 잔디밭을 벗어!
384 바이트는 어셈블러에서 상당히 복잡한 것을 만들 수있는 충분한 공간입니다.
컴퓨터가 방의 크기였던 때로 역사를 다시 살펴보면 <1k에서 실제로 놀라운 예술적 위업을 발견 할 수 있습니다.
예를 들어, Mel-A Real Programmer의 Story를 읽으십시오 . 분명히, 그 사람들은 퇴폐적 인 이교도들과 함께 4096 단어의 기억을 가지고 놀았습니다.
또한 "인트로"를 플로피의 부트 블록에 맞추는 것이 어려웠던 전형적인 데모 장면 경쟁을 살펴보십시오. 일반적인 대상은 4k 또는 40k이며 일반적으로 음악과 애니메이션을 포함합니다.
추가 편집 : 320 단어로 세계 최초의 100 달러 과학 계산기 를 구현할 수 있습니다 .
젊은이들을위한 편집 :
마이크로 컨트롤러는 과거 몇 년 동안 불연속 논리를 사용했을 가능성이있는 간단한 작업을 수행하는 데 종종 사용하기에 충분히 저렴합니다. 정말 간단한 것들. 예를 들어, 장치가 5 초마다 1 초 동안 출력을 켤 수 있기를 원할 수 있습니다.
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
명령을 서브 루틴으로 옮길 수 있지만 그렇게하면 작업이 덜 강력 해집니다. 기록 된대로 결함으로 인해 리턴 주소 스택이 손상 되더라도 실행이 기본 루프로 리턴 될 때까지 워치 독이 공급되지 않습니다. 그렇게되지 않으면 워치 독은 몇 초 후에 칩을 재설정합니다.
clrwdt
명령 보다 복잡 합니다. 이것은 가장 절대적으로 실패 할 수있는 카운터 배열은 아니지만, 안전 문제 (예 : clrwdt
서브 루틴 내에서 의 회피)를 고려해야 합니다.
"384 바이트"만?
과거로 돌아가서 저는 선박, 파이프 라인 및 정유소 관리 산업에 서비스를 제공하는 전문 컴퓨터를 위해 전체 운영 체제를 직접 작성했습니다. 이 회사의 첫 번째 제품은 6800 기반이며 6809로 업그레이드되었으며 6809와 함께 새로운 OS를 사용하여 원래 운영 체제의 라이센스 비용을 제거 할 수 있기를 원했습니다. 또한 부팅 ROM의 크기를 32 바이트에서 64 바이트로 올렸습니다. 올바르게 기억하면 약 33 년 전입니다! -엔지니어들에게 128 바이트를 제공하여 전체 운영 체제의 장치 드라이버를 ROM에 배치하여 전체 장치를보다 안정적이고 다목적으로 만들 수 있도록했습니다. 여기에는 다음이 포함됩니다.
그렇습니다. 이러한 모든 것들은 맨손으로 이루어졌으며 모든 불필요한 사이클을 제거하기 위해 수동으로 최적화되었지만 완벽하게 서비스 가능하고 신뢰할 수 있습니다. 예, 나는 그 모든 것을 사용 가능한 바이트로 분류했습니다. 오, 그것은 또한 인터럽트 처리, 다양한 스택을 설정하고 실시간 / 멀티 태스킹 운영 체제를 초기화하고 사용자에게 부팅 옵션을 프롬프트하고 시스템을 부팅했습니다.
회사 (후임자)와 여전히 제휴 관계를 맺고있는 친구가 몇 년 전 제 코드가 아직 서비스 중이라고 말했습니다.
384 바이트로 LOT을 할 수 있습니다 ...
로직 게이트 또는 555 타이머에 필요한 것보다 풋 프린트가 작은 매우 작은 애플리케이션 (예 : 지연된 PSU 시작 , 555 타이머 교체 , 트라이 악 기반 제어 , LED 깜박임 등) 에이 기능을 사용할 수 있습니다 .
식물의 물의 양을 추적하고 식물에 물이 필요한 경우 LED를 깜박이는 식물의 습도 센서를 설계했습니다. 센서가 플랜트 유형을 학습하도록하여 실행 중에 설정을 변경할 수 있습니다. 배터리의 저전압을 감지합니다. 나는 플래시와 램이 부족했지만이 제품이 완벽하게 작동하도록 C 코드로 모든 것을 쓸 수있었습니다.
나는 당신이 언급 한 pic10f를 사용했다.
플랜트 워터 센서 용으로 작성한 코드는 다음과 같습니다. ADC 모듈이 있기 때문에 pic10f220을 사용했으며 pic10f200 과 동일한 메모리를 가지고 있으므로 내일 도식을 찾으려고 노력할 것입니다.
코드는 스페인어로되어 있지만 매우 간단하며 쉽게 이해할 수 있습니다. Pic10F가 슬립 모드에서 깨어날 때 리셋되므로 파워 업 또는 리셋인지 확인하고 그에 따라 작동해야합니다. 플랜트 설정은 실제로 전원이 꺼지지 않기 때문에 램에 보관됩니다.
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
궁금한 점이 있으면 알려주세요. 기억하고있는 내용에 따라 답변을 드리겠습니다. 나는 몇 년 전에 이것을 코딩 했으므로 코딩 기술을 확인하지 않으면 개선되었습니다 :).
최종 노트. 저는 하이테크 C 컴파일러를 사용했습니다.
고등학교에 다닐 때 교사와 같이 가벼운 어둡게하기가 학생과 같은 과제를하기에는 너무 어렵다고 주장했습니다.
따라서 나는 트라이 악을 사용하여 위상 기반의 광 조광을 배우고 이해 하고이 위업을 수행하기 위해 마이크로 칩에서 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 비트의 넓은 포트를 가지고 있지 않기 때문에 입력을 위해 저렴한 직렬 루틴을 추가 할 필요가있을 것입니다. 아주 작은 코드로 수행하십시오-위 프로그램의 10 개 사본을 10F200에 맞출 수 있습니다.
내 Light Dimming 페이지 에서 더 많은 프로젝트 정보를 찾을 수 있습니다 . 우연히 나는 이것을 선생님에게 보여주지 않았지만 결국 DJ 친구를 위해 많은 조명 장비를 만들었습니다.
글쎄, 몇 년 전에 나는 직렬 I / O (MCU에 UART가 없기 때문에 직렬 I / O를 비트 뱅킹)와 컨트롤러와 대화하는 간단한 명령 해석기를 갖춘 온도 컨트롤러를 작성했습니다. MCU는 무려 504 바이트의 프로그램 메모리 (OTPROM)와 약 32 바이트의 RAM을 가진 Motorola (현재 Freescale) MC68HC705K1이었다. 참조하는 PIC만큼 작지는 않지만 일부 ROM이 남아있는 것을 기억합니다. 17 년이 지난 지금도 몇 개의 조립 단위가 남아 있습니다. 하나 사겠습니까?
예, 적어도 조립에서 가능합니다.
어쨌든, 최근 최적화 된 384 바이트 안에 들어갈 수있는 매우 간단한 C 프로그램을 작성했습니다. 모든 것이 크고 복잡한 소프트웨어를 요구하는 것은 아닙니다.
프로그램 메모리가 384 바이트 인 LED를 깜박임 등으로 작성할 수 있습니다.
내가 아는 한 외부 칩으로 프로그램 메모리를 확장 할 수는 없습니다 (완전한 ASM 해석기를 작성하지 않는 한) 384 바이트 를 느린 것입니다). 그러나 외부 칩 (EEPROM, SRAM)으로 데이터 메모리를 확장 할 수 있습니다.
실제로 당신이 생각하는 것보다 더 나쁩니다. 링크 된 Mouser 페이지는이 프로세서에 384 바이트의 프로그램 메모리가있는 것으로 지정하면 혼동됩니다. PIC10F200에는 실제로 256 개의 12 비트 워드 프로그램 메모리가 있습니다.
그래서 그걸로 무엇을 할 수 있습니까? 12 비트 PIC 명령어 세트 PIC10F20에 의해 사용되는 X의 장치는 모두 한 단어 지침, 그래서 당신이 프로세서 설정을위한 몇 가지 지침을 빼기 후에는 약 250 단계의 프로그램에 대한 충분한 공간이 남아 있습니다. 많은 응용 프로그램에 충분합니다. 예를 들어 그런 종류의 공간에 세탁기 컨트롤러를 쓸 수 있습니다.
방금 사용 가능한 PIC C 컴파일러를 살펴본 결과 절반 정도가 PIC10F200에 대한 코드를 생성하지 않는 것처럼 보입니다. 아마도 상용구 코드를 너무 많이 넣어서 남은 공간에 LED 플래셔 만 쓸 수있을 것입니다. 그러한 프로세서에 어셈블리 언어를 사용하고 싶을 것입니다.
내 지팡이 흔들며내 하루에 를 , 우리는 모래에서 우리 자신의 비트를 에칭해야했습니다!
1976 년에 Atari 2600 VCS 시스템은 당시 가장 인기있는 "비디오 게임 플랫폼"중 하나였습니다. 마이크로 프로세서 (MOSTEK 6507)는 ~ 1MHz에서 작동했으며 **** 128 바이트의 RAM **을 사용했습니다.
매우 제한된 RAM (~ 128 바이트) 을 가진 마이크로 컨트롤러를 회상 한 두 번째 예 는 DC-DC 변환기에 사용되는 PIC12F입니다. 이 마이크로는 또한 실행하기 위해 어셈블리 언어를 사용해야했습니다.