这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 综合技术 » 基础知识 » 430,IIC 请教冲大侠等430的朋友们?模拟IIC程序问题?

共2条 1/1 1 跳转至

430,IIC 请教冲大侠等430的朋友们?模拟IIC程序问题?

院士
2006-09-17 18:14:16     打赏
430,IIC 请教冲大侠等430的朋友们?模拟IIC程序问题?



关键词: 请教     大侠     朋友们     模拟     程序     问题    

院士
2006-12-22 22:43:00     打赏
2楼
问 以下是我编的程序---用P47(SDA)P46(SCL)模拟IIC总线,SDA SCL已接上拉电阻,目的:将努num的16个数写到eeprom:24lc01中,然后将2401中的16个数再读到num1

??? 单独写读一个数,没问题;写读两个以上就不对了,请朋友们帮帮忙,小虾在此谢过!
#include <in430.h>
#include <msp430x44x.h>
#define ERRORCOUNT 10
unsigned char num[16]={88,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
unsigned char num1[16];
unsigned char CY;
void IICStart(void);
void IICStop(void);
void delay(void);
void IICAck(void);
void IICNoAck(void);
unsigned char IICRecAck(void);
void IICSendByte(unsigned char sendbyte);
unsigned char IICReceiveByte(void);
void Read_word(unsigned int Address,
unsigned char ControlByte,unsigned char j);
void Write_word(unsigned int Address,
unsigned char ControlByte,unsigned char j);

void delay(void)
{
_NOP();
_NOP();
_NOP();
_NOP();

}
void IICStart(void)
{
P4DIR|=0Xc0;//SDA=SCL=0占用总线
P4OUT&=0X3F;
P4DIR&=0X7F;//SDA=1
delay();
P4DIR&=0XBF;//SCL=1
delay();
P4DIR|=0X80;//SDA=0(前面P4OUT&=0X3F;)
delay();
P4DIR|=0X40;//SCL=0关掉时钟线
delay();
}
void IICStop(void)//出现一个SCL高SDA由低到高的脉冲
{

P4DIR|=0Xc0;//原为0x80
P4OUT&=0X3f;//HOUJIA
P4DIR|=0X80;//SDA=0
delay();
P4DIR&=0XBF;//SCL=1
delay();
P4DIR&=0X7F;//SDA=1
delay();
P4DIR|=0X80;
delay();
P4DIR|=0X40;
delay();
}
void IICAck(void)//对IIC总线产生应答
{

P4DIR|=0Xc0;//SDA=SCL=0占用总线
P4OUT&=0X3F;

P4DIR|=0X80;//SDA=0
delay();
P4DIR&=0XBF;//SCL=1;
delay();
P4DIR|=0X40;//SCL=0
delay();
P4DIR&=0X7F;//SDA=1
delay();
}
void IICNoAck(void)//不对IIC总线产生应答
{

P4DIR|=0Xc0;//SDA=SCL=0占用总线
P4OUT&=0X3F;

P4DIR&=0X7F;//SDA=1
delay();
P4DIR&=0XBF;//SCL=1;
delay();
P4DIR|=0X40;
delay();
P4DIR|=0X80;
delay();
}
unsigned char IICRecAck(void)//返回1无应答
{
P4DIR|=0X40;
P4OUT&=0XBF; //SCL=0
P4DIR&=0X7F;//SDA=1
P4DIR&=0XBF;//SCL=1
delay();
if((P4IN&0X80)==0x80) CY=1;
else CY=0; //因为返回值总是放在CY中的
P4DIR|=0X40;//SCL=0
return(CY);
}


void IICSendByte(unsigned char sendbyte)
{
unsigned char j;

P4DIR|=0Xc0;//SDA=SCL=0占用总线
P4OUT&=0X3F;
for(j=0;j<8;j++)//,高位再先
{
if((sendbyte&0x80)==0x80)//WR1
{

P4DIR&=0X7F;//SDA=1
delay();
P4DIR&=0XBF;//SCL=1//通知eeprom接收数据,SCL由高到底
delay();
delay();
P4DIR|=0X40;//SCL=0
delay();
}
else //wr0
{

P4DIR|=0X80;//SDA=0
delay();
P4DIR&=0XBF;//SCL=1
delay();
delay();
P4DIR|=0X40;//SCL=0
delay();
}

sendbyte<<=1;
}

}

unsigned char IICReceiveByte(void)
{
unsigned char receivebyte=0;
unsigned char data=0;
unsigned char i;

P4DIR|=0Xc0;//SDA=SCL=0占用总线
P4OUT&=0X3F;
for(i=0;i<8;i++)// 波形图中SCL由低到高接受
{
P4DIR&=0X7F;//SDA=1 释放总线
delay();
P4DIR|=0X40;//SCL=0;
delay();
delay();
P4DIR&=0XBF;//houjia SCL=1
delay();
if((P4IN&0X80)==0x80) receivebyte=1;
else receivebyte=0;
delay();
data=(data<<1)|receivebyte;
}
return(data);
}

void Write_word(unsigned int Address,
unsigned char ControlByte,unsigned char j)
{

unsigned char i,l,m;
unsigned char errorflag=1;

for(i=0;i<ERRORCOUNT;i++)
{
IICStart();
IICSendByte(ControlByte&0xfe);//发送控制字
if(IICRecAck()) continue;
IICSendByte((unsigned char)Address);//发送地字节地址
if(IICRecAck()) continue;

for(l=0;l<j;l++)
{
IICSendByte(num[l]);
for(m=0;m<ERRORCOUNT;m++)
{

if(IICRecAck()) continue;
else m=ERRORCOUNT-1;
}
}
}
IICStop();
}

void Read_word(unsigned int Address,
unsigned char ControlByte,unsigned char j)
{

unsigned char i,l,add;
add=0;
for(i=0;i<ERRORCOUNT;i++)
{
IICStart();
IICSendByte(ControlByte&0xfe);//发送控制字
if(IICRecAck()) continue;
IICSendByte((unsigned char)Address);//发送地字节地址
if(IICRecAck()) continue;

IICStart();
IICSendByte(ControlByte);
if(IICRecAck()) continue;
for(l=0;l<j-1;l++)
{
num1[l]=IICReceiveByte();
IICAck();

}

num1[j-1]=IICReceiveByte();
IICNoAck();
break;


}
IICStop();
}
void main(void)
{
unsigned char time=0;
unsigned int i;
WDTCTL = WDTPW + WDTHOLD;

P6SEL&=0X7F;
P4SEL&=0X3F;
P4DIR|=0Xc0;
P4OUT&=0X3f; // ;要发送数据个数为15个
do
{


if(!time)
{
Write_word(0xf0,0xa0,16);
for(i=0;i<1000;i++);
Read_word(0xf0,0xa1,16);
time=1;
}
}
while(1);
} 1: 我以前发过一个贴子,上面有I2C的程序,你可以参考一下,就这样把一个大程序贴上来让别人看。恐怕没有人有那么多时间闲着给你看錒! 2: 在连续写程序和读程序之间加上几个毫秒的延时 3: 连续读出时,是需要加延时的。同意楼上的看法 4: 连续读应该不要延时吧!
循环"连续写"要加延时 5: 注意第一次操作完后的端口设置回原状态。 6: 我用的是24C32,P3.3(SDA),P3.4(SCL),开始不行,后来参考了你的程序,经测试连续写(page write)没问题.程序如下:
void start_i2c(void)
{
P3DIR |= 0x18;
P3OUT &= 0xe7; //SDA=SCL=LOW,10us
P3DIR &= 0xf7; //SDA=HIGH
P3DIR &= 0xef; //SCL=HIGH
P3DIR |= 0x08; //SDA=LOW
P3DIR |= 0x10; //SCL=LOW
}

void stop_i2c(void)
{
P3DIR |= 0x18;
P3OUT &= 0xe7; //SDA=SCL=LOW
P3DIR |= 0x08; //SDA=LOW
P3DIR &= 0xef; //SCL=HIGH
P3DIR &= 0xf7; //SDA=HIGH
P3DIR |= 0x18; //SCL=SDA=LOW
}

BOOL receive_ack(void)
{
BOOL flag = FALSE;

P3DIR |= 0x10;
P3OUT &= 0xef; //SCL=LOW
P3DIR &= 0xf7; //SDA=HIGH
P3DIR &= 0xef; //SCL=HIGH

if ((P3IN & 0x08) == 0x08)
{
flag = TRUE;
}

P3DIR |= 0x10;

return flag;
}

void send_i2c(ABYTE i_data)
{
ABYTE i;

P3DIR |= 0x18;
P3OUT &= 0xe7; //SDA=SCL=LOW

for (i=0;i<8;i++)
{
if((i_data & 0x80) == 0x80)
{
P3DIR &= 0xf7;
}
else
{
P3DIR |= 0x08;
}

P3DIR &= 0xef; //SCL=HIGH
P3DIR |= 0x10; //SLC=LOW

i_data <<= 1;
}
}

ABYTE receive_i2c(void)
{
ABYTE i=0;
ABYTE out_data=0;

P3DIR |= 0x18;
P3OUT &= 0xe7; //SDA=SCL=LOW

for (i=0;i<8;i++)
{
out_data <<= 1;
P3DIR &= 0xf7;

P3DIR |= 0x10; //SCL=LOW
P3DIR &= 0xef;

if ((P3IN & 0x08) == 0x08)
{
out_data++;
}
}

return out_data;
}

BOOL write_address(AWORD address)
{
start_i2c();
send_i2c(WRITE);

if (receive_ack() == TRUE)
{
return FALSE;
}
else
{
send_i2c(MSB(address));
if (receive_ack() == TRUE)
{
return FALSE;
}
else
{
send_i2c(LSB(address));
if (receive_ack() == TRUE)
{
return FALSE;
}
else
{
return TRUE;
}
}
}
}

BOOL byte_write(AWORD address,ABYTE user_data)
{
BOOL flag=FALSE;

if (write_address(address) == TRUE)
{
send_i2c(user_data);
if (receive_ack() == FALSE)
{
flag = TRUE;
}
}

stop_i2c();

return flag;
}

ABYTE random_read(AWORD address)
{
ABYTE data_receive=0x00;

if (write_address(address) == TRUE)
{
start_i2c();
send_i2c(READ);

if (receive_ack() == FALSE)
{
data_receive = receive_i2c();

if (receive_ack() == FALSE)
{
data_receive = 0x00;
}
}
}

stop_i2c();

return data_receive;
}

BOOL page_write(AWORD address,ABYTE *data_buf,ABYTE data_length)
{
ABYTE i=0;
ABYTE write_flag = TRUE;

if (write_address(address) == TRUE)
{
do
{
send_i2c(*(data_buf + i));
if (receive_ack() == TRUE)
{
stop_i2c();
write_flag = FALSE;
return write_flag;
}
}while(write_flag && (++i != data_length));
}
else
{
write_flag = FALSE;
}

stop_i2c();

return write_flag;
} 7: 想问一下,改变方向寄存器的值,例如上面的P3DIR |= 0x08; //SDA=LOW 是改变与SDA接的那个引脚为输出模式,那么就等于给SDA一个低电平了吗?这个语句和P3OUT &=0xf7;在
P3.3位输出模式时,有什么不同吗?
谢谢! 8: 一样的.当设置好P3OUT &= 0xf7后,P3OUT的值就不会因为P3DIR的改变而改变.所以只要P3.3是输出模式时,就会输出低电平.

共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]