我用兩個(gè)138級(jí)聯(lián)作為行驅(qū)動(dòng)器,8個(gè)595作為列驅(qū)動(dòng)器,下面的程序能實(shí)現(xiàn)四個(gè)字的靜態(tài)顯示,請(qǐng)問如何實(shí)現(xiàn)字的左右移動(dòng)和上下移動(dòng),不甚感激,謝謝!!(我用的匯編)
附件里面有原理圖和程序,請(qǐng)給予指教,萬分感謝!!
自己以前找的,希望對(duì)你有用!
(2)移位控制... 21
點(diǎn)陣的移位一般有上、下、左、右的移動(dòng),這里我們重點(diǎn)講上移和左移,其它同理。
1. 點(diǎn)陣的上移:
點(diǎn)陣的上移相對(duì)來說很簡單,看效果圖如下:
源代碼:(該程序?qū)崿F(xiàn)了循環(huán)上移顯示“邢臺(tái)”)
/************16*16LED點(diǎn)陣屏顯示*****************/
#include<reg52.h>
sbit R="P2"^0; //數(shù)據(jù)輸入端口
sbit CLK="P2"^1; // 時(shí)鐘信號(hào)
sbit STB="P2"^2; // 鎖存端
char code table[]={
/*-- 文字: 邢 --*/
/*-- 宋體12; 此字體下對(duì)應(yīng)的點(diǎn)陣為:寬x高=16x16 --*/
0x00,0x00,0xFE,0x3E,0x48,0x22,0x48,0x22,
0x48,0x12,0x48,0x12,0x48,0x0A,0xFF,0x13,
0x48,0x22,0x48,0x42,0x48,0x42,0x48,0x46,
0x44,0x2A,0x44,0x12,0x42,0x02,0x40,0x02,
/*-- 文字: 臺(tái) --*/
/*-- 宋體12; 此字體下對(duì)應(yīng)的點(diǎn)陣為:寬x高=16x16 --*/
0x40,0x00,0x40,0x00,0x20,0x00,0x10,0x04,
0x08,0x08,0x04,0x10,0xFE,0x3F,0x00,0x20,
0x00,0x08,0xF8,0x1F,0x08,0x08,0x08,0x08,
0x08,0x08,0x08,0x08,0xF8,0x0F,0x08,0x08,
};
void delay(int z)
{
int x,y;
for(x=0;x<z;x++)
for(y=0;y<110;y++);
}
void WriteByte(char dat) //寫一個(gè)字節(jié)的數(shù)據(jù)
{
char i;
for(i=0;i<8;i++) //循環(huán)8次把編碼傳給鎖存器
{
dat=dat>>1; //右移一位,取出該字節(jié)的最低位
R=CY; //將該字節(jié)的最低位傳給R
CLK=0; //將數(shù)據(jù)送出,上升沿
CLK=1;
}
}
void main()
{
int num,move,speed;
while(1)
{
if(++speed>8) //移動(dòng)速度控制
{
speed=0;
move++; //移位
if(move>16) //是否完成移位一個(gè)漢字
move=0; //從頭開始
}
for(num=0;num<16;num++)
{
WriteByte(table[2*num+move*2]); //送出一個(gè)字節(jié)
WriteByte(table[2*num+1+move*2]);
P1=num; //行選
STB=1; //輸出鎖存器中的數(shù)據(jù),下降沿
STB=0;
delay(2);
}
}
}
可以看到這個(gè)程序和靜態(tài)顯示的程序沒有太大的差距,主要就是加入了一個(gè)move變量來控制移動(dòng),WriteByte(table[2*num+move*2])中當(dāng)move變量變化的時(shí)候更改了寫入595中的數(shù)據(jù),正好實(shí)現(xiàn)了移動(dòng)顯示的效果。而speed變量的if判斷語句能夠控制移動(dòng)速度的大小。下面重點(diǎn)講左移。
2. 點(diǎn)陣的左移:
因?yàn)辄c(diǎn)陣的數(shù)據(jù)最終是一個(gè)一個(gè)字節(jié)的并行送出的,所以要實(shí)現(xiàn)點(diǎn)陣的左移,我們就需要考慮如何才能夠動(dòng)態(tài)的更改每一個(gè)發(fā)送字節(jié)的數(shù)據(jù),而漢字的每一個(gè)字節(jié)的編碼是固定的,這里我們可以使用一個(gè)數(shù)據(jù)緩沖區(qū)來完成點(diǎn)陣的左移。重點(diǎn)說一下點(diǎn)陣左移中關(guān)鍵的一步操作temp=(BUFF>>tempyid) | (BUFF[s+1]<<(8-tempyid))。這里temp作為要發(fā)送的一個(gè)字節(jié)數(shù)據(jù),它由數(shù)據(jù)緩沖區(qū)中的數(shù)據(jù)組合而成,并且動(dòng)態(tài)的變化,大致來說就是首先第一個(gè)字節(jié)的數(shù)據(jù)右移tempyid位,第二個(gè)字節(jié)的數(shù)據(jù)左移8-tempyid位,兩者相或后組成一個(gè)字節(jié)新的數(shù)據(jù),只要我們一直不斷地移位、相或、發(fā)送,就能實(shí)現(xiàn)左移的效果。不太好理解,先來看實(shí)例(循環(huán)左移顯示“邢臺(tái)學(xué)院”),效果圖如下:
見源代碼:
#include <AT89x51.H>
#define uchar unsigned char
#define uint unsigned int
uchar yid,h; //YID為移動(dòng)計(jì)數(shù)器,H為行段計(jì)數(shù)器
uint zimuo; //字模計(jì)數(shù)器
uchar code hanzi[]; //漢字字模
uchar BUFF[4]; //緩存
void in_data(void); //調(diào)整數(shù)據(jù)
void rxd_data(void); //發(fā)送數(shù)據(jù)
void sbuf_out(); //16段掃描
uchar code table[]={//篇幅有限,省略編碼};
void main(void)
{
uchar i,d=10;
yid=0;
zimuo=0;
while(1)
{
while(yid<16) //數(shù)據(jù)移位。
{
for(i=0;i<d;i++) //移動(dòng)速度
{
sbuf_out();
}
yid++; //移動(dòng)一步
}
yid=0;
zimuo=zimuo+32; //后移一個(gè)字,
if(zimuo>=96) //到最后從頭開始,有字?jǐn)?shù)決定
zimuo=0;
}
}
/********************************/
void sbuf_out()
{
for(h=0;h<16;h++) //16行掃描
{
in_data(); //調(diào)整數(shù)據(jù)
rxd_data(); //串口發(fā)送數(shù)據(jù)
P1=0x7f; //關(guān)閉顯示。
P1_7=1; //鎖存為高,595鎖存信號(hào)
P1=h; //送行選
}
}
/******************************************************/
void in_data(void)
{
char s;
for(s=1;s>=0;s--) //h為向后先擇字節(jié)計(jì)數(shù)器,zimuoo為向后選字計(jì)數(shù)器
{
BUFF[2*s+1]=table[zimuo+1+32*s+2*h]; //把第一個(gè)字模的第一個(gè)字節(jié)放入BUFF0
//中,第二個(gè)字模的第一個(gè)字節(jié)放入BUFF2中
BUFF[2*s]=table[zimuo+32*s+2*h]; // 把第一個(gè)字模的第二個(gè)字節(jié)放入BUFF1中,
//第二個(gè)字模的第二個(gè)字節(jié)放入BUFF3中
}
}
/*******************************************************/
void rxd_data(void) //串行發(fā)送數(shù)據(jù)
{
char s;
uchar inc,tempyid,temp;
if(yid<8)
inc=0;
else
inc=1;
for(s=0+inc;s<2+inc;s++) //發(fā)送2字節(jié)數(shù)據(jù)
{
if(yid<8)
tempyid=yid;
else
tempyid=yid-8;
temp=(BUFF>>tempyid)|(BUFF[s+1]<<(8-tempyid));//h1左移tempyid位后和h2右移8-tempyid相或,取出移位后的數(shù)據(jù)
SBUF=temp;//把BUFF中的字節(jié)從大到小移位相或后發(fā)送輸出。
while(!TI); //注:這里使用了串口,串口數(shù)據(jù)的發(fā)送為最低位在前。
TI=0; //等待發(fā)送中斷
}
}
首先來看定義的數(shù)據(jù)緩沖區(qū)BUFF[ ],這里一開始將會(huì)存儲(chǔ)第一個(gè)漢字與第二個(gè)漢字的第一行的編碼,該緩沖區(qū)動(dòng)態(tài)的存儲(chǔ)點(diǎn)陣屏每一行要發(fā)送的數(shù)據(jù),注意這里BUFF的大小為4個(gè)字節(jié),比16*16點(diǎn)陣屏要顯示的漢字多了一個(gè)漢字行的大小,這一點(diǎn)是必要的,這樣我們才能實(shí)現(xiàn)利用該緩沖區(qū)進(jìn)行左移控制,接著來看in_data(void)函數(shù),利用該函數(shù),我們實(shí)現(xiàn)了動(dòng)態(tài)的修改緩沖區(qū)中的數(shù)據(jù),這里不再詳述過程,重點(diǎn)看程序的注釋即可。然后看rxd_data(void)函數(shù),該函數(shù)的作用正是利用串口串行發(fā)送數(shù)據(jù),也就是上面提到的移位、相或然后發(fā)送,關(guān)于在移位過程中的具體實(shí)現(xiàn)細(xì)節(jié)以及如何協(xié)調(diào)的進(jìn)行數(shù)據(jù)發(fā)送,首先來看inc變量,該變量決定了從BUFF緩沖區(qū)中的第一個(gè)還是第二個(gè)數(shù)據(jù)開始讀取,當(dāng)移位開始后,在移完一個(gè)字節(jié)的數(shù)據(jù)之前我們都從BUFF數(shù)據(jù)緩沖區(qū)中的第一個(gè)字節(jié)開始讀取,當(dāng)移完一個(gè)字節(jié)后,inc變成1,這時(shí)我們從BUFF數(shù)據(jù)緩沖區(qū)中的第二個(gè)字節(jié)開始讀取,于此同時(shí)后一個(gè)字節(jié)總是在和前一個(gè)字節(jié)的數(shù)據(jù)進(jìn)行移位相或,達(dá)到慢慢向前推進(jìn)的效果,這里有一個(gè)臨界點(diǎn),就是當(dāng)移位滿16位后,即一個(gè)漢字移出點(diǎn)陣屏后,這時(shí)候我們就需要將數(shù)據(jù)緩沖區(qū)中的數(shù)據(jù)進(jìn)行更新,即后移一個(gè)字,這時(shí)數(shù)據(jù)緩沖區(qū)中的數(shù)據(jù)就變成了第二個(gè)漢字和第三個(gè)漢字的第一行漢字的編碼,以此類推。下面來看sbuf_out()函數(shù),該函數(shù)實(shí)現(xiàn)了16行的掃描,最后來看while循環(huán)內(nèi),這時(shí)主函數(shù)內(nèi)已經(jīng)很簡單了,首先在while(yid<16)內(nèi),有控制移動(dòng)速度的for循環(huán),即顯示幾次靜態(tài)的畫面移動(dòng)一步,而zimuo變量為移位過程中漢字的選擇變量,它每32位的變化,正好是一個(gè)16*16漢字的編碼個(gè)數(shù)。這樣就完成了整個(gè)點(diǎn)陣左移的控制(這里使用了串口實(shí)現(xiàn)點(diǎn)陣的左移,當(dāng)然我們也可以不用串口,關(guān)于非串口實(shí)現(xiàn)的左移后面介紹),它的過程比較復(fù)雜,需反復(fù)思考。
期待中.....
很好哦
歡迎光臨 (http://www.zg4o1577.cn/bbs/) | Powered by Discuz! X3.1 |