yikuang 发表于 2011-12-31 18:53:44

贴上一个关于指针的例程,用1602演示,希望对初学者有帮助!

研究了两三天的指针,虽然研究的不是很深,但是我觉得能掌握一些平时常见常用的就不错了(这里是针对学单片机中常用到的指针),在这里希望对初学者有一点的帮助
    这个例程几乎能用指针的地方都用了,(其实我本人还不够理解使用指针的真正意义和目的,还不会真正灵活的去运用,所以在这里有些地方我是故意使用指针,可能存在多此一举吧!请大家勿笑话)都是用比较基础的知识;这里没有做理论性的讲解,不过代码注释应该比较通俗易懂了,主要是通过实践证明,用1602液晶演示实验效果
    不足、错误之处还望前辈们的批评指正!!!
/********************************************************************************************/
                                 1602头文件
/****************************************************************************************/
#ifndef _LCD_H_
#define _LCD_H_

#include<reg52.h>

#define LCD_DATA P0

sbit wela=P2^7;            //本人开发板的端口复用需要,与主程序无关
sbit dula=P2^6;                //本人开发板的端口复用需要,与主程序无关

sbit EN=P3^4;           //使能       1使能       0禁止
sbit RS=P3^5;           //数据与指令选择控制端       0写1读
sbit RW=P3^6;           //读写           0指令   1数据

void delay(unsigned int i);                //延时子函数

void LCD1602(void);           //保障正常开始

void read_busy(void);          //判忙子函数

void write_LCD(unsigned char value,bit i);           //写指令、数据子函数

void init_LCD(void);       //初始化

void display_byte(unsigned char y,unsigned char x,unsigned value);       //在任意位置显示一个字符

void display_test(unsigned char y,unsigned char x,unsigned char *value);        //在任意位置显示字符串

void display_define(unsigned char addr,unsigned char *x);//显示自定义字符

void disp_L_move(unsigned char mun,signed char *x);                  //整屏左移

#endif




/*********************************************************************************/
                                  1602 C文件
/*********************************************************************************/
#include "LCD1602.h"

void LCD1602(void)                  //保障正常开始
{
    EN=0;
    RS=1;
    RW=1;
    LCD_DATA=0xff;
}

void read_busy(void)                //读忙
{
    LCD_DATA = 0xff;
    RS=0;
    RW=1;
    EN=1;
    while(LCD_DATA&0x80);    //等待STA7位01禁止0允许
    EN=0;
}

void write_LCD(unsigned char value,bit i)                //i=0,写指令; i=1;写数据       
{
    read_busy();          //每次写都要判忙
    LCD_DATA=value;
    RS=i;
    RW=0;   //写
    EN=1;
    EN=0;
}

void init_LCD(void)
{
    delay(15000);
    write_LCD(0x38,0);
    delay(5000);
    write_LCD(0x38,0);
    delay(5000);
    write_LCD(0x38,0);               
    write_LCD(0x08,0);                   //写指令,显示关闭 00001000
    write_LCD(0x01,0);           //写指令,显示清屏00000001
    write_LCD(0x06,0);                   //写指令,显示光标移动设置 00000110
    write_LCD(0x0c,0);           //写指令,显示开及光标设置00001100
}

void display_byte(unsigned char y,unsigned char x,unsigned value)                //<2>
{
    y&=0x01;          //限制y的范围0/1
    x&=0x0f;          //限制x的范围0~15
    if(y)
    {
      x+=0x40;
    }
    x+=0x80;
    write_LCD(x,0);
    write_LCD(value,1);
}

void display_test(unsigned char y,unsigned char x,unsigned char *value)               //<3>           字符串
{
    y&=0x01;
    x&=0x0f;
    while(*value!='\0')          //判断是否到了最后一个字符
    {
      display_byte(y,x,*value++);           //*value++ 结合方向        自右而左 先取*value 再value+1
      x++;                                                 //显示地址加
    }
}
void display_define(unsigned char addr,unsigned char *x)                  //<4>   自定义字符          同上
{
    unsigned int i;
    write_LCD(0x40,0);          //每显示下一个自定义字符地址+8
    for(i=0;i<8;i++)
    {
      write_LCD(*(x+i),1);   //*(x+i) x为数组名(数组首地址),i是偏移量,即i为多少,则指针指向数组的第几个元素,然后再取其值
    }
    write_LCD(0x80,0);
    write_LCD(addr,1);          //addr的范围为0x00~0x07 只可以显示8个自定义字符使用时必须按顺序
}

