STM32F10x IIC 小教程

本文介绍了IIC(Inter-Integrated Circuit)两线式串行总线的基本原理及其在STM32开发板上的应用。重点讲解了IIC总线的信号定义、工作流程、器件地址分配等内容,并给出了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

前言:

        。。。。

 

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

  1. ***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);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值