OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3828|回复: 0

stm32f4标准库开发——模拟iic

[复制链接]

1

主题

2

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2018-11-7
在线时间
5 小时
发表于 2022-1-8 00:32:10 | 显示全部楼层 |阅读模式
stm32f4标准库开发——模拟iic主要概念:
IIC总线:I2C总线是一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。
IIC总线定义:时钟线:sck数据线:sda
软件模拟:通过软件控制普通GPIO 引脚高低点评切换,来模拟总线时序,从而达到与总线协议一样的效果。
缺点:与使用硬件IIC 相比,会占用更多的 CPU 时间。
实验目的:
本实现通过软件模拟IIC 时序,编写 IIC 发送接收函数。
硬件电路:
本实验的蜂鸣器为有源蜂鸣器
PB8-->  IIC_SCL
PB9-->  IIC_SDA
08_hardware1.png
主要库函数调用:
#definesda_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_tiic_wait_ack(void)
{
    uint8_tucerrtime = 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_ttxd)
{                        
    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_tiic_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();
    returnreceive;
}
//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_ttxd);
uint8_tiic_read_byte(unsigned char ack);
uint8_tiic_wait_ack(void);
void iic_ack(void);
void iic_nack(void);

void iic_write_one_byte(uint8_tdaddr, uint8_t addr, uint8_t data);
uint8_tiic_read_one_byte(uint8_t daddr, uint8_t addr);     

#endif
编译运行:result
如下,编译无报错,无警告。
01_build.png
总结:
理论上gpio操作加上精确的延时,能模拟出任何总线的时序
iic.c将移植部分单独摘取出来,方便未来的移植开发
公众号:
关注公众号InsertingAll,获取嵌入式学习资源,学习更多嵌入式知识
attention.png

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-26 06:36

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表