关于IIC通信的问题,大牛来指点一下!

pcf00 2008-10-14 06:02:34
目前我用430的硬件IIC通信,采用主发送、从接收方式,就是一个单片机先采用主机方式发送数据,完后处于从接收模式;另一个单片机也如此,不知道这个方法有没有什么问题?
目前遇到的问题是:主发送一次后变为从方式,从接收后变为主方式返回数据,能够发送正确一次,返回数据错误!

大牛们看看问题出在那里?
...全文
222 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
pcf00 2008-10-17
  • 打赏
  • 举报
回复
代码如下,大牛们看看:主从机配置代码一样,只是命令码不同

#include"msp430x16x.h"

#pragma vector=USART0TX_VECTOR
__interrupt void I2C_ISR(void);

void IIC_senddat(unsigned char S_count,unsigned char *D);
void delay(unsigned int num);
void intIIC(void);

unsigned char TXdata[10]={0x42,0x50,};//0x0a};
char l=0;
void main(void)
{
WDTCTL=WDTPW+WDTHOLD;
P5DIR|=BIT0; // test_led
P5OUT&=~BIT0;
intIIC();
_EINT();
P5OUT|=BIT0;
delay(50);
P5OUT&=~BIT0;
TXdata[2]=0x81;
while(1)
{
if(TXdata[2]==0x81)
{
TXdata[2]=0x0a;
IIC_senddat(3,TXdata);
P5OUT^=BIT0;

delay(200);
intIIC();
}
}
}
#pragma vector=USART0TX_VECTOR
__interrupt void I2C_ISR(void)
{
switch(I2CIV)
{
case 6:_NOP();
break;
case 10 :// 接收
TXdata[l]=I2CDRB;
l++;
if(l>2)l=0;
break;
case 12 :// 发送
I2CDRB=TXdata[l];
l++;
if(l>9)l=0;
break;
default:break;
}
}
// IIC发送数据
void IIC_senddat(unsigned char S_count,unsigned char *D)
{
I2CNDAT=S_count;
U0CTL|=MST;
I2CSA=0X0048; // 主机发送目标地址:从地址
I2CTCTL |= I2CSTT+I2CTRX+ I2CSTP; // Initiate transfer - write to slave
while((I2CIFG & NACKIFG) == 0x02);

for(char k=0;k<S_count;k++)
{
while ((I2CIFG & TXRDYIFG) == 0);
I2CDRB=TXdata[k];
}
while ((I2CTCTL & I2CSTP) == 0x02); // Wait for Stop Condition
delay(50);
I2CTCTL &= ~I2CTRX;
}
void delay(unsigned int num)
{
unsigned char i;
unsigned int l;
for(l=0;l<num;l++)
for(i=0;i<200;i++);
}
void intIIC(void)
{
delay(50);
U0CTL=0;
U0CTL |= SWRST; // Reset USART state machine
U0CTL &= ~CHAR;
I2CIE&=~RXRDYIE;
I2CIFG=0;
P3SEL|=0X0A;
U0CTL|=I2C+SYNC;
U0CTL&=~I2CEN;
I2CTCTL|=I2CSSEL1;
I2COA=0X0050; // 本机地址
I2CIE|=RXRDYIE+OAIFG;
U0CTL|=I2CEN;
delay(50);
}
pcf00 2008-10-17
  • 打赏
  • 举报
回复
代码如下,大牛们看看:主从机配置代码一样,只是命令码不同

#include"msp430x16x.h"

#pragma vector=USART0TX_VECTOR
__interrupt void I2C_ISR(void);

void IIC_senddat(unsigned char S_count,unsigned char *D);
void delay(unsigned int num);
void intIIC(void);

