// I2C实验程序解析
//头文件
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_i2c.h"
#include "driverlib/i2c.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "utils/uartstdio.h"
#include "driverlib/rom.h"
#include "driverlib/fpu.h"
// 变量定义部分
#define NUM_I2C_DATA 3 // 定义要通过I2C发送的数据包的数目
// 设定slave(从)模块的地址,是一个7-bit的地址加上RS位,
//具体形式如下:
// [A6:A5:A4:A3:A2:A1:A0:RS]
// RS位是一个指示位,如果RS=0,则说明是主发送数据,从接收数据;
//RS=1说明是主接收数//据,从发送数据
#define SLAVE_ADDRESS 0x3C
// UART0的配置及初始化部分。*
// UART0模块用于通过计算机虚拟串口显示过程信息,主要包括InitConsole
//函数和一些UARTprintf语句。
void InitConsole(void)
{
// 由于UART0使用PA0、PA1两个引脚,因此需要使能GPIOA模块
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
//将PA0和PA1两个引脚的功能选择为执行UART0模块的功能
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
// 将PA0和PA1两个引脚配置为UART功能
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
// UART的标准初始化
UARTStdioConfig(0,115200,50000000);
}
// main 函数
// 将I2C0模块配置为一个主模块和一个从模块,并且通过LOOPBACK模式,
//将它们的时钟线和//数据线连接起来。由于在LOOPBACK模式下,
//主模块和从模块是在内部连接起来的。因此从//模块可以接收到主模块
//自己发送的数据。
int main(void)
{
//使能FPU
FPUEnable();
FPULazyStackingEnable();
//定义发送数据和接收数据的缓存
ui32 ulDataTx[NUM_I2C_DATA];
ui32 ulDataRx[NUM_I2C_DATA];
ui32 ulindex;
// 设置系统时钟为50MHz
SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);//错误
SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
// 使能I2C0模块的时钟信号.
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
// 由于I2C0使用PB2、PB3两个引脚,需要使能GPIOB模块对应的
//时钟信号
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
// 将PB2的功能选择为I2C0模块的时钟信号,将PB3选择为数据信号
GPIOPinConfigure(GPIO_PB2_I2C0SCL);
GPIOPinConfigure(GPIO_PB3_I2C0SDA);
// 对PB2和PB3两个引脚做有关I2C功能的配置
GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_2 | GPIO_PIN_3);//错误
GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);//正确
// 寄存器操作:将I2C0模块配置为运行于LOOPBACK模式。
// 在LOOPBACK模式下,I2C0模块在内部连接了主、从模块的信号线。
// 因此既可以作为主模块发送数据,也可以作为从模块接收数据
HWREG(I2C0_BASE + I2C_O_MCR) |= 0x01;
// 使能并初始化I2C0的主模块,对于I2C0模块使用系统时钟。
// 语句的最后一个参数是用来设定数据传输速率的。
// false表示传输速率是100kbps,true则意味着传输速率是400kbps。
//此处使用的是100kbps的传输速率
I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet(), false);
// 使能I2C0从模块。注:只是为了测试使用。
I2CSlaveEnable(I2C0_BASE);
// 设置从模块的地址
I2CSlaveInit(I2C0_BASE, SLAVE_ADDRESS);
// 设置I2C0主模块将要放在总线上的从模块地址
// false代表主模块发送,从模块接收
I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, false);
// 使能UART模块,只是为了显示信息用
InitConsole();
// 显示一些关于样例的初始信息
UARTprintf("I2C Loopback Example ->");
UARTprintf("\n Module = I2C0");
UARTprintf("\n Mode = Single Send/Receive");
UARTprintf("\n Rate = 100kbps\n\n");
// 设置要发送的数据
ulDataTx[0] = 'I';
ulDataTx[1] = '2';
ulDataTx[2] = 'C';
// 主模块向从模块发送3个数据。
// 初始化接收缓存区
for(ulindex = 0; ulindex < NUM_I2C_DATA; ulindex++)
{
ulDataRx[ulindex] = 0;
}
// 输出信息指示是主模块发送,从模块接收
UARTprintf("Tranferring from: Master -> Slave\n");
// 主模块向从模块发送3个I2C数据
for(ulindex = 0; ulindex < NUM_I2C_DATA; ulindex++)
{
// 显示主模块正发送的数据
UARTprintf(" Sending: '%c' . . . ", ulDataTx[ulindex]);
// 把将发送的数据存入数据寄存器中
I2CMasterDataPut(I2C0_BASE, ulDataTx[ulindex]);
// 主模块开始发送数据
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
// 等待,直到从模块接收到数据,并且发送ACK信号回应该数据
while(!(I2CSlaveStatus(I2C0_BASE) & I2C_SCSR_RREQ))
{
}
// 从从模块中读取接收到的数据
ulDataRx[ulindex] = I2CSlaveDataGet(I2C0_BASE);
// 等待主模块发送完毕
while(I2CMasterBusy(I2C0_BASE))
{
}
// 显示已接收到的数据
UARTprintf("Received: '%c'\n", ulDataRx[ulindex]);
}
// 从模块向从模块发送3个数据。
// 重置接收缓存区
for(ulindex = 0; ulindex < NUM_I2C_DATA; ulindex++)
{
ulDataRx[ulindex] = 0;
}
// 输出信息指示是从模块发送,主模块接收
UARTprintf("\n\nTranferring from: Slave -> Master\n");
// 更改数据传输方向,ture代表主模块接收,从模块发送
I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, true);
// 一次虚假的接收,用于确保不会收到前面留下的垃圾数据
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
// 一次虚假的确认,以清除掉那些不该存在的flag,即指示信号
while(!(I2CSlaveStatus(I2C0_BASE) & I2C_SLAVE_ACT_TREQ))
{
}
// 从模块向主模块发送3个I2C数据
for(ulindex = 0; ulindex < NUM_I2C_DATA; ulindex++)
{
// 显示从模块正发送的数据
UARTprintf(" Sending: '%c' . . . ", ulDataTx[ulindex]);
// 把将发送的数据存入数据寄存器中
I2CSlaveDataPut(I2C0_BASE, ulDataTx[ulindex]);
// 主模块开始读取数据
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
// 等待,直到从模块完成了数据发送
while(!(I2CSlaveStatus(I2C0_BASE) & I2C_SLAVE_ACT_TREQ))
{
}
// 从主模块中读取已接收的数据
ulDataRx[ulindex] = I2CMasterDataGet(I2C0_BASE);
// 显示已接收到的数据
UARTprintf("Received: '%c'\n", ulDataRx[ulindex]);
}
// 输出程序完毕信息
UARTprintf("\nDone.\n\n");
return(0);
}