目次
前
次
方向指示器
2個のプッシュスイッチ、2個のLEDを利用して
方向指示器を作ります。
プッシュスイッチは、1度押すと点滅を開始し
再度押すと消灯します。内部にモードを表す
変数を用意して対応。
プッシュスイッチを押したかの判定に、シフト
レジスタを使い、内部のモード変数を更新します。
モード変数の値で、点滅と消灯を切替え。
シフトレジスタによるモード切替は、次のように
記述すればよいでしょう。
if ( SFLAG == ON ) {
/* clear flag */
SFLAG = OFF ;
/* get pin state */
ltrg_sft <<= 1 ;
rtrg_sft <<= 1 ;
ltrg_sft &= MASK03 ;
rtrg_sft &= MASK03 ;
if ( LEFT_BUTTON == OFF ) { ltrg_sft |= ON ; }
if ( RIGHT_BUTTON == OFF ) { rtrg_sft |= ON ; }
/* update mode */
if ( ltrg_sft == 0x01 ) {
lmode++ ;
lmode &= 1 ;
}
if ( ltrg_sft == 0x01 ) {
rmode++ ;
rmode &= 1 ;
}
}
フラグSFLAGは、タイマー割込みで10msごとに通知
されるとしておきます。チャタリング除去できる
程度のインターバルにしておけば、充分でしょう。
モードは、フラグで扱えばよいので、変数値を
インクリメントし、最下位ビットの値をフラグ
に利用。
点滅は、タイマー割込みで250msごと通知してもらい
LEDに1あるいは0の論理値を出力します。
if ( TFLAG == ON ) {
/* clear flag */
TFLAG = OFF ;
/* increment */
lcnt++ ;
rcnt++ ;
/* left LED handling */
if ( lmode ) {
LEFT_LED = (lcnt & 1) ;
} else {
LEFT_LED = ON ;
}
/* right LED handling */
if ( lmode ) {
RIGHT_BUTTON = (rcnt & 1) ;
} else {
RIGHT_BUTTON = ON ;
}
}
モード変数値で、点滅、消灯を切り替えます。
負論理で点灯としておき、カウンタの値で
1と0を確定します。
10msと250msの通知は、タイマー割込みでフラグをセット
して通知します。タイマー割込みは、以下とします。
void interrupt(void)
{
/* generate 1ms */
if ( INTCON.T0IF == ON ) {
/* clear flag */
INTCON.T0IF = OFF ;
/* initialize */
TMR0 = 6 ;
/* increment */
timcnt++ ;
/* get lower 8 bits */
timv = timcnt & MASKFF ;
/* judge */
if ( (timv & 15) == 10 ) { SFLAG = ON ; }
if ( timv == 250 ) { TFLAG = ON ; }
}
}
タイマー割込みは、4MHzから1kHzを生成するので
次のイメージとなります。
初期化をひとつの関数の中に入れていまいます。
void init_usr(void)
{
/* I/O state */
GPIO = 0x03 ;
/* I/O directions */
TRISIO = (1 << LB_BIT) | (1 << RB_BIT) ;
/* bit5,4 as input , others as output */
/* disable compare module */
CMCON = 0x07 ;
/* pull-up */
WPU = (1 << LB_BIT) | (1 << RB_BIT) ;
/* initialize Timer 0 */
{
ltrg_sft = 0 ;
rtrg_sft = 0 ;
/*
4MHz/4 = 1MHz -> 1MHz/4 = 250kHz prescaler = 1:4
all inputs are pull-up .
*/
OPTION_REG = 0x01 ;
/* 256 - 250 = 6 */
TMR0 = 6 ;
/* enable timer0 overflow interrupt */
INTCON.T0IE = ON ;
}
/* enable general interrupt */
INTCON.GIE = ON ;
/* clear flags */
xflags.DR = 0 ;
/* clear */
timcnt = 0 ;
lmode = 0 ;
rmode = 0 ;
lcnt = 0 ;
rcnt = 0 ;
}
部品点数を減らすため、内蔵プルアップ抵抗を利用して
います。また、フラグは8ビット中の2ビットを利用し
フラグに使う変数を減らしています。
まとめます。
/* redefine data type */
typedef unsigned char UBYTE ;
typedef unsigned int UWORD ;
typedef unsigned long ULONG ;
#define OFF 0
#define ON OFF+1
#define LB_BIT 5
#define RB_BIT 4
#define LLED 0
#define RLED 1
#define MASKFF 0xff
#define MASK30 0x30
#define MASK0F 0x0f
#define MASK03 0x03
#define LEFT_BUTTON GPIO.B5
#define RIGHT_BUTTON GPIO.B4
#define LEFT_LED GPIO.B0
#define RIGHT_LED GPIO.B1
typedef union {
struct {
unsigned B7:1;
unsigned B6:1;
unsigned B5:1;
unsigned B4:1;
unsigned B3:1;
unsigned B2:1;
unsigned B1:1;
unsigned B0:1;
} BIT ;
unsigned char DR ;
} FLAGSP ;
volatile FLAGSP xflags ;
#define TFLAG xflags.BIT.B0
#define SFLAG xflags.BIT.B1
ULONG timcnt ;
UBYTE timv ;
UBYTE ltrg_sft ;
UBYTE rtrg_sft ;
UBYTE lmode ;
UBYTE rmode ;
UBYTE lcnt ;
UBYTE rcnt ;
/* function prototype */
void init_usr(void);
/* interrupt handler */
void interrupt(void)
{
/* generate 1ms */
if ( INTCON.T0IF == ON ) {
/* clear flag */
INTCON.T0IF = OFF ;
/* initialize */
TMR0 = 6 ;
/* increment */
timcnt++ ;
/* get lower 8 bits */
timv = timcnt & MASKFF ;
/* judge */
if ( (timv & 15) == 10 ) { SFLAG = ON ; }
if ( timv == 250 ) { TFLAG = ON ; }
}
}
void main(void)
{
/* user initialize */
init_usr();
/* endless loop */
while ( ON ) {
/* switch handling */
if ( SFLAG == ON ) {
/* clear flag */
SFLAG = OFF ;
/* get pin state */
ltrg_sft <<= 1 ;
rtrg_sft <<= 1 ;
ltrg_sft &= MASK03 ;
rtrg_sft &= MASK03 ;
if ( LEFT_BUTTON == OFF ) { ltrg_sft |= ON ; }
if ( RIGHT_BUTTON == OFF ) { rtrg_sft |= ON ; }
/* update mode */
if ( ltrg_sft == 0x01 ) {
lmode++ ;
lmode &= 1 ;
}
if ( ltrg_sft == 0x01 ) {
rmode++ ;
rmode &= 1 ;
}
}
/* 250ms seconds pass handling */
if ( TFLAG == ON ) {
/* clear flag */
TFLAG = OFF ;
/* increment */
lcnt++ ;
rcnt++ ;
/* left LED handling */
if ( lmode ) {
LEFT_LED = (lcnt & 1) ;
} else {
LEFT_LED = ON ;
}
/* right LED handling */
if ( lmode ) {
RIGHT_BUTTON = (rcnt & 1) ;
} else {
RIGHT_BUTTON = ON ;
}
}
}
}
/* define function body */
void init_usr(void)
{
/* I/O state */
GPIO = 0x03 ;
/* I/O directions */
TRISIO = (1 << LB_BIT) | (1 << RB_BIT) ;
/* bit5,4 as input , others as output */
/* disable compare module */
CMCON = 0x07 ;
/* pull-up */
WPU = (1 << LB_BIT) | (1 << RB_BIT) ;
/* initialize Timer 0 */
{
ltrg_sft = 0 ;
rtrg_sft = 0 ;
/*
4MHz/4 = 1MHz -> 1MHz/4 = 250kHz prescaler = 1:4
all inputs are pull-up .
*/
OPTION_REG = 0x01 ;
/* 256 - 250 = 6 */
TMR0 = 6 ;
/* enable timer0 overflow interrupt */
INTCON.T0IE = ON ;
}
/* enable general interrupt */
INTCON.GIE = ON ;
/* clear flags */
xflags.DR = 0 ;
/* clear */
timcnt = 0 ;
lmode = 0 ;
rmode = 0 ;
lcnt = 0 ;
rcnt = 0 ;
}
内蔵クロックを利用するので、スイッチ
LED、抵抗を接続するだけです。
目次
前
次