前言:
IIC(IIC,inter-Integrated circuit),两线式串行总线,用于MCU和外设间的通信。 又俗称 I2C
IIC只需两根线:数据线SDA和时钟线SCL。以半双工方式实现MCU和外设之间数据传输,速度可达400kbps。
这里我用的开发板时正点原子的MiniSTM32,芯片型号为STM32F103RCT6. This is easy, so you can do that very easily!
[objc] view plain copy
***REMENBER STM32 is you! :)
我们在这里进行通俗的讲解,详细的内容,可以在以后再去看STM32手册。
总线信号 :
SDA :串行数据线
SCL :串行时钟
总线空闲状态 :
SDA :高电平
SCL :高电平
起始位:SCL为高电平期间 SDA出现下降沿
终止位:SCL为高电平期间 SDA出现上升沿
数据传输 :SDA的数据在SCL高电平期间被写入从机。所以SDA的数据变化要发生在SCL低电平期间。
IIC时钟频率:不高于400K
应答:当IIC主机(不一定是发送端还是接受端)将8位数据或命令传出后,会将SDA信号设置为输入,等待从机应答(等待SDA由高电平拉为低电平)
若从机正确应答,表明数据或者命令传输成功,否则传输失败,注意,应答信号是数据接收方发送给数据发送方的。
IIC器件地址:每一个IIC器件都有一个器件地址,有的器件地址在出厂时地址就设定好了,用户不可以更改,比如OV7670的
地址为0x42。有的器件例如EEPROM,前四个地址已经确定为1010,后三个地址是由硬件链接确定的,所以一个IIC总线最多能连8个EEPROM芯片。
多主从的系统结构
以上为简单原理介绍,下面看代码:
void IIC_Config(void){
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = SDA_Pin | SCL_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(I2C_PORT, &GPIO_InitStructure);
}
初始化。。。
void SDA_Input(void){
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = SDA_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(I2C_PORT,&GPIO_InitStructure);
}
void SDA_Output(void){
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = SDA_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(I2C_PORT,&GPIO_InitStructure);
}
uint8_t SDA_ReadIn(){
uint8_t bitstatus = 0x00;
if ((I2C_PORT->IDR & SDA_Pin) != (uint32_t)Bit_RESET)
{
bitstatus = (uint8_t)Bit_SET;
}
else
{
bitstatus = (uint8_t)Bit_RESET;
}
return bitstatus;
}
SDA的输出读取配置
void SDA_(u8 n){
n != Low ? (I2C_PORT->BSRR = SDA_Pin): (I2C_PORT->BRR = SDA_Pin);
}
void SCL_(u8 n){
n != Low ? (I2C_PORT->BSRR = SCL_Pin): (I2C_PORT->BRR = SCL_Pin);
}
设置SDA SCL高低电平
void IIC_Start(void){
SDA_H;delay;
SCL_H;delay;
SDA_L;delay;
SCL_L;delay;
}
I2C开始
void IIC_Stop(void){
SCL_L;delay;
SDA_L;delay;
SCL_H;delay;
SDA_H;delay;
}
I2C停止
unsigned char IIC_WaitAck(void){
u8 ErrorTime = 5;
SDA_Input();
delay;
SCL_H;delay;
while((uint8_t)SDA_ReadIn()){
ErrorTime--;
delay;
if(0 ==ErrorTime){
SDA_Output();
IIC_Stop();
return FAILURE;
}
}
SDA_Output();
SCL_L;delay;
return SUCCESS;
}
等待应答
void IIC_SendAck(void){
SDA_L;delay;
delay;
SCL_H;delay;
SCL_L;delay;
}
发送应答
void IIC_SendNoAck(void){
SDA_H;delay;
delay;
SCL_H;delay;
SCL_L;delay;
}
不产生应答
void IIC_SendByte(unsigned char byte){
unsigned char t = 8;
for(;t>0;t--){
SCL_L;delay;
SDA_(byte & 0x80);delay;
byte+=byte;
delay;
SCL_H;delay;
}
SCL_L;delay;
}
发送字节
unsigned char IIC_RecByte(void){
unsigned char t = 8;
unsigned char RevByte = 0;
SDA_Input();
for(;t>0;t--){
RevByte+=RevByte;
SCL_L;delay;
delay;
SCL_H;delay;
RevByte|= SDA_ReadIn();
}
SCL_L;delay;
SDA_Output();
return RevByte;
}
读取字节
#include "stm32f10x.h"
#define I2C_PORT GPIOB
#define SDA_Pin GPIO_Pin_7
#define SCL_Pin GPIO_Pin_6
#define FAILURE 0
#define SUCCESS 1
#define High 1
#define Low 0
#define delay {unsigned int i = 0 ; for(;i<500;++i);}
#define SDA_H SDA_(High)
#define SDA_L SDA_(Low)
#define SCL_H SCL_(High)
#define SCL_L SCL_(Low)
void IIC_Config(void);
void SDA_Input(void);
void SDA_Output(void);
void SDA_(u8 n);
void SCL_(u8 n);
void IIC_Start(void);
void IIC_Stop(void);
unsigned char IIC_WaitAck(void);
void IIC_SendAck(void);
void IIC_SendNoAck(void);
void IIC_SendByte(unsigned char byte);
unsigned char IIC_RecByte(void);
以上为头文件定义
设计资源 培训 开发板 精华推荐
- TP5000X充电板
- max1879
- L7818C远程关断稳压器的典型应用
- LTC3423EMS 1 节电池至 1.8V/600mA 升压转换器的典型应用电路
- MAXREFDES124#:隔离式12V至5.5V 22W无光耦反激电源
- 单片机自动清洁机器人设计(电路图+原理图+流程图+源程序)
- LT8495IFE 750kHz、16V 至 32V 输入、48V 输出、0.5A 升压转换器的典型应用电路
- ANT7-M24LR16E,用于 M24LR16E-R 双接口 EEPROM 的 15 mm x 15 mm 双层天线参考板
- 使用 Infineon Technologies AG 的 OMR7812SR 的参考设计
- 自制10KV 电子负载