stm32软件模拟IIC协议:
IIC协议需要SCl,SDA两根线,在主机的视角来看由六个基本单元组成:起始信号,终止信号,发送字节,接收字节,发送应答,接收应答。
下面用一个初始化函数,以及六个分别与基本单元对应的函数来完成IIC底层驱动:
GuiStar_IIC.h:
/**
****************************************************************************************
* @file GuiStar_IIC.h
* @author GuiStar-李什么恩
* @version V2.0.1
* @date 2023-1-20
* @brief IIC通讯协议基本单元函数
* @note 本程序没有设置SCL,SDA线上拉电阻,需要硬件上提供!
****************************************************************************************
*/
#ifndef __GUISTAR_IIC_H__
#define __GUISTAR_IIC_H__
#include "stm32f10x.h" // Device header
#include "IO.h"
#include "Delay.h"
void GuiStar_IIC_Init(GPIO_TypeDef* SCL_Port, uint16_t SCL_Pin, GPIO_TypeDef* SDA_Port, uint16_t SDA_Pin, uint8_t Delay_TIME);
void GuiStar_IIC_Start(void);
void GuiStar_IIC_Stop(void);
void GuiStar_IIC_SendByte(uint8_t Byte);
uint8_t GuiStar_IIC_ReceiveByte(void);
void GuiStar_SendAck(uint8_t AckBit);
uint8_t GuiStar_ReceiveAck(void);
#endif
/***********************IIC时序的一般结构(未完待续。。。)**************************/
GuiStar_IIC.c:
#include "GuiStar_IIC.h"
GPIO_TypeDef* scl_Port;
uint16_t scl_Pin;
GPIO_TypeDef* sda_Port;
uint16_t sda_Pin;
uint8_t Delay_time;
#define GuiStar_W_SCL(x) GPIO_WriteBit(scl_Port, scl_Pin, (BitAction) (x))//时钟线控制宏
#define GuiStar_W_SDA(x) GPIO_WriteBit(sda_Port, sda_Pin, (BitAction) (x))//数据线写宏
#define GuiStar_R_SDA GPIO_ReadInputDataBit(sda_Port, sda_Pin) //数据线读宏
#define waiting_Delay_time Delay_us(Delay_time) //延时函数宏
/**
* @brief IIC初始化函数,完成引脚选择和初始化
* @param SCL_Port 选择SCL端口
* @param SCL_Pin 选择SCL引脚
* @param SDA_Port 选择SDA端口
* @param SDA_Pin 选择SDA引脚
* @param Delay_TIME 选择延时时长,单位us
* @retval 无
*/
void GuiStar_IIC_Init(GPIO_TypeDef* SCL_Port, uint16_t SCL_Pin, GPIO_TypeDef* SDA_Port, uint16_t SDA_Pin, uint8_t Delay_TIME)
{
//全局传参
scl_Port=SCL_Port;
scl_Pin=SCL_Pin;
sda_Port=SDA_Port;
sda_Pin=SDA_Pin;
Delay_time=Delay_TIME;
//初始化IO为开漏输出
IO_Init(SCL_Port, SCL_Pin, GPIO_Mode_Out_OD);
IO_Init(SDA_Port, SDA_Pin, GPIO_Mode_Out_OD);
//IO置高电平(开漏输出下,高电平为浮空状态,但是可以接受外部硬件上拉电阻拉高电平)
GuiStar_W_SCL(1);
GuiStar_W_SDA(1);
}
//IIC起始信号
void GuiStar_IIC_Start(void)
{
GuiStar_W_SDA(1);
GuiStar_W_SCL(1);
waiting_Delay_time;
GuiStar_W_SDA(0);
waiting_Delay_time;
GuiStar_W_SCL(0);
waiting_Delay_time;
}
//IIC终止信号
void GuiStar_IIC_Stop(void)
{
GuiStar_W_SDA(0);
waiting_Delay_time;
GuiStar_W_SCL(1);
waiting_Delay_time;
GuiStar_W_SDA(1);
waiting_Delay_time;
}
/**
* @brief SDA总线向从机发送一个字节
* @param Byte 要发送的字节
* @retval 无
*/
void GuiStar_IIC_SendByte(uint8_t Byte)
{
uint8_t i;
for(i=0;i<8;i++)
{
GuiStar_W_SDA((0x80>>i)&Byte);
waiting_Delay_time;
GuiStar_W_SCL(1);
waiting_Delay_time;
GuiStar_W_SCL(0);
waiting_Delay_time;
}
}
/**
* @brief 主机(stm32)在SDA总线上接收一个字节
* @param 无
* @retval Byte 接受的字节
*/
uint8_t GuiStar_IIC_ReceiveByte(void)
{
uint8_t i;
uint8_t Byte=0x00;
GuiStar_W_SDA(1);//主机释放SDA为输入模式,SDA将由从机掌管高低电平
waiting_Delay_time;
for(i=0;i<8;i++)
{
GuiStar_W_SCL(1);
waiting_Delay_time;
if(GuiStar_R_SDA)
{
Byte |= (0x80>>i);
}
GuiStar_W_SCL(0);
waiting_Delay_time;
}
return Byte;
}
/**
* @brief 主机发送应答
* @param AckBit 0代表主机应答从机,1代表主机不应答从机
* @retval 无
*/
void GuiStar_SendAck(uint8_t AckBit)
{
GuiStar_W_SDA(AckBit);
waiting_Delay_time;
GuiStar_W_SCL(1);
waiting_Delay_time;
GuiStar_W_SCL(0);
waiting_Delay_time;
}
/**
* @brief 主机接收从机应答
* @param 无
* @retval AckBit 0代表从机应答主机,1代表从机不应答主机
*/
uint8_t GuiStar_ReceiveAck(void)
{
uint8_t AckBit;
GuiStar_W_SDA(1);//主机释放SDA为输入模式,SDA将由从机掌管高低电平
GuiStar_W_SCL(1);
waiting_Delay_time;
AckBit=GuiStar_R_SDA;//读取Ack
GuiStar_W_SCL(0);
waiting_Delay_time;
return AckBit;
}