【国信长天蓝桥杯】⑥ STM32G431 IIC的使用,驱动24C02存取数据,驱动可可编程电阻MCP4017

摘要

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

M4开发板 IIC接口

在这里插入图片描述

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



IIC 通信 使用步骤

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

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

工程目录 -> Src 文件夹下,新建文件 i2c.c, 内容如下:

#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);
}

工程目录 -> Inc文件夹下,新建文件 i2c.h, 内容如下:

#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 开发环境里面的 Application/User , 打开添加文件对话框,在向上一级 -> Src中,找到i2c.c并添加。添加后如下图所示:
在这里插入图片描述

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

main.c 适当位置添加 #include "i2c.h",添加后如下图所示:
在这里插入图片描述
③ 复制24C02 读写代码

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

//从24C02中读取数据
uint8_t x24c02_read(uint8_t address)
{
	unsigned char val;
	
	I2CStart(); 
	I2CSendByte(0xa0);
	I2CWaitAck(); 
	
	I2CSendByte(address);
	I2CWaitAck(); 
	I2CStop();
	
	I2CStart();
	I2CSendByte(0xa1); 
	I2CWaitAck();
	val = I2CReceiveByte(); 
	I2CSendNotAck();
	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 读写程序

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

//设置可变电阻当前的阻值
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()

如下图所示,在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 步骤总结如下:

  1. 创建i2c.ci2c.h文件,并添加到工程中
  2. main.c中添加 #include "i2c.h"
  3. 复制24C02MCP4017的控制代码到main.c
  4. 在主函数中调用 I2CInit();
  5. 读写/控制 24C02 与 MCP4017

如果此文章对你有帮助,欢迎点赞 关注 收藏 转发.


我是鹏老师

  • 13
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值