导航: 老古网老古论坛XMOS公共讨论区XMOS开源项目区单片机程序设计嵌入式系统广告区域
→C51编程:各位大虾,小弟发现一个奇怪的问题,我已无法解决,

* 1952: C51编程:各位大虾,小弟发现一个奇怪的问题,我已无法解决,想请各位大虾帮帮忙,进来看一下,点拨一二!

   东海飘萍客 
东海飘萍客发表的帖子 

 C51编程:各位大虾,小弟发现一个奇怪的问题,我已无法解决,想请各位大虾帮帮忙,进来看一下,点拨一二!
#include <reg51.h>
#include <intrins.h>
#include <string.h>
#define uchar unsigned char
#define uint  unsigned int
sbit     SDA=P1^5;sbit     SCL=P1^4;
sbit     p06=P0^6;sbit     p05=P0^5;
sbit     p04=P0^4;sbit     p03=P0^3;
sbit     p02=P0^2;sbit     p01=P0^1;
sbit     p00=P0^0;sbit     bell=P2^5;
sbit     led_yellow=P2^2;sbit     led_red=P2^1;
uchar    mode;
void delay(uint delay_time);           //延时delay_timeMS
void I_start(void);
void I_stop(void);
bit I_clock(void);
bit I_send(uchar I_data);
uchar I_receive(void);
void E_read_address(uchar Address,uchar *p,uchar R_size);
void E_write_address(uchar Address,uchar *p,uchar W_size);
void bellx(uchar bell_count);
void delay_us(uint delay_time);
bit  Input_Keyboard(uchar *p2);
uchar demand_keyboard();
uchar  scan_keyboard();     /*键盘扫描*/
void main(void)
{
bit temp;
uchar Ram_Key[8],Input_Key[8];
SCL=0;
I_stop();
delay(100);
E_read_address(0x01,Ram_Key,0x06);
    delay(100);
    led_red=0;
    led_yellow=1;
    delay(100);
    Input_Keyboard(Input_Key);
delay(100);
if(Input_Key[0]==0x30)  bellx(3);
else 
{
bellx(1);
led_red=0;
led_yellow=0;
}
delay(100);
temp=strncmp(Ram_Key,Input_Key,8);
if(temp==0)  bellx(3);
else 
{
bellx(1);
led_red=1;
led_yellow=1;
}
while(1);
}
/*键盘扫描子程序,返回值为0,代表没扫描到按键,返回值为1,正确。输入的密码放入
board_key[8]里,结束符为ox0x0c.*/
bit  Input_Keyboard(uchar *p2)
{
 uchar i,temp;
 bit   flag;
 uchar temp1[16];
 uchar *p1;
 p1=temp1;
 for(i=0;i<16;i++)
 
    {                                                                    
                                                                                
               
      *p1++=0;    
     }
 p1=temp1;      
 for(i=0;i<16;i++)
    {
     temp=demand_keyboard();
     switch(temp)
         {
          case 0: return 0;
          case 1:
          case 2:
          case 3:
          case 4:
          case 5:
          case 6:
          case 7:
          case 8:
          case 9: *p1++=temp;
                  break;
          case 10:flag=1;
               *p1=0x0c;
                 break;
          case 11:*p1++=0;        
                    break;
        case 12:p1--;
                  *p1=0;
                    break;
         }    
      if(flag)  break;
    } 

p1=temp1;
for(i=0;i<8;i++)
    {
     *p2=*p1++;
     *p2<<=4;
     *p2&=0xf0;
     *p2+=*p1++;
     p2++;
    }
bellx(2);
return 1;
}

uchar demand_keyboard( )
{
 uchar keyboard_key;
 uint  keyboard_count;
 for(keyboard_count=4000;keyboard_count>0;keyboard_count--)
    {
    keyboard_key=scan_keyboard();
     if(!(keyboard_key==0)) 
         {
         bellx(1);
        return keyboard_key;
      }
     delay(20);
    }
bellx(4);
led_red=0;
led_yellow=0;
return 0;     
}

uchar  scan_keyboard()     /*键盘扫描*/
{
uchar temp,i;
temp=0xfe;
for(i=0;i<4;i++)
    {
    P0=temp;
     if(!(P0==temp))
        {
         delay(5);
         if(!(P0==temp))
            {
            if(!p04)  return i*3+1; 
          if(!p05)  return i*3+2;
          if(!p06)  return i*3+3;
           }
        }
     temp<<=1;
     temp+=1; 
      }        
 return  0 ;
}

/*功能:提供I2C总线工作时序的起始位。*/
void I_start(void)
{
SCL=1;
_nop_();
_nop_();
_nop_();    
SDA=0;
_nop_();
_nop_();
_nop_();
SCL=0;
_nop_();
_nop_();
_nop_();
}

