本帖最后由 dirtwillfly 于 2017-7-2 22:48 编辑
实例代码:
// MSP430FR59xx Demo - eUSCI_B0 I2C Master RX multiple bytes from MSP430 Slave
//
// Description: This demo connects two MSP430's via the I2C bus. The master
// reads 5 bytes from the slave. This is the MASTER CODE. The data from the slave
// transmitter begins at 0 and increments with each transfer.
// The USCI_B0 RX interrupt is used to know when new data has been received.
// ACLK = n/a, MCLK = SMCLK = BRCLK = DCO = 1MHz
//
// *****used with "MSP430FR59xx_euscib0_i2c_11.c"****
//
// /|\ /|\
// MSP430FR5969 10k 10k MSP430F5969
// slave | | master
// ----------------- | | -----------------
// -|XIN P1.6/UCB0SDA|<-|----+->|P1.6/UCB0SDA XIN|-
// | | | | | 32kHz
// -|XOUT | | | XOUT|-
// | P1.7/UCB0SCL|<-+------>|P1.7/UCB0SCL |
// | | | P1.0|--> LED
//
// P. Thanigai
// Texas Instruments Inc.
// Feb 2012
// Built with CCS V5.5
//******************************************************************************
#include <msp430.h>
volatile unsigned char RXData;
int main(void)
{
WDTCTL = WDTPW | WDTHOLD;
// Configure GPIO
P1OUT &= ~BIT0; // Clear P1.0 output latch
P1DIR |= BIT0; // For LED
P1SEL1 |= BIT6 | BIT7; // I2C pins
// Disable the GPIO power-on default high-impedance mode to activate
// previously configured port settings
PM5CTL0 &= ~LOCKLPM5;
// Configure USCI_B0 for I2C mode
UCB0CTLW0 |= UCSWRST; // Software reset enabled
UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC; // I2C mode, Master mode, sync
UCB0CTLW1 |= UCASTP_2; // Automatic stop generated
// after UCB0TBCNT is reached
UCB0BRW = 0x0008; // baudrate = SMCLK / 8
UCB0TBCNT = 0x0005; // number of bytes to be received
UCB0I2CSA = 0x0048; // Slave address
UCB0CTL1 &= ~UCSWRST;
UCB0IE |= UCRXIE | UCNACKIE | UCBCNTIE;
while (1)
{
__delay_cycles(2000);
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
UCB0CTL1 |= UCTXSTT; // I2C start condition
__bis_SR_register(LPM0_bits | GIE); // Enter LPM0 w/ interrupt
}
}
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG))
{
case USCI_NONE: break; // Vector 0: No interrupts
case USCI_I2C_UCALIFG: break; // Vector 2: ALIFG
case USCI_I2C_UCNACKIFG: // Vector 4: NACKIFG
UCB0CTL1 |= UCTXSTT; // I2C start condition
break;
case USCI_I2C_UCSTTIFG: break; // Vector 6: STTIFG
case USCI_I2C_UCSTPIFG: break; // Vector 8: STPIFG
case USCI_I2C_UCRXIFG3: break; // Vector 10: RXIFG3
case USCI_I2C_UCTXIFG3: break; // Vector 12: TXIFG3
case USCI_I2C_UCRXIFG2: break; // Vector 14: RXIFG2
case USCI_I2C_UCTXIFG2: break; // Vector 16: TXIFG2
case USCI_I2C_UCRXIFG1: break; // Vector 18: RXIFG1
case USCI_I2C_UCTXIFG1: break; // Vector 20: TXIFG1
case USCI_I2C_UCRXIFG0: // Vector 22: RXIFG0
RXData = UCB0RXBUF; // Get RX data
__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
break;
case USCI_I2C_UCTXIFG0: break; // Vector 24: TXIFG0
case USCI_I2C_UCBCNTIFG: // Vector 26: BCNTIFG
P1OUT ^= BIT0; // Toggle LED on P1.0
break;
case USCI_I2C_UCCLTOIFG: break; // Vector 28: clock low timeout
case USCI_I2C_UCBIT9IFG: break; // Vector 30: 9th bit
default: break;
}
}
由于前面介绍UART学习的时候已经对端口操作,时钟操作做了详细的介绍,这里就只介绍I2C的内容。
1、配置USCI_B0为I2C模式。
(1)在配置或者重新配置eUSCI_B模块时应该先将UCSWRST置1以避免出现配置错误,配置完之后释放复位。
UCB0CTLW0 |= UCSWRST; // Software reset enabled
UCB0CTL1 &= ~UCSWRST;
(2)设置模式。
其中,UCMODE_3 = 0x0600, UCMST = 0x0800, UCSYNC = 0x0100。
注意:eUSCI_B时钟源默认是SMCLK。
(3)设置停止条件
UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC; // I2C mode, Master mode, sync
UCB0CTLW1 |= UCASTP_2; // Automatic stop generated
// after UCB0TBCNT is reached
其中,UCASTP_2 = 0x0008。
(4)设置设置比特率。
UCB0BRW = 0x0008; // baudrate = SMCLK / 8
f BitClock = fBRCLK/UCBRx
(5)设置接收字节计数器阈值
UCB0TBCNT = 0x0005; // number of bytes to be received
(6)设置从机地址。
UCB0I2CSA = 0x0048; // Slave address
(7)设置中断使能。
UCB0IE |= UCRXIE | UCNACKIE | UCBCNTIE;
其中,UCRXIE = 0x0001,UCNACKIE = 0x0020,UCBCNTIE = 0x0040。
2、在配置完USCI_B0后,需要先检测下现有的传输有没有完成。完成后发送开始位进行数据传输。
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
UCB0CTL1 |= UCTXSTT; // I2C start condition
这里我遇到了一个问题,导致我停顿了一些时间,那就是从机地址与R/W读写位的关系。
这里可以知道,MSPFR5969默认是对从机读操作的,所以代码里面没有对这操作,后面的从机code就有说明。
UCB0CTLW0 |= UCTR | UCTXSTT; // I2C TX, start condition
我之前用逻辑分析依抓到地址不是0x48,而是0x91,是因为硬件I2C默认会将7位地址左移一位,然后读写位作为最低位。
0x48 = 1001000
0x91 = 10010001 , R/W = 1为读,0为写。
3、这里分析下低功耗模式。
用户手册1.4节有对工作模式的详细说明。里面有这样一幅图:
可以很清楚的看到在各个模式下的工作状况。
我将原文的翻译直接摘录一部分:
MSP430系列设计用于超低功耗应用,并使用不同的工作模式,如图1-5所示。
操作模式考虑到三种不同的需求:
•超低功耗
•速度和数据吞吐量
•最小化单个外围电流消耗
LPM0至LPM4的低功耗模式通过SR中的CPUOFF,OSCOFF,SCG0和SCG1位进行配置。在SR中包括CPUOFF,OSCOFF,SCG1和SCG1模式控制位的优点是在中断服务程序期间将当前操作模式保存到堆栈中。如果在中断服务程序期间保存的SR值未被更改,则程序流程将返回到上一个操作模式。程序流程可以通过在中断服务程序中操作堆栈内的保存的SR值来返回到不同的操作模式。当设置任何modecontrol位时,所选的操作模式将立即生效。使用任何禁用时钟的外设将被禁用,直到时钟变为活动状态。外设也可以通过其各自的控制寄存器设置来禁用。所有I / O端口引脚,RAM和寄存器都不变。通过所有使能的中断可以从LPM0到LPM4进行写操作。
进入LPMx.5(LPM3.5或LPM4.5)时,电源管理模块(PMM)的稳压器被禁用。所有RAM和寄存器内容都将丢失。虽然I / O寄存器内容丢失,但是I / O引脚状态被锁定在LPMx.5条目上。有关详细信息,请参见数字I / O章节。通过电源序列,RST事件或特定的I / O可以从LPM4.5唤醒。通过电源序列,RST事件,RTC事件或特定的I / O可以从LPM3.5唤醒。
注意:
TEST / SBWTCK引脚用于通过Spy-Bi-Wire或JTAG调试协议实现外部开发工具与器件的连接。当TEST / SBWTCK为高电平时,通常启用连接。连接启用后,设备进入调试模式。在调试模式下,进入和从低功耗模式唤醒时间可能与正常操作相比。使用连接到开发工具的设备使用低功耗模式时,请注意实时行为!
有关详细信息,请参阅EEM章节。
__bis_SR_register(LPM0_bits | GIE); // Enter LPM0 w/ interrupt
这条代码用于进入LPM0模式,并开启通用中断使能,允许从中断模式唤醒。
__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0 这条代码用于退出LPM0模式。
几乎所有的低功耗模式都可以这样调用进入和退出。
4、中断子程序
其实MSP430的中断程序官方给出的例程很完整了,按照你自己的应用改一下就能用,具体的我没有深究,就是按我自己的要求修改了下,都可以正常运行。这里有一点需要注意的就是:
这里显示MSPFR5969可以设置本机地址,也就是说一个MSPFR5969可以作为四个从机。
转自http://www.deyisupport.com/question_answer/microcontrollers/msp430/f/55/t/134752.aspx
|