打印
[AVR单片机]

函数指针变量 疑问

[复制链接]
1158|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wdmhzh|  楼主 | 2014-2-12 16:00 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
用ICC7写了一个12864驱动函数,本想用函数指针变量调用函数来减小代码量,但实际代码量却由7%曾大到10%了,不知怎么回事,忘高手解惑??
#include<mytouwenjian.h>
#define ddr_com DDRC|=0X7E //控制口输出
#define RS_COM PORTC&=~bit(4)//命令
#define RS_DATE PORTC|=bit(4)
#define WR_R PORTC|=bit(5)//读
#define WR_W PORTC&=~bit(5)
#define E PORTC|=bit(6)//使能
#define E_N PORTC&=~bit(6)
#define PSB_B PORTC|=bit(1)//并口模式
#define PSB_C PORTC&=~bit(1)
#define RET PORTC&=~bit(3)//复位 低电平有效
#define RET_N PORTC|=bit(3)
#define ddr PORTA //数据口
#define ddr_r PINA //读引脚
#define ddr_in DDRA=0//数据口输入
#define ddr_out DDRA=0xff //数据口输出

void wrie_com12864(uchar com);//写指令
void wrie_date12864(uchar date);//写8位数据
void inlist12864();//初始化
void write_lianxu12864(uchar date[],uchar lenth);//连续写数据
uchar read_date12864( );//读8位数据
uchar read_mang12864( );//读忙
void huitu_dadian12864(uchar dress_x,uchar dress_y);//任意位置打点函数x(0--127) y(0--63)
void huitu_inlist12864();
void write_changfangxing(uchar start_x,uchar start_y,uchar lang,uchar waite);//画方形 16位起始位置 长和宽
void main()
{  
  uchar n,nn,mm,aa[]="任意打点",bb[]="Good";
  inlist12864();
  huitu_inlist12864();
  
  
  write_changfangxing(3,3,122,58);
  write_changfangxing(10,10,108,44);
  
  for(nn=0;nn<20;nn++) huitu_dadian12864(30+nn,30+nn);
  write_changfangxing(28,28,21,21);
  write_changfangxing(55,23,21,21);
  write_changfangxing(10,18,108,0);
  write_changfangxing(90,10,0,44);
  write_changfangxing(93,25,20,5);
  write_changfangxing(103,32,5,20);
   /*
      n=sizeof(aa)-1;//计算数组长度
  wrie_com12864(0x82);
  write_lianxu12864(aa,n);
   n=sizeof(bb)-1;//计算数组长度
  wrie_com12864(0x93);
  write_lianxu12864(bb,n);*/
  
}

void wrie_com12864(uchar com)//写指令
{
  while(read_mang12864( ));//读忙
  ddr_out;
  RS_COM;
  WR_W;
  E;
  ddr=com;
  yanshi_5us(1);
  E_N;
}
void wrie_date12864(uchar date)//写8位数据
{
  while(read_mang12864( ));//读忙
  ddr_out;
  RS_DATE;
  WR_W;
  E;
  ddr=date;
  yanshi_5us(1);
  E_N;
}
uchar read_date12864( )//读8位数据
{
  uchar date;
  while(read_mang12864( ));//读忙
  ddr_in;
  RS_DATE;
  WR_R;
  E_N;
  E;
  yanshi_5us(1);
  date=ddr_r;
  E_N;
  return date;
}
uchar read_mang12864( )//读忙
{
  uchar com;
  ddr_in;
  RS_COM;
  WR_R;
  E_N;
  E;
  yanshi_5us(1);
  com=ddr_r;
  E_N;
  com&=0x80;//返回0或者非0
  return com;
}
void inlist12864()//初始化
{
   
  yanshi_1ms(20);
  ddr_com;//控制口设置为输出
  RET;  //复位
  RET_N;
  PSB_B;//并口
  wrie_com12864(0x30);
  yanshi_1ms(10);
  wrie_com12864(0x30);
  yanshi_1ms(10);
  wrie_com12864(0x0c);//整体显示 不显示光标
  yanshi_1ms(10);
  wrie_com12864(0x01);//清屏
  yanshi_1ms(10);
  wrie_com12864(0x06);//光标右移
  yanshi_1ms(10);
}

