打印

自制<<手把手教你学单片机C程序设计>>实验板

[复制链接]
楼主: gdqinci
手机看帖
扫描二维码
随时随地手机跟帖
161
gdqinci|  楼主 | 2010-6-17 11:24 | 只看该作者 回帖奖励 |倒序浏览
本帖最后由 gdqinci 于 2010-6-17 11:25 编辑

以下是第22章

在51 MCU DEMO试验板上实现16X2LCM演示程序1

#include <REG51.H>
#include <intrins.H>
#define uchar unsigned char
#define uint unsigned int
#define DataPort P0
sbit LCM_RS=P2^0;
sbit LCM_RW=P2^1;
sbit LCM_EN=P2^2;
uchar code str0[]={"-This is a LCD-!"};
uchar code str1[]={"-Design by ZXH-!"};
uchar code str2[]={"                "};
//--------------------------------------
void delay(uint k)
{
uint data i,j;
for(i=0;i<k;i++)
    {
  for(j=0;j<121;j++)
     {;}
}
}
//--------------------------------------
void WaitForEnable(void)
{
DataPort=0xff;
LCM_RS=0;
LCM_RW=1;_nop_();
LCM_EN=1;_nop_();_nop_();
while(DataPort&0x80);
LCM_EN=0;
}
//---------------------------------------
void WriteCommandLCM(uchar CMD,uchar Attribc)
{
if(Attribc)WaitForEnable();
LCM_RS=0;
LCM_RW=0;_nop_();
DataPort=CMD;_nop_();
LCM_EN=1;_nop_();_nop_();
LCM_EN=0;
}
//--------------------------------------------------
void WriteDataLCM(uchar dataW)
{
WaitForEnable();
LCM_RS=1;
LCM_RW=0;_nop_();
DataPort=dataW;_nop_();
LCM_EN=1;_nop_();_nop_();
LCM_EN=0;
}
//------------------------------------------------
void InitLcd()
{
WriteCommandLCM(0x38,1);
WriteCommandLCM(0x08,1);
WriteCommandLCM(0x01,1);
WriteCommandLCM(0x06,1);
WriteCommandLCM(0x0c,1);
}
//-----------------------------------------------
void DisplayOneChar(uchar X,uchar Y,uchar DData)
{
Y&=1;
X&=15;
if(Y)X|=0x40;
X|=0x80;
WriteCommandLCM(X,0);
WriteDataLCM(DData);
}
//--------------------------------------------------
void DisplayListChar(uchar X,uchar Y,uchar code *DData)
{
uchar ListLength=0;
Y&=0x1;
X&=0xF;
while(X<=15)
  {
  DisplayOneChar(X,Y,DData[ListLength]);
ListLength++;
X++;
  }
}
//--------------------------------------------------
void main(void)
{
char i,m;
delay(500);
InitLcd();
//-----------------
for(i=15;i>=0;i--)
{
WriteCommandLCM(0x01,1);
DisplayOneChar(i,0,0x20);
DisplayListChar(i,0,str0);
DisplayListChar(i,1,str1);
delay(200);
}
delay(2800);
//------------------------------------
for(i=0;i<16;i++)
{
WriteCommandLCM(0x01,1);
DisplayOneChar(i,0,0x20);
DisplayListChar(i,0,str0);
DisplayListChar(i,1,str1);
delay(200);
}
WriteCommandLCM(0x01,1);
delay(3000);
//-----------------------------------
for(i=0;i<10;i++)
{
WriteCommandLCM(0x01,1);
delay(500);
DisplayListChar(0,0,str0);
DisplayListChar(0,1,str1);
delay(500);
i++;
}
delay(3000);
//**************************************
while(1)
{
//**************************************
for(i=15;i>=0;i--)
{
WriteCommandLCM(0x01,1);
DisplayOneChar(i,0,0x20);
DisplayListChar(i,0,str0);
DisplayListChar(i,1,str1);
delay(200);
}
//---------------------------------
for(i=1;i<16;i++)
{
m=16-i;
WriteCommandLCM(0x01,1);
DisplayOneChar(0,0,0x20);
DisplayListChar(0,0,&str0);
DisplayListChar(0,1,&str1);
DisplayListChar(m,0,str2);
DisplayListChar(m,1,str2);
delay(200);
}
WriteCommandLCM(0x01,1);
delay(200);
}
}

