Por ejemplo un PIC10F200T
Prácticamente cualquier código que escriba será más grande que eso, a menos que sea un chip de un solo propósito. ¿Hay alguna forma de cargar más memoria de programa desde un almacenamiento externo o algo así? Solo tengo curiosidad, no veo cómo esto podría ser muy útil... pero debe serlo.
¡Niños, salgan de mi césped!
384 bytes es mucho espacio para crear algo bastante complejo en ensamblador.
Si rebuscas en la historia hasta cuando las computadoras tenían el tamaño de una habitación, encontrarás algunas hazañas artísticas realmente asombrosas ejecutadas en <1k.
Por ejemplo, lea el clásico Story of Mel - A Real Programmer . Es cierto que esos tipos tenían 4096 palabras de memoria para jugar, los infieles decadentes.
También mire algunas de las viejas competencias de demostración donde el desafío era colocar una "introducción" en el bloque de arranque de un disquete, los objetivos típicos eran 4k o 40k y generalmente lograban incluir música y animación.
Edite para agregar : resulta que puede implementar la primera calculadora científica de $ 100 del mundo en 320 palabras.
Editar para los jóvenes:
Los microcontroladores son lo suficientemente baratos como para que a menudo se usen para hacer cosas realmente simples que en el pasado probablemente se hubieran hecho con lógica discreta. Cosas realmente simples. Por ejemplo, uno podría querer que un dispositivo encienda una salida durante un segundo cada cinco segundos, con más precisión de lo que sería capaz de hacer un temporizador 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
Esa sería una aplicación real y utilizable, en menos de 32 palabras (48 bytes) de espacio de código. Uno podría agregar fácilmente algunas opciones para que algunos pines de E/S controlen las opciones de temporización y todavía tenga mucho espacio de sobra, pero incluso si todo lo que hiciera el chip fuera precisamente lo que se muestra arriba, aún podría ser más barato y más fácil que cualquier alternativa usando discreto lógica. Por cierto, las clrwdt
instrucciones podrían moverse a la subrutina, pero hacerlo haría que las cosas fueran menos sólidas. Tal como está escrito, incluso si una falla hace que la pila de direcciones de retorno se corrompa, el perro guardián no se alimentará hasta que la ejecución regrese al bucle principal. Si eso nunca sucede, el perro guardián restablecerá el chip después de un par de segundos.
count0
será cero, por lo que las veces posteriores que se alcance el bucle interno se ejecutarán 256 veces. Adiviné los números a usar; si fuera un proyecto real, los habría calculado con más precisión. En cualquier caso, si la memoria sirve, el PIC tiene 16 bytes de RAM; Estoy usando menos del 20%.clrwdt
instrucciones. Este no es el arreglo de contador más absolutamente seguro contra fallas posible, pero se le da cierta consideración a los problemas de seguridad (por ejemplo, la evitación de clrwdt
dentro de una subrutina).¿"SÓLO" 384 bytes?
Hace mucho tiempo, tuve el trabajo de escribir un sistema operativo completo (por mí mismo) para una computadora especializada que servía a la industria de administración de barcos, oleoductos y refinerías. El primer producto de este tipo de la compañía estaba basado en 6800 y se estaba actualizando a 6809, y querían un nuevo sistema operativo que acompañara al 6809 para poder eliminar los costos de licencia del sistema operativo original. También aumentaron el tamaño de la rom de arranque a 64 bytes, en lugar de 32. Si no recuerdo mal, ¡FUE hace unos 33 años! - Convencí a los ingenieros para que me dieran 128 bytes para poder poner todos los drivers del dispositivo del sistema operativo en la rom y así hacer todo el dispositivo más fiable y versátil. Esto incluía:
Sí, todos estos fueron tan básicos como parece, y optimizados a mano para eliminar todos los ciclos extraños, pero perfectamente reparables y confiables. Sí, calcé todo eso en los bytes disponibles; oh, TAMBIÉN configuró el manejo de interrupciones, las diversas pilas e inicializó el sistema operativo en tiempo real / multitarea, le indicó al usuario las opciones de arranque y arrancó el sistema.
Un amigo mío que todavía está afiliado a la empresa (su sucesor) me dijo hace unos años que mi código todavía está en servicio.
Puedes hacer MUCHO con 384 bytes...
Puede usar esto para aplicaciones muy pequeñas (por ejemplo , inicio retrasado de la fuente de alimentación , reemplazo del temporizador 555 , control basado en triac , parpadeo de LED, etc.) con una huella más pequeña de lo que necesitaría con puertas lógicas o un temporizador 555.
Una cosa que no he visto mencionada: el microcontrolador que mencionó cuesta solo $ 0.34 cada uno en cantidades de 100. Entonces, para productos baratos producidos en masa, puede tener sentido pasar por el problema de codificación adicional impuesto por una unidad tan limitada. Lo mismo podría aplicarse al tamaño o al consumo de energía.
Diseñé un sensor de humedad para plantas que rastrea la cantidad de agua que tiene la planta y parpadea un LED si la planta necesita agua. Puede hacer que el sensor aprenda el tipo de planta y, por lo tanto, cambie su configuración mientras se ejecuta. Detecta bajo voltaje en la batería. Me quedé sin flash y ram, pero pude escribir todo en código C para que este producto funcionara sin problemas.
Usé el pic10f que mencionas.
Aquí está el código que hice para mi sensor de agua de planta. Usé el pic10f220 ya que tiene un módulo ADC, tiene la misma memoria que el pic10f200, trataré de encontrar el esquema mañana.
El código está en español, pero es muy simple y debe entenderse fácilmente. Cuando Pic10F se despierta del modo de suspensión, se reiniciará, por lo que debe verificar si fue un encendido o un reinicio y actuar en consecuencia. La configuración de la planta se mantiene en RAM ya que nunca se apaga realmente.
C PRINCIPAL
/*
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);
}
}
PRINCIPAL.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
Avíseme si tiene preguntas, intentaré responder según lo que recuerdo. Codifiqué esto hace varios años, así que no revises mis habilidades de codificación, han mejorado :).
Nota Final. Usé el compilador Hi-Tech C.
Cuando estaba en la escuela secundaria, tuve un maestro que insistía en que atenuar la luz era una tarea demasiado difícil de abordar para un estudiante como yo.
Así desafiado, pasé bastante tiempo aprendiendo y comprendiendo la atenuación de luz basada en fases usando triacs, y programando el 16C84 desde el microchip para realizar esta hazaña. Terminé con este código ensamblador:
'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
Por supuesto, necesitaría modificar esto para el chip que menciona, y tal vez agregar una rutina serial barata para la entrada ya que su chip no tiene un puerto de 8 bits de ancho para escuchar, pero la idea es que un trabajo aparentemente complejo puede hacerse con muy poco código: puede colocar diez copias del programa anterior en el 10F200.
Puede encontrar más información sobre el proyecto en mi página de atenuación de luz . Por cierto, nunca le mostré esto a mi maestro, pero terminé haciendo una serie de equipos de iluminación para mi amigo DJ.
Bueno, hace años escribí un controlador de temperatura con E/S en serie (golpeando la E/S en serie porque la MCU no tenía un UART) y un intérprete de comandos simple para hablar con el controlador. MCU era un Motorola (ahora Freescale) MC68HC705K1 que tenía la friolera de 504 bytes de memoria de programa (OTPROM) y alrededor de 32 bytes de RAM. No tan pequeño como el PIC al que hace referencia, pero recuerdo que me sobró algo de ROM. Todavía me quedan algunas unidades ensambladas, 17 años después; ¿quieres comprar uno?
Entonces sí, se puede hacer, al menos en ensamblaje.
En cualquier caso, recientemente he escrito programas en C muy simples que probablemente habrían cabido dentro de 384 bytes cuando se optimizaron. No todo requiere un software grande y complejo.
Puede escribir un parpadeo de un LED con memoria de programa de 384 bytes, e incluso más.
Hasta donde yo sé, no es posible extender la memoria del programa con un chip externo (a menos que esté construyendo un intérprete ASM completo en los 384 bytes , lo que sería lento). Sin embargo, es posible ampliar la memoria de datos con un chip externo (EEPROM, SRAM).
En realidad es peor de lo que crees. Su página vinculada de Mouser es confusa cuando especifica que este procesador tiene 384 bytes de memoria de programa. El PIC10F200 en realidad tiene 256 palabras de 12 bits de memoria de programa.
Entonces, ¿qué puedes hacer con eso? El conjunto de instrucciones PIC de 12 bits utilizado por los dispositivos PIC10F20 x son todas instrucciones de una sola palabra, por lo que después de restar algunas instrucciones para la configuración del procesador, queda suficiente espacio para un programa de aproximadamente 250 pasos. Eso es suficiente para muchas aplicaciones. Probablemente podría escribir un controlador de lavadora en ese tipo de espacio, por ejemplo.
Revisé los compiladores PIC C disponibles y parece que la mitad de ellos ni siquiera intentarán emitir código para un PIC10F200. Aquellos que probablemente emitan tanto código repetitivo que es posible que solo pueda escribir una luz intermitente LED en el espacio que queda. Realmente desea utilizar el lenguaje ensamblador con dicho procesador.
agitando mi bastón en mi día, ¡tuvimos que grabar nuestros propios pedacitos en la arena!
En 1976 (más o menos) el sistema Atari 2600 VCS era una de las "plataformas de videojuegos" más populares de la época. En él, el microprocesador (MOSTEK 6507) funcionaba a una increíble velocidad de ~1 MHz y tenía ****128 bytes de RAM**.
Un segundo ejemplo que recuerdo de un microcontrolador con RAM extremadamente limitada (~128 bytes) fue un PIC12F utilizado en un convertidor DC-DC. Este micro también tuvo que usar lenguaje ensamblador para poder ejecutarse.
david tweed
chris stratton
Juan Burton
Hammar
Jeanne Píndaro
Kaz
jon purdy
Warren P.
Zoredache
codificador543
russell borogove
Andrei Vihrov
Juan Burton
Jeanne Píndaro
usuario16743
int 13h
para borrar su disco duro en menos de 0x1BE (446) bytes. ¿Cuenta mi programa de sector de arranque para x86?doug65536
maxthon-chan
thexeno