TI | TM4C123Gx单片机之---I2C接口笔记

一、I2C接口的介绍:

       内部集成电路(I2C)总线通过一个两线设计(串行数据线 SDA 和串行时钟线 SCL)来提供双向数据传输,并且与外部 I2C 器件诸如串行存储器(RAM 和 ROM),网络设备,LCD,音频发生器等联系。I2C 总线也可用于产品开发和制造的系统测试和诊断的目的。TM4C123GH6PM 微控制器提供与其他 I2C 总线上的设备交互(发送和接收)的能力。TM4C123GH6PM 控制器的 I2C 模块具有以下特点:
I2C 总线上的设备可被配置为主机或从机
— 支持一个主机或从机发送和接收数据
— 同时支持主机和从机操作
 四个 I2C 模式:
— 主机发送模式
— 主机接收模式
— 从机发送模式
— 从机接收模式
 四个发送速率:
— 标准模式(100 Kbps)
— 快速模式(400 Kbps)
— 超快速模式(1Mbps)
— 高速模式(3.33Mbps)
 时钟低超时中断的
 双从地址能力
 抗干扰
 主机和从机中断的产生
— 当主机发送或接收操作完成时(或因错误终止时),产生中断
— 当从机发送数据或主机需要数据或检测到起始或停止条件时,产生中断
 主机由仲裁和时钟同步,支持多主机,以及 7 位寻址模式

二、结构图:

三、 初始化与配置
以下例子给出如何配置 I2C 模块用于主机传输一个字节。这里假定系统时钟为 20 MHz 。
1. 在系统控制模块使用 RCGCI2C 寄存器使能 I2C 时钟。
2. 通过在系统控制模块的 RCGCGPIO 寄存器为相应的 GPIO 模块使能时钟。要了解使能哪些GPIO 端口。
3. 在 GPIO 模块,通过 GPIOAFSEL 寄存器位它们的复用功能使能相应的引脚。请参看表 23-4,以确定配置那个 GPOI。
4. 使能 I2CSDA 引脚来配置开漏操作。
5. 在 GPIOPCTL 寄存器配置 PMCn 位组为相应的引脚配置 I2C 信号。
6. 向 I2CMCR 寄存器写入 0x00000010 值来初始化 I2C 主机。
7. 通过写入 I2CMTPR 寄存器正确的值来设置所需的 100 Kbps 的 SCL 时钟速度。写入I2CMTPR 寄存器的值代表在一个 SCL 时钟周期中系统时钟周期数。TPR 值由以下等式确定:
TPR = (System Clock/(2*(SCL_LP + SCL_HP)*SCL_CLK))-1;
TPR = (20MHz/(2*(6+4)*100000))-1;
TPR = 9向 I2CMTPR 寄存器写入 0x00000009.
8. 规定主机的从机地址,下一个操作是一个发送,该发送通过向 I2CMSA 寄存器值写入0x00000076 实现。这设置了从机地址为 0x3B。
9. 通过向 I2CMDR 寄存器写入所需数据将数据(位)传输到数据寄存器。
10. 启动从主机到从机的数据单字节的传输是通过向 I2CMCS 寄存器写入 0x00000007 (STOP,START, RUN)实现。
11. 等待直到传输完成,通过轮询 I2CMCS 寄存器的 BUSBSTY 位,直到该位被清除。
12. 检测 I2CMCS 寄存器的 ERROR 位以确保传输被应答。

四、环路操作实验
      可以通过设置 I2C 主机配置(I2CMCR)寄存器的 LPBK 位将 I2C 模块放入一个内部环路模式用于诊断或调试工作。在环回模式下,来自主机的 SDA 和 SCL 信号和从机模块的 SDA 和SCL 信号绑定在一起,并允许内部的设备测试,而不必去通过 I / O实验的验证就是通过主机发送数据-从机接收,从机发数据-主机接收

/********************************************************
 *实验功能:通过环路模式实现单字节的主机/从机数据的发送和接收
 *时间:2019-6-30
 *作者:MountXing
 *******************************************************/

//包含一系列头文件
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_i2c.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"


//要发送的I2C数据包的数量
#define NUM_I2C_DATA  5

//地址
#define SLAVE_ADDRESS 0x3C

/*****************************************************************************
 *初始化配置使用 UART0 外设
 *-UART0RX - PA0
 *-UART0TX - PA1
*****************************************************************************/
void Init_Console_Uart0(void)
{
   
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);     //内部16M时钟
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    UARTStdioConfig(0, 115200, 16000000);
}

/*****************************************************************************
 *配置I2C0主从机,并使用环回模式连接它们。
 *初始化I2C0外设
 *I2C0SCL - PB2
 *I2C0SDA - PB3
 *****************************************************************************/