使用特权

评论回复
162
gdqinci|  楼主 | 2010-6-17 11:26 | 只看该作者
在51 MCU DEMO试验板上实现16X2LCM演示程序2

#include <REG51.H>
#include <intrins.H>
#define uchar unsigned char
#define uint unsigned int
#define DataPort P0
sbit LCM_RS=P2^0;
sbit LCM_RW=P2^1;
sbit LCM_EN=P2^2;
uchar code exampl[]="ForAnExample www.hlelectron.com";
void Delay400ms(void);
void Delay5ms(void);
void WaitForEnable(void);
void WriteDataLCM(uchar data W);
void WriteCommandLCM(uchar CMD,uchar Attribc);
void InitLcd(void);
void Display(uchar dd);
void DisplayOneChar(uchar x,uchar y,uchar Wdata);
void ePutstr(uchar x,uchar y,uchar code *ptr);
//========================================
void main()
{
uchar temp;
Delay400ms();
InitLcd();
temp=32;
ePutstr(0,0,exampl);
Delay400ms();
Delay400ms();
Delay400ms();
Delay400ms();
Delay400ms();
Delay400ms();
Delay400ms();
Delay400ms();
while(1)
{
temp&=0x7f;
if(temp<32)temp=32;
Display(temp++);
Delay400ms();
}
}
//===================================
void InitLcd(void)
{
WriteCommandLCM(0x38,0);
Delay5ms();
WriteCommandLCM(0x38,0);
Delay5ms();
WriteCommandLCM(0x38,0);
Delay5ms();
WriteCommandLCM(0x38,1);
WriteCommandLCM(0x08,1);
WriteCommandLCM(0x01,1);
WriteCommandLCM(0x06,1);
WriteCommandLCM(0x0c,1);
}
//-----------------------------------------------
void Delay5ms(void)
{
uint i=5552;
while(i--);
}
//--------------------------------------------
void Delay400ms(void)
{
uchar i=5;
uint j;
while(i--)
{
j=7269;
while(j--);
}
}
//--------------------------------------------
void LocateXY(char posx,char posy)
{
uchar temp;
temp&=0x7f;
temp=posx&0x0f;
posy&=0x01;
if(posy)temp|=0x40;
temp|=0x80;
WriteCommandLCM(temp,0);
}
//-------------------------------------------------
void WaitForEnable(void)
{
DataPort=0xff;
LCM_RS=0;
LCM_RW=1;_nop_();
LCM_EN=1;_nop_();_nop_();
while(DataPort&0x80);
LCM_EN=0;
}
//---------------------------------------
void WriteDataLCM(uchar dataW)
{
WaitForEnable();
LCM_RS=1;
LCM_RW=0;_nop_();
DataPort=dataW;_nop_();
LCM_EN=1;_nop_();_nop_();
LCM_EN=0;
}
//------------------------------------------------
void WriteCommandLCM(uchar CMD,uchar Attribc)
{
if(Attribc)WaitForEnable();
LCM_RS=0;
LCM_RW=0;_nop_();
DataPort=CMD;_nop_();
LCM_EN=1;_nop_();_nop_();
LCM_EN=0;
}
//--------------------------------------------------
void Display(uchar dd)
{
uchar i;
for(i=0;i<16;i++)
  {
  DisplayOneChar(i,1,dd++);
dd&=0x7f;
if(dd<32)dd=32;
  }
}
//--------------------------------------------------
void DisplayOneChar(uchar x,uchar y,uchar Wdata)
{
LocateXY(x,y);
WriteDataLCM(Wdata);
}
//--------------------------------------------------
void ePutstr(uchar x,uchar y,uchar code *ptr)
{
uchar i,l=0;
while(ptr[l]>31){l++;}
for(i=0;i<l;i++)
   {
   DisplayOneChar(x++,y,ptr);
   if(x==16)
     {
     x=0;y^=1;
     }
   }
}

使用特权

评论回复
163
gdqinci|  楼主 | 2010-6-17 11:31 | 只看该作者
因为数码相机没带回公司,这几章的效果相片等待以后回老家再补上

