本帖最后由 破力達 于 2015-2-16 22:00 編輯
費了點時間做了一個lcd1602并口轉串口的轉換板。
一開始以為這個很簡單,應該很快就能弄好,但是實際操作遇到了很多問題。雖說這些問題解決了,但不知道為什么。
我既想發表一下這轉接板又想問問題,所以也不知道要在單片機DIY制作發表好,還是在24小時必答區發表好,最好還是選了這。
因為問題不多。
這個是用STC12C5410AD 晶振12M做的轉接板,聽起來確實有點小題大做。但是沒辦法,手頭上只有它了,或者給自己另一個理由有錢任性。
有了這個轉接板以后就不用為要接著么多線所煩惱了。就兩條通信的線,和兩個電源線,還有一個對比度的調節(也可以在轉接板接好就行了)。
這個基本原理就是通過一條線來脈沖計數控制IO口德高低電平,另一條線也是通過脈沖計數來傳輸lcd D0-D7 的數據。一個畫面刷新速度是76ms;
IMG_20150215_184159.jpg (1.79 MB, 下載次數: 247)
下載附件
2015-2-16 20:28 上傳
IMG_20150215_184241.jpg (1.74 MB, 下載次數: 256)
下載附件
2015-2-16 20:29 上傳
很簡單
IMG_20150216_203722.jpg (1.46 MB, 下載次數: 246)
下載附件
2015-2-16 20:38 上傳
IMG_20150215_184355.jpg (1.54 MB, 下載次數: 239)
下載附件
2015-2-16 20:29 上傳
IMG_20150215_220005.jpg (1.89 MB, 下載次數: 216)
下載附件
正常顯示
2015-2-16 20:28 上傳
這下面是轉接板的程序,直接貼出(由于轉接板單片機數據接線和lcd的相反,所以要把接收到的數據倒過來在輸入給lcd)
#include <reg52.h>
#include <STC12C5410AD.H>
#define uint unsigned int
#define uchar unsigned char
sbit DAT=P3^3;
sbit IO=P3^2;
sbit ledvcc=P3^7;
sbit led=P2^7;
sbit rs=P2^6;
sbit rw=P2^1;
sbit lcde=P2^0;
sbit p0=P1^0;
sbit p1=P1^1;
sbit p2=P1^2;
sbit p3=P1^3;
sbit p4=P1^4;
sbit p5=P1^5;
sbit p6=P1^6;
sbit p7=P1^7;
uchar count;count1;count2;io;
uchar dat;
void init()
{
P2M0=0X0C; //00001100
P2M1=0X80; //10000000
P3M0=0X01; //00000001
P3M1=0X80; //10000000
IT0=1;
EX0=1;
IT1=1;
EX1=1;
EA=1;//打開總中斷
ledvcc=1;
led=0;
}
void IOdispose()
{
while((IO==0)&&(count1<40)) //50us
{
count1++;
}
if(count1>39)
{
led=io&0x01; //11.2us
io>>=1;
lcde=io&0x01; //取出數據
io>>=1;
rw=io&0x01;
io>>=1;
rs=io&0x01;
count1=io=0;
}
}
void datdispose()
{
// uchar dat1;
while((DAT==0)&&(count2<40)) //50us
{
count2++;
}
if(count2>39)
{
p0=dat>>7; //把數據倒過來,例:0x0f倒為0xf0
dat<<=1;
p1=dat>>7;
dat<<=1;
p2=dat>>7;
dat<<=1;
p3=dat>>7;
dat<<=1;
p4=dat>>7;
dat<<=1;
p5=dat>>7;
dat<<=1;
p6=dat>>7;
dat<<=1;
p7=dat>>7;
dat=count2=0;
// for(count=0;count<7;count++)
// {
// dat1=dat1|(dat&0x01);
// dat>>=1;
// dat1<<=1;
// }
// P1=dat1;
// dat=dat1=count2=0;
}
}
void main()
{
init();
while(1)
{
IOdispose();
datdispose();
}
}
void Int0() interrupt 0 //外部中斷0的中斷函數(IO)
{
io++;
count1=0;
}
void Int1() interrupt 2 //外部中斷1的中斷函數(DAT)
{
dat++;
count2=0;
}
搞不懂的就是為什么這里這樣寫為什么就不行
// for(count=0;count<7;count++) //把數據倒過來,例:0x0f倒為0xf0
// {
// dat1=dat1|(dat&0x01);
// dat>>=1;
// dat1<<=1;
// }
// P1=dat;
// dat=dat1=count2=0;
如果這樣寫就可以
p0=dat>>7; //把數據倒過來,例:0x0f倒為0xf0
dat<<=1;
p1=dat>>7;
dat<<=1;
p2=dat>>7;
dat<<=1;
p3=dat>>7;
dat<<=1;
p4=dat>>7;
dat<<=1;
p5=dat>>7;
dat<<=1;
p6=dat>>7;
dat<<=1;
p7=dat>>7;
dat=count2=0;
還有個更加奇怪的問題是這樣把dat重打一行dat倒過來輸入給lcd就行 ,如果一起打在同一行就不行,這是為什么。我只知道這樣打所占的data是不同的(前者data小,后者大),就是由于這個以為不是問題的問題讓我弄了好久。大蝦們幫忙解決一下。
uchar count;count1;count2;io;
uchar dat;
下面是你想讓1602顯示內容的程序,其實這通信協議很簡單,看起來沒什么改變。
#include <reg52.h>
#include <intrins.h>
#include <STC12C5410AD.H>
#define uint unsigned int
#define uchar unsigned char
sbit IO=P2^2;
sbit DAT=P2^3;
sbit c=P2^0;
uchar rs;rw;lcde;led;count;
uchar dat1;
// 00 10 20 30 40 50 60 70 80 90
uchar code charset[]="0123456789 abcdefghi jklmnopqr stuvwxyzA BCDEFGHIJ KLMNOPQRS TUVWSYZ., ?!<>=+-() ;*/%~#_[] {}:' ";
uchar code charset_1[]="Welcome to use!!"; //歡迎使用
uchar code charset_2[]=" <PLD> "; //破力達
void delay_short(uint x) //延時(us)
{
while(x--);
}
void delay_long(uint y) //延時(ms)
{
uint i,j;
y=7*y;
for(i=y;i>0;i--)
for(j=160;j>0;j--);
}
void sendIO()
{
uchar com=2;
com=com|rs;
com<<=1;
com=com|rw;
com<<=1;
com=com|lcde;
com<<=1;
com=com|led;
while(com--)
{
IO=1;
_nop_(); //_nop_()*9:1.1us
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
IO=0;
delay_short(5); //11.3us
}
delay_short(80); //80us 終止時間
IO=1;
}
void senddat()
{
while(dat1--)
{
DAT=1; //此IO口無法太快
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
DAT=0;
delay_short(5); //11.3us
}
delay_short(80); //80us 終止時間
DAT=1;
}
void write_com(uchar com) //寫命令
{
rs=0;
rw=0;
sendIO(); //發送IO口數據
dat1=com;
senddat(); //發送數據
lcde=1;
sendIO(); //發送IO口數據
lcde=0;
sendIO(); //發送IO口數據
}
void write_dat(uchar dat) //寫數據
{
rs=1;
rw=0;
sendIO(); //發送IO口數據
dat1=dat;
senddat(); //發送數據
lcde=1;
sendIO(); //發送IO口數據
lcde=0;
sendIO(); //發送IO口數據
}
void lcde_init()
{
led=0;
write_com(0x38); //設置顯示模式
write_com(0x0c); //開顯示且光標不顯示
write_com(0x06); //寫一字符指針加一
write_com(0x01); //清屏
delay_long(1);
c=1;
}
void display()
{
write_com(0x80);
for(count=0;count<16;count++)
{
write_dat(charset_1[count]);
}
write_com(0xc0);
for(count=0;count<16;count++)
{
write_dat(charset_2[count]);
}
delay_long(1000);
}
void main()
{
lcde_init(); //初始化LCDE
while(1)
{
display();
}
}
隨便畫個電路
IMG_20150216_215810.jpg (1.56 MB, 下載次數: 263)
下載附件
2015-2-16 22:00 上傳
|