Aitendoのラジオ用LCD(その3)
やっぱり年越しそばまで特にすることもないので、ソフトをタイマー割り込み方に変えました。
ちょっと見てたら簡単に変えられそうだったし。
下が今なおしたソフトです。タイマー1割り込みで、lcdstateの状態でセグメントと位相を判断してLCD制御を行います。
メインからはSet_Num()で表示周波数を、Set_Band()でバンドを設定すれば後は勝手に表示します。
やっつけっぽいコードですが、スピードがいるわけでもないのでこのまま使おうかと思います。
#include "P24FJ64GA004.h"
//config
_CONFIG2(0xF9FC);
_CONFIG1(0x3F7F);
unsigned int coldata[3];
unsigned int lcdstate;
//main loop
int main(void)
{
unsigned int i,j;
lcdstate =0;
//Setup clock
OSCCON = 0x11C0; // FRCPLL
CLKDIV = 0x0030; // 1MIPS SETTING
//IO PORT SETTING
AD1PCFG = 0xffff; // Analog input disable
TRISA = 0x000f; // All output (Will be changed)
TRISB = 0x0000; // All output
TRISC = 0x0000; // All output
// INITIALIZE
coldata[0] = 0;coldata[1] = 0;coldata[2] = 0;
Set_Num(1234); // 4桁で周波数を指定
Set_Band(1); // バンド指定 0=AM / 1=SW / 2=FM
// タイマ1の設定
PR1 = 300;
T1CON = 0b1000000000110000;
IEC0bits.T1IE = 1; // タイマ1割り込み許可
//メインループ 周波数・バンド変化
while(1){
for (i=0;i<=2;i++) {
for (j=0;j<9999;j++) {
Set_Num(j);
Set_Band(i);
Wait_Time(10);
}
}
}
}
// NUMERIC SET 4桁の数字を一気にバッファにセットする
void Set_Num(unsigned int num){
coldata[0] &= 0x0000;coldata[1] &= 0x0001;coldata[2] = 0xe000;
Set_1digit(3,num/1000);
Set_1digit(2,(num%1000)/100);
Set_1digit(1,(num%100)/10);
Set_1digit(0,num%10);
}
// BAND SET SW/AM/FM MHz/KHz/少数点 インジケータをセットする
void Set_Band(unsigned int band){
if (band ==0) { coldata[2] &= 0x1ffe;
coldata[0] &= 0x0924;
coldata[0] |= 0x2001; // AM KHz 小数点以下なし
coldata[1] &= 0x1ffe;
}
if (band ==1) { coldata[2] &= 0x1ffe;
coldata[0] &= 0x0924;;
coldata[0] |= 0x8010; // SW MHz 小数点以下2桁
coldata[1] |= 0x0001;
}
if (band ==2) { coldata[2] &= 0x1ffe;
coldata[0] &= 0x0924;
coldata[0] |= 0x0408; // FM MHz 小数点以下1桁
coldata[1] |= 0x0001;
}
}
// NUMERIC SET 1桁の数字をセットするルーチン
void Set_1digit(unsigned int col,unsigned int num){
unsigned int wk1,wk2,wk3;
wk1 = 0;wk2=0;wk3=0;
switch (num) { // 0-9す数字に合わせてセグメントデータを設定
case 0: wk3 =0x07;wk2=0x05;wk1=2;break;
case 1: wk3 =0x01;wk2=0x01;wk1=0;break;
case 2: wk3 =0x03;wk2=0x06;wk1=2;break;
case 3: wk3 =0x03;wk2=0x03;wk1=2;break;
case 4: wk3 =0x05;wk2=0x03;wk1=0;break;
case 5: wk3 =0x06;wk2=0x03;wk1=2;break;
case 6: wk3 =0x06;wk2=0x07;wk1=2;break;
case 7: wk3 =0x03;wk2=0x01;wk1=0;break;
case 8: wk3 =0x07;wk2=0x07;wk1=2;break;
case 9: wk3 =0x07;wk2=0x03;wk1=2;break;
deafult: break;
}
coldata[0]=coldata[0] | (wk1 << (col*3+1));
coldata[1]=coldata[1] | (wk2 << (col*3+1));
coldata[2]=coldata[2] | (wk3 << (col*3+1));
}
// SEGMENT CONTROL ここでLCDを制御
void __attribute__((interrupt, auto_psv))
_T1Interrupt(void)
{
unsigned int wk;
wk = coldata[lcdstate/2];
if ((lcdstate%2)==0) {
PORTB = wk ^ 0xffff; // オンするセグメントを0Vにする
PORTA = 0xffff;
switch (lcdstate/2) { // Col選択 選択したColだけ1をドライブ(3V)
case 0 : // それ以外はフロート(1.5V)
TRISA = 0xfffe;break;
case 1 :
TRISA = 0xfffd;break;
case 2 :
TRISA = 0xfeff;break;
default :break;
}
}else{
PORTB = wk; // オンするセグメントを3Vにする
PORTA = 0x0000; // 選択したColを0Vに。それ以外は1.5Vのまま
}
lcdstate++;
if (lcdstate>5) {
lcdstate =0;
}
IFS0bits.T1IF = 0;// 割り込みフラグクリア
}
// WAIT LOOP 適当なウェイトルーチン
void Wait_Time(unsigned int t) {
int t0,t1;
for (t0=0;t0<t;t0++) {
for (t1=0;t1<100;t1++) {
}
}
}
ただいま雪国に帰省中です。外は荒れてて出かける気にもならないし、新年もちょっと年始の挨拶回りしたらとくにやることもないです。テレビは面白くないし。ネット環境も遅くていまいち。
酒飲んで寝てるだけでは体にも心にもよくないので、この正月はDSPラジオ基板の方に手を出そうかと思います。
それではまたです。
最近のコメント