另外对第22章的程序还没做详细分析,特别是对时序部分的操作,个人感觉C对

时序操作比汇编差,由于1602以前用汇编写过,所以在此只是想了解C对其操作

方式。

使用特权

评论回复
164
ytfyiu| | 2010-6-18 15:46 | 只看该作者
哎..谢谢了...
   我有学习板的,手工焊的。资源跟这个差不多。  
   我还以为是他错了呢。 不过这本书的汇编版地址没有+0X80。难道这也可以吗?
附件是我通过了防真的1602代码,和另外一本书上的防真。LZ有空就帮我试验下

code.rar

29.46 KB

使用特权

评论回复
165
gdqinci|  楼主 | 2010-6-21 08:50 | 只看该作者
本帖最后由 gdqinci 于 2010-6-21 08:55 编辑

不过这本书的汇编版地址没有+0X80。难道这也可以吗?
//=======================================

这本书没有汇编地址呀,1602的DDRAM是应该加80H的,这个是肯定的,数据手册就是这样规定的

我不想再去折腾你那个仿真了, 要不咱们来个贴子把1602和12864走一遍如何?

另外既然你有实物学习板为何不在实板上验证一下程序?那样不是更实在?

加我QQ,我给你发站内消息了

使用特权

评论回复
166
ytfyiu| | 2010-6-21 11:33 | 只看该作者
好啊,怎么走**
你写一篇硬件的,我写一篇防真的吗?

......我只是没有1602的屏.128*64倒是有一块

使用特权

评论回复
167
自然从容子| | 2010-7-4 20:36 | 只看该作者
刚刚注册,新手,看到这样的帖子很开心,觉得学到不少,谢谢楼主了

使用特权

评论回复
168
jljjie163| | 2010-7-4 22:02 | 只看该作者
呵呵 楼主辛苦了:handshake

使用特权

评论回复
169
autopccopy| | 2010-7-6 20:45 | 只看该作者
顶LZ, 自己做了一块板。我的板是买的,慢慢在学C程序中。。。 :)

使用特权

评论回复
170
c329372422| | 2010-7-6 22:06 | 只看该作者
对于像我这样的初学者来说这真是好帖 很详细 这阵正好学单片机 看了lz的帖子真是收获不少啊

使用特权

评论回复
171
gdqinci|  楼主 | 2010-7-7 09:03 | 只看该作者
谢谢兄弟们的支持

使用特权

评论回复
172
gdqinci|  楼主 | 2010-7-7 11:08 | 只看该作者
对原书中1602实验一的程序算法很不爽,于是今天以原书中实验一的要求用汇编重写了一次