unsigned char TXdata[10]={0x42,0x50,};//0x0a};
char l=0;
void main(void)
{
WDTCTL=WDTPW+WDTHOLD;
P5DIR|=BIT0; // test_led
P5OUT&=~BIT0;
intIIC();
_EINT();
P5OUT|=BIT0;
delay(50);
P5OUT&=~BIT0;
TXdata[2]=0x81;
while(1)
{
if(TXdata[2]==0x81)
{
TXdata[2]=0x0a;
IIC_senddat(3,TXdata);
P5OUT^=BIT0;

delay(200);
intIIC();
}
}
}
#pragma vector=USART0TX_VECTOR
__interrupt void I2C_ISR(void)
{
switch(I2CIV)
{
case 6:_NOP();
break;
case 10 :// 接收
TXdata[l]=I2CDRB;
l++;
if(l>2)l=0;
break;
case 12 :// 发送
I2CDRB=TXdata[l];
l++;
if(l>9)l=0;
break;
default:break;
}
}
// IIC发送数据
void IIC_senddat(unsigned char S_count,unsigned char *D)
{
I2CNDAT=S_count;
U0CTL|=MST;
I2CSA=0X0048; // 主机发送目标地址:从地址
I2CTCTL |= I2CSTT+I2CTRX+ I2CSTP; // Initiate transfer - write to slave
while((I2CIFG & NACKIFG) == 0x02);

for(char k=0;k<S_count;k++)
{
while ((I2CIFG & TXRDYIFG) == 0);
I2CDRB=TXdata[k];
}
while ((I2CTCTL & I2CSTP) == 0x02); // Wait for Stop Condition
delay(50);
I2CTCTL &= ~I2CTRX;
}
void delay(unsigned int num)
{
unsigned char i;
unsigned int l;
for(l=0;l<num;l++)
for(i=0;i<200;i++);
}
void intIIC(void)
{
delay(50);
U0CTL=0;
U0CTL |= SWRST; // Reset USART state machine
U0CTL &= ~CHAR;
I2CIE&=~RXRDYIE;
I2CIFG=0;
P3SEL|=0X0A;
U0CTL|=I2C+SYNC;
U0CTL&=~I2CEN;
I2CTCTL|=I2CSSEL1;
I2COA=0X0050; // 本机地址
I2CIE|=RXRDYIE+OAIFG;
U0CTL|=I2CEN;
delay(50);
}
lovexieli 2008-10-16
  • 打赏
  • 举报
回复

总线仲裁是关键!就是分配他们的优先级。
pcf00 2008-10-16
  • 打赏
  • 举报
回复
总线仲裁是关键!就是分配他们的优先级。

这个优先级怎么分配?
zyzhang365 2008-10-15
  • 打赏
  • 举报
回复
还可以考虑加数字IO信号,比如从准备好时送中断过来。
pcf00 2008-10-15
  • 打赏
  • 举报
回复
对于1楼朋友提供的“参考访问EEPROM的协议”也考虑过,它是读取时就有数据立即返回,而我的情况是:发送读取命令后,约有30~120秒的时间才有数据返回,间隔时间太长,所以才考虑主从变换的方式。
对于你提到的“需要在初始化的时候规定好起始时谁主谁从; ”那么一开始时使2机都处于从机状态,待有数据发送时转换为主机,另一方再根据接收到的命令做主从转换的抉择,原理上讲似乎可行!不知大牛们觉得如何?
miss_wendy 2008-10-15
  • 打赏
  • 举报
回复
你找个示波器查看一下电平,如果俩单片机的程序都自己写的话,你跟踪一变各个状态就知道为什么了。
zyzhang365 2008-10-15
  • 打赏
  • 举报
回复
从机需要自己设置好自己的地址, 会话都是主机发起的,主机在start信号之后送出的就是slave地址。看I2C的规范吧。
pcf00 2008-10-15
  • 打赏
  • 举报
回复
从机地址发送是单独发送的吗,还是IIC通信开始就自动发送了?
zyzhang365 2008-10-14
  • 打赏
  • 举报
回复
从I2C的规范讲, 一条总线上实现多主多从是可以的. 当多个主设备同时存在时, 需要处理总线仲裁的问题.


对于LZ的情形, 需要在初始化的时候规定好起始时谁主谁从; 第一次通讯结束后需要转换主从角色, 并重新配置I2C控制器. 对于新的从设备不要忘记配置地址, 对于主要配置波特率; 转换期间最好延时一下, 并暂时关闭I2C中断.


其实,可以简单处理是把一个一直做主, 另一个做从, 协议可以参考访问EEPROM的协议. 供你参考. 

6,127

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 硬件设计
社区管理员
  • 硬件设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