搜索
bottom↓
回复: 24

MSP430F2013的I2C与C8051F410的SMBus通信问题

[复制链接]

出0入0汤圆

发表于 2011-6-22 22:57:51 | 显示全部楼层 |阅读模式
请问有没有人用过MSP430F2013的USI---I2C与 C8051F410的SMBus 进行通信?有没有什么注意事项?我尝试用它们的例程,C8051F410为主机,MSP430F2013为从机,不知为何,从机没有响应??

出0入0汤圆

 楼主| 发表于 2011-6-23 09:18:44 | 显示全部楼层
请问两个单片机的系统时钟要求一致吗?

出0入0汤圆

 楼主| 发表于 2011-6-23 20:11:10 | 显示全部楼层
请问有没有谁用过MSP430F2013的I2C模块,有没有什么要注意的方面?为什么和C8051F410连接没有响应呢?

出0入0汤圆

发表于 2011-6-23 20:25:19 | 显示全部楼层
同样问题,帮顶。
我的问题是,MSP430F2013的USI---I2C做为从,只能识到地址,下一步接数据就有问题了,

出0入0汤圆

 楼主| 发表于 2011-6-23 23:57:01 | 显示全部楼层
楼上请问你是怎么看出来识别出地址的?

出0入0汤圆

发表于 2011-6-24 09:08:32 | 显示全部楼层
可以用仿真看,程序状态啊!

出0入0汤圆

 楼主| 发表于 2011-6-24 22:12:49 | 显示全部楼层
回复【5楼】sunrun
-----------------------------------------------------------------------

哦,是的,我也用示波器看了一下,当时只是显示开始和发送地址的波形

出0入0汤圆

 楼主| 发表于 2011-6-24 22:21:17 | 显示全部楼层
昨天晚上终于找到原因了,说出来很惭愧,不过还是得说,以此自警。
采用的例程会在从机没有响应的时候重新开始通信。调试过程中偶然间看到了数据发送的波形,事实上我并没有对程序进行修改,但之前一直没有通信,只是显示开始和地址波形。这样发送的数据波形时有时无,有些不解。找原因。偶然想到可能是单片机焊接的不还,引脚接触不良。于是又焊了一下,测试,的确是这个原因!忙了好几天,最后发现是这个原因!以此自警!!谨记谨记!

出0入0汤圆

 楼主| 发表于 2011-6-24 22:25:11 | 显示全部楼层
回复【3楼】sunrun
同样问题,帮顶。
我的问题是,msp430f2013的usi---i2c做为从,只能识到地址,下一步接数据就有问题了,
-----------------------------------------------------------------------

地址接收了说明可以正常通信,你的程序是自己写的还是TI的例程?是不是从机ACK发送错了(发送的是NACK?)?地址设置的对吗?你可以先用TI的例程试一下,另外也可以用示波器观察一下,这样比较直观

出0入0汤圆

 楼主| 发表于 2011-6-24 22:40:17 | 显示全部楼层
//******************************************************************************
//  MSP430F20xx Demo - I2C Slave Receiver / Slave Transmitter, multiple bytes
//
//  Description: I2C Master communicates with I2C Slave using
//  the USI. Master data should increment from 0x55 with each transmitted byte.
//  ACLK = n/a, MCLK = SMCLK = Calibrated 1MHz
//
//  ***THIS IS THE SLAVE CODE***
//
//                  Slave                      Master
//                                    (msp430x20x3_usi_12.c)
//               MSP430F20x2/3              MSP430F20x2/3
//             -----------------          -----------------
//         /|\|              XIN|-    /|\|              XIN|-
//          | |                 |      | |                 |
//          --|RST          XOUT|-     --|RST          XOUT|-
//            |                 |        |                 |
//      LED <-|P1.0             |        |                 |
//            |                 |        |             P1.0|-> LED
//            |         SDA/P1.7|------->|P1.6/SDA         |
//            |         SCL/P1.6|<-------|P1.7/SCL         |
//
//  Note: internal pull-ups are used in this example for SDA & SCL
//
//  R. B. Elliott / H. Grewal
//  Texas Instruments Inc.
//  February 2008
//  Built with IAR Embedded Workbench Version: 3.42A
//******************************************************************************