RS EQU P2.0
RW EQU P2.1
E EQU P2.2
DataPort EQU P0
;================
ORG 0000H
AJMP START
ORG 0030H
START:
MOV SP,#30H;30H--4FH做堆栈
;===================
MAIN:
LCALL CHECK_BF
MOV DataPort,#00000001B;清屏
ACALL WRITE_CMD
MOV DataPort,#00111000B;8总线2行5X7点阵
ACALL WRITE_CMD
MOV DataPort,#00001111B;显示开,光标开,光标闪烁开
ACALL WRITE_CMD
MOV DataPort,#00000110B;写入数据后AC加1光标加1(向右移)写入数据后光标移动而屏幕不移动
ACALL WRITE_CMD
;==================将两行数据分别写入DDRAM的10H和50H,调用之前先给50H和60H赋值==============================
MOV 50H,#90H
MOV 60H,#0D0H
LCALL WRITE_TWOline
;====================左右滚动屏幕=======================
MOV R1,#16
MOV R2,#00011000B
LCALL MOV_LR
;--------------------
LCALL DELAY_520mS
LCALL DELAY_520mS
;--------------------
MOV R1,#16
MOV R2,#00011100B
LCALL MOV_LR
;--------------------
;==================将两行数据分别写入DDRAM的00H和40H,调用之前先给50H和60H赋值==============================
MOV 50H,#80H
MOV 60H,#0C0H
LCALL WRITE_TWOline
LCALL DELAY_520mS
MOV R3,#5
SANSUO:;======================闪烁==================
MOV DataPort,#00001011B;显示关,光标开,光标闪烁开
ACALL WRITE_CMD
LCALL DELAY_520mS
MOV DataPort,#00001111B;显示开,光标开,光标闪烁开
ACALL WRITE_CMD
LCALL DELAY_520mS
DJNZ R3,SANSUO
;=========================================
MOV DataPort,#00000001B;清屏
ACALL WRITE_CMD
;==================将两行数据分别写入DDRAM的10H和50H,调用之前先给50H和60H赋值==============================
MOV 50H,#90H
MOV 60H,#0D0H
LCALL WRITE_TWOline
;====================左右滚动屏幕=======================
LOOP1:
MOV R1,#32
MOV R2,#00011000B
LCALL MOV_LR
;--------------------光标和屏滚归位-----------------
MOV DataPort,#00000010B
LCALL WRITE_CMD
LJMP LOOP1
;===================以下子程序=============================
;--------;查BF(读指令)-----------
CHECK_BF:
MOV DataPort,#0FFH
CLR RS
SETB RW
SETB E
JB DataPort.7,CHECK_BF
RET
;---------;写指令----------------
WRITE_CMD:
SETB E
CLR RS
CLR RW
CLR E
ACALL CHECK_BF
RET
;---------;读数据----------------
READ_DATA:
SETB RS
SETB RW
SETB E
RET
;----------;写数据---------------
WRITE_DATA:
SETB E
SETB RS
CLR RW
CLR E
ACALL CHECK_BF
RET
;==============写两行数据DDRAM地址放在50H和60H中===========
WRITE_TWOline:
MOV DataPort,50H;第一行起始字符DDRAM地址
LCALL WRITE_CMD
MOV DPTR,#TAB1;第一行显示字符表头地址
LCALL DISPLAY;显示第一行数据
;-------------------------------------------
MOV DataPort,60H;第二行起始字符DDRAM地址
LCALL WRITE_CMD
MOV DPTR,#TAB2;第二行显示字符表头地址
LCALL DISPLAY;显示第二行数据
RET
;===============连续写多个字符到DDRAM中==============
DISPLAY:MOV R1,#16;准备显示一行16个字符
DISPLAY1:CLR A;将ACC清零
MOVC A,@A+DPTR;查表取得要显示的数据
MOV DataPort,A
LCALL WRITE_DATA;写入一个数据
INC DPTR;数据表指针加1,准备取下一个数据
DJNZ R1,DISPLAY1;一行没有显示完就继续
RET
;=====================滚动屏幕,滚动多少格存在R1,滚动方向存在R2=====================
MOV_LR:
MOV DataPort,R2
ACALL WRITE_CMD
LCALL DELAY_520mS
DJNZ R1,MOV_LR
RET
;----------------------------------
DELAY_520mS:
MOV R7,#255
DA1:
MOV R6,#255
DA2:
MOV R5,#3
DA3:
DJNZ R5,DA3
DJNZ R6,DA2
DJNZ R7,DA1
RET
;================================================
TAB1:DB "-This is a LCD-!"
TAB2:DB "-Design by ZXH-!"
END

使用特权

评论回复
173
gdqinci|  楼主 | 2010-7-7 11:10 | 只看该作者
等一下我将上面的汇编用C再来写一次

使用特权

评论回复
174
lovemcu1987| | 2010-7-7 11:44 | 只看该作者
强:)

使用特权

评论回复
175
gdqinci|  楼主 | 2010-7-14 08:52 | 只看该作者
因为对书中的程序很不满意,所以自己又把它C了一遍。
由于自己对C还不是很熟悉,在重写过程中遇到了两个问题,已经另外发帖向大家请教了,在此感谢帮助我解决问题的前辈们。