void write_lianxu12864(uchar date[],uchar lenth)//连续写数据
{
uchar n;
for(n=0;n<lenth;n++)
    wrie_date12864(date[n]);
}
void huitu_inlist12864()
{
  uchar n,m;
  wrie_com12864(0x34);//绘图功能 显示关
  for(n=0;n<32;n++)
  {
    wrie_com12864(0x80+n);//先写Y轴地址
  wrie_com12864(0x80); //再写X轴地址(连续 前面不能有语句)显示数据写完后X轴地址自动加一
  for(m=0;m<16;m++)
  {
   wrie_date12864(0x00);
       wrie_date12864(0x00);
   }
  
  }
  wrie_com12864(0x36);//绘图功能 显示开
  wrie_com12864(0x32);//返回基本功能 显示开
}
void huitu_dadian12864(uchar dress_x,uchar dress_y)//任意位置打点函数
{
  uchar d_x,d_y,dat,dress_date_l,dress_date_h;
  wrie_com12864(0x34);//绘图功能 显示关
  
  /************************计算打点位置************************/
  if(dress_y<32)//判断上半屏
    {
    d_y=dress_y;  //判断dress_y在Y轴位置0--31
    if(dress_x<15) d_x=0;//判断dress_x在X轴位置
      else d_x=dress_x/16;  //X轴上半屏位置0--7
  }
  else   //判断下半屏
    {
    d_y=dress_y-32;
    if(dress_x<15) d_x=8;
      else d_x=dress_x/16+8;//X轴下半屏位置8--15
  }
  wrie_com12864(0x80+d_y);
  wrie_com12864(0x80+d_x);
  
  
/***********************计算打点数据************************/
  dat=dress_x%16;//得到点位置16位粗数据
  if(dat<8) //点在高字节
    {
     dat=bit(7-dat);//原dat为高位点 须倒位
   /* 处理数据实现打点时不对旁边位置数据有影响*/
   dress_date_h=read_date12864( );//假读
   dress_date_h=read_date12864( );//读当前位置数据
   dress_date_l=read_date12864( );//读当前位置数据
   dress_date_h=dat|dress_date_h;
   
     wrie_com12864(0x80+d_y);//读数据导致地址改变 须重新设置地址
         wrie_com12864(0x80+d_x);
     wrie_date12864(dress_date_h);  //先写高位再写低位
       wrie_date12864(dress_date_l);
  }
  else //点在低字节
    {
     dat=dat%8;
   dat=bit(7-dat);//倒位
   dress_date_h=read_date12864( );//假读
   dress_date_h=read_date12864( );//读当前位置数据  
   dress_date_l=read_date12864( );//读当前位置数据
     dress_date_l=dat|dress_date_l;
   
     wrie_com12864(0x80+d_y);
         wrie_com12864(0x80+d_x);
       wrie_date12864(dress_date_h);
   wrie_date12864(dress_date_l);
  }
  wrie_com12864(0x36);//绘图功能 显示开
  wrie_com12864(0x32);//返回基本功能 显示开
}
void write_changfangxing(uchar start_x,uchar start_y,uchar lang,uchar waite)//16位起始位置 长和宽
{
    uchar n;
    //huitu_dadian12864(start_x,start_y);//任意位置打点函数
  for(n=0;n<=lang;n++) huitu_dadian12864(start_x+n,start_y);//水平画线
  for(n=0;n<=lang;n++) huitu_dadian12864(start_x+n,start_y+waite);
  for(n=0;n<=waite;n++) huitu_dadian12864(start_x,start_y+n);//垂直画线
  for(n=0;n<=waite;n++) huitu_dadian12864(start_x+lang,start_y+n);
}



下面使用了函数指针变量来调用函数

