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;
}
我想请各位大虾帮忙看一下,问题出在什么地方?如何解决?