#include <REG51.H>
#include <intrins.H>
#define uchar unsigned char
#define uint unsigned int
#define DataPort P0
sbit RS=P2^0;
sbit RW=P2^1;
sbit E=P2^2;
uchar code str0[]={"-This is a LCD-!"};
uchar code str1[]={"-Design by ZXH-!"};
//--------------------------------------
void delay(uint k);
//-----查BF(读指令)------------------
void CHECK_BF(void)
{
DataPort=0xff;
RS=0;
RW=1;
E=1;
while(DataPort&0x80);
}
//-------写指令------------------------
void WRITE_CMD(uchar CMD)
{
DataPort=CMD;
E=1;
RS=0;
RW=0;
E=0;
CHECK_BF();
}
//-------读数据----------------
uchar READ_DATA(void)
{
uchar RE_DATA;
RS=1;
RW=1;
E=1;
return RE_DATA;
}
//-------写数据-------------------------
void WRITE_DATA(uchar DATA1)
{
DataPort=DATA1;
E=1;
RS=1;
RW=0;
E=0;
CHECK_BF();
}
//==============================================================================================
//--------连续显示多个数据,DDRAM地址坐标放在X、Y中,确定显示位置并写入显示数据-----------------
void WRITE_TWOline(uchar X,uchar Y,uchar count)
{
uchar i;
switch(Y)
      {
    case 1:X|=0x80;
     WRITE_CMD(X);//调用写指令确定DDRAM地址
              for(i=0;i<=count;i++)
               {
                   WRITE_DATA(str0[i]);
                }
     break;
       case 2:
           X=(X+0x40)|0x80;
     WRITE_CMD(X);//调用写指令确定DDRAM地址
              for(i=0;i<=count;i++)
              {
                  WRITE_DATA(str1[i]);
              }
              break;
    default:break;
     }
}
//==============滚动屏幕,滚动多少格存在Place,滚动方向存在Direction==========
void MOV_char(uchar Direction,uchar Place)
{
  while(Place>0)
    {
  WRITE_CMD(Direction);
  delay(520);
  Place--;
  }
}
//================延时KmS=============
void delay(uint k)
{
uint data i,j;
for(i=0;i<k;i++)
    {
  for(j=0;j<121;j++)
     {;}
}
}
//=====================================
//************************************************************************************************
void main()
{
uchar sansuo=4;
//--------------------初始化--------------------
CHECK_BF();
WRITE_CMD(0x01);
WRITE_CMD(0x38);
WRITE_CMD(0x0F);
WRITE_CMD(0x06);
//---------------------------写入两行并左右滚动--------------
WRITE_TWOline(16,1,15);
WRITE_TWOline(16,2,15);
MOV_char(0x18,16);
delay(1000);
MOV_char(0x1c,16);
//-------------------------闪烁5--------------------------
WRITE_TWOline(0,1,15);
WRITE_TWOline(0,2,15);
delay(1000);
while(sansuo>0)
     {
   WRITE_CMD(0x0b);
   delay(1000);
   WRITE_CMD(0x0f);
   delay(1000);
   sansuo--;
   }
//===================清屏=============================
WRITE_CMD(0x01);
//====================================================
WRITE_TWOline(16,1,15);
WRITE_TWOline(16,2,15);
while(1)
     {
   MOV_char(0x18,32);
      delay(10);
   WRITE_CMD(0x02);
   delay(520);
  }
}
//************************************

使用特权

评论回复
176
hotpower| | 2010-7-14 08:55 | 只看该作者
哈哈~~~匠人是书托~~~

大家赞成的跟菜农起哄~~~

使用特权

评论回复
177
gdqinci|  楼主 | 2010-7-14 09:02 | 只看该作者
哈哈~~~菜农,你打错一个字了

应该是:
//========================

哈哈~~~这人是书托~~~

大家赞成的跟菜农起哄~~~
//========================

你把“这”字打成“匠”

结果变成匠人是书托了

可怜的匠人

不知道我猜得对不对?

☆⌒_⌒☆

使用特权

评论回复
178
李冬发| | 2010-7-14 09:05 | 只看该作者
就是匠人是书托!
;P

使用特权

评论回复
179
gdqinci|  楼主 | 2010-7-14 09:07 | 只看该作者
照逻辑来推的话应该是说我是书托才对啊

使用特权

评论回复
180
程序匠人| | 2010-7-14 10:01 | 只看该作者
匠人很愿意当书托。

书托是一项很高尚的职业。

如果身边有更多的朋友写书,匠人愿意为他们奔走呼叫,大力推荐。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则