/*功能:提供I2C总线工作时序的停止位。*/
void I_stop(void)
{
SDA=0;
_nop_();
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
SDA=1;
_nop_();
_nop_();
_nop_();
SCL=0;
_nop_();
_nop_();
_nop_();    
}


/*功能:提供I2C总线的时钟信号,并返回在时钟电平位高期间SDA信号线
上状态。本函数可用于数据发送,也可用于数据接收*/
bit I_clock(void)
{
bit sample;
SCL=1;
_nop_();
_nop_();
_nop_();
sample=SDA;
SCL=0;
_nop_();
_nop_();
_nop_();
return(sample);    
}

/*功能:向I2C总线发送8位数据,并请求一个应答信号ACK。如果收到
ACK应答则返回1(TRUE),否则返回0(FALSE)。*/
bit I_send(uchar I_data)
{
register uchar i;
/*发送8位数据*/
for(i=0;i<8;i++)
    {
    SDA=(bit)(I_data&0x80);
    I_data=I_data<<1;
    I_clock();    
    }
SDA=1;
return (~I_clock());
}

/*功能:从I2C总线上接收8位数据信号,并将接收到8位数据作为一个字节
返回,不回送应答信号ACK。主函数在调用本函数之前应保证SDA信号线处于
浮置状态,即使8051的P1.7脚置1。*/
uchar I_receive(void)
{
uchar I_data=0;
register uchar i;
for(i=0;i<8;i++)
    {
    I_data*=2;
    if(I_clock())
        I_data++;
    }
return(I_data);    
}


/*功能:从24c01中读取data_size个字节的数据并存放到databuff里,采用序列读操作方式
从片
内ADDRESS地址处连续读取数据。如果24c01不接收指定的地址在返回0*/ 
void E_read_address(uchar Address,uchar *p,uchar R_size)
{
Address<<=1;
Address+=0x01;
I_start();
I_send(Address); 
for(;R_size>0;R_size--)
    {
   *p++=I_receive();
   SDA=0;
   I_clock();
   SDA=1;    
    }
I_clock();
I_stop();
return;

}


/*功能:将数据缓冲区databuff中的数据写入到24c01的以Address地址开始的data_size个
字节。
采用字节写操作方式,每次写入时都需要指定片内地址。如果24c01不接受指定的地址或某
个传送
的字节未收到应答信号ACK,在返回0(FALSE).*/
void E_write_address(uchar Address,uchar *p,uchar W_size)
{
Address<<=1;
for(;W_size>0;W_size--)
    {
   I_start();
   I_send(Address);
   I_send(*p++);
   I_stop();
    Address+=2;
   delay(20);
    }
return ;
}

void bellx(uchar bell_count)
{
uint count1;
do
    {
    for(count1=0x019b;count1>0;count1--)
          {
        bell=0;
        delay_us(55);
        bell=1;
        delay_us(55);
         }
    delay(80);
    bell_count--;
    }
while(bell_count);
return ;
}
void delay_us(uint delay_time)
{
for(;delay_time>0;delay_time--)
      {
     _nop_();
     _nop_();
    }

  return;
}
void delay(uint delay_time)           //延时delay_timeMS

delay_time*=50;
for(;delay_time>0;delay_time--)
      {
     _nop_();
    }
  return;
}
上面主要是一个24c01的读写函数和键盘的输入函数。上面的程序能够正常执行,但是如果
主函数中的E_read_address()函数读超过6个字节的内存,键盘函数工作就会不正常。如
果换成写的函数,又可以。如果把读24C01的函数改成下面这样,则无论读几个字节都不行
(所谓不行,是键盘函数不能正常工作)。注意:两个函数单独运行都完全正确。
void E_read_address(uchar Address,uchar *p,uchar R_size)
{
Address<<=1;
Address+=0x01;
I_start();
I_send(Address); 
for(;R_size>1;R_size--)
    {
   *p++=I_receive();
   SDA=0;
   I_clock();
   SDA=1;    
    }
*p=I_receive();
I_clock();
I_stop();
return;

}
我想请各位大虾帮忙看一下,问题出在什么地方?如何解决?

发表时间:2001年10月20日10:21:00

  
回复该帖

本主题共有 2 帖,分页:>>>>>该主题的所有内容[2]条

 *树形目录 只列出部分跟帖的标题以及简单的摘要信息 该主题的部分跟帖如下:

  1959.[详细]斑竹,能帮帮忙吗,我已经无计可施了!
摘要:......(无内容)
- [东海飘萍客][2232次] 2001年10月20日

[上一篇帖子]:补充说明:要对外面的电平进行判断!在判断的时候端口最好是高阻态!
[下一篇帖子]:我遇到过类似的问题!但是不敢保证和你的一样!请在初始化时SETB P1.2!千万不要CLR