2016-02-09 13:21 | カテゴリ:1/8モデル
電子回路の工作の続きです。
プログラムを一部紹介しましたので、長いです、すみません。


音声合成LSIの動作不具合で秋月さんにメールしたら、メーカーに問い合わせるとの事。
もう少し時間がかかりそうですが、今朝、再度実験したら、一切正常の動作はしなくなり、どんなコマンドを送信しても、関係の無いコードを送り返してきました。
故障でしょうね。


そこで、LEDのランダム点滅のプログラミングを進めました。

まずは、今日の結果をご覧ください。


POWERを入れた後、赤色LEDが一回点滅し、動作開始。
その後は、試験的にセットした、赤色と黄色のLEDをランダムに点滅しています。
点灯時間と消灯時間をそれぞれ乱数的に決めて、点滅させていますので、良い感じです。

簡単にプログラムの説明をしますと、

プログラムは
各種の変数と関数の定義をして


//-------------------------------------------------------------------------
// プログラム初期設定
//-------------------------------------------------------------------------
#include

#include

#include

#pragma config FOSC = HS //高速オシレーター(4MHz以上)使用
#pragma config WDTE = OFF //ウォッチドッグタイマーOFF
#pragma config CP = OFF //コードプロテクションOFF
#pragma config PWRTE = ON //パワーアップタイマーON
#pragma config LVP = OFF//
//PICのクロック設定
#define _XTAL_FREQ 20000000 //PICのクロックをHzで設定(20MHz)


//-----------------------------------------------------------------------
// 定義エリア
//-----------------------------------------------------------------------

//------------------------------------------------------------------------
// 変数初期設定
//------------------------------------------------------------------------

unsigned char led_sw[25][2]; // LED毎の点滅時間カウントとON/OFF状態記憶用
unsigned char rcv_1B; // 送受信バイトの変数
unsigned char msg[40]; // 音声モジュールへの文字データ
unsigned char send_1B;
int led_time; //ランダム点滅のカウント値
int i, j; // LOOPカウンター

//------------------------------------------------------------------------
// 関数定義
//------------------------------------------------------------------------
static void interrupt tmr0_int(void);
void RS232_ini(void);
void RS232_write(unsigned char send_1B);
unsigned char RS232_read(void);
void Sound_ini(void);
void Sound_sta(void);
void voice(const char *p);
void PIC_ini(void);
void MTX_set(void);
void LED_brink(void);




メインルーチンでは、
タイマー0を256の分周で使用して、約3msecの定期的な割り込み発生を設定します。
また、タイマー1は使用しない設定にします。

//-------------------------------------------------------------------------
// メインプログラム
//-------------------------------------------------------------------------

main() {

//---------------------------------------
// PIC 初期設定
//---------------------------------------
PIC_ini();

RA1 = 0; // RA0 点灯
__delay_ms(1000);
RA1 = 1; // RA0 消灯
__delay_ms(1000);


//----------------------------------------------------------------
// TRM0 setting 割り込み使用、プリスケーラ256設定
//----------------------------------------------------------------
OPTION_REG = 0b10000111; /// Prescaller 1/256 (3msec interval)
INTCON = 0b00100000;
GIE = 0; // 全体割り込み禁止
T0IE = 1; // TMR0 使用
T0IF = 0; // TMR0 割り込みフラッグクリア

//---------------------------------------------------------------
// TMR1 setting TMR1は使用しない設定に
//---------------------------------------------------------------
T1CON = 0b00000000; // Prescaler 1/8
T1OSCEN = 0; // TMR1
T1SYNC = 0;
TMR1CS = 0; // Internal clock
TMR1ON = 0; // TMR1 clock start
TMR1IE = 0; // TMR1 flag clear
TMR1IE = 0; // TMR1 overflow int off
PEIE = 0; // Peripher al int off
GIE = 0; // GIE is off

//--------------------------------------------------------------
// 配列に初期値をセット
//--------------------------------------------------------------
// 初期値として、最初に最大時間で全LEDを点灯させる設定
MTX_set(); // 255と1をセット

最後に、割り込みを許可して、メインルーチンは、無限ループに入って、お休み。

//--------------------------------------------------------------
// メインルーチン終了LOOP(以降、メインルーチンは無限ループ
//--------------------------------------------------------------
while (1) {
}

//-----------------メインルーチン最後----------------------------------------------
}