#include  <msp430x20x3.h>
#define Number_of_Bytes  5                  // **** How many bytes?? ****

void Setup_USI_Slave(void);

char MST_Data = 0;                          // Variable for received data
char SLV_Data = 0x55;
char SLV_Addr = 0x90;                       // Address is 0x48<<1 for R/W
int I2C_State, Bytecount, transmit = 0;     // State variables

void Data_RX(void);
void TX_Data(void);
void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog
  if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)                                    
  {  
    while(1);                               // If calibration constants erased
                                            // do not load, trap CPU!!
  }
  BCSCTL1 = CALBC1_1MHZ;                    // Set DCO
  DCOCTL = CALDCO_1MHZ;
  Setup_USI_Slave();
  
  LPM0;                                     // CPU off, await USI interrupt
  _NOP();
}

//******************************************************************************
// USI interrupt service routine
// Rx bytes from master: State 2->4->6->8
// Tx bytes to Master: State 2->4->10->12->14
//******************************************************************************
#pragma vector = USI_VECTOR
__interrupt void USI_TXRX (void)
{
  if (USICTL1 & USISTTIFG)                  // Start entry?
  {
    P1OUT |= 0x01;                          // LED on: sequence start
    I2C_State = 2;                          // Enter 1st state on start
  }

  switch(__even_in_range(I2C_State,14))
    {
      case 0:                               // Idle, should not get here
              break;

      case 2: // RX Address
              USICNT = (USICNT & 0xE0) + 0x08; // Bit counter = 8, RX address
              USICTL1 &= ~USISTTIFG;        // Clear start flag
              I2C_State = 4;                // Go to next state: check address
              break;

      case 4: // Process Address and send (N)Ack
              if (USISRL & 0x01){            // If master read...
                SLV_Addr = 0x91;             // Save R/W bit
                transmit = 1;}
              else{transmit = 0;
                  SLV_Addr = 0x90;}
              USICTL0 |= USIOE;             // SDA = output
              if (USISRL == SLV_Addr)       // Address match?
              {
                USISRL = 0x00;              // Send Ack
                P1OUT &= ~0x01;             // LED off
                if (transmit == 0){
                  I2C_State = 6;}           // Go to next state: RX data
                if (transmit == 1){  
                  I2C_State = 10;}          // Else go to next state: TX data
              }
              else
              {
                USISRL = 0xFF;              // Send NAck
                P1OUT |= 0x01;              // LED on: error
                I2C_State = 8;              // next state: prep for next Start
              }
              USICNT |= 0x01;               // Bit counter = 1, send (N)Ack bit
              break;

    case 6: // Receive data byte
              Data_RX();
              break;  

      case 8:// Check Data & TX (N)Ack
              USICTL0 |= USIOE;             // SDA = output
              if (Bytecount <= (Number_of_Bytes-2))         
                                            // If not last byte
              {
                USISRL = 0x00;              // Send Ack
                I2C_State = 6;              // Rcv another byte
                Bytecount++;
                USICNT |= 0x01;             // Bit counter = 1, send (N)Ack bit
              }
              else                          // Last Byte
              {
                USISRL = 0xFF;              // Send NAck
              USICTL0 &= ~USIOE;            // SDA = input
              SLV_Addr = 0x90;              // Reset slave address
              I2C_State = 0;                // Reset state machine
              Bytecount =0;                 // Reset counter for next TX/RX
              }
              
              
              break;

     case 10: // Send Data byte
              TX_Data();
              break;

      case 12:// Receive Data (N)Ack
              USICTL0 &= ~USIOE;            // SDA = input
              USICNT |= 0x01;               // Bit counter = 1, receive (N)Ack
              I2C_State = 14;               // Go to next state: check (N)Ack
              break;

      case 14:// Process Data Ack/NAck
           if (USISRL & 0x01)               // If Nack received...
              {
              USICTL0 &= ~USIOE;            // SDA = input
              SLV_Addr = 0x90;              // Reset slave address
              I2C_State = 0;                // Reset state machine
               Bytecount = 0;
             // LPM0_EXIT;                  // Exit active for next transfer
              }
              else                          // Ack received
              {
                P1OUT &= ~0x01;             // LED off
                TX_Data();                  // TX next byte
               }
               break;
   
      }
  USICTL1 &= ~USIIFG;                       // Clear pending flags
}