#include<mytouwenjian.h>
#define ddr_com DDRC|=0X7E //控制口输出
#define RS_COM PORTC&=~bit(4)//命令
#define RS_DATE PORTC|=bit(4)
#define WR_R PORTC|=bit(5)//读
#define WR_W PORTC&=~bit(5)
#define E PORTC|=bit(6)//使能
#define E_N PORTC&=~bit(6)
#define PSB_B PORTC|=bit(1)//并口模式
#define PSB_C PORTC&=~bit(1)
#define RET PORTC&=~bit(3)//复位 低电平有效
#define RET_N PORTC|=bit(3)
#define ddr PORTA //数据口
#define ddr_r PINA //读引脚
#define ddr_in DDRA=0//数据口输入
#define ddr_out DDRA=0xff //数据口输出
void (*p_hanshu)(uchar);//定义全局函数指针变量
uchar (*pp_hanshu)();
void (*ppp_hanshu)(uchar,uchar);
void wrie_com12864(uchar com);//写指令
void wrie_date12864(uchar date);//写8位数据
void inlist12864();//初始化
void write_lianxu12864(uchar date[],uchar lenth);//连续写数据
uchar read_date12864( );//读8位数据
uchar read_mang12864( );//读忙
void huitu_dadian12864(uchar dress_x,uchar dress_y);//任意位置打点函数
void huitu_inlist12864();
void write_changfangxing(uchar start_x,uchar start_y,uchar lang,uchar waite);//16位起始位置 长和宽
void main()
{  
  uchar n,nn,mm,aa[]="任意打点",bb[]="Good";
  inlist12864();
  huitu_inlist12864();
  
  
  write_changfangxing(3,3,122,58);
  write_changfangxing(10,10,108,44);
  
  for(nn=0;nn<20;nn++) huitu_dadian12864(30+nn,30+nn);
  write_changfangxing(28,28,21,21);
  write_changfangxing(55,23,21,21);
  write_changfangxing(10,18,108,0);
  write_changfangxing(90,10,0,44);
  write_changfangxing(93,25,20,5);
  write_changfangxing(103,32,5,20);
   /*
      n=sizeof(aa)-1;//计算数组长度
  wrie_com12864(0x82);
  write_lianxu12864(aa,n);
   n=sizeof(bb)-1;//计算数组长度
  wrie_com12864(0x93);
  write_lianxu12864(bb,n);*/
  
}

void wrie_com12864(uchar com)//写指令
{
  pp_hanshu=read_mang12864;//将读忙函数地址给函数指针变量
  while(*pp_hanshu);//调用读忙函数
  ddr_out;
  RS_COM;
  WR_W;
  E;
  ddr=com;
  yanshi_5us(1);
  E_N;
}
void wrie_date12864(uchar date)//写8位数据
{
  pp_hanshu=read_mang12864;//将读忙函数地址给函数指针变量
  while(*pp_hanshu);//调用读忙函数
  ddr_out;
  RS_DATE;
  WR_W;
  E;
  ddr=date;
  yanshi_5us(1);
  E_N;
}
uchar read_date12864( )//读8位数据
{
  uchar date;
  pp_hanshu=read_mang12864;//将读忙函数地址给函数指针变量
  while(*pp_hanshu);//调用读忙函数
  ddr_in;
  RS_DATE;
  WR_R;
  E_N;
  E;
  yanshi_5us(1);
  date=ddr_r;
  E_N;
  return date;
}
uchar read_mang12864( )//读忙
{
  uchar com;
  ddr_in;
  RS_COM;
  WR_R;
  E_N;
  E;
  yanshi_5us(1);
  com=ddr_r;
  E_N;
  com&=0x80;//返回0或者非0
  return com;
}
void inlist12864()//初始化
{
   p_hanshu=wrie_com12864;
  yanshi_1ms(20);
  ddr_com;//控制口设置为输出
  RET;  //复位
  RET_N;
  PSB_B;//并口
  (*p_hanshu)(0x30);
  yanshi_1ms(10);
  (*p_hanshu)(0x30);
  yanshi_1ms(10);
  (*p_hanshu)(0x0c);//整体显示 不显示光标
  yanshi_1ms(10);
  (*p_hanshu)(0x01);//清屏
  yanshi_1ms(10);
  (*p_hanshu)(0x06);//光标右移
  yanshi_1ms(10);
}

