#include <18f14k50.h>
#fuses INTRC_IO, NOWDT, PROTECT, PUT, BROWNOUT, BORV22
#fuses NOLVP, MCLR, NOIESO, NOFCMEN, NOPLLEN, CPUDIV1
//INTRC_IO:内部クロックを使用する ピンはIOで使用可能
//NOWDT:ウォッチドッグ・タイマーを使用しない
//PROTECT:コード・プロテクトする
//PUT:パワーアップ・タイマーを使用する
//BROWNOUT:ブラウンアウト・リセットを使用する
//BORV22:2.2Vでブラウンアウト・リセット
//NOLVP:低電圧(5V)プログラミングを使用しない
//MCLR:MCLRピンを有効にする
//NOIESO:クロックの内部外部切替を無効にする
//NOFCMEN:クロックの監視を無効にする
//NOPLLEN:4X HW PLLを無効にする
//CPUDIV1:クロック分周比1/1
//内部クロック8MHz(CPUDIV1)
#use delay(clock=8000000)
//RS232C使用宣言
#use rs232(baud=9600, xmit=PIN_B7, rcv=PIN_B5, parity=N, bits=8, stop=1)
//RS232C有効
#byte RCSTA = 0xFAB
#bit CREN = RCSTA.4 //CREN = 1
#bit SPEN = RCSTA.7 //SPEN = 1
//RS232C ASYNC設定
#byte TXSTA = 0xFAC
#bit SYNC = TXSTA.4 //SYNC = 0
#bit TXEN = TXSTA.5 //TXEN = 1
//USBモジュール無効
#byte UCON = 0xF64
#bit USBEN = UCON.3 //USBEN = 0
//USBプルアップ無効
#byte UCFG = 0xF61
#bit UPUEN = UCFG.4 //UPUEN = 0
//7segLED(出力)
#define LED_LT PIN_A5 //F-9
#define LED_LB PIN_C5 //E-1
#define LED_CT PIN_C6 //A-7
#define LED_CM PIN_A4 //G-10
#define LED_CB PIN_C4 //D-2
#define LED_RT PIN_C7 //B-6
#define LED_RB PIN_C3 //C-4
//7segLED 点灯:0V 消灯:5V
#define LED_ON 0
#define LED_OFF 1
//送信ボタン(入力)
#define SW_SEND PIN_C2
//シフトインターバル時間設定スイッチ
#define SW_INTERVAL PIN_B6
//スイッチ ON:0V OFF:5V
//送信ボタン 時間設定スイッチ用
#define SW_ON 0
#define SW_OFF 1
//XBee スリープ要求端子 9番ピン(出力)
#define XB_SLEEP_RQ PIN_B4
//XBee スリープ要求 スリープ:5V 解除:0V
#define XB_SLEEP_RQ_SLEEP 1
#define XB_SLEEP_RQ_WAKE 0
//XBee ON/SELLP端子 13番ピン(入力)
#define XB_ON_SLEEP PIN_C0
//XBee ON/SELLP端子 動作:5V スリープ:0V
#define XB_ON_SLEEP_WAKE 1
#define XB_ON_SLEEP_SLEEP 0
//XBee ASSOCIATE端子 15番ピン(入力)
#define XB_ASSOC PIN_C1
//XBee ASSOCIATE端子 ネットワーク検索中:5V 接続中(点滅):0V
#define XB_ASSOC_SEARCH 1
#define XB_ASSOC_CONNECT 0
//グローバル変数、定数宣言
#define MAX_EEPROM 0x100 //最大アドレス(0xFF:256バイト)
#define MAX_SLEEPCOUNT 20 //2周分
//Xbee(COORDINATOR) リモートアドレス
char XBEE_REMOTE_ADDR[8]; //COORDINATOR リモートアドレス
//Xbee(COORDINATOR) 出力ピン
char XBEE_REMOTE_SW[10][2];
//インターバル用
int IntervalSec; //インターバル秒数
int SleepCount; //スリープまでの回数カウンタ 最大数は MAX_SLEEPCOUNT で定義する
//プロトタイプ
void init(void);
void xbee_wake(void);
void xbee_send(int);
int led_shift(int);
void led_display(int, int);
void led_flash(int, int, int);
/*********************************
* INT2割り込み処理
*********************************/
#int_ext2
void ext2_isr(void)
{
SleepCount = 0;
delay_ms(10);
}
/*********************************
* 初期化関数
*********************************/
void init(void)
{
int i;
setup_oscillator(OSC_8MHZ); //内部クロックを8MHzにする
setup_adc_ports(NO_ANALOGS); //全ピンをデジタルIOモードにする
setup_comparator(nc_nc_nc); //コンパレータは動作しない
//RS232C設定
CREN = 1;
SPEN = 1;
//RS232C ASYNC設定
SYNC = 0;
TXEN = 1;
//USBを使わない
USBEN = 0;
UPUEN = 0;
//7segLED 消灯
output_high(LED_LT);
output_high(LED_LB);
output_high(LED_CT);
output_high(LED_CM);
output_high(LED_CB);
output_high(LED_RT);
output_high(LED_RB);
//Xbee(COORDINATOR) リモートアドレスを読み込み
for (i = 0; i < 8; i++) {
XBEE_REMOTE_ADDR[i] = read_eeprom(0x10 + i);
}
//Xbee(COORDINATOR) 出力ピンのATコマンドを設定
// D0(DIO0) 0x44 0x30
// D1(DIO1) 0x44 0x31
// D2(DIO2) 0x44 0x32
// D3(DIO3) 0x44 0x33
// D4(DIO4) 0x44 0x34
// D5(DIO5) 0x44 0x35
// D6(DIO6) 0x44 0x36
// D7(DIO7) 0x44 0x37
// P1(DIO11) 0x50 0x31
// P2(DIO12) 0x50 0x32
XBEE_REMOTE_SW[0][0] = 0x44;
XBEE_REMOTE_SW[0][1] = 0x30;
XBEE_REMOTE_SW[1][0] = 0x44;
XBEE_REMOTE_SW[1][1] = 0x31;
XBEE_REMOTE_SW[2][0] = 0x44;
XBEE_REMOTE_SW[2][1] = 0x32;
XBEE_REMOTE_SW[3][0] = 0x44;
XBEE_REMOTE_SW[3][1] = 0x33;
XBEE_REMOTE_SW[4][0] = 0x44;
XBEE_REMOTE_SW[4][1] = 0x34;
XBEE_REMOTE_SW[5][0] = 0x44;
XBEE_REMOTE_SW[5][1] = 0x35;
XBEE_REMOTE_SW[6][0] = 0x44;
XBEE_REMOTE_SW[6][1] = 0x36;
XBEE_REMOTE_SW[7][0] = 0x44;
XBEE_REMOTE_SW[7][1] = 0x37;
XBEE_REMOTE_SW[8][0] = 0x50;
XBEE_REMOTE_SW[8][1] = 0x31;
XBEE_REMOTE_SW[9][0] = 0x50;
XBEE_REMOTE_SW[9][1] = 0x32;
}
/*********************************
* メイン
*********************************/
void main(void)
{
int swNum; //スイッチ番号
int assoc_count; //アソシエーションをカウントした数
init();
//インターバル秒数設定 (0はシフト停止)
IntervalSec = read_eeprom(0);
if ((IntervalSec != 2) && (IntervalSec != 4) && (IntervalSec != 6) && (IntervalSec != 8) && (IntervalSec != 0)) {
IntervalSec = 2; //未定義時はインターバル 2秒
}
led_flash(IntervalSec, 2, 250); //7segLED フラッシュ
//シフト停止の場合、前回の番号を読み込み
if (IntervalSec == 0) {
swNum = read_eeprom(1);
} else {
swNum = 1;
}
xbee_wake(); //XBee スリープ解除
//割り込み許可
enable_interrupts(GLOBAL); //グローバル割り込み許可
//割り込み設定
ext_int_edge(2, L_TO_H); //INT2立上がりエッジ指定
//割り込み許可
enable_interrupts(INT_EXT2); //INT2(RC2)割り込み許可
//メインループ
while (1) {
//スリープ
if (SleepCount >= MAX_SLEEPCOUNT) {
output_high(XB_SLEEP_RQ); //XBee スリープ
led_display(0, LED_OFF); //7segLED 消灯
sleep(); //PIC スリープ
xbee_wake(); //XBee スリープ解除
}
//ネットワーク検索中ならLEDを検索中の表示にする
assoc_count = 0;
while (input(XB_ASSOC) == XB_ASSOC_SEARCH) {
assoc_count++;
//ネットワーク検索中の状態を10回カウント(0.5秒)したらLEDを検索中の表示にする
if (assoc_count == 10) {
output_high(LED_LT);
output_high(LED_LB);
output_low(LED_CT);
output_low(LED_CM);
output_low(LED_CB);
output_high(LED_RT);
output_high(LED_RB);
}
delay_ms(50);
}
//7segLEDシフト
swNum += led_shift(swNum);
if (swNum > 10)
swNum = 1;
SleepCount++;
}
}
/*********************************
* XBee スリープ解除
*********************************/
void xbee_wake(void)
{
//XBee スリープ解除
output_low(XB_SLEEP_RQ); //XBee スリープ解除
//スリープ解除後の処理
SleepCount = 0;
output_low(LED_CT);
output_low(LED_CM);
output_low(LED_CB);
delay_ms(50);
//XBee スリープ解除したかチェック
while (input(XB_ON_SLEEP) == XB_ON_SLEEP_SLEEP) {
delay_ms(50);
}
delay_ms(4000); //復帰時間かせぎ 4秒
}
/*********************************
* XBee リモートSWの ON/OFF
*********************************/
void xbee_send(int num)
{
char r_dio11[20];
long check_sum_total;
char check_sum;
int i;
num--;
//リモートXBeeのSWをON
r_dio11[0] = 0x7E;
r_dio11[1] = 0x00;
r_dio11[2] = 0x10;
r_dio11[3] = 0x17;
r_dio11[4] = 0x01;
r_dio11[5] = XBEE_REMOTE_ADDR[0];
r_dio11[6] = XBEE_REMOTE_ADDR[1];
r_dio11[7] = XBEE_REMOTE_ADDR[2];
r_dio11[8] = XBEE_REMOTE_ADDR[3];
r_dio11[9] = XBEE_REMOTE_ADDR[4];
r_dio11[10] = XBEE_REMOTE_ADDR[5];
r_dio11[11] = XBEE_REMOTE_ADDR[6];
r_dio11[12] = XBEE_REMOTE_ADDR[7];
r_dio11[13] = 0xFF;
r_dio11[14] = 0xFE;
r_dio11[15] = 0x02;
r_dio11[16] = XBEE_REMOTE_SW[num][0];
r_dio11[17] = XBEE_REMOTE_SW[num][1];
r_dio11[18] = 0x05;
r_dio11[19] = 0x00;
//チェックサムを計算する
check_sum_total = 0;
for (i = 3; i < 19; i++)
check_sum_total += r_dio11[i];
check_sum = 0xFF - (char)(check_sum_total & 0xFF);
r_dio11[19] = check_sum;
//データ送信
for (i = 0; i < 20; i++)
putc(r_dio11[i]);
delay_ms(500);
//リモートXBeeのSWをOFF
r_dio11[0] = 0x7E;
r_dio11[1] = 0x00;
r_dio11[2] = 0x10;
r_dio11[3] = 0x17;
r_dio11[4] = 0x01;
r_dio11[5] = XBEE_REMOTE_ADDR[0];
r_dio11[6] = XBEE_REMOTE_ADDR[1];
r_dio11[7] = XBEE_REMOTE_ADDR[2];
r_dio11[8] = XBEE_REMOTE_ADDR[3];
r_dio11[9] = XBEE_REMOTE_ADDR[4];
r_dio11[10] = XBEE_REMOTE_ADDR[5];
r_dio11[11] = XBEE_REMOTE_ADDR[6];
r_dio11[12] = XBEE_REMOTE_ADDR[7];
r_dio11[13] = 0xFF;
r_dio11[14] = 0xFE;
r_dio11[15] = 0x02;
r_dio11[16] = XBEE_REMOTE_SW[num][0];
r_dio11[17] = XBEE_REMOTE_SW[num][1];
r_dio11[18] = 0x04;
r_dio11[19] = 0x00;
//チェックサムを計算する
check_sum_total = 0;
for (i = 3; i < 19; i++)
check_sum_total += r_dio11[i];
check_sum = 0xFF - (char)(check_sum_total & 0xFF);
r_dio11[19] = check_sum;
//データ送信
for (i = 0; i < 20; i++)
putc(r_dio11[i]);
delay_ms(500);
}
/*********************************
* 7segLED Shift
* 戻り値 0:シフト停止 1:シフト開始
*********************************/
int led_shift(int num)
{
int xbee_send_flag;
long count, c_max;
int result;
if (IntervalSec == 0) {
c_max = 300; //シフト停止の場合、約3秒でループを抜ける数値に設定する
} else {
c_max = (long)IntervalSec * 100;
}
//XBeeとのRS232C通信可にフラグをセットする
xbee_send_flag = 1;
//7segLED点灯
led_display(num, LED_ON);
count = 0;
while (count < c_max) {
//送信スイッチが押されていたら送信する
if (input(SW_SEND) == SW_ON) {
delay_ms(20); //チャタリング防止時間かせぎ 20ms
if (input(SW_SEND) == SW_ON) { //もう一度送信スイッチが押されているかチェック
//送信スイッチを押し続けても、一回しか送信しないようにする処理
if (xbee_send_flag == 1) {
xbee_send(num);
xbee_send_flag = 0; //RS232C通信不可にフラグをセットする
}
//送信スイッチが押されていたら、カウンタをリセットする
count = 0;
}
} else {
//送信スイッチを離したら、RS232C通信可にフラグをセットする
xbee_send_flag = 1;
//カウンタを進める
count++;
delay_ms(10);
//インターバル変更(2,4,6,8秒 0表示はシフト停止)
if (input(SW_INTERVAL) == SW_ON) {
delay_ms(20); //チャタリング防止時間かせぎ 20ms
//もう一度インターバル変更スイッチが押されているかチェック
if (input(SW_INTERVAL) == SW_ON) {
IntervalSec += 2;
if (IntervalSec > 8) {
IntervalSec = 0;
}
//7segLED Flash
led_flash(IntervalSec, 2, 250);
//7segLED点灯
led_display(num, LED_ON);
//シフト停止の場合
if (IntervalSec == 0) {
c_max = 300; //シフト停止の場合、約3秒でループを抜ける数値に設定する
write_eeprom(1, num); //シフト停止する番号をnum番に記憶する
} else {
c_max = (long)IntervalSec * 100;
}
write_eeprom(0, IntervalSec); //インターバル秒数を記憶する
count = 0; //カウンタをリセットする
}
}
}
}
//シフト開始か、シフト停止かを判定
if (IntervalSec == 0)
result = 0; //シフト停止
else
result = 1; //シフト開始
return result;
}
/*********************************
* 7segLED表示
*********************************/
void led_display(int num, int led_on_off)
{
if (led_on_off == LED_ON) {
//7segLED点灯
switch (num) {
case 1: //No1
output_high(LED_LT);
output_high(LED_LB);
output_high(LED_CT);
output_high(LED_CM);
output_high(LED_CB);
output_low(LED_RT);
output_low(LED_RB);
break;
case 2: //No2
output_high(LED_LT);
output_low(LED_LB);
output_low(LED_CT);
output_low(LED_CM);
output_low(LED_CB);
output_low(LED_RT);
output_high(LED_RB);
break;
case 3: //No3
output_high(LED_LT);
output_high(LED_LB);
output_low(LED_CT);
output_low(LED_CM);
output_low(LED_CB);
output_low(LED_RT);
output_low(LED_RB);
break;
case 4: //No4
output_low(LED_LT);
output_high(LED_LB);
output_high(LED_CT);
output_low(LED_CM);
output_high(LED_CB);
output_low(LED_RT);
output_low(LED_RB);
break;
case 5: //No5
output_low(LED_LT);
output_high(LED_LB);
output_low(LED_CT);
output_low(LED_CM);
output_low(LED_CB);
output_high(LED_RT);
output_low(LED_RB);
break;
case 6: //No6
output_low(LED_LT);
output_low(LED_LB);
output_low(LED_CT);
output_low(LED_CM);
output_low(LED_CB);
output_high(LED_RT);
output_low(LED_RB);
break;
case 7: //No7
output_low(LED_LT);
output_high(LED_LB);
output_low(LED_CT);
output_high(LED_CM);
output_high(LED_CB);
output_low(LED_RT);
output_low(LED_RB);
break;
case 8: //No8
output_low(LED_LT);
output_low(LED_LB);
output_low(LED_CT);
output_low(LED_CM);
output_low(LED_CB);
output_low(LED_RT);
output_low(LED_RB);
break;
case 9: //No9
output_low(LED_LT);
output_high(LED_LB);
output_low(LED_CT);
output_low(LED_CM);
output_low(LED_CB);
output_low(LED_RT);
output_low(LED_RB);
break;
case 10: //No10(0)
output_low(LED_LT);
output_low(LED_LB);
output_low(LED_CT);
output_high(LED_CM);
output_low(LED_CB);
output_low(LED_RT);
output_low(LED_RB);
break;
case 0: //No10(0)
output_low(LED_LT);
output_low(LED_LB);
output_low(LED_CT);
output_high(LED_CM);
output_low(LED_CB);
output_low(LED_RT);
output_low(LED_RB);
break;
}
} else {
output_high(LED_LT);
output_high(LED_LB);
output_high(LED_CT);
output_high(LED_CM);
output_high(LED_CB);
output_high(LED_RT);
output_high(LED_RB);
}
}
/*********************************
* 7segLED Flash
*********************************/
void led_flash(int num, int flash, int d_time)
{
int i;
for(i = 0; i < flash; i++) {
//7segLED点灯
led_display(num, LED_ON);
delay_ms(d_time);
//7segLED消灯
output_high(LED_LT);
output_high(LED_LB);
output_high(LED_CT);
output_high(LED_CM);
output_high(LED_CB);
output_high(LED_RT);
output_high(LED_RB);
delay_ms(d_time);
}
}