當年開發的一款設備運動控制器部分程序,
包括240X64顯示屏顯示,字庫芯片GT21L16S2W讀寫,
字庫豎置橫排旋轉成橫置橫排顯示,24C64讀寫正負數。
相信對于新手還是非常有用。
/*漢字旋轉子程序 將字庫讀出豎置橫排結構的32字節數據
旋轉90度成橫置橫排結構,轉換后點陣結構為
左上部 右上部
左下部 右下部
顯示時先取左上部最頂端數據,再取右上部頂端數據,
再取左上部第二行數據,右上部第二行數據 ......*****/24064液晶屏 240X64顯示屏 兼容T6963C LCD LCM
#include <reg52.h>
#include <intrins.h>
#include <stdlib.h>
#define uchar unsigned char
#define uint unsigned int
typedef unsigned char BYTE;
typedef unsigned int WORD;
sbit cd=P7^7; // PIN 56
sbit ce=P4^5; // PIN 57
sbit rst=P4^6; // PIN 58
sbit wr=P7^6; // PIN 55
sbit rd=P7^5; // PIN 54
sbit fs=P6^0; // PIN 5
sbit SCL=P1^7; // PIN17 外部EEPROM
sbit SDA=P5^4; // PIN18 外部EEPROM
bdata char com_data; /********/
sbit mos_bit=com_data^7; /****高位****/
sbit low_bit=com_data^0; /****低位****/
bit PosiNegate_Flag;
#define ulong unsigned long
#define dataport P0 //P0為數據口
long X,XBuff;
sbit Rom_CS=P1^4; /*1字庫IC接口定義Rom_CS就是字庫IC的CS#*/
sbit Rom_SCK=P1^6; /*2字庫IC接口定義:Rom_SCK就是字庫IC的SCK*/
sbit Rom_OUT=P1^3; /*字庫IC接口定義:Rom_OUT就是字庫IC的OUT*/
sbit Rom_IN=P1^5; /*字庫IC接口定義:Rom_IN就是字庫IC的IN*/
uchar fontbuff[32]; //字庫中讀出的數據存放緩沖數組單元
uchar newbuff[32]; //將字庫中讀出的數據進行轉換
uchar code Testbuff[32]={
0X07,0X04,0X04,0X04,0X07,0X04,0X04,0X04,
0XF0,0X10,0X10,0X10,0XF0,0X10,0X10,0X10,
0X07,0X04,0X08,0X08,0X10,0X20,0X40,0X00,
0XF0,0X10,0X10,0X10,0X10,0X10,0X50,0X20
};
int code fontadd[32]={0,8,1,9,2,10,3,11, //豎置橫排轉橫置橫排點陣排列表
4,12,5,13,6,14,7,15,
16,24,17,25,18,26,19,27,
20,28,21,29,22,30,23,31};
int code xsadd[16]={0,16,32,48,64,80,96,112,128,144,160,176,192,208,224}; //0-9首地址 每字64字節
uchar code tab0[256]={
0X00,0X3C,0X42,0X42,0X42,0X42,0X42,0X42,
0X42,0X42,0X42,0X42,0X42,0X42,0X3C,0X00,//0
0X00,0X30,0X50,0X10,0X10,0X10,0X10,0X10,
0X10,0X10,0X10,0X10,0X10,0X10,0X38,0X00,//1
0X00,0X3C,0X42,0X02,0X02,0X02,0X04,0X08,
0X10,0X20,0X20,0X40,0X40,0X42,0X7E,0X00,//2
0X00,0X3C,0X42,0X02,0X02,0X02,0X02,0X3C,
0X02,0X02,0X02,0X02,0X02,0X42,0X3C,0X00,//3
0X00,0X0C,0X14,0X24,0X24,0X44,0X44,0X84,
0X84,0XFE,0X04,0X04,0X04,0X04,0X04,0X00,//4
0X00,0X7E,0X40,0X40,0X40,0X40,0X7C,0X02,
0X02,0X02,0X02,0X02,0X42,0X42,0X3C,0X00,//5
0X00,0X3C,0X42,0X40,0X40,0X40,0X7C,0X42,
0X42,0X42,0X42,0X42,0X42,0X42,0X3C,0X00,//6
0X00,0X3E,0X42,0X04,0X04,0X08,0X08,0X10,
0X10,0X10,0X10,0X10,0X10,0X10,0X10,0X00,//7
0X00,0X3C,0X42,0X42,0X42,0X42,0X42,0X3C,
0X42,0X42,0X42,0X42,0X42,0X42,0X3C,0X00,//8
0X00,0X3C,0X42,0X42,0X42,0X42,0X42,0X3C,
0X02,0X02,0X02,0X02,0X02,0X42,0X3C,0X00,//9
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"清除",*/
0X00,0X00,0X42,0X42,0X24,0X24,0X18,0X18,
0X18,0X18,0X24,0X24,0X42,0X42,0X00,0X00,//X
0X00,0X00,0X41,0X41,0X22,0X14,0X08,0X08,
0X08,0X08,0X08,0X08,0X08,0X08,0X00,0X00,//Y
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X60,0X60,0X00,//.
0X00,0X3C,0X42,0X42,0X40,0X40,0X40,0X3C,
0X02,0X02,0X02,0X02,0X42,0X42,0X3C,0X00, //S 14
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,//清除光標
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00//15
};
uchar code tab1[16]={
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,//-
0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X00 //
};
/*------------延時子程序---------------------*/
void delay(unsigned int t)
{
unsigned int i,j;
for(i=0;i<t;i++)
for(j=0;j<100;j++);
}
/**************************************/
void start()
{
SDA=1;_nop_();_nop_();_nop_();_nop_();
SCL=1;_nop_();_nop_();_nop_();_nop_();
SDA=0;_nop_();_nop_();_nop_();_nop_();
SCL=0;_nop_();_nop_();_nop_();_nop_();
}
/***************************************/
void stop()
{
SDA=0;_nop_();_nop_();_nop_();_nop_();
SCL=1;_nop_();_nop_();_nop_();_nop_();
SDA=1;_nop_();_nop_();_nop_();_nop_();
}
/***************************************/
void ack()
{
SCL=1;_nop_();_nop_();_nop_();_nop_();
SCL=0;_nop_();_nop_();_nop_();_nop_();
}
/***************************************/
void shift8(char a)
{
data uchar i;
com_data=a;
for(i=0;i<8;i++)
{
SDA=mos_bit;
SCL=1;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
SCL=0;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
com_data=com_data*2;
}
}
/***************************************/
void delay_iic(int v)
{
int i,j;
for(i=1;i<v;i++)
{
for(j=0;j<50;j++)
{
_nop_();
}
}
}
/**************************************/
void at24c64init() //IIC初始化
{
SDA=1;
delay(1);
SCL=1;
delay(1);
}
/***************************************/
uchar rd_24C64(char a)
{
uint addh,addl;
data uint i,command;
addl=a;
addh=a>>8;
SDA=1;_nop_();_nop_();_nop_();_nop_();
SCL=0;_nop_();_nop_();_nop_();_nop_();
start();
command=160;
shift8(command); /*****寫入160*****/
ack();
shift8(addh); /*****寫高八位地址addh 高三位無效*****/
ack();
shift8(addl); /*****寫入低八位地址 addl*****/
ack();
start();
command=161;
shift8(command); /*****寫入161*****/
ack();
SDA=1;_nop_();_nop_();_nop_();_nop_();
for(i=0;i<8;i++)
{
com_data=com_data*2;
SCL=1;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
low_bit=SDA;
SCL=0;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
}
stop();
return(com_data);
}
/***************************************/
void wr_24C64(uint a,char b) //a地址 b數據
{
uint addh,addl;
data uint command;
addl=a;
addh=a>>8;
_nop_();_nop_();_nop_();_nop_();_nop_();
SDA=1;_nop_();_nop_();_nop_();_nop_();
SCL=0;_nop_();_nop_();_nop_();_nop_();
start();
command=160;
shift8(command); /*****寫入160*****/
ack();
shift8(addh); /*****寫高八位地址addh 高三位無效*****/
ack();
shift8(addl); /*****寫入低八位地址 addl*****/
ack();
shift8(b); /*****寫入 b *****/
ack();
stop();
_nop_();_nop_();_nop_();_nop_();_nop_();
}
/************延時函數****************/
void delay_nms(unsigned int n)
{
unsigned int i,j;
for(i=n;i>0;i--)
{
for(j=2000;j>0;j--)
{
}
}
}
/***狀態檢查函數*指令,數據讀寫狀態檢查**/
void Lcd_Busy()
{
uchar dat;
do
{
dataport=0xff;
ce=0;
cd=1;
wr=1;
rd=0;
dat=dataport;
rd=1;
dat=0x03&dat;//STA0,STA1是否準備好
}
while(dat!=0x03);
}
/*******數據自動寫狀態檢查*****************/
void autowcheck()
{
uchar dat;
do
{
dataport=0xff;
ce=0;
cd=1;
wr=1;
rd=0;
dat=dataport;
rd=1;
dat=0x08&dat;//STA3是否準備好
}
while(dat==0x00);
}
/*------輸入/出函數,與T6963通訊------------------------------------------------*/
// 向數據口發Data
void wr_data(uchar dat)
{
ce=0;
cd=0;
dataport=dat;
wr=0;
wr=1;
}
/*****寫有1個參數命令***********/
void wr_com1(uchar command)
{
Lcd_Busy();
cd=1;
ce=0;
rd=1;
dataport=command;
wr=0;
wr=1;
}
/******寫有 3 個參數命令*******************/
void wr_com3(uchar data1, uchar data2, uchar command)
{
Lcd_Busy();
wr_data(data1);
Lcd_Busy();
wr_data(data2);
wr_com1(command);
}
/*--------------------------------*/
void lcd_address(uchar urow,uchar ucol) //urow 為1---30(240/8=30),,ucol為1---64
{
uint ipos;
uchar urow1;
uchar ucol1;
urow1=urow-1; // 1---30
ucol1=ucol-1; // 1---64
ipos=ucol1*30+urow1;
wr_com3(ipos&0xff,0x08+ipos/256,0x24);
}
/************清屏*******************/
void ClearScreen()
{
unsigned int i;
wr_com3(0x00,0x00,0x24); //設置指針地址0000H
wr_com1(0xb0); //設置自動寫狀態
for(i=0;i<9600;i++) //320X240/8=9600
{
autowcheck();
wr_data(0x00);
}
wr_com1(0xb2); // 自動寫結束
}
/**********初始化LCD****************/
void InitLCD()
{
cd=1;
wr=1;
rd=1;
wr_com3(0x00,0x00,0x40); //設置文本顯示區域首地址GraphAddr
wr_com3(0x1e,0x00,0x41); //設置文本顯示區域寬度:1eH 1 1110 16+8+4+2=30
wr_com3(0x00,0x08,0x42); //設置圖形顯示區域首地址GraphAddr
wr_com3(0x1e,0x00,0x43); //設置圖形顯示區域寬度:1eH
wr_com1(0XA0); //設置顯示方式: CGROM方式 文本\圖形 "或"
wr_com1(0X80); //設置顯示方式: CGROM方式 文本\圖形 "或"
wr_com1(0X9C); //顯示開關設置,開文本和圖形顯示*/
ClearScreen();
}
/*顯示字庫處理漢字字符表漢字點陣代碼*/
void display_chines_16x16(uchar urow,uchar ucol,uchar *dp)
{
uchar i,j,K;
K=0;
for(j=0;j<16;j++)
{
lcd_address(urow,ucol+j);
wr_com1(0xb0); //設置自動寫狀態
for(i=0;i<2;i++)
{
autowcheck(); /*寫數據到LCD,每寫完一個8位的數據后列地址自動加1*/
wr_data(*(dp+fontadd[K]));
K++;
}
wr_com1(0xb2); // 自動寫結束
}
}
/********************************/
void display_graphic_16x8(uchar urow,uchar ucol,int mm,uchar *dp)
{
uchar j;
for(j=0;j<16;j++)
{
lcd_address(urow,ucol+j);
wr_com1(0xb0); //設置自動寫狀態
autowcheck(); /*寫數據到LCD,每寫完一個8位的數據后列地址自動加1*/
wr_data(*(dp+mm));
dp++;
wr_com1(0xb2); // 自動寫結束
}
}
/*反碼顯示字庫處理漢字字符表漢字點陣代碼*/
void display_negate_16x16(uchar urow,uchar ucol,uchar *dp)
{
uchar i,j,K;
K=0;
for(j=0;j<16;j++)
{
lcd_address(urow,ucol+j);
wr_com1(0xb0); //設置自動寫狀態
for(i=0;i<2;i++)
{
autowcheck(); /*寫數據到LCD,每寫完一個8位的數據后列地址自動加1*/
wr_data(~*(dp+fontadd[K]));
K++;
}
wr_com1(0xb2); // 自動寫結束
}
}
/***********字庫芯片程序*************************/
/***********送指令到字庫IC***********************/
void send_command_to_ROM( uchar datu )
{
uchar i;
for(i=0;i<8;i++)
{
if(datu&0x80)
Rom_IN=1;
else
Rom_IN=0;
datu=datu<<1;
Rom_SCK=0;
Rom_SCK=1;
}
}
/*****(從字庫IC中取漢字或字符數據(1個字節****/
static uchar ROMDATA( )
{
uchar i;
uchar ret_data=0;
Rom_SCK=1;
for(i=0;i<8;i++)
{
Rom_OUT=1;
delay(1);
Rom_SCK=0;
ret_data=ret_data<<1;
if( Rom_OUT )
ret_data=ret_data+1;
else
ret_data=ret_data+0;
Rom_SCK=1;
}
return(ret_data);
}
/*從相關地址High地址高字節Mid地址中字節Low地址低字節中連續讀出DataLen個字節的數據到 pBuff的地址*/
void BytesDataFromROM(uchar ADHigh,ADMid, ADLow,DataLen,uchar *pBuff)
{
uchar i;
Rom_CS = 0;
Rom_SCK=0;
send_command_to_ROM(0x03);
send_command_to_ROM(ADHigh);
send_command_to_ROM(ADMid);
send_command_to_ROM(ADLow);
for(i=0;i<DataLen;i++ )
*(pBuff+i)=ROMDATA();
Rom_CS=1;
}
/******************************************************************/
void displayGB2312(uchar MSB,uchar LSB)
{
ulong fontaddr=0;
uchar i= 0;
uchar addrHigh,addrMid,addrLow ;
if(((MSB>=0xb0) &&(MSB<=0xf7))&&(LSB>=0xa1))
{
/*國標簡體(GB2312)漢字在字庫IC中的地址由以下公式來計算:*/
/*Address = ((MSB - 0xB0) * 94 + (LSB - 0xA1)+ 846)*32+ BaseAdd;BaseAdd=0*/
/*由于擔心8位單片機有乘法溢出問題,所以分三部取地址*/
fontaddr = (MSB-0xb0)*94;
fontaddr += (LSB-0xa1)+846;
fontaddr = (ulong)(fontaddr*32);
addrHigh = (fontaddr&0xff0000)>>16; /*地址的高8位,共24位*/
addrMid = (fontaddr&0xff00)>>8; /*地址的中8位,共24位*/
addrLow = fontaddr&0xff; /*地址的低8位,共24位*/
BytesDataFromROM(addrHigh,addrMid,addrLow,32,fontbuff);/*取32個字節的數據,存到"fontbuf[32]"*/
i+=2;
}
else if(((MSB>=0xa1) &&(MSB<=0xa3))&&(LSB>=0xa1))
{
/*國標簡體(GB2312)15x16點的字符在字庫IC中的地址由以下公式來計算:*/
/*Address = ((MSB - 0xa1) * 94 + (LSB - 0xA1))*32+ BaseAdd;BaseAdd=0*/
/*由于擔心8位單片機有乘法溢出問題,所以分三部取地址*/
fontaddr = (MSB- 0xa1)*94;
fontaddr += (LSB-0xa1);
fontaddr = (ulong)(fontaddr*32);
addrHigh = (fontaddr&0xff0000)>>16; /*地址的高8位,共24位*/
addrMid = (fontaddr&0xff00)>>8; /*地址的中8位,共24位*/
addrLow = fontaddr&0xff; /*地址的低8位,共24位*/
BytesDataFromROM(addrHigh,addrMid,addrLow,32,fontbuff);/*取32個字節的數據,存到"fontbuf[32]"*/
i+=2;
} //
else if((MSB>=0x20) &&(MSB<=0x7e))
{
unsigned char fontbuff[16];
fontaddr = (MSB- 0x20);
fontaddr = (unsigned long)(fontaddr*16);
fontaddr = (unsigned long)(fontaddr+0x3cf80);
addrHigh = (fontaddr&0xff0000)>>16;
addrMid = (fontaddr&0xff00)>>8;
addrLow = fontaddr&0xff;
BytesDataFromROM(addrHigh,addrMid,addrLow,16,fontbuff);/*取16個字節的數據,存到"fontbuf[32]"*/
i+=1;
}
else
i++;
}
/*漢字旋轉子程序 將字庫讀出豎置橫排結構的32字節數據
旋轉90度成橫置橫排結構,轉換后點陣結構為
左上部 右上部
左下部 右下部
顯示時先取左上部最頂端數據,再取右上部頂端數據,
再取左上部第二行數據,右上部第二行數據 ......*****/
void fontchange(void)
{
uchar fontbuf;
uint buff,i,step;
for(step=0;step<8;step++) //16X16 左上角部分 總循環8步
{
fontbuf=0; //初始化 字節運算緩存器等于0
buff=0; //字節緩沖器初始化.
for(i=0;i<8;i++) //第一層循環,取豎置橫排8字節第1個點。
{
fontbuf<<=1; //數據自右向左移動,共移動7位,合并一字節
buff=fontbuff[ i]>>step; //將當前轉換的列地址fontbuff[ i]右移step步.[ i][ i]
buff&=0X01; //保留最低位置,
fontbuf|=buff; //字節緩存器等于新的運算字節和最低位相與
}
newbuff[step]=fontbuf; //將當前運算的一字節新數據存當前運算地址.
}
for(step=0;step<8;step++) //16X16 右上角部分總循環8步
{
fontbuf=0; //初始化 字節運算緩存器等于0
buff=0; //字節緩沖器初始化.
for(i=0;i<8;i++) //第一層循環,取豎置橫排8字節第1個點。
{
fontbuf<<=1; //數據自右向左移動,共移動7位,合并一字節
buff=fontbuff[i+8]>>step; //將當前轉換的列地址fontbuff[ i]右移step步.[ i]
buff&=0X01; //保留最低位置,
fontbuf|=buff; //字節緩存器等于新的運算字節和最低位相與
}
newbuff[step+8]=fontbuf; //將當前運算的一字節新數據存當前運算地址.
}
for(step=0;step<8;step++) //16X16 左下角部分總循環8步
{
fontbuf=0; //初始化 字節運算緩存器等于0
buff=0; //字節緩沖器初始化.
for(i=0;i<8;i++) //第一層循環,取豎置橫排8字節第1個點。
{
fontbuf<<=1; //數據自右向左移動,共移動7位,合并一字節
buff=fontbuff[i+16]>>step; //將當前轉換的列地址fontbuff[ i]右移step步.[ i]
buff&=0X01; //保留最低位置,
fontbuf|=buff; //字節緩存器等于新的運算字節和最低位相與
}
newbuff[step+16]=fontbuf; //將當前運算的一字節新數據存當前運算地址.
}
for(step=0;step<8;step++) //16X16 右下角部分總循環8步
{
fontbuf=0; //初始化 字節運算緩存器等于0
buff=0; //字節緩沖器初始化.
for(i=0;i<8;i++) //第一層循環,取豎置橫排8字節第1個點。
{
fontbuf<<=1; //數據自右向左移動,共移動7位,合并一字節
buff=fontbuff[i+24]>>step; //將當前轉換的列地址fontbuff[ i]右移step步.[ i]
buff&=0X01; //保留最低位置,
fontbuf|=buff; //字節緩存器等于新的運算字節和最低位相與
}
newbuff[step+24]=fontbuf; //將當前運算的一字節新數據存當前運算地址.
}
}
/************************************/
void X_dec(long X1)
{
long i,j,k,l,m,n;
if(X1>=0) //X值正負標志
{
display_graphic_16x8(6,17,xsadd[10],tab0);//正標志
}
else
{
display_graphic_16x8(6,17,0,tab1);//負標志顯示-
X1=X1-2*X1;
}
i=X1/100000;
j=(X1/10000)%10;
k=(X1/1000)%10;
l=(X1/100)%10;
m=(X1/10)%10;
n=X1%10;
display_graphic_16x8(5,17,xsadd[11],tab0); //X
display_graphic_16x8(7,17,xsadd[ i],tab0); //0 [ i]
display_graphic_16x8(8,17,xsadd[j],tab0); //0
display_graphic_16x8(9,17,xsadd[k],tab0); //0
display_graphic_16x8(10,17,xsadd[l],tab0); //0
display_graphic_16x8(11,17,xsadd[13],tab0); //.
display_graphic_16x8(12,17,xsadd[m],tab0); //0
display_graphic_16x8(13,17,xsadd[n],tab0); //0
}
/************************************/
long red24_a()
{
long X;
uchar l,m,n;
n=rd_24C64(1);
m=rd_24C64(2);
l=rd_24C64(3);
X=l*100+m*10+n;
return X;
}
/************************************/
long red24_b()
{
long X;
uchar l,m,n;
n=rd_24C64(4);
m=rd_24C64(5);
l=rd_24C64(6);
X=l*100+m*10+n;
return X;
}
/************************************/
void main(void)
{
P0M0=0;
P0M1=0;
P1M0=0;
P1M1=0;
P2M0=0;
P2M1=0;
P3M0=0;
P3M1=0;
P4M0=0;
P4M1=0;
rst=0;
delay_nms(100);
rst=1;
delay_nms(100);
fs=0;
InitLCD();
ClearScreen();
X=0;
at24c64init();
wr_24C64(5,1); // 個位
wr_24C64(5,2); //
wr_24C64(2,3); //
wr_24C64(2,4); //
wr_24C64(9,5); //
wr_24C64(1,6); //
while(1)
{
X=red24_a();
X_dec(X);
display_graphic_16x8(5,1,xsadd[1],tab0); //X
delay_nms(1000);
X=red24_b();
X_dec(X);
display_graphic_16x8(5,1,xsadd[0],tab0); //X
delay_nms(1000);
}
}
|