void disp_L_move(unsigned char m,unsigned char *x)
{
   unsigned char i,j;
   write_LCD(0x80+0x10,0);
   for(i=0;*(x+i)!='\0';i++)          //判断是否到了最后一个字符
   {
         write_LCD(*(x+i),1);       //同<4>中的说明
         delay(1500);
   }

   for(j=0;j<m;j++)
   {
         write_LCD(0x18,0);                //整屏向左移
         delay(20000);
   }
}

void delay(unsigned int i)
{
   while(--i);
}

/**********************************************************************************************/
                                       主程序
/************************************************************************************************/
#include<reg52.h>
#include "LCD1602.h"

#define uint unsigned int
#define uchar unsigned char

uchar code table1={"Happy every day!"};                //这里表面16个字符,实际是17个(在内存中,字符串的最后被自动加了一个'\0')
uchar code table2={"love MCU!"};                //同上

uchar table4[]={0x01,0x03,0x1d,0x11,           //喇叭的图模
0x1d,0x03,0x01,0x00};

uchar tab_ASCII[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};

uchar tab1[]={0,1,2,3,4,5};

uchar *tab=tab_ASCII;

uchar max,min;

void delay_s(uint x)
{
        uint i,j;
        for(i=0;i<x;i++)
                for(j=0;j<110;j++);
}

void p_swap(uchar *p1,uchar *p2)    //交换地址
{
        uchar *p;
    p=p1;               
        p1=p2;
        p2=p;               
}

void swap(uchar *p1,uchar *p2)          //值交换          指针变量作函数参数
{
        uchar temp;
        temp=*p1;
        *p1=*p2;
        *p2=temp;
}

void inv(uchar x[],uchar n)                  //数组顺序交换        下标法
{
        uchar temp,i,j,m=(n-1)/2;          //位置指示变量i,j。i的初值为0,j初值为n-1

        for(i=0;i<=m;i++)                          //                                0        1        2        3        4        5
        {                                                          //                                |                |                        |
                j=n-1-i;                                  //                                i                m                        j
                temp=x;                                  //                                5        4        3        2        1        0
                x=x;                                  //
                x=temp;                                  //
        }
}
                                                                                           //                       tab1数组
void p_inv(uchar *x,uchar n)                                   //       i,x --->               
{                                                                                           //                   0
        uchar *p,temp,*i,*j,m=(n-1)/2;                          //                               
                                                                                          //                               1
        i=x;                                                                          //                               
        j=x+n-1;                                                                  ///                               2
        p=x+m;                                                                          //   p=x+m --->                       
        for(;i<=p;i++,j--)                                                  //                               3
        {                                                                               //
                temp=*i;                                                       //                                       4
                *i=*j;                                                               //               j       --->
                *j=temp;                                                       //                                       5
        }                                                                                //
}

void max_min_value(uchar array[],uchar n)           //从一组数组中求出最大值和最小值
{
        uchar *p,*array_end;
        array_end=array+n;
        max=min=*array;
        for(p=array+1;p<array_end;p++)
        if(*p>max)
                max=*p;
        else if(*p<min)
                min=*p;
}

void sawp_str(uchar *x)                               //字符串复制
{
        uchar str,*pd=str;

        for(;*x!='\0';x++,pd++)
                *pd=*x;
        *pd='\0';

        display_test(1,7,str);
}                                                               

