SWM32系列教程7-I2C及其应用

本文介绍了如何在STM32S单片机上配置和使用I2C模块,以驱动电容触摸芯片GT911为例。首先配置GPIO端口映射和上拉功能,接着设置I2C为主机模式,7位地址,400KHz时钟,并展示了I2C初始化函数。I2C结构体包含主机和从机模式参数,文中主要讲解了主机模式。I2C读写函数包括启动、停止、写入和读取,遵循标准的I2C通信流程。最后给出了GT911读写寄存器的示例函数。
摘要由CSDN通过智能技术生成

72ca8b6f150583353d76767fff07b128.jpeg

SWM32S单片机有2个I2C外设,其特点如下:

    1. 支持最高1MHZ速率主机模式

    2. 支持最高400KHZ速率从机模式

    3. 支持7位或10位地址

    4. 波特率可配置

    5. 支持中断功能

今天就以驱动电容触摸芯片GT911为例,介绍一下I2C模块的使用。

配置I2C之前,首先要配置一下端口映射,这里使用GPIOA9和GPIOA10,使能端口上拉功能(注意该单片机不是所有端口支持内部上拉功能)。

然后配置I2C为主机模式,地址为7位,时钟频率400K,不使能中断。程序如下:

void i2c_initialization(void)
{
  I2C_InitStructure I2C_initStruct;


  PORT_Init(PORTA, PIN10, FUNMUX0_I2C0_SCL, 1);  //GPIOA.10配置为I2C0 SCL引脚
  PORT->PORTA_PULLU |= (1 << PIN10);        //必须使能上拉,用于模拟开漏
  PORT_Init(PORTA, PIN9, FUNMUX1_I2C0_SDA, 1);  //GPIOA.9配置为I2C0 SDA引脚
  PORT->PORTA_PULLU |= (1 << PIN9);        //必须使能上拉,用于模拟开漏


  I2C_initStruct.Master = 1;
  I2C_initStruct.Addr7b = 1;
  I2C_initStruct.MstClk = 400000;
  I2C_initStruct.MstIEn = 0;
  I2C_Init(I2C0, &I2C_initStruct);


  I2C_Open(I2C0);
}

再看一下I2C结构体的定义,里面还有一些从机的成员变量。从机模式用的比较少,这里就不做介绍了。

typedef struct {
  uint8_t  Master;    //1 主机模式
  uint8_t  Addr7b;    //1 7位地址     0 10位地址


  uint32_t MstClk;    //主机传输时钟频率
  uint8_t  MstIEn;    //主机模式中断使能


  uint16_t SlvAddr;    //从机地址
  uint8_t  SlvRxEndIEn;  //从机接收完成中断使能
  uint8_t  SlvTxEndIEn;  //从机发送完成中断使能
  uint8_t  SlvSTADetIEn;  //从机检测到起始中断使能
  uint8_t  SlvSTODetIEn;  //从机检测到终止中断使能
  uint8_t  SlvRdReqIEn;  //从机接收到读请求中断使能
  uint8_t  SlvWrReqIEn;  //从机接收到写请求中断使能
} I2C_InitStructure;

I2C读写相关的函数有以下几个。顺便说一句,官方的库函数基本上都有中文注释,这一点比较友好。

uint8_t I2C_Start(I2C_TypeDef * I2Cx, uint8_t addr);
void I2C_Stop(I2C_TypeDef * I2Cx);
uint8_t I2C_Write(I2C_TypeDef * I2Cx, uint8_t data);
uint8_t I2C_Read(I2C_TypeDef * I2Cx, uint8_t ack);

使用时,按照芯片定义的时序调用相关函数即可。

一般的I2C器件写数据流程为:

  1. 启动I2C,发送器件地址

  2. 发送寄存器地址(如果是EEPROM,则是存储地址)

  3. 发送寄存器数据(如果是EEPROM,则是存储的数据)

  4. 停止I2C

读数据流程为:

  1. 启动I2C,发送器件地址

  2. 发送寄存器地址(如果是EEPROM,则是存储地址)

  3. 重新启动I2C,发送器件地址

  4. 读取寄存器数据(前面读取发送ACK,最后一次发送NACK)

  5. 停止I2C

GT911读写寄存器函数如下:

//功能说明:  读GT911寄存器
static uint8_t GT911_RdReg(uint16_t reg, uint8_t *buf, uint8_t len)
{
    uint8_t i;
    uint8_t ack;


    ack = I2C_Start(I2C0, (DEV_ADDR << 1) | 0);
    if (ack == 0)
        goto rd_fail;


    ack = I2C_Write(I2C0, reg >> 8);
    if (ack == 0)
        goto rd_fail;


    ack = I2C_Write(I2C0, reg & 0XFF);
    if (ack == 0)
        goto rd_fail;


    ack = I2C_Start(I2C0, (DEV_ADDR << 1) | 1); //ReStart
    if (ack == 0)
        goto rd_fail;


    for (i = 0; i < len - 1; i++)
    {
        buf[i] = I2C_Read(I2C0, 1);
    }
    buf[i] = I2C_Read(I2C0, 0);


    I2C_Stop(I2C0);
    delay();
    return 1;


rd_fail:
    I2C_Stop(I2C0);
    delay();
    return 0;
}
//功能说明:  写GT911寄存器
static uint8_t GT911_WrReg(uint16_t reg, uint8_t *buf, uint8_t len)
{
    uint8_t i;
    uint8_t ack;


    ack = I2C_Start(I2C0, (DEV_ADDR << 1) | 0);
    if (ack == 0)
        goto wr_fail;


    ack = I2C_Write(I2C0, reg >> 8);
    if (ack == 0)
        goto wr_fail;


    ack = I2C_Write(I2C0, reg & 0XFF);
    if (ack == 0)
        goto wr_fail;


    for (i = 0; i < len; i++)
    {
        ack = I2C_Write(I2C0, buf[i]);
        if (ack == 0)
            goto wr_fail;
    }


    I2C_Stop(I2C0);
    delay();
    return 1;


wr_fail:
    I2C_Stop(I2C0);
    delay();
    return 0;
}

推荐阅读:

UART波特率对时钟精度的要求有多高?

PCB大电流设计方法简介

超级电容有什么用?

   欢迎关注公众号"嵌入式技术开发",大家可以后台给我留言沟通交流。如果觉得该公众号对你有所帮助,也欢迎推荐分享给其他人。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值