たとえば、PIC10F200T
単一の目的のチップでない限り、実質的にあなたが書くコードはそれよりも大きくなります。外部ストレージなどからより多くのプログラムメモリをロードする方法はありますか?私はただ興味があります、これがどのように非常に役立つかわかりません...しかし、そうでなければなりません。
たとえば、PIC10F200T
単一の目的のチップでない限り、実質的にあなたが書くコードはそれよりも大きくなります。外部ストレージなどからより多くのプログラムメモリをロードする方法はありますか?私はただ興味があります、これがどのように非常に役立つかわかりません...しかし、そうでなければなりません。
回答:
あなたの子供たち、私の芝生を降りてください!
384バイトは、アセンブラーで非常に複雑なものを作成するための十分なスペースです。
コンピューターが部屋の大きさであった時代まで歴史を掘り下げると、<1kで実行された芸術性の本当に素晴らしい偉業を見つけることができます。
たとえば、古典的なStory of Mel-A Real Programmerを読んでください。確かに、それらの男たちは、退廃的な異教徒たちと遊ぶための4096語の記憶を持っていました。
また、「イントロ」をフロッピーのブートブロックに収めることが課題であった典型的なデモシーンコンペもご覧ください。典型的なターゲットは4kまたは40kで、通常は音楽とアニメーションを含めることができます。
編集して追加:世界初の100ドルの科学計算用電卓を320語で実装できることがわかりました。
若い 'unsの編集:
マイクロコントローラーは十分に安価であるため、過去数年ではディスクリートロジックで行われていた可能性が非常に高い単純なことを実行するためによく使用されます。本当にシンプルなもの。たとえば、555タイマーでできるよりも正確に、デバイスに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ピンでタイミングオプションを制御し、十分な余裕を持たせることができますが、チップがすべて上記のとおりであったとしても、ディスクリートを使用する他の選択肢よりも安くて簡単かもしれません論理。ところで、clrwdt
命令をサブルーチンに移動することもできますが、そうすると物事の堅牢性が低下します。書かれているように、グリッチによってリターンアドレススタックが破損したとしても、実行がメインループに戻るまでウォッチドッグはフィードされません。それが起こらない場合、ウォッチドッグは数秒後にチップをリセットします。
clrwdt
命令よりも複雑になります。これは可能な限り絶対的なフェールセーフカウンター配置ではありませんが、安全性の問題(clrwdt
サブルーチン内での回避など)を考慮します。
「オンリー」384バイト?
昔、私は船、パイプライン、製油所管理業界にサービスを提供する特殊なコンピューター用にオペレーティングシステム全体を(自分で)書く仕事をしていました。同社の最初の製品は6800ベースで6809にアップグレードされていたため、元のオペレーティングシステムのライセンスコストをなくすために6809に新しいOSを追加したかったのです。彼らはまた、ブートROMのサイズを32バイトから64バイトに増やしました。正しく思い出せば、それは約33年前でした!-オペレーティングシステムのデバイスドライバー全体をROMに配置して、デバイス全体の信頼性と汎用性を高めることができるように、エンジニアに128バイトを提供するよう説得しました。これに含まれるもの:
はい、これらはすべて必要最低限の機能であり、余分なサイクルをすべて取り除くように手作業で最適化されていますが、完全に保守可能で信頼性があります。はい、すべてを利用可能なバイトに押し込みました-ああ、割り込み処理、さまざまなスタックを設定し、リアルタイム/マルチタスクオペレーティングシステムを初期化し、ユーザーにブートオプションを促し、システムを起動しました。
まだ会社と提携している私の友人(後継者)が、数年前に私のコードがまだ使用中であると私に言った!
あなたは384バイトでLOTを行うことができます...
これは、ロジックゲートや555タイマーで必要なサイズよりも小さなフットプリントで、非常に小さなアプリケーション(遅延PSU起動、555タイマー交換、トライアックベースの制御、LED点滅など)に使用できます。
植物の水分量を追跡し、植物に水が必要な場合はLEDを点滅させる、植物用の湿度センサーを設計しました。センサーにプラントのタイプを学習させ、実行中にその設定を変更できます。バッテリーの低電圧を検出します。フラッシュとRAMを使い果たしましたが、Cコードですべてを記述して、この製品を問題なく動作させることができました。
あなたが言及したpic10fを使用しました。
これが私の植物水センサー用に作成したコードです。ADCモジュールがあり、pic10f200と同じメモリを持っているため、pic10f220を使用しました。明日、回路図を見つけようとします。
コードはスペイン語ですが、非常にシンプルであり、簡単に理解できるはずです。Pic10Fがスリープモードから復帰すると、Pic10Fはリセットされるため、パワーアップまたはリセットであったかどうかを確認し、それに応じて行動する必要があります。プラントの設定は実際にはパワーダウンしないため、RAMに保持されます。
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コンパイラを使用しました。
私が高校にいたとき、私は、私などの生徒が取り組むことのできない光の減光は難しい作業であると主張する教師がいました。
したがって、トライアックを使用して位相ベースの調光を学習および理解し、この偉業を実行するためにマイクロチップから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(現在のフリースケール)MC68HC705K1でした。参照するPICほどではありませんが、ROMが残っていることを覚えています。17年後、まだいくつかの組み立てられたユニットが残っています。買いたい?
ええ、それは少なくともアセンブリでできます。
いずれにせよ、最適化するとおそらく384バイト以内に収まると思われる非常に単純なCプログラムを最近作成しました。すべてが大規模で複雑なソフトウェアを必要とするわけではありません。
384バイトのプログラムメモリでLEDを点滅させることができます。
私の知る限り、外部チップでプログラムメモリを拡張することはできません(384バイトで完全なASMインタープリターを構築している場合を除き、低速になります)。ただし、外部チップ(EEPROM、SRAM)でデータメモリを拡張することは可能です。
実際には、あなたが思っているよりも悪いです。リンクされたマウサーページは、このプロセッサが384バイトのプログラムメモリを持っていると指定した場合、混乱を招く問題です。PIC10F200には、実際には256個の12ビットワードのプログラムメモリがあります。
それで、あなたはそれで何ができますか?12ビットPIC命令セット PIC10F20ので使用されるXのデバイスはすべて、単一ワード命令なので、あなたがプロセッサのセットアップのためのいくつかの指示を減算した後、あなたは約250ステップのプログラムのために十分なスペースを残しています。多くのアプリケーションにはこれで十分です。たとえば、そのようなスペースに洗濯機のコントローラーを書くことができます。
私は利用可能なPIC Cコンパイラを調べたところ、それらの半分はPIC10F200のコードを出力しようとさえしないようです。おそらく非常に多くの定型コードを出しているので、残っているスペースにしかLEDフラッシャーを書くことができないかもしれません。あなたは本当にそのようなプロセッサでアセンブリ言語を使いたいです。
私の日に杖を振って、私たちは砂から自分のビットをエッチングしなければなりませんでした!
1976年(またはその周辺)に、Atari 2600 VCSシステムは、当時最も人気のあった「ビデオゲームプラットフォーム」の1つでした。その中で、マイクロプロセッサ(MOSTEK 6507)は、1 MHzの超高速で実行され、**** 128バイトのRAM **を搭載していました。
RAMが非常に限られている(〜128バイト)マイクロコントローラーを思い出す2番目の例は、DC-DCコンバーターで使用されるPIC12Fでした。このマイクロも、まったく実行するためにアセンブリ言語を使用する必要がありました。