搜索
bottom↓
回复: 8

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

[复制链接]

出0入0汤圆

发表于 2011-12-31 18:53:44 | 显示全部楼层 |阅读模式
研究了两三天的指针,虽然研究的不是很深,但是我觉得能掌握一些平时常见常用的就不错了(这里是针对学单片机中常用到的指针),在这里希望对初学者有一点的帮助
    这个例程几乎能用指针的地方都用了,(其实我本人还不够理解使用指针的真正意义和目的,还不会真正灵活的去运用,所以在这里有些地方我是故意使用指针,可能存在多此一举吧!请大家勿笑话)都是用比较基础的知识;这里没有做理论性的讲解,不过代码注释应该比较通俗易懂了,主要是通过实践证明,用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位0  1禁止  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[17]={"Happy every day!"};                //这里表面16个字符,实际是17个(在内存中,字符串的最后被自动加了一个'\0')
uchar code table2[12]={"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[j];                                  //
                x[j]=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[12],*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[0]));                   //下标法
        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])); */

        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[0]));                   //下标法
        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])); */

        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[a]);
                        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;         //注意这里,退出循环后,指针回到数组首地址
/*******************************************************************************/                                                                                   
        }
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2011-12-31 18:56:08 | 显示全部楼层
本来代码还写的蛮整齐的,贴上来就变了形。。。

出0入0汤圆

发表于 2012-1-1 08:17:20 | 显示全部楼层
谢谢,学习了。

出0入0汤圆

发表于 2012-1-1 15:20:04 | 显示全部楼层
好贴,支持

出0入0汤圆

 楼主| 发表于 2012-1-1 17:27:22 | 显示全部楼层
谁能说一下,在这个例程那个地方使用的的指针用的比较好一点,哪里用的多此一举的,谢谢!其实我还是不够了解怎样去运用它,让程序更加精炼、高效!期待高手解答!

出0入0汤圆

发表于 2012-1-1 20:34:36 | 显示全部楼层
大家元旦快乐!我对指针理解没有深刻,常常写错……不知谁有什么办法一下子形象地记住指针的用法

出0入0汤圆

发表于 2012-1-1 22:09:47 | 显示全部楼层
这样的东西用附件上传,应该好些

出0入0汤圆

发表于 2012-3-24 21:33:50 | 显示全部楼层
MARK!最近也在学习指针......

出0入0汤圆

发表于 2012-3-24 21:46:23 | 显示全部楼层
ID被删掉,郁闷重头再来吧!留名一个!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 02:30

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表