3722|1

72

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

单片机smbus总线通讯,数据只能确认0? [复制链接]

大家好,我现在用smbus(I2C)总线进行两个C8051F系列单片机的通讯。单片机中有控制逻辑模块,不需要自己写驱动程序。
我设置的模式是主器件发送,从器件接受。
我现在的问题是,发送数据只能对0确认,其他的数,字符一概不确认,不知是什么原因啊?
调试好几周了,没有结果,很着急。谢谢大家帮忙啊!
这是主发送器的程序:
//-------------------------
//c8051f410_smbus_master.c
//-------------------------
//*********文件包含***********
#include               //特殊寄存器地址表声明文件

//********全局常量声明********
#define sysclk        3686400
#define smb_frequency 10000
#define write         0x00
#define read          0x01
#define slave_addr    0xF0
#define smb_start     0xE0
#define already_trans 0xC0
#define receive_data  0x80

//********全局变量*********
unsigned char pdata array _at_ 0x0000;
unsigned char smb_data_in;
unsigned char smb_data_out;
unsigned char target;
          bit smb_busy;
              bit smb_rw;
unsigned long num_errors;
        sfr16 TMR3RL =0x92;
        sfr16 TMR3 =0x94;
         sbit SDA =P0^0;
         sbit SCL =P0^1;

//*********函数原形**********
void config(void);
void smbus_init(void);
void smbus_ISR(void);
void Timer3_ISR(void);
void smb_write(void);
void t0_wait_ms(unsigned char ms);

//---------------------------
//         主程序
//---------------------------
void main(void)
{
unsigned char i;

PCA0MD &= ~0x40;                 //禁止看门狗
//**********如果由于不恰当的复位或错误,从机将SDA信号拉为低电平
//       提供一个时钟脉冲使从机跳出当前状态,释放SDA***********
while(!SDA)
{
  XBR1=0x40;                      //使能交叉开关
  SCL=0;
  for(i=0;i<255;i++);
  SCL=1;
  while(!SCL);
  for(i=0;i<10;i++);
  XBR1=0x00;                     //禁止交叉开关
  }

config();
smbus_init();
EIE1 |=0x01;
EA=1;
//********开始测试********
array=2;
num_errors=0;
while(1)
{
  smb_data_out=array;
  target=slave_addr;
  smb_write();
  while(smb_busy);
  t0_wait_ms(1);
  }
}

//-----------------------
//        函数块
//-----------------------
void config(void)
{         
//********端口配置********
        P1MDIN &= ~0x03;            //配置XTAL1和XTAL2为模拟输入
        P1SKIP |= 0x03;        
        P1     |= 0x03;
        XBR0=0x0D;                  //时钟、SMBUS、uart均连接到io端口引脚
        XBR1=0x40;                  //使能交叉开关
        P0 =0xff;
        P0MDOUT=0x00;               //漏极开路
//*********振荡器配置**********
        OSCXCN=0x66;
        t0_wait_ms(1);
        while(!(OSCXCN & 0x80));
    RSTSRC=0x06;
        CLKSEL=0x31;
    OSCICN=0x00;
//**********定时器1配置**********
   #if((sysclk/smb_frequency/3)<255)
    #define scale 1
        CKCON |=0x08;               //系统时钟
   #elif((sysclk/smb_frequency/4/3)<255)
    #define scale 4
        CKCON |=0x01;
        CKCON &=~0x0A;              //系统时钟4分频
   #endif
    TMOD=0x20;                  //8位自动重装载

        TH1= -(sysclk/smb_frequency/scale/3);
        TL1=TH1;
        TR1=1;                      //启动定时期T1
//*********定时器3配置***********
    TMR3CN=0x00;                //16位自动重装载,中断禁止
        CKCON &=~0x40;              //系统时钟12分频
        TMR3RL= -(sysclk/12/40);    //????
    TMR3=TMR3RL;               
        EIE1 |=0x80;                //定时器3中断使能
        TMR3CN |=0x40;              //打开定时器3
}

void smbus_init(void)
{
SMB0CF=0x5D;
SMB0CF |=0x80;
}

void t0_wait_ms(unsigned char ms)
{
TCON &= ~0x30;                 //停止定时器0清中断标志
TMOD &= ~0x0f;
TMOD &= ~0x01;                 //16位模式
CKCON |=0x04;                  //系统时钟

while(ms){
   TR0=0;
   TH0= -(sysclk/1000>>8);      //??????
   TL0= -(sysclk/1000);         //??????
   TF0=0;
   TR0=1;
   while(!TF0);
   ms--;
  }
   TR0=0;
}

void smbus_ISR(void) interrupt 7
{
bit fail=0;
static bit addr_send=0;
if(ARBLOST==0)
{
  switch(SMB0CN & 0xF0)
  {
   case smb_start:
     SMB0DAT=target;
         SMB0DAT &=0xFE;
         SMB0DAT |=smb_rw;
         STA=0;
         addr_send=1;
         break;

   case already_trans:
     if(ACK)
         {
          if(addr_send)
          {
           addr_send=0;
           if(smb_rw==write)
           {
            SMB0DAT=smb_data_out;
                }
       else{}

           }
          else
          {
           STO=1;
           smb_busy=0;
           }
          }
          else
          {
           STO=1;
           STA=1;
           smb_busy=0;
           num_errors++;
           }
           break;
   
   case receive_data:
     smb_data_in=SMB0DAT;
         smb_busy=0;
         ACK=0;
         STO=1;
         break;

   default:
     fail=1;
         break;
   }
  }
else
{
  fail=1;
  }
if(fail)
{
  SMB0CF &=~0x80;
  SMB0CF |=0x80;
  STA=0;
  STO=0;
  ACK=0;
  smb_busy=0;
  fail=0;
  num_errors++;
  }
  SI=0;
}

void Timer3_ISR(void) interrupt 14
{
SMB0CF &=~0x80;
SMB0CF |=0x80;
TMR3CN &=~0x80;
STA=0;
smb_busy=0;
}

void smb_write(void)
{
while(smb_busy);
smb_busy=1;
smb_rw=0;
STA=1;
}  

//-------------------------
//     End of file
//-------------------------

最新回复

IO的上拉加上没有? 呵呵   详情 回复 发表于 2008-9-30 12:17
点赞 关注

回复
举报

80

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
IO的上拉加上没有?

呵呵
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表