STM32模拟I2C通讯的驱动程序

目录

STM32模拟I2C通讯的驱动程序

开发环境

引脚连接

驱动程序


STM32模拟I2C通讯的驱动程序

开发环境
复制代码
立创天空星开发板、主控芯片为STM32F407VxT6
引脚连接
复制代码
使用stm32的PB9引脚模拟I2C时钟线SCL、PB8引脚模拟I2C数据线SDA
驱动程序
复制代码
i2c.h文件如下:
cpp 复制代码
#ifndef _I2C_H
#define _I2C_H

#include "stm32f4xx.h"

//端口宏定义
#define RCC_I2C_GPIO          RCC_AHB1Periph_GPIOB
#define PORT_I2C_GPIO         GPIOB

#define GPIO_SDA             GPIO_Pin_8
#define GPIO_SCL             GPIO_Pin_9

//设置SDA输出模式
#define SDA_OUT()   {        \
                        GPIO_InitTypeDef  GPIO_InitStructure; \
                        GPIO_InitStructure.GPIO_Pin = GPIO_SDA; \
                        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; \
                        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; \
                        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; \
                        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; \
                        GPIO_Init(PORT_I2C_GPIO, &GPIO_InitStructure); \
                     }
//设置SDA输入模式
#define SDA_IN()    {        \
                        GPIO_InitTypeDef  GPIO_InitStructure; \
                        GPIO_InitStructure.GPIO_Pin = GPIO_SDA; \
                        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; \
                        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; \
                        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; \
                        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; \
                        GPIO_Init(PORT_I2C_GPIO, &GPIO_InitStructure); \
                    }
//获取SDA引脚的电平
#define SDA_GET()       GPIO_ReadInputDataBit(PORT_I2C_GPIO, GPIO_SDA)

//SDA与SCL输出高低电平
#define SDA(x)          GPIO_WriteBit(PORT_I2C_GPIO, GPIO_SDA, (x?Bit_SET:Bit_RESET) )
#define SCL(x)          GPIO_WriteBit(PORT_I2C_GPIO, GPIO_SCL, (x?Bit_SET:Bit_RESET) )


//模拟I2C引脚初始化
void I2C_GPIO_Init(void);

//I2C起始时序
void I2C_Start(void);

//I2C停止时序
void I2C_Stop(void);

//主机发送应答或者非应答信号
void I2C_Send_Ack(unsigned char ack);

//主机等待从机应答
unsigned char I2C_WaitAck(void);

//主机发送一个字节数据
void Send_Byte(uint8_t dat);

//主机接收一个字节数据
unsigned char Read_Byte(void);

#endif
复制代码
i2c.c文件如下:
cpp 复制代码
#include "i2c.h"

/******************************************************************
 * 函 数 名 称:I2C_GPIO_Init
 * 函 数 说 明:模拟IIC引脚初始化
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 备       注:无
******************************************************************/
void I2C_GPIO_Init(void)
{
    RCC_AHB1PeriphClockCmd(RCC_I2C_GPIO, ENABLE); // 使能GPIO时钟

    GPIO_InitTypeDef  GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Pin = GPIO_SDA | GPIO_SCL;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(PORT_I2C_GPIO, &GPIO_InitStructure);
}


/******************************************************************
 * 函 数 名 称:I2C_Start
 * 函 数 说 明:IIC起始时序
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 备       注:无
******************************************************************/
void I2C_Start(void)
{
    SDA_OUT();
    SCL(1);
    SDA(0);

    SDA(1);
    delay_us(5);
    SDA(0);
    delay_us(5);

    SCL(0);
}


/******************************************************************
 * 函 数 名 称:I2C_Stop
 * 函 数 说 明:I2C停止信号
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 备       注:无
******************************************************************/
void I2C_Stop(void)
{
    SDA_OUT();
    SCL(0);
    SDA(0);

    SCL(1);
    delay_us(5);
    SDA(1);
    delay_us(5);
}