void Data_RX(void){
  
              USICTL0 &= ~USIOE;            // SDA = input
              USICNT |=  0x08;              // Bit counter = 8, RX data
              I2C_State = 8;                // next state: Test data and (N)Ack
}

void TX_Data(void){
              USICTL0 |= USIOE;             // SDA = output
              USISRL = SLV_Data++;
              USICNT |=  0x08;              // Bit counter = 8, TX data
              I2C_State = 12;               // Go to next state: receive (N)Ack
}

void Setup_USI_Slave(void){
  P1OUT = 0xC0;                             // P1.6 & P1.7 Pullups
  P1REN |= 0xC0;                            // P1.6 & P1.7 Pullups
  P1DIR = 0xFF;                             // Unused pins as outputs
  P2OUT = 0;
  P2DIR = 0xFF;
  
  USICTL0 = USIPE6+USIPE7+USISWRST;         // Port & USI mode setup
  USICTL1 = USII2C+USIIE+USISTTIE;          // Enable I2C mode & USI interrupts
  USICKCTL = USICKPL;                       // Setup clock polarity
  USICNT |= USIIFGCC;                       // Disable automatic clear control
  USICTL0 &= ~USISWRST;                     // Enable USI
  USICTL1 &= ~USIIFG;                       // Clear pending flag
  
  transmit = 0;
  _EINT();

}

出0入0汤圆

发表于 2011-6-26 09:37:17 | 显示全部楼层
我的程序是自已改的.改动不多.调了几天还是找不到问题.手上没有示波器,真是寸步难行啊....

出0入0汤圆

发表于 2011-6-26 09:42:17 | 显示全部楼层
请问楼主.这下地址主机你发的是什么."char SLV_Addr = 0x90;                       // Address is 0x48<<1 for R/W "
是发0x90还是发的 0x48,

地址为什么要左移一位呢.

出0入0汤圆

 楼主| 发表于 2011-6-26 10:45:24 | 显示全部楼层
回复【11楼】sunrun
请问楼主.这下地址主机你发的是什么."char slv_addr = 0x90;                       // address is 0x48&lt;&lt;1 for r/w "
是发0x90还是发的 0x48,
地址为什么要左移一位呢.
-----------------------------------------------------------------------

我用C8051F410做主机,地址和从机的地址一样,都是0x90,最后一位是读写控制位,不用移位。注释的意思是0x90=0x48<<1,这样最后一位就是读写控制位了。实际是0x90代表从机地址为0x90,主机进行写操作;0x91表示从机地址为0x90,主机进行读操作,所以发送的是0x90(主机写)或0x91(主机读)。

能不能借台示波器,通过波形可以分析程序的运行情况,尤其是第一次使用I2C,没有经验,用处的确很大...

出0入0汤圆

发表于 2011-6-26 11:01:04 | 显示全部楼层
我也是这样写的.示波器没有熟人借不到.以前到写过IIC.但是没有用430的USI写过.真是晕......
不知道 是我的从机没有发应答还是其它原因/
-----------------------------------------------------------------------
回复【楼主位】PowerSource
请问有没有人用过msp430f2013的usi---i2c与 c8051f410的smbus 进行通信?有没有什么注意事项?我尝试用它们的例程,c8051f410为主机,msp430f2013为从机,不知为何,从机没有响应??
-----------------------------------------------------------------------
楼主用SMBUS是用在哪方面啊.能不将代码发给我参考一下,方便的话请发到:sunrun@sunrun.tk

谢谢

出0入0汤圆

 楼主| 发表于 2011-6-26 11:46:12 | 显示全部楼层
