IIC协议层
空闲状态
当IIC总线SDA以及SCL均处于高电平时,规定此状态为空闲状态,对应输出状态为高阻态(各场器件输出效应管截止,导致场效应管电阻很大),由上拉电阻将电平拉高。
起始信号
起始条件:SCL线是高电平时,SDA线从高电平向低电平切换
先写SDA,容易写程序,容易理解
static void I2C_START(void)
{
I2C_SDA_SET();
I2C_SCL_SET();
delay_us(1);
I2C_SDA_CLR();
delay_us(1);
I2C_SCL_CLR();
delay_us(1);
}
停止信号
停止条件:SCL线是高电平时,SDA线从低电平向高电平切换
先写SDA,容易写程序,容易理解
static void I2C_STOP(void)
{
I2C_SDA_CLR();
delay_us(1);
I2C_SCL_SET();
delay_us(1);
I2C_SDA_SET();
delay_us(1);
}
数据有效性
SDA的高或低电平状态只有在 SCL 线的时钟信号是低电平时才能改变。
SDA在SCL的上升沿到来前准备好,并在下降沿到来之前必须稳定。
static void I2C_WriteByte(unsigned char I2C_Byte)
{
unsigned char i = 0;
for(i=0;i<8;i++)
{
I2C_SCL_CLR();
delay_us(1);
if( I2C_Byte & 0x80 )
{
I2C_SDA_SET();
}
else
{
I2C_SDA_CLR();
}
I2C_Byte <<= 1;
delay_us(1);
I2C_SCL_SET();
delay_us(1);
}
I2C_SCL_CLR();
delay_us(1);
I2C_Wait_Ack();
}
应答信号
对于反馈有效应答位ACK的要求是,接收器在第九个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。
static unsigned char I2C_Wait_Ack(void)
{
unsigned char Ack;
I2C_SCL_CLR();
delay_us(1);
I2C_SDA_SET();
delay_us(1);
I2C_SCL_SET();
delay_us(1);
if( I2C_SDA_Read() )
{
Ack = I2C_NO_Ack;
}
else
{
Ack = I2C_Ack;
}
I2C_SCL_SLR();
delay_us(1);
return Ack;
}
配置引脚初始化
void OLED_GPIO_Init(void)
{
GPIO_InitTypeDef I2C_GPIOStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
I2C_GPIOStructure.GPIO_Mode = GPIO_Mode_Out_OD;
I2C_GPIOStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
I2C_GPIOStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &I2C_GPIOStructure);
I2C_SDA_SET();
I2C_SCL_SET();
}
整合软件IIC代码
oled.c
#include "stm32f10x.h"
#include "oled.h"
#include "SysTick.h"
#include "oledfront.h"
void OLED_GPIO_Init(void)
{
GPIO_InitTypeDef I2C_GPIOStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
I2C_GPIOStructure.GPIO_Mode = GPIO_Mode_Out_OD;
I2C_GPIOStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
I2C_GPIOStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &I2C_GPIOStructure);
I2C_SDA_SET();
I2C_SCL_SET();
}
static void I2C_Start(void)
{
I2C_SDA_SET();
I2C_SCL_SET();
delay_us(1);
I2C_SDA_CLR();
delay_us(1);
I2C_SCL_CLR();
delay_us(1);
}
static void I2C_Stop(void)
{
I2C_SDA_CLR();
delay_us(1);
I2C_SCL_SET();
delay_us(1);
I2C_SDA_SET();
delay_us(1);
}
static unsigned char I2C_Wait_Ack(void)
{
unsigned char Ack;
I2C_SCL_CLR();
delay_us(1);
I2C_SDA_SET();
delay_us(1);
I2C_SCL_SET();
delay_us(1);
if( I2C_SDA_Read() )
{
Ack = I2C_NO_Ack;
}
else
{
Ack = I2C_Ack;
}
I2C_SCL_CLR();
delay_us(1);
return Ack;
}
static void I2C_WriteByte(unsigned char I2C_Byte)
{
unsigned char i = 0;
for(i=0;i<8;i++)
{
I2C_SCL_CLR();
delay_us(1);
if(I2C_Byte & 0x80)
{
I2C_SDA_SET();
}
else
{
I2C_SDA_CLR();
}
I2C_Byte <<= 1;
delay_us(1);
I2C_SCL_SET();
delay_us(1);
}
I2C_SCL_CLR();
delay_us(1);
I2C_Wait_Ack();
}
oled.h
#ifndef _OLED_H
#define _OLED_H
#define I2C_SCL_SET() GPIO_SetBits(GPIOB, GPIO_Pin_0)
#define I2C_SCL_CLR() GPIO_ResetBits(GPIOB, GPIO_Pin_0)
#define I2C_SDA_SET() GPIO_SetBits(GPIOB, GPIO_Pin_1)
#define I2C_SDA_CLR() GPIO_ResetBits(GPIOB, GPIO_Pin_1)
#define I2C_SDA_Read() GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_1)
#define I2C_Ack 0
#define I2C_NO_Ack 1
void OLED_GPIO_Init(void);
static void I2C_Start(void);
static void I2C_Stop(void);
static unsigned char I2C_Wait_Ack(void);
static void I2C_WriteByte(unsigned char I2C_Byte);
#endif
|