stm32f4标准库开发——模拟iic

534 阅读1分钟

stm32f4标准库开发——模拟iic

主要概念:

​ IIC总线:I2C 总线是一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。

​ IIC总线定义:时钟线:sck 数据线:sda

​ 软件模拟:通过软件控制普通 GPIO 引脚高低点评切换,来模拟总线时序,从而达到与总线协议一样的效果。

​ 缺点:与使用硬件 IIC 相比,会占用更多的 CPU 时间。

实验目的:

​ 本实现通过软件模拟 IIC 时序,编写 IIC 发送接收函数。

硬件电路:

​ 本实验的蜂鸣器为有源蜂鸣器

​ PB8 --> IIC_SCL

​ PB9 --> IIC_SDA

08_hardware1.png

主要库函数调用:

#define sda_in()  {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=0<<9*2;}
#define sda_out() {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=1<<9*2;}
#define iic_sda_out(x)		PBout(9)=x
#define iic_scl_out(x)		PBout(8)=x
#define iix_read_sda()		PBin(9)

代码:

//iic.c
#include "iic.h"
#include "base.h"
#include "delay.h"

//***********************************************************************
//移植修改部分
#define sda_in()  {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=0<<9*2;}
#define sda_out() {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=1<<9*2;}
#define iic_sda_out(x)		PBout(9)=x
#define iic_scl_out(x)		PBout(8)=x
#define iix_read_sda()		PBin(9)

static void iic_gpio_init(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
	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_UP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}

static void iic_gpio_deinit(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}
//***********************************************************************


void iic_init(void)
{			
	iic_gpio_init();
	
	iic_scl_out(1);
	iic_sda_out(1);
}

void iic_deinit(void)
{			
	iic_gpio_deinit();
	
	iic_scl_out(1);
	iic_sda_out(1);
}

void iic_start(void)
{
	sda_out();
	iic_sda_out(1);	  	  
	iic_scl_out(1);
	delay_us(4);
 	iic_sda_out(0);
	delay_us(4);
	iic_scl_out(0);
}

void iic_stop(void)
{
	sda_out();
	iic_scl_out(0);
	iic_sda_out(0);
 	delay_us(4);
	iic_scl_out(1); 
	iic_sda_out(1);
	delay_us(4);							   	
}

uint8_t iic_wait_ack(void)
{
	uint8_t ucerrtime = 0;
	sda_in(); 
	iic_sda_out(1);
	delay_us(1);	   
	iic_scl_out(1);
	delay_us(1);	 
	while(iix_read_sda())
	{
		ucerrtime++;
		if(ucerrtime > 250)
		{
			iic_stop();
			return 1;
		}
	}
	iic_scl_out(0);   
	return 0;  
}

void iic_ack(void)
{
	iic_scl_out(0);
	sda_out();
	iic_sda_out(0);
	delay_us(2);
	iic_scl_out(1);
	delay_us(2);
	iic_scl_out(0);
}

void iic_nack(void)
{
	iic_scl_out(0);
	sda_out();
	iic_sda_out(1);
	delay_us(2);
	iic_scl_out(1);
	delay_us(2);
	iic_scl_out(0);
}	

void iic_send_byte(uint8_t txd)
{                        
    uint8_t t;
	
	sda_out(); 	    
    iic_scl_out(0);
    for(t = 0; t < 8; t++)
    {              
        iic_sda_out((txd & 0x80) >> 7);
        txd <<= 1; 	  
		delay_us(2);
		iic_scl_out(1);
		delay_us(2); 
		iic_scl_out(0);	
		delay_us(2);
    }	 
} 

uint8_t iic_read_byte(unsigned char ack)
{
	unsigned char i, receive = 0;
	
	sda_in();
    for(i = 0; i < 8; i++ )
	{
        iic_scl_out(0); 
        delay_us(2);
		iic_scl_out(1);
        receive <<= 1;
        if(iix_read_sda())
			receive++;   
		delay_us(1); 
    }					 
    if (!ack)
        iic_nack();
    else
        iic_ack(); 
    return receive;
}

//iic.h
#ifndef _IIC_H
#define _IIC_H

#include "stdint.h"

void iic_init(void);
void iic_deinit(void);
void iic_start(void);
void iic_stop(void);
void iic_send_byte(uint8_t txd);
uint8_t iic_read_byte(unsigned char ack);
uint8_t iic_wait_ack(void);
void iic_ack(void);
void iic_nack(void);

void iic_write_one_byte(uint8_t daddr, uint8_t addr, uint8_t data);
uint8_t iic_read_one_byte(uint8_t daddr, uint8_t addr);	 

#endif

编译运行:result

如下,编译无报错,无警告。

01_build.png

总结:

​ 理论上gpio操作加上精确的延时,能模拟出任何总线的时序

​ iic.c将移植部分单独摘取出来,方便未来的移植开发

公众号:

​ 关注公众号 InsertingAll,获取嵌入式学习资源,学习更多嵌入式知识

扫码570x208.png