int main(void)
{
    uint32_t pui32DataTx[NUM_I2C_DATA];   //发送数据缓冲区
    uint32_t pui32DataRx[NUM_I2C_DATA];   //接受数据缓冲区
    uint32_t ui32Index;                   //要发送数据到缓冲区的位置

    //配置外部时钟为20M
    SysCtlClockSet(SYSCTL_SYSDIV_1|SYSCTL_USE_OSC|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);   //使能I2C0外设
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);  //使能PB端口
    //配置引脚的复用功能 PB2 PB3
    GPIOPinConfigure(GPIO_PB2_I2C0SCL);           
    GPIOPinConfigure(GPIO_PB3_I2C0SDA);
    //配置I2C引脚
    GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
    GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);

     //I2CLoopbackEnable(I2C0_BASE);     //调用固件库的环回模式。(I2C.c固件库里没有这个函数)
     HWREG(I2C0_BASE + I2C_O_MCR) |= 0x01; //调用寄存器的环回模式 (改用寄存器实现)

    //初始化并使能主机模式,使用系统时钟为 I2C0 模块提供时钟频率,
    //主机模块传输速//率为 100Kbps
    I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet(), false);

    // 使能从机模式
    I2CSlaveEnable(I2C0_BASE);

    //设置从机地址
    I2CSlaveInit(I2C0_BASE, SLAVE_ADDRESS);

    //设置主机放在总线上的地址,写入从机
    I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, false);

    //调用uart初始化函数串口显示
    Init_Console_Uart0();
    UARTprintf("I2C 回送例子--->");
    UARTprintf("\n   模式 = I2C0");
    UARTprintf("\n   模式 = 单独的发送/接收");
    UARTprintf("\n   比率 = 100kbps\n\n");

    // 数据初始化发送.
    pui32DataTx[0] = 'I';
    pui32DataTx[1] = '2';
    pui32DataTx[2] = 'C';
    pui32DataTx[3] = 'O';
    pui32DataTx[4] = 'K';
   

    // 初始化接收缓冲区.
    for(ui32Index = 0; ui32Index < NUM_I2C_DATA; ui32Index++)
    {
        pui32DataRx[ui32Index] = 0;
    }
    UARTprintf("转换方式: 主机 -> 从机\n");

    // 将I2C数据从主机发送到从机
    for(ui32Index = 0; ui32Index < NUM_I2C_DATA; ui32Index++)
    {
      UARTprintf("  发送: '%c'  . . .  ", pui32DataTx[ui32Index]);

        // 将要发送的数据放在数据寄存器中
        I2CMasterDataPut(I2C0_BASE, pui32DataTx[ui32Index]);

        //从机回显发送数据到主机
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);

        // 等待从机接收应答
        while(!(I2CSlaveStatus(I2C0_BASE) & I2C_SLAVE_ACT_RREQ))
        {
          
        }

        // 从从机寄存器读取数据
        pui32DataRx[ui32Index] = I2CSlaveDataGet(I2C0_BASE);

        // 等待主机接收应答
        while(I2CMasterBusy(I2C0_BASE))
        {
          
        }

        UARTprintf("接收: '%c'\n", pui32DataRx[ui32Index]);
    }

    // 重置接收缓冲区
    for(ui32Index = 0; ui32Index < NUM_I2C_DATA; ui32Index++)
    {
        pui32DataRx[ui32Index] = 0;
    }
    
    UARTprintf("\n\n转换方式: 从机 -> 主机\n");

    //主机从该地址读取数据
    I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, true);

    // 初始化I2C主机模块状态为单端接收
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);

    // 等待主机请求从机发送数据
    while(!(I2CSlaveStatus(I2C0_BASE) & I2C_SLAVE_ACT_TREQ))
    {
      
    }

    for(ui32Index = 0; ui32Index < NUM_I2C_DATA; ui32Index++)
    {

      UARTprintf("  发送: '%c'  . . .  ", pui32DataTx[ui32Index]);

        //将要发送的数据放到从机数据寄存器中
        I2CSlaveDataPut(I2C0_BASE, pui32DataTx[ui32Index]);

        // 初始化I2C主机模块状态为单端接收
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);

        // 等待从机发送完毕
        while(!(I2CSlaveStatus(I2C0_BASE) & I2C_SLAVE_ACT_TREQ))
        {
          
        }

        // 从主机数据寄存器读取数据
        pui32DataRx[ui32Index] = I2CMasterDataGet(I2C0_BASE);
        UARTprintf("接收: '%c'\n", pui32DataRx[ui32Index]);
    }

    //显示实验结束
    UARTprintf("\n传输实验结束.\n\n");
    return 0;
}

实验结果:

 


 

  • 2
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值