|
楼主
查看: 3813回复: 1
发表于 2019-11-25 23:20:25
只看该作者
SDK例程解析,源码与SDK有所改动,请参考帖子中的源码进行实验。
例程描述和实验现象,请参考下边的图片;
|
更多的细节可参考以下代码:
主机端的代码:
- /******************************************************************************
- * MSP432 I2C - EUSCI_B0 I2C Master TX bytes to MSP432 Slave - Timeout
- *
- * 描述:
- * 两个MSP432通过IIC总线进行连接。主机发送数据到从机。
- *
- * 该例程是主机端的代码。
- * 主机发送1个字节数据,紧跟着RESTART, 读取多个数据;
- * P1.0接红色LED,P2.1接绿色LED,P2.2接蓝色LED;
- * 当主机接收到正常的数据时,点亮红色LED;接收到错误的数据时,点亮绿色LED;
- * 主机检测到SLC拉低超时时,蓝色LED灯闪烁;
- *
- * 注意:主机的代码只发送1次地址,也就是和从机之发起1次通信;
- * 在实验时,可将从机接调试器,通过设置断点来构造实验条件,(在CCS中复位从机不会断开连接)
- * 先让从机全速运行,再手动复位主机;
- *
- *
- *****************************************************************************/
- //库函数头文件包含
- #include <ti/devices/msp432p4xx/driverlib/driverlib.h>
- //标准头文件
- #include <stdint.h>
- #include <stdbool.h>
- #include <string.h>
- //例程相关的定义
- #define SLAVE_ADDRESS 0x48
- #define NUM_OF_REC_BYTES 10
- //变量
- const uint8_t TXData[] = {0x04};
- static uint8_t RXData[NUM_OF_REC_BYTES];
- static volatile uint32_t rxIndex;
- static volatile bool stopSent;
- unsigned int i=0, timeout=0;
- //主机的IIC参数配置,速率选择(100KBPS, 400KBPS)
- const eUSCI_I2C_MasterConfig i2cConfig =
- {
- EUSCI_B_I2C_CLOCKSOURCE_SMCLK, // 选择时钟源SMCLK
- 3000000, // SMCLK的频率是3MHz (默认)
- EUSCI_B_I2C_SET_DATA_RATE_100KBPS, // 设置I2C时钟速率为100khz
- 0, // 不使用字节计数阈值
- EUSCI_B_I2C_NO_AUTO_STOP // 不自动产生STOP
- };
- int main(void)
- {
- volatile uint32_t ii;
- //关闭看门狗
- MAP_WDT_A_holdTimer();
- //P1.0接有LED,设置为输出.初始状态低电平 ,LED熄灭
- MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
- MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);
- //P2.1指示灯
- MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN1);
- MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN1);
- //P2.2指示灯
- MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN2);
- MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN2);
- //选择P1.6和P1.7用作功能引脚,IIC接口(UCB0SIMO/UCB0SDA, UCB0SOMI/UCB0SCL).
- MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
- GPIO_PIN6 + GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);
- stopSent = false;
- memset(RXData, 0x00, NUM_OF_REC_BYTES);
- //IIC配置成主机,具体参数在i2cConfig中定义
- MAP_I2C_initMaster(EUSCI_B0_BASE, &i2cConfig);
- //设置时钟线拉低超时时间,如果从机拉低SCL>28ms,会触发中断
- MAP_I2C_setTimeout(EUSCI_B0_BASE, EUSCI_B_I2C_TIMEOUT_28_MS);
- //设置通信的从机地址
- MAP_I2C_setSlaveAddress(EUSCI_B0_BASE, SLAVE_ADDRESS);
- //使能IIC模块
- MAP_I2C_enableModule(EUSCI_B0_BASE);
- //使能接收中断和SCL拉低超时中断
- MAP_Interrupt_enableInterrupt(INT_EUSCIB0);
- MAP_I2C_enableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
- MAP_I2C_enableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_CLOCK_LOW_TIMEOUT_INTERRUPT);
- //判断总线上最后一次传输是否完成
- while (MAP_I2C_masterIsStopSent(EUSCI_B0_BASE));
- // MAP_Interrupt_enableSleepOnIsrExit();
- //开启全局中断
- MAP_Interrupt_enableMaster();
- //发送START和第一个字节
- MAP_I2C_masterSendMultiByteStart(EUSCI_B0_BASE, TXData[0]);
- //设置为接收
- rxIndex = 0;
- MAP_I2C_masterReceiveStart(EUSCI_B0_BASE);
- while(1)
- {
- // MAP_PCM_gotoLPM0InterruptSafe();
- //如果发生超时,P2.2 蓝色LED闪烁
- while(timeout)
- {
- MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN2);
- for (ii = 0; ii < 40000; ii++);
- // __delay_cycles(300000);
- }
- }
- }
- /*******************************************************************************
- * eUSCIB0 ISR.
- * RESTART和接收操作在中断服务程序中完成.
- *******************************************************************************/
- void EUSCIB0_IRQHandler(void)
- {
- uint_fas**_t status;
- status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B0_BASE);
- MAP_I2C_clearInterruptFlag(EUSCI_B0_BASE, status);
- //判断SCL超时标志
- if (status & EUSCI_B_I2C_CLOCK_LOW_TIMEOUT_INTERRUPT)
- {
- timeout++;
- //三色LED,熄灭绿色LED. 只闪烁蓝色LED
- MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN1);
- }
- //将接收到的数据放入接收缓冲区中
- if (status & EUSCI_B_I2C_RECEIVE_INTERRUPT0)
- {
- //NUM_OF_REC_BYTES=10, rxIndex=8,禁用接收中断了即倒数第2个字节;
- if (rxIndex == NUM_OF_REC_BYTES - 2)
- {
- MAP_I2C_disableInterrupt(EUSCI_B0_BASE,EUSCI_B_I2C_RECEIVE_INTERRUPT0);
- MAP_I2C_enableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_STOP_INTERRUPT);
- //接收到倒数第2个字节发送STOP. 最后1个接收到的字节可以在STOP中断里边读取
- MAP_I2C_masterReceiveMultiByteStop(EUSCI_B0_BASE);
- RXData[rxIndex++] = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B0_BASE);
- }
- else
- {
- RXData[rxIndex++] = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B0_BASE);
- }
- }
- else if (status & EUSCI_B_I2C_STOP_INTERRUPT)
- {
- // MAP_Interrupt_disableSleepOnIsrExit();
- MAP_I2C_disableInterrupt(EUSCI_B0_BASE,EUSCI_B_I2C_STOP_INTERRUPT);
- //读取最后1个字节
- RXData[rxIndex++] = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B0_BASE);
- rxIndex = 0;
- //对接收到的数据结果进行判断
- //抽测3-5个数据,如果对的话,就认为全对了
- if((RXData[0]==0x00)&&(RXData[1]==0x11)&&(RXData[8]==0x88)&&(RXData[9]==0x99))
- {
- //接收到的数据符合预期,红灯点亮
- MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
- }
- else
- {
- //接收到的数据不符合预期,绿灯点亮
- MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN1);
- }
- }
- }
复制代码
从极端的代码:
- /******************************************************************************
- * MSP432 I2C - EUSCI_B0 I2C Master TX bytes to MSP432 Slave - Timeout
- *
- * 描述:
- * 两个MSP432通过IIC总线进行连接。主机发送数据到从机。
- *
- * 该例程是主机端的代码。
- * 主机发送1个字节数据,紧跟着RESTART, 读取多个数据;
- * P1.0接红色LED,P2.1接绿色LED,P2.2接蓝色LED;
- * 当主机接收到正常的数据时,点亮红色LED;接收到错误的数据时,点亮绿色LED;
- * 主机检测到SLC拉低超时时,蓝色LED灯闪烁;
- *
- * 注意:主机的代码只发送1次地址,也就是和从机之发起1次通信;
- * 在实验时,可将从机接调试器,通过设置断点来构造实验条件,(在CCS中复位从机不会断开连接)
- * 先让从机全速运行,再手动复位主机;
- *
- *
- *****************************************************************************/
- //库函数头文件包含
- #include <ti/devices/msp432p4xx/driverlib/driverlib.h>
- //标准头文件
- #include <stdint.h>
- #include <stdbool.h>
- #include <string.h>
- //例程相关的定义
- #define SLAVE_ADDRESS 0x48
- #define NUM_OF_RX_BYTES 1
- #define NUM_OF_TX_BYTES 10
- //变量定义
- static volatile uint8_t RXData[NUM_OF_RX_BYTES];
- static volatile uint32_t rxIndex;
- static volatile uint32_t txIndex;
- const uint32_t TXData[NUM_OF_TX_BYTES] =
- {
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99
- };
- int main(void)
- {
- //停用看门狗
- MAP_WDT_A_holdTimer();
- rxIndex = 0;
- txIndex = 0;
- //P1.0用作指示灯
- MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
- MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);
- //选择P1.6和P1.7用作功能引脚,IIC接口.
- MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
- GPIO_PIN6 + GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);
- //IIC配置成从机
- MAP_I2C_initSlave(EUSCI_B0_BASE, SLAVE_ADDRESS, EUSCI_B_I2C_OWN_ADDRESS_OFFSET0,
- EUSCI_B_I2C_OWN_ADDRESS_ENABLE);
- //使能模块和使能中断
- MAP_I2C_enableModule(EUSCI_B0_BASE);
- MAP_I2C_clearInterruptFlag(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
- MAP_I2C_enableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
- MAP_I2C_enableInterrupt(EUSCI_B0_BASE,EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
- MAP_Interrupt_enableInterrupt(INT_EUSCIB0);
- MAP_Interrupt_enableSleepOnIsrExit();
- MAP_Interrupt_enableMaster();
- //系统进入低功耗状态
- while (1)
- {
- MAP_PCM_gotoLPM0();
- }
- }
- /*******************************************************************************
- * eUSCIB0 ISR.
- * 在中断服务程序中进行数据的发送和接收
- ******************************************************************************/
- void EUSCIB0_IRQHandler(void)
- {
- uint_fas**_t status;
- status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B0_BASE);
- MAP_I2C_clearInterruptFlag(EUSCI_B0_BASE, status);
- //可以在两个不同的场景构建SCL拉低超时
- //从机在接收的时候,如果UCBxRXBUF数据未读取,SCL拉低
- //从机在发送的时候,SCL拉低,等待往TXBUF写入有效数据
- //接收中断标志 RXIFG
- if (status & EUSCI_B_I2C_RECEIVE_INTERRUPT0)
- {
- //此处设置断点,不读取收到的数据
- RXData[rxIndex++] = MAP_I2C_slaveGetData(EUSCI_B0_BASE);
- //如果已达到最后,清零index
- if (rxIndex >= NUM_OF_RX_BYTES)
- {
- rxIndex = 0;
- txIndex = 0;
- }
- }
- //发送中断标志 TXIFG
- if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0)
- {
- //此处设置断点,不往TXBUF里写数据
- //txIndex: 0,1, ... , 8,9
- MAP_I2C_slavePutData(EUSCI_B0_BASE, TXData[txIndex++]);
- //如果已达到最后,清零index
- if (txIndex >= NUM_OF_TX_BYTES)
- {
- txIndex = 0;
- //指示数据帧的发送
- MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
- }
- }
- }
复制代码
|
|