タイマー割り込みルーチンでは、

//----------------------------------------------------------------
//TMR0割り込み処理(LED駆動と音声処理起動)
//----------------------------------------------------------------

static void interrupt tmr0_int(void) {
// テスト処理。LEDデータ配列の「0と1」だけを点滅する
GIE = 0; // 割り込み処理中に次の割り込みが入らないように割り込み禁止

最初に割り込みを一時禁止して、次の割り込みが勝手に入らないようにします。

for (i = 0; i <= 6; i++) { // 配列の0番目から1番目(実際は24番目まで拡張する)
// を繰り返して処理

led_sw[i][0] = led_sw[i][0] - 1; // LED点滅配列の最初のカウンターを-1する
if (led_sw[i][0] == 0) { // カウンターがゼロなら
if (led_sw[i][1] == 0) { // LED表示FLGがOFFならONに
led_sw[i][1] = 1;
} else {
led_sw[i][1] = 0; // 表示ONならOFFにセット
}
led_time = rand();

led_sw[i][0] = led_time / 1024; // 新しくカウンター値をセット
}
}


設定した表示用の配列の0番目から順番に読み出して、カウンターをー1します。
もし、カウンターが0になったら、そのLEDが表示ON中なら表示OFFとして、配列に1を、表示OFF中なら表示ONとして、配列に0を代入します。
ハード上、ポートに1出力でLEDがOFF、0出力でLEDがONとなります。

最後に、配列の各LEDの出力を各ポートに出して、割り込みを許可して、処理終了となります。

LED_brink(); // LED点滅配列に沿ってLEDを表示
// led_sw[n][1]ならON
// led_sw[n][0]ならOFF
GIE = 1; // 割り込み許可

T0IF = 0; // タイマー割り込みFLGクリア
} // 割り込み処理終了


また、関連の関数は

//-------------------------------------------------------------
//PIC Initialize
//-------------------------------------------------------------

void PIC_ini(void) {
//PICのポート設定
ADCON0 = 0b10000000; //アナログ使用しない
ADCON1 = 0b00000110; //For degital I/O

//割り込み不使用
INTCON = 0b00000000;

//TMRをフリーランで使用
OPTION_REG = 0b10000000;
GIE = 0; // 全体割り込み禁止
TMR0 = 0;

//周辺機器割り込み不使用
PIE1 = 0;

//周辺機器割り込みフラグクリア
PIR1 = 0;



TRISA = 0b00000000;
TRISB = 0b00000000;
TRISC = 0b10010000; // OUT = RX, Input from Sound LEI
TRISD = 0b00000000;
TRISE = 0b00000000;

PORTA = 0b11111111; // set data port all H
PORTB = 0b11111111;
PORTC = 0b11111111;
PORTD = 0b11111111;
PORTE = 0b11111111;


}

//-----------------------------------------------------------------
// 配列データの初期セットアップ
//-----------------------------------------------------------------

void MTX_set(void) {
int i;
for (i = 0; i <= 19; i++) {
led_sw[i][0] = 255;
led_sw[i][1] = 1;
}

}

//-----------------------------------------------------------------
// 配列データを元にLEDを点灯・消灯する
//-----------------------------------------------------------------

void LED_brink(void) {
int i;
RA0 = led_sw[0][1]; // Body SW LED TR

RA1 = led_sw[1][1]; // Head LED


RE1 = led_sw[2][1];
RE2 = led_sw[3][1];

RC0 = led_sw[4][1]; // Antena
RC1 = led_sw[5][1];
RC2 = led_sw[6][1];

RB7 = led_sw[7][1]; // 12 of color LEDs
RB6 = led_sw[8][1];
RB5 = led_sw[9][1];
RB4 = led_sw[10][1];
RB3 = led_sw[11][1];
RB2 = led_sw[12][1];
RB1 = led_sw[13][1];
RB0 = led_sw[14][1];
RD7 = led_sw[15][1];
RD6 = led_sw[16][1];
RD5 = led_sw[17][1];
RD4 = led_sw[18][1];
RB0 = led_sw[19][1];

RD0 = led_sw[20][1]; // Body 5mm LED
RD1 = led_sw[21][1];


}



です。

これで、LEDのランダム点滅にめどが立ちました。



管理者のみに表示する