/******************************************************************
 * 函 数 名 称:I2C_Send_Ack
 * 函 数 说 明:主机发送应答或者非应答信号
 * 函 数 形 参:0发送应答  1发送非应答
 * 函 数 返 回:无
 * 备       注:无
******************************************************************/
void I2C_Send_Ack(unsigned char ack)
{
    SDA_OUT();
    SCL(0);
    SDA(0);
    delay_us(5);
    if(!ack) 
        SDA(0);
    else     
        SDA(1);
    SCL(1);
    delay_us(5);
    SCL(0);
    SDA(1);
}


/******************************************************************
 * 函 数 名 称:I2C_WaitAck
 * 函 数 说 明:主机等待从机应答
 * 函 数 形 参:无
 * 函 数 返 回:0有应答  1超时无应答
 * 备       注:无
******************************************************************/
unsigned char I2C_WaitAck(void)
{
    char ack = 0;
    unsigned char ack_flag = 10;
    SCL(0);
    SDA(1);
    SDA_IN();

    SCL(1);
    while( (SDA_GET()==1) && ( ack_flag ) )
    {
        ack_flag--;
        delay_us(5);
    }

    if( ack_flag <= 0 )
    {
        I2C_Stop();
        return 1;	//应答超时返回1
    }
    else
    {
        SCL(0);
        SDA_OUT();
    }
    return ack;		//正常通讯返回应答
}


/******************************************************************
 * 函 数 名 称:Send_Byte
 * 函 数 说 明:主机发送一个字节数据
 * 函 数 形 参:dat要发送的数据
 * 函 数 返 回:无
 * 备       注:无
******************************************************************/
void Send_Byte(uint8_t dat)
{
    int i = 0;
    SDA_OUT();
    SCL(0);//拉低时钟开始数据传输

    for( i = 0; i < 8; i++ )
    {
        SDA( (dat & 0x80) >> 7 );
        delay_us(1);
        SCL(1);
        delay_us(5);
        SCL(0);
        delay_us(5);
        dat<<=1;
    }
}


/******************************************************************
 * 函 数 名 称:Read_Byte
 * 函 数 说 明:主机接收一个字节数据
 * 函 数 形 参:无
 * 函 数 返 回:接收到的数据
 * 备       注:无
******************************************************************/
unsigned char Read_Byte(void)
{
    unsigned char i,receive=0;
    SDA_IN();
    for(i=0;i<8;i++ )
    {
        SCL(0);
        delay_us(5);
        SCL(1);
        delay_us(5);
        receive<<=1;
        if(SDA_GET())
        {
            receive |= 1;
        }
        delay_us(5);
    }
    SCL(0);
  	return receive;
}

​ ​

相关推荐
zhangzhangkeji2 小时前
stm32 5-2 : 中断,代码篇,对射式红外计数器,旋转编码器。 本 M3中等密度的中断向量列表
stm32
尼喃2 小时前
Type-C快充取电芯片工作流程:从适配器识别到电压输出
嵌入式硬件
昌原的儿子LEO2 小时前
ARM 汇编核心知识点总结
嵌入式硬件·学习
老当益壮梁奶奶2 小时前
ARM 汇编学习笔记(二)启动代码、指令、函数调用与 C 混合编程
c语言·arm开发·单片机·嵌入式硬件·51单片机
学习FPGA的电气小兴兴3 小时前
基于FPGA的CORDIC向量模式实现arctan运算,Verilog HDL实现
嵌入式硬件·fpga开发·数字信号处理·verilog·fpga·cordic·arctan
国科安芯3 小时前
商业航天星载数据管理单元的存储容错与接口集成方案研究
嵌入式硬件·架构·ecc·商业航天·抗辐射
天空'之城3 小时前
单片机基础核心知识点汇总(三十八)
单片机·嵌入式硬件
Zw-awa4 小时前
标准外设库到底在替你做什么:从时钟到 GPIO 的一次完整调用
stm32
wuminyu4 小时前
Markword在紧凑对象头上的实现原理剖析
java·linux·c语言·jvm·c++
潘潘的嵌入式日记4 小时前
位操作怎么写才不出错?置位、清位、翻转、取位一次讲清
c语言·嵌入式·寄存器·位操作