void main()
{
        uchar i;

        uchar *p_1,*p_2,c=6,d=7;

        uchar *pointer_1,*pointer_2,a=4,b=5;

        p_1=&c;
        p_2=&d;

        pointer_1=&a;                          
        pointer_2=&b;

    wela=0;               //本人开发板的端口复用需要,与主程序无关
        dula=0;               //本人开发板的端口复用需要,与主程序无关

        LCD1602();
        init_LCD();

        disp_L_move(16,table1);
        delay_s(2000);
        write_LCD(0x01,0);           //写指令,显示清屏00000001

        write_LCD(0x80+0x40,0);                  
        write_LCD(*(tab_ASCII+5),1);          //显示字符方式1指针引用数组方式1

        display_byte(0,3,*(tab+13));        //显示字符方式2指针引用数组方式2
                                            
        display_test(1,2,table2);          //显示字符串   指针引用字符串

        display_define(0x00,table4);        //自定义字符   指针引用数组

        delay_s(2000);
        delay_s(2000);
       
        write_LCD(0x01,0);           //写指令,显示清屏00000001
/***********************************************************************************/       
        inv(tab1,6);                                                        //数组顺序交换        下标法        显示543210
/*        display_byte(1,0,*(tab+tab1));                   //下标法
        display_byte(1,1,*(tab+tab1));
        display_byte(1,2,*(tab+tab1));
        display_byte(1,3,*(tab+tab1));
        display_byte(1,4,*(tab+tab1));
        display_byte(1,5,*(tab+tab1)); */

        display_byte(0,0,*(tab+*tab1));                                //指针法
        display_byte(0,1,*(tab+*(tab1+1)));
        display_byte(0,2,*(tab+*(tab1+2)));
        display_byte(0,3,*(tab+*(tab1+3)));
        display_byte(0,4,*(tab+*(tab1+4)));
        display_byte(0,5,*(tab+*(tab1+5)));

       

        p_inv(tab1,6);                                                       //指针法   注意;这里显示012345 由于经过inv(tab1,6);数组tab1[]里已经变成543210
                                                                                       //经过这里再一次变换,又变回012345了
/*        display_byte(1,0,*(tab+tab1));                   //下标法
        display_byte(1,1,*(tab+tab1));
        display_byte(1,2,*(tab+tab1));
        display_byte(1,3,*(tab+tab1));
        display_byte(1,4,*(tab+tab1));
        display_byte(1,5,*(tab+tab1)); */

        display_byte(1,0,*(tab+*tab1));                                //指针法
        display_byte(1,1,*(tab+*(tab1+1)));
        display_byte(1,2,*(tab+*(tab1+2)));
        display_byte(1,3,*(tab+*(tab1+3)));
        display_byte(1,4,*(tab+*(tab1+4)));
        display_byte(1,5,*(tab+*(tab1+5)));

        max_min_value(tab1,6);                                          //从一组数组中求出最大值和最小值
        display_byte(0,7,*(tab+max));
        display_byte(0,9,*(tab+min));

        sawp_str(table2);
               
        delay_s(2000);
        delay_s(2000);
/****************************************************************************************/
        write_LCD(0x01,0);           //写指令,显示清屏00000001
        while(1)
        {       
/**************************************************************************/          
                if(c<d)                                                           //地址交换
                {
                        p_swap(p_1,p_2);
                        display_byte(0,0,*(tab+c));
                        display_byte(0,1,*(tab+d));       
                }
/****************************************************************************/
          if(a<b)                                                          //值交换
          {
                        swap(pointer_1,pointer_2);

                //        display_byte(0,2,tab_ASCALL);
                        display_byte(0,3,tab_ASCII);           //直接引用数组

                        display_byte(0,5,*(tab_ASCII+a));                //指针引用数组方式1
                        display_byte(0,6,*(tab+b));                           //指针引用数组方式2
          }
/******************************************************************************/               
                for(i=0;i<10;i++)                                                  
                {       
                        display_byte(0,8,*tab);
                        delay_s(1000);
                        tab++;       
                }
                tab-=1;               //指针指向了第11元素地址,减1回到第10位
                tab=tab_ASCII;       //注意这里,退出循环后,指针回到数组首地址
/*******************************************************************************/                                                                                 
        }
}

yikuang 发表于 2011-12-31 18:56:08

本来代码还写的蛮整齐的,贴上来就变了形。。。

highter 发表于 2012-1-1 08:17:20

谢谢,学习了。

yhy630 发表于 2012-1-1 15:20:04

好贴,支持

yikuang 发表于 2012-1-1 17:27:22

谁能说一下,在这个例程那个地方使用的的指针用的比较好一点,哪里用的多此一举的,谢谢!其实我还是不够了解怎样去运用它,让程序更加精炼、高效!期待高手解答!

yyt1372 发表于 2012-1-1 20:34:36

大家元旦快乐!我对指针理解没有深刻,常常写错……不知谁有什么办法一下子形象地记住指针的用法

zDFY 发表于 2012-1-1 22:09:47

这样的东西用附件上传,应该好些

371278638 发表于 2012-3-24 21:33:50

MARK!最近也在学习指针......

HeP028 发表于 2012-3-24 21:46:23

ID被删掉,郁闷重头再来吧!留名一个!
页: [1]
查看完整版本: 贴上一个关于指针的例程,用1602演示,希望对初学者有帮助!