单片机
返回首页

⑥ STM32G431 IIC的使用,驱动24C02存取数据,驱动可可编程电阻MC

2025-11-05 来源:bilibili

摘要

本文章基于国信长天M4开发板,讲述了STM32G431 IIC通信使用步骤,驱动开发板上的24C02存储芯片及可编程电阻MCP4017,祝各位学生蓝桥杯电子比赛取得好成绩!

M4开发板 IIC接口

由上图可以看出,IIC总线使用的是引脚PB6和PB7,总线上挂接了两个设备,分别是存储芯片24C02和可编程电阻MCP4017。


IIC 通信 使用步骤

下面将基于硬件原厂提供的显示屏示例代码: 介绍IIC驱动 和 的使用步骤:


① 新建(或复制) i2c.c , i2c.h,并添加到工程


在  ->  文件夹下,新建文件 , 内容如下:


#include 'i2c.h'


#define DELAY_TIME 20


void SDA_Input_Mode()

{

    GPIO_InitTypeDef GPIO_InitStructure = {0};


    GPIO_InitStructure.Pin = GPIO_PIN_7;

    GPIO_InitStructure.Mode = GPIO_MODE_INPUT;

    GPIO_InitStructure.Pull = GPIO_PULLUP;

    GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;

    HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);

}


void SDA_Output_Mode()

{

    GPIO_InitTypeDef GPIO_InitStructure = {0};


    GPIO_InitStructure.Pin = GPIO_PIN_7;

    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;

    GPIO_InitStructure.Pull = GPIO_NOPULL;

    GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;

    HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);

}


void SDA_Output( uint16_t val )

{

    if ( val )

    {

        GPIOB->BSRR |= GPIO_PIN_7;

    }

    else

    {

        GPIOB->BRR |= GPIO_PIN_7;

    }

}


void SCL_Output( uint16_t val )

{

    if ( val )

    {

        GPIOB->BSRR |= GPIO_PIN_6;

    }

    else

    {

        GPIOB->BRR |= GPIO_PIN_6;

    }

}


uint8_t SDA_Input(void)

{

if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) == GPIO_PIN_SET){

return 1;

}else{

return 0;

}

}


static void delay1(unsigned int n)

{

    uint32_t i;

    for ( i = 0; i < n; ++i);

}


void I2CStart(void)

{

    SDA_Output(1);

    delay1(DELAY_TIME);

    SCL_Output(1);

    delay1(DELAY_TIME);

    SDA_Output(0);

    delay1(DELAY_TIME);

    SCL_Output(0);

    delay1(DELAY_TIME);

}


void I2CStop(void)

{

    SCL_Output(0);

    delay1(DELAY_TIME);

    SDA_Output(0);

    delay1(DELAY_TIME);

    SCL_Output(1);

    delay1(DELAY_TIME);

    SDA_Output(1);

    delay1(DELAY_TIME);


}


unsigned char I2CWaitAck(void)

{

    unsigned short cErrTime = 5;

    SDA_Input_Mode();

    delay1(DELAY_TIME);

    SCL_Output(1);

    delay1(DELAY_TIME);

    while(SDA_Input())

    {

        cErrTime--;

        delay1(DELAY_TIME);

        if (0 == cErrTime)

        {

            SDA_Output_Mode();

            I2CStop();

            return ERROR;

        }

    }

    SDA_Output_Mode();

    SCL_Output(0);

    delay1(DELAY_TIME);

    return SUCCESS;

}


void I2CSendAck(void)

{

    SDA_Output(0);

    delay1(DELAY_TIME);

    delay1(DELAY_TIME);

    SCL_Output(1);

    delay1(DELAY_TIME);

    SCL_Output(0);

    delay1(DELAY_TIME);

}


void I2CSendNotAck(void)

{

    SDA_Output(1);

    delay1(DELAY_TIME);

    delay1(DELAY_TIME);

    SCL_Output(1);

    delay1(DELAY_TIME);

    SCL_Output(0);

    delay1(DELAY_TIME);

}


void I2CSendByte(unsigned char cSendByte)

