|
/********************************************************************************
;* 標題: TOPAV-2008單片機開發系統演示程序 *
;* 硬件: TOPAV-2008 *
;* 文件: MA016.C *
;* 日期: 2007-5-1 *
;* 版本: 1.0 *
;* 作者: 單片機音響技術網 - zhangshaobin *
;********************************************************************************
;* 描述: *
;* PT6312VFD屏演示(頻譜花式,HELLO字符顯示,按鍵掃描) *
;* *
;********************************************************************************
;* 跳線設置: *
;* 矩陣鍵盤上方跳線組(短接STB,CLK,DATA) *
;* 安裝好6312VFD模塊(注意絲印對應且全部腳插入)VFD為真空玻璃注意愛護 *
;* 特別注意保護VFD屏左邊真空抽氣孔(小凸起部分不可破裂 *
;********************************************************************************
;* 【版權】 Copyright(C)單片機音響技術網All Rights Reserved *
;* 【聲明】 此程序僅用于學習與參考,引用請注明版權和作者信息! *
;*******************************************************************************/
//來,一起玩轉VFD屏及PT6312驅動
#include "reg51.h"
typedef bit BIT;
typedef unsigned char BYTE;
typedef unsigned int WORD;
sbit PT6312_STB = P2^3;
sbit PT6312_CLK = P2^4;
sbit PT6312_DATA = P2^5;
BYTE DISP_ARRAY[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
//BYTE code DISP_CHAR1[] = {4,192,55,118,91,58}; //TUNER
BYTE code DISP_CHAR1[] = {1,62,91,19,19,119}; //HELLO
//BYTE code DISP_CHAR1[] = {4,0,125,127,93,247}; //98.50
BYTE code DISP_KEY01[] = {0,0,119,119,119,36};
BYTE code DISP_KEY02[] = {0,0,119,119,119,107};
BYTE code DISP_KEY03[] = {0,0,119,119,119,109};
BYTE code DISP_KEY04[] = {0,0,119,119,119,60};
BYTE code DISP_KEY05[] = {0,0,119,119,119,93};
BYTE code DISP_KEY06[] = {0,0,119,119,119,95};
BYTE code DISP_KEY07[] = {0,0,119,119,119,100};
BYTE code DISP_KEY08[] = {0,0,119,119,119,127};
BYTE code DISP_KEY09[] = {0,0,119,119,119,125};
BYTE code DISP_KEY10[] = {0,0,119,119,36,119};
BYTE code DISP_KEY11[] = {0,0,119,119,36,36};
BYTE code DISP_KEY12[] = {0,0,119,119,36,107};
BIT NEW_KEY_FLAG=0;
BIT OLD_KEY_FLAG=0;
BYTE bKEY;
BYTE oldKEY;
BYTE code DISP_FREQ1[] = {1,3,7,15,31,63,127,255}; //頻譜上升
BYTE code DISP_FREQ2[] = {1,2,4,8,16,32,64,128}; //頻譜下降
BYTE code DISP_FREQ3[] = {128,192,224,240,248,252,254,255}; //頻譜中間跳動
BYTE SEC_TIME;
BYTE DISC_RUN_TIME;
BYTE FREQ_TIME;
BYTE FREQ_SEC_TIME;
BYTE FREQ_ST_TIME;
BYTE FREQ_RANGE[4]; //手動設置的頻譜,沒有音頻取樣,假頻譜... :)
BYTE KEY_BUF[3];
#define VFD_DISP_MODE 0x02 // 設置段位為 6d/16s
#define VFD_DIM_QUANTITY 0x8f //占空比14/16,顯示為開
#define VFD_DATWR_MODE 0x40 //正常寫入后地址加1
#define VFD_ADDSET_COMD 0xC0 //PT6312片內RAM從OOH~15H,6段使用00H~0BH共12BYTE每段16BIT兩個RAM
#define VFD_SPH 0x00
#define MS20H 0xb1 //定時器0初值
#define MS20L 0xe0 //12M 20MS;45536=B1E0H 65536-45536=20000US=20MS
void Write_A_ByteTo_VFD(BYTE); //一些函數聲明,如果帶行參變量,編譯器會忽略
void Init_vfd();
void Light_all_Write();
void Write_GID6(BYTE *);
BYTE RD_A_Bytefrom_VFD();
void KEY_Scan_Save();
BYTE Get_KEYVAL();
void KEY_Process();
void disp_Chag_disc();
void Write_GID4(BYTE *,BYTE *);
void freqrange_to_disp();
void disp_Chag_freq(); //以上函數做了申明,主程序可以寫在最前面
void main()
{
TMOD = 0x11; //TMOD = 0x01,定時器0方式設置
IE = 0X82; //開總中斷允許,開定時器0允許
Init_vfd(); //DISP_ARRAY數組初始化全部為0所以顯示無內容,只是設置了段位,允許VFD顯示
TH0 = MS20H; //定時器初值設定
TL0 = MS20L;
TR0 = 1; //開定時器0
Write_GID6(&DISP_CHAR1); //顯示HELLO
while(1)
{
disp_Chag_freq(); //調用頻譜條變化
disp_Chag_disc(); //調用DVD轉盤旋轉
KEY_Process(); //按鍵按下顯示按鍵值
Light_all_Write(); //PT6312數據更新
}
}
/*************************************************************************************************/
void Init_vfd() //PT6312初始化
{
PT6312_STB = 1;
PT6312_STB = 0;
Write_A_ByteTo_VFD(VFD_DISP_MODE); //0x02 6d/16s根據顯示VFD的段位設置
PT6312_STB = 1;
PT6312_STB = 0;
Write_A_ByteTo_VFD(0x8f); //占空比14/16,顯示為開
PT6312_STB = 1;
Light_all_Write(); //寫入所有數據到PT6312
}
void Write_A_ByteTo_VFD(BYTE vfd_data) //寫一個字節數據到PT6312
{
BYTE wr_temp;
PT6312_CLK = 1;
for(wr_temp = 0;wr_temp < 8;wr_temp++)
{
PT6312_CLK = 0;
if (vfd_data & 0x01)
PT6312_DATA = 1;
else
PT6312_DATA = 0;
vfd_data >>= 1;
PT6312_CLK = 1;
}
}
void KEY_Process(void)
{
KEY_Scan_Save();
bKEY = Get_KEYVAL();
oldKEY = bKEY;
if ((bKEY == oldKEY) && (FREQ_SEC_TIME == 0))
Write_GID6(&DISP_CHAR1);
switch(bKEY)
{
case 1:
Write_GID6(&DISP_KEY01);
break;
case 2:
Write_GID6(&DISP_KEY02);
break;
case 3:
Write_GID6(&DISP_KEY03);
break;
case 4:
Write_GID6(&DISP_KEY04);
break;
case 5:
Write_GID6(&DISP_KEY05);
break;
case 6:
Write_GID6(&DISP_KEY06);
break;
case 7:
Write_GID6(&DISP_KEY07);
break;
case 8:
Write_GID6(&DISP_KEY08);
break;
case 9:
Write_GID6(&DISP_KEY09);
break;
case 10:
Write_GID6(&DISP_KEY10);
break;
case 11:
Write_GID6(&DISP_KEY11);
break;
case 12:
Write_GID6(&DISP_KEY12);
break;
// default:
// Write_GID6(&DISP_CHAR1);
// break;
}
}
BYTE Get_KEYVAL(void)
{
BYTE keyval;
if (KEY_BUF[0])
{
while (KEY_BUF[0]) //按鍵在KEY_BUF[0],如: 0001 0000,keyval == 5
{
keyval++;
KEY_BUF[0] >>= 1;
};
};
if (KEY_BUF[1])
{
keyval = 8;
while (KEY_BUF[1]) //按鍵在KEY_BUF[1],如: 0001 0000,keyval == 13
{
keyval++;
KEY_BUF[1] >>= 1;
};
};
if (KEY_BUF[2])
{
keyval = 16;
while (KEY_BUF[2]) //按鍵在KEY_BUF[2],如: 0000 1000,keyval == 20
{
keyval++;
KEY_BUF[2] >>= 1;
};
};
return(keyval);
}
void KEY_Scan_Save(void)
{
BYTE keybuf_number;
PT6312_STB = 0;
Write_A_ByteTo_VFD(0x76);
for (keybuf_number = 0 ;keybuf_number < 3;keybuf_number++)
{
KEY_BUF[keybuf_number] = RD_A_Bytefrom_VFD() ;
}
PT6312_STB = 1;
}
BYTE RD_A_Bytefrom_VFD(void)
{
BIT rd_temp_flag;
BYTE key_data;
BYTE rd_temp,rd_temp_keydata;
PT6312_CLK = 1;
PT6312_DATA = 1;
key_data = 0;
for(rd_temp = 0;rd_temp < 8;rd_temp++)
{
PT6312_CLK = 0;
rd_temp_flag = PT6312_DATA;
if (rd_temp_flag)
{
rd_temp_keydata = 0x80;
rd_temp_keydata >>= (7-rd_temp);
key_data |= rd_temp_keydata;
}
PT6312_CLK = 1;
}
return(key_data);
}
void Light_all_Write(void) //顯示數據暫存數組的所有要顯示的內容寫入到PT6312
{
BYTE fill_temp;
PT6312_STB = 1;
PT6312_STB = 0;
Write_A_ByteTo_VFD(0x40); //數據寫入到PT6312后其內部地址自動+1
PT6312_STB = 1;
for (fill_temp=0;fill_temp<12;fill_temp++)
{
PT6312_STB = 0;
Write_A_ByteTo_VFD(0xC0+(11-fill_temp));
Write_A_ByteTo_VFD(DISP_ARRAY[fill_temp]); //暫存顯示數據的數組和PT6312內部地址一一對應
PT6312_STB = 1;
}
}
/*************************************************************************************************/
void Write_GID6(BYTE *charp)
{
BYTE char_temp;
for( char_temp = 2;char_temp < 8;char_temp++) //DISP_ARRAY數組DISP_ARRAY[2]~DISP_ARRAY[7]主顯示內容更新
{
DISP_ARRAY[char_temp] = *charp;
charp++; //指針++指象實參數組下一個元素
}
}
/*************************************************************************************************/
void disp_Chag_disc() //DISC圖標動畫
{
DISP_ARRAY[0] = 0x50; //點亮其他一些圖標"ALL","播放"
switch(DISC_RUN_TIME)
{
case 0:
{
DISP_ARRAY[1] = 0x5f; //01011111 //圖標可以單獨給個位變量來"與"&
break;
}
case 1:
{
DISP_ARRAY[1] = 0x6f;
break;
}
case 2:
{
DISP_ARRAY[1] = 0x77;
break;
}
case 3:
{
DISP_ARRAY[1] = 0x7b;
break;
}
case 4:
{
DISP_ARRAY[1] = 0x7d;
break;
}
case 5:
{
DISP_ARRAY[1] = 0x7e;
break;
}
}
}
/*************************************************************************************************/
void freqrange_to_disp() //顯示頻譜
{
switch(FREQ_TIME) //模擬的一些頻譜幅度,后續根據這個幅度取DISP_FREQ1~3數組的值
//如果有動態的音頻取樣只需要取樣值變化再取顯示點亮的格數值
{
case 0:
{
FREQ_RANGE[0] = 2;
FREQ_RANGE[1] = 4;
FREQ_RANGE[2] = 1;
FREQ_RANGE[3] = 1;
break;
}
case 1:
{
FREQ_RANGE[0] = 1;
FREQ_RANGE[1] = 6;
FREQ_RANGE[2] = 1;
FREQ_RANGE[3] = 2;
break;
}
case 2:
{
FREQ_RANGE[0] = 4;
FREQ_RANGE[1] = 7;
FREQ_RANGE[2] = 3;
FREQ_RANGE[3] = 4;
break;
}
case 3:
{
FREQ_RANGE[0] = 3;
FREQ_RANGE[1] = 4;
FREQ_RANGE[2] = 5;
FREQ_RANGE[3] = 2;
break;
}
case 4:
{
FREQ_RANGE[0] = 6;
FREQ_RANGE[1] = 5;
FREQ_RANGE[2] = 7;
FREQ_RANGE[3] = 5;
break;
}
case 5:
{
FREQ_RANGE[0] = 6;
FREQ_RANGE[1] = 1;
FREQ_RANGE[2] = 3;
FREQ_RANGE[3] = 1;
break;
}
case 6:
{
FREQ_RANGE[0] = 3;
FREQ_RANGE[1] = 2;
FREQ_RANGE[2] = 1;
FREQ_RANGE[3] = 2;
break;
}
case 7:
{
FREQ_RANGE[0] = 7;
FREQ_RANGE[1] = 6;
FREQ_RANGE[2] = 4;
FREQ_RANGE[3] = 3;
break;
}
case 8:
{
FREQ_RANGE[0] = 2;
FREQ_RANGE[1] = 4;
FREQ_RANGE[2] = 5;
FREQ_RANGE[3] = 1;
break;
}
case 9: //十種變化
{
FREQ_RANGE[0] = 5;
FREQ_RANGE[1] = 7;
FREQ_RANGE[2] = 6;
FREQ_RANGE[3] = 7;
break;
}
}
}
void disp_Chag_freq()
{
freqrange_to_disp();
switch(FREQ_ST_TIME)
{
case 0:
{
Write_GID4(&DISP_FREQ1,&FREQ_RANGE);
break;
}
case 1:
{
Write_GID4(&DISP_FREQ2,&FREQ_RANGE);
break;
}
case 2:
{
Write_GID4(&DISP_FREQ3,&FREQ_RANGE);
break;
}
default:
Write_GID4(&DISP_FREQ1,&FREQ_RANGE);
}
}
void Write_GID4(BYTE *freqp,BYTE *freqrp) //兩個指針的應用
{
BYTE freq_temp;
for( freq_temp = 8;freq_temp < 12;freq_temp++)
{
DISP_ARRAY[freq_temp] = freqp[*freqrp];
freqrp++;
}
}
/*************************************************************************************************/
void TR0_Service(void) interrupt 1 using 2 //TR0的定時中斷函數,此函數應簡單。使用寄存器組2
{
TH0 = MS20H; //重點掌握此定時方式可任意定時
TL0 = MS20L;
if(!SEC_TIME) //基準時間5X20MS = 100ms
{
DISC_RUN_TIME++;
if( DISC_RUN_TIME == 6) //DVD轉盤旋轉一圈需要6種狀態改變,DISC_RUN_TIME變化就改變一下狀態
DISC_RUN_TIME = 0;
SEC_TIME = 5;
if(!FREQ_TIME)
{
FREQ_TIME = 10; //根據FREQ_TIME值可更新10種頻譜幅度每100MS變化一次
if(!FREQ_SEC_TIME)
{
FREQ_SEC_TIME = 15; //15s //15s基準
if(!FREQ_ST_TIME) //FREQ_ST_TIME賦值則可根據FREQ_ST_TIME值每15S調用更新
{
FREQ_ST_TIME = 3; //三種主顯示內容和頻譜模式,他們復用每判斷
}
else
{
FREQ_ST_TIME--;
}
}
else
{
FREQ_SEC_TIME--;
}
}
else
{
FREQ_TIME--;
}
}
else
{
SEC_TIME--;
}
}
/*end code 2009/1/7 How to program C!*/ |
-
-
vfd6311.pdf
2024-3-29 11:52 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
24.64 KB, 下載次數: 2, 下載積分: 黑幣 -5
-
-
vfd6312.pdf
2024-3-29 11:52 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
24.35 KB, 下載次數: 2, 下載積分: 黑幣 -5
|