安全確認装置
高電圧を扱う装置から、規定電圧になっているのかを
確認して、全部が準備できているのかを、1ビットで
判断できるユニットを考えました。
回路は、以下。
動作は、単純で各装置が準備完了かを、論理値で出力して
1バイトの各ビットにアサインして処理します。
アナログコンパレータでは、高電圧装置の出力電圧を
扱いやすい電圧まで分圧し、その電圧を規定値と比較
して論理値に変換。
アナログマルチプレクサは、最大8装置分の準備OK状態を
入力するために使います。
ピン数の多いマイコンは、プログラム容量も大きいので
勿体無いと考えれば、アナログマルチプレクサを使って
論理値を入力する方が得策でしょう。
今回は、PIC12F1501を使っています。
動作シーケンスは、次のように考えました。
- マルチプレクサを使い、各装置の準備状態を論理値で入力
- 取得した論理値で、OK、NGの信号を出力
- 時間待ち
- 1に戻る
時間待ちがあるので、タイマー割込みを使ってmain処理の
中に入れればよいと判断。
次のように無限ループを構成して対応。
/* timer interrupt handling */
if ( TFLAG == ON ) {
/* clear flag */
TFLAG = OFF ;
/* initialize */
xstate = 0 ;
/* get current state */
for ( ii = 0 ; ii < 8 ; ii++ ) {
/* impress select */
PORTA = ii & 7 ;
/* get state and store */
if ( PORTA.F4 == ON ) {
/* get bit pattern */
tmp = bpat[ii] ;
/* set target bit */
xstate |= tmp ;
}
}
/* copy */
state = xstate ;
}
イベント通知フラグを利用して、マルチプレクサを使っての
論理値入力とします。
1バイトの変数に、1ビットずつ、該当装置の準備OKかの
フラグをセットかリセット。
割込みハンドラでは、イベント通知フラグをセットする
だけにします。
void interrupt(void)
{
/* generate 500Hz */
if ( INTCON.T0IF == ON ) {
/* clear flag */
INTCON.T0IF = OFF ;
/* initialize (/250) */
TMR0 = CNTBEGIN ;
/* set flag */
TFLAG = ON ;
}
}
タイマー0は、オーバーフローで割込みが発生するので
256−6=250となるように再初期化をしてます。
入出力設定やレジスタの初期化などを、ひとつの関数に
まとめて、わかりやすくします。
void init_usr(void)
{
/* 4MHz */
OSCCON = (0x0d << 3) | 0x03 ;
/* disable D/A converter */
DACCON0.DACEN = OFF ;
/* disable compare module */
CM1CON0.C1ON = OFF ;
CM1CON0.C1OE = OFF ;
/* initialize A/D converter */
ADCON0.ADON = OFF ;
/* I/O state */
PORTA = 0x00 ;
/* I/O directions */
TRISA = 0x18 ; /* bit0,1,2,5 as output , others as input */
/* initialize Timer 0 */
{
/*
4MHz/4 = 1MHz -> 1MHz/8 = 125kHz prescaler = 1:8
*/
OPTION_REG = 0x02 ;
/* 256 - 6 = 250 => 125kHz / 250 = 500 Hz */
TMR0 = CNTBEGIN ;
/* enable timer0 overflow interrupt */
INTCON.T0IE = ON ;
}
/* enable general interrupt */
INTCON.GIE = ON ;
/* initialize flags */
xflags = 0 ;
/* enable general interrupt */
INTCON.GIE = ON ;
/* clear flag */
xflags = 0 ;
/* others */
xstate = 0 ;
state = 0 ;
bpat[0] = 128 ;
bpat[1] = 64 ;
bpat[2] = 32 ;
bpat[3] = 16 ;
bpat[4] = 8 ;
bpat[5] = 4 ;
bpat[6] = 2 ;
bpat[7] = 1 ;
}
クロックは内部を使い、A/D変換器やコンパレータは
使わないようにしてあります。
また、グローバルの割込みを許可し、タイマー割込み
の周期を設定。
1バイトの変数の中の装置担当ビットをセットするため
予め配列の中に、1ビットだけをセットして格納して
わかりやすくしておきました。
まとめると、以下。
/*
scon.c
check unit stanby
PIC12F1501
4MHz system clock
PORTA_0 74HC4051 A
PORTA_1 74HC4051 B
PORTA_2 74HC4051 C
PORTA_3 reset
PORTA_4 input
PORTA_5 ouput
Author Kensuke Ooyu
Date 14th September 2020 create
*/
/* redefine data type */
typedef unsigned char UBYTE ;
#define OFF 0
#define ON OFF+1
#define CNTBEGIN 6
#define NOWSTATE PORTA.F5
volatile UBYTE xflags ;
#define TFLAG xflags.F0
#define SBIT xflags.F1
volatile UBYTE tmp ;
volatile UBYTE ii ;
volatile UBYTE xstate ;
volatile UBYTE state ;
volatile UBYTE bpat[8] ;
/* function prototype */
void init_usr(void);
/* interrupt handler */
void interrupt(void)
{
/* generate 500Hz */
if ( INTCON.T0IF == ON ) {
/* clear flag */
INTCON.T0IF = OFF ;
/* initialize (/250) */
TMR0 = CNTBEGIN ;
/* set flag */
TFLAG = ON ;
}
}
void main(void)
{
/* user initialize */
init_usr();
/* endless loop */
while ( ON ) {
/* timer interrupt handling */
if ( TFLAG == ON ) {
/* clear flag */
TFLAG = OFF ;
/* initialize */
xstate = 0 ;
/* get current state */
for ( ii = 0 ; ii < 8 ; ii++ ) {
/* impress select */
PORTA = ii & 7 ;
/* get state and store */
if ( PORTA.F4 == ON ) {
/* get bit pattern */
tmp = bpat[ii] ;
/* set target bit */
xstate |= tmp ;
}
}
/* copy */
state = xstate ;
}
/* judge and impress */
if ( state == 0xff ) { NOWSTATE = ON ; }
else { NOWSTATE = OFF ; }
}
}
/* define function body */
void init_usr(void)
{
/* 4MHz */
OSCCON = (0x0d << 3) | 0x03 ;
/* disable D/A converter */
DACCON0.DACEN = OFF ;
/* disable compare module */
CM1CON0.C1ON = OFF ;
CM1CON0.C1OE = OFF ;
/* initialize A/D converter */
ADCON0.ADON = OFF ;
/* I/O state */
PORTA = 0x00 ;
/* I/O directions */
TRISA = 0x18 ; /* bit0,1,2,5 as output , others as input */
/* initialize Timer 0 */
{
/*
4MHz/4 = 1MHz -> 1MHz/8 = 125kHz prescaler = 1:8
*/
OPTION_REG = 0x02 ;
/* 256 - 6 = 250 => 125kHz / 250 = 500 Hz */
TMR0 = CNTBEGIN ;
/* enable timer0 overflow interrupt */
INTCON.T0IE = ON ;
}
/* enable general interrupt */
INTCON.GIE = ON ;
/* initialize flags */
xflags = 0 ;
/* enable general interrupt */
INTCON.GIE = ON ;
/* clear flag */
xflags = 0 ;
/* others */
xstate = 0 ;
state = 0 ;
bpat[0] = 128 ;
bpat[1] = 64 ;
bpat[2] = 32 ;
bpat[3] = 16 ;
bpat[4] = 8 ;
bpat[5] = 4 ;
bpat[6] = 2 ;
bpat[7] = 1 ;
}
目次
前
次