{

    unsigned char  i = 8;

    while (i--)

    {

        SCL_Output(0);

        delay1(DELAY_TIME);

        SDA_Output(cSendByte & 0x80);

        delay1(DELAY_TIME);

        cSendByte += cSendByte;

        delay1(DELAY_TIME);

        SCL_Output(1);

        delay1(DELAY_TIME);

    }

    SCL_Output(0);

    delay1(DELAY_TIME);

}


unsigned char I2CReceiveByte(void)

{

    unsigned char i = 8;

    unsigned char cR_Byte = 0;

    SDA_Input_Mode();

    while (i--)

    {

        cR_Byte += cR_Byte;

        SCL_Output(0);

        delay1(DELAY_TIME);

        delay1(DELAY_TIME);

        SCL_Output(1);

        delay1(DELAY_TIME);

        cR_Byte |=  SDA_Input();

    }

    SCL_Output(0);

    delay1(DELAY_TIME);

    SDA_Output_Mode();

    return cR_Byte;

}


void I2CInit(void)

{

GPIO_InitTypeDef GPIO_InitStructure = {0};


GPIO_InitStructure.Pin = GPIO_PIN_7 | GPIO_PIN_6;

GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;

GPIO_InitStructure.Pull = GPIO_PULLUP;

GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;

HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);

}

在  -> 文件夹下,新建文件 , 内容如下:


#ifndef __I2C_H

#define __I2C_H


#include 'main.h'


void I2CStart(void);

void I2CStop(void);

unsigned char I2CWaitAck(void);

void I2CSendAck(void);

void I2CSendNotAck(void);

void I2CSendByte(unsigned char cSendByte);

unsigned char I2CReceiveByte(void);

void I2CInit(void);


#endif



双击Keil 开发环境里面的  , 打开添加文件对话框,在 -> 中,找到并添加。添加后如下图所示:

② main.c 添加#include "i2c.h"


在  适当位置添加,添加后如下图所示:

③ 复制24C02 读写代码


将下列代码复制到的适当位置


//从24C02中读取数据

uint8_t x24c02_read(uint8_t address)

{

unsigned char val;


I2CStart();

I2CSendByte(0xa0);

I2CWaitAck();


I2CSendByte(address);

I2CWaitAck();


I2CStart();

I2CSendByte(0xa1);

I2CWaitAck();

val = I2CReceiveByte();

I2CWaitAck();

I2CStop();


return(val);

}


//向24C02写数据

void x24c02_write(unsigned char address,unsigned char info)

{

I2CStart();

I2CSendByte(0xa0);

I2CWaitAck();


I2CSendByte(address);

I2CWaitAck();

I2CSendByte(info);

I2CWaitAck();

I2CStop();

}

④ 复制MCP4017 读写程序


将下列代码复制到的适当位置


//设置可变电阻当前的阻值

void write_resistor(uint8_t value)

{

I2CStart();

I2CSendByte(0x5E);

I2CWaitAck();


I2CSendByte(value);

I2CWaitAck();

I2CStop();

}


//读取可变电阻当前的阻值

uint8_t read_resistor(void)

{

uint8_t value;

I2CStart();

I2CSendByte(0x5F);

I2CWaitAck();


value = I2CReceiveByte();

I2CSendNotAck();

I2CStop();


return value;

}



⑤在main() 中调用 I2CInit();


如下图所示,在 函数的适当位置调用 

⑥ 读写24C02芯片内部的数据


uint8_t val = 0;

val = x24c02_read(0); //读取24C02 0地址的数据

x24c02_write(0, val); //向24C02 0 地址写入数据

⑦ 读取/设置MCP4017的电阻值


uint8_t val = 0;

val = read_resistor(); //读取电阻值,真实电阻值要 * 0.7874

write_resistor(20); //设置电阻值为 0.7874 * 20 K

总结

IIC 驱动 24C02和MCP4017 步骤总结如下:


创建i2c.c,i2c.h文件,并添加到工程中


main.c中添加 #include "i2c.h"


复制24C02及MCP4017的控制代码到main.c;


在主函数中调用 I2CInit();


读写/控制 24C02 与 MCP4017


进入单片机查看更多内容>>
相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 便携式混音器

  • 18W乙类音频放大器

  • 6晶体管H桥

  • USB LED调光器

  • USB自供电声卡

  • AVR LCD温度计—LM35

    相关电子头条文章