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