SMBus是双向串行总线,和I2C兼容,我用的就是Silicon laboratories的例程,下面是主机收发多字节的代码,程序加上注释太长了,压缩一下传上去,你可以看看。里面包括主从,单字节,多字节收发的例程。

出0入0汤圆

 楼主| 发表于 2011-6-26 11:48:18 | 显示全部楼层
下面是C8051F410的SMBus的例程:
C8051F410的SMBus例程ourdev_652449K42AFJ.rar(文件大小:30K) (原文件名:SMBus.rar)

出0入0汤圆

发表于 2011-6-26 22:03:16 | 显示全部楼层
非常感谢楼主.其实我也做过IIC通讯的例子.以前用AVR mega88/16都挺好的.只是,转到MSP430F2013上就有这个问题.我在MSP430f2132上也调通过(USCI模块),为什么在2013(USI模块)调不通,麻烦楼主能不能将调好的2013程序发给我参考一下.谢谢!

出0入0汤圆

发表于 2011-6-27 08:22:40 | 显示全部楼层
问题已解决了,昨晚将单片机时钟调到16MHz,就可以通讯了.晕啊430单片机的指令周期是几个时钏啊,以前用AVR的只要2M就跑得很好了.现在430在8MHz下死活不行.必须在12M才可以(主机IIC时钟才60-90KHz).是不是我哪里设置还有问题啊!!!!!!!!!!以此自警!!谨记谨记!

出0入0汤圆

 楼主| 发表于 2011-6-27 13:23:22 | 显示全部楼层
回复【17楼】sunrun

呵呵,解决了就好!我之前向人请教,他告诉我需要注意系统时钟设置,但是当时改了时钟也不行
(单片机引脚都没焊好,肯定不行,就把这个原因忽略了)原来系统时钟也很关键.一块学习!
我设置的I2C时钟就是10KHz,有空我再试试其他系统时钟或I2C时钟是不是有影响.我也不是很懂,第一次使用I2C.

刚才在网上查了一下,在430中,
一个时钟周期= MCLK晶振的倒数.如果MCLK是8M,则一个时钟周期为1/8us;
一个机器周期 =一个时钟周期,即430每个动作都能完成一个基本操作;
一个指令周期 = 1~6个机器周期,具体根据具体指令而定。
详细可参考:http://hi.baidu.com/cdutwbj1/blog/item/740d28d198ca4739970a169c.html

AVR单片机,采用哈佛结构(数据和程序分开存储)和精简指令集,一个机器周期等于一个时钟周期。
也就是执行一条单周期指令只需要一个时钟脉冲。
参考网址:http://www.91avr.com/htm/question/34.html  
http://080520130.blog.163.com/blog/static/116095844201111211252432/

出0入0汤圆

发表于 2011-6-27 14:18:10 | 显示全部楼层
是啊.弄得我好几天都不痛快.以后还得多多学习
谢谢楼主

出0入0汤圆

 楼主| 发表于 2011-6-27 18:42:10 | 显示全部楼层
互相学习,共同进步!

出0入0汤圆

发表于 2011-7-14 21:01:32 | 显示全部楼层
我有个问题:smbus通信,采用多主模式,一边是C8051F340,系统时钟是24M, I2C时钟速率是1M,另一边是C8051F360,系统时钟是98M,I2C时钟速率为1M,C8051F340作为主机时,C8051F360可以接收数据,但是360作为主机时,340不能接收数据,而360的I2C时钟速率设为500K才能通信,为什么这样的?

出0入0汤圆

发表于 2011-7-23 14:48:02 | 显示全部楼层
你的时钟频率有点高了。现在好像增强型是可以达到1M的速率,但是不是很稳定,最好是设在400K以下会好点。

出0入0汤圆

发表于 2011-9-23 11:37:54 | 显示全部楼层
回复【3楼】sunrun
-----------------------------------------------------------------------

我的连地址都识别不出来。好像从机根本就没反应似的,你那有没有430的I2C初始化程序,有的话传一个给我。我的邮箱是57462554qq@.com

出0入0汤圆

发表于 2016-11-27 23:48:38 | 显示全部楼层
学习了,谢谢卤煮~~~
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-19 18:21

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表