|
研究了两三天的指针,虽然研究的不是很深,但是我觉得能掌握一些平时常见常用的就不错了(这里是针对学单片机中常用到的指针),在这里希望对初学者有一点的帮助
这个例程几乎能用指针的地方都用了,(其实我本人还不够理解使用指针的真正意义和目的,还不会真正灵活的去运用,所以在这里有些地方我是故意使用指针,可能存在多此一举吧!请大家勿笑话)都是用比较基础的知识;这里没有做理论性的讲解,不过代码注释应该比较通俗易懂了,主要是通过实践证明,用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周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|