void write_lianxu12864(uchar date[],uchar lenth)//连续写数据
{
uchar n;
p_hanshu=wrie_date12864;
for(n=0;n<lenth;n++)
    (*p_hanshu)(date[n]);
}
void huitu_inlist12864()
{
  uchar n,m;
  p_hanshu=wrie_com12864;
  (*p_hanshu)(0x34);//绘图功能 显示关
  for(n=0;n<32;n++)
  {
    p_hanshu=wrie_com12864;
    (*p_hanshu)(0x80+n);//先写Y轴地址
  (*p_hanshu)(0x80); //再写X轴地址(连续 前面不能有语句)显示数据写完后X轴地址自动加一
  for(m=0;m<16;m++)
  {
      p_hanshu=wrie_date12864;
   (*p_hanshu)(0x00);
       (*p_hanshu)(0x00);
   }
  
  }
  p_hanshu=wrie_com12864;
  (*p_hanshu)(0x36);//绘图功能 显示开
  (*p_hanshu)(0x32);//返回基本功能 显示开
}
void huitu_dadian12864(uchar dress_x,uchar dress_y)//任意位置打点函数
{
  uchar d_x,d_y,dat,dress_date_l,dress_date_h;
  p_hanshu=wrie_com12864;
  (*p_hanshu)(0x34);//绘图功能 显示关
  
  /************************计算打点位置************************/
  if(dress_y<32)//判断上半屏
    {
    d_y=dress_y;  //判断dress_y在Y轴位置0--31
    if(dress_x<15) d_x=0;//判断dress_x在X轴位置
      else d_x=dress_x/16;  //X轴上半屏位置0--7
  }
  else   //判断下半屏
    {
    d_y=dress_y-32;
    if(dress_x<15) d_x=8;
      else d_x=dress_x/16+8;//X轴下半屏位置8--15
  }
  (*p_hanshu)(0x80+d_y);
  (*p_hanshu)(0x80+d_x);
  
  
/***********************计算打点数据************************/
  dat=dress_x%16;//得到点位置16位粗数据
  if(dat<8) //点在高字节
    {
     pp_hanshu=read_date12864;
     dat=bit(7-dat);//原dat为高位点 须倒位
   dress_date_h=(*pp_hanshu)( );//假读
   dress_date_h=(*pp_hanshu)( );//读当前位置数据
   dress_date_l=(*pp_hanshu)( );//读当前位置数据
   dress_date_h=dat|dress_date_h;
     p_hanshu=wrie_com12864;
     (*p_hanshu)(0x80+d_y);//读数据导致地址改变 须重新设置地址
         (*p_hanshu)(0x80+d_x);
   p_hanshu=wrie_date12864;
     (*p_hanshu)(dress_date_h);  //先写高位再写低位
       (*p_hanshu)(dress_date_l);
  }
  else //点在低字节
    {
     dat=dat%8;
   dat=bit(7-dat);//倒位
   pp_hanshu=read_date12864;
   dress_date_h=(*pp_hanshu)( );//假读
   dress_date_h=(*pp_hanshu)( );//读当前位置数据
   dress_date_l=(*pp_hanshu)( );//读当前位置数据
     dress_date_l=dat|dress_date_l;
     p_hanshu=wrie_com12864;
     (*p_hanshu)(0x80+d_y);
         (*p_hanshu)(0x80+d_x);
   p_hanshu=wrie_date12864;
       (*p_hanshu)(dress_date_h);
   (*p_hanshu)(dress_date_l);
  }
  p_hanshu=wrie_com12864;
  (*p_hanshu)(0x36);//绘图功能 显示开
  (*p_hanshu)(0x32);//返回基本功能 显示开
}
void write_changfangxing(uchar start_x,uchar start_y,uchar lang,uchar waite)//16位起始位置 长和宽
{
    uchar n;
    //huitu_dadian12864(start_x,start_y);//任意位置打点函数
  ppp_hanshu=huitu_dadian12864;
  for(n=0;n<=lang;n++) (*ppp_hanshu)(start_x+n,start_y);//水平画线
  for(n=0;n<=lang;n++) (*ppp_hanshu)(start_x+n,start_y+waite);
  for(n=0;n<=waite;n++) (*ppp_hanshu)(start_x,start_y+n);//垂直画线
  for(n=0;n<=waite;n++) (*ppp_hanshu)(start_x+lang,start_y+n);
}


相关帖子

沙发
天命风流| | 2014-2-17 10:05 | 只看该作者
:)

使用特权

评论回复
板凳
qin552011373| | 2014-2-17 14:30 | 只看该作者
指针的话应该不会减小代码的大小,你用指针指向函数的入口地址,肯定会增大的

使用特权

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

本版积分规则

54

主题

130

帖子

2

粉丝