stm32之软件模拟IIC

这篇具有很好参考价值的文章主要介绍了stm32之软件模拟IIC。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        在之前的文章中分析过在52上的IIC时序,也测试过stm32的自带IIC功能,这里大致写下如何模拟stm32上的IIC。实验硬件基于stm32f103c8t6

废话不多说,先直接上代码。

一、源码

头文件


#include "stdint.h"
#include "gpio.h"

#ifndef __IIC_H__
#define	__IIC_H__


/*********************引脚和主频根据情况更换*****************************/
#define CPU_FREQUENCY_MHZ  72		 			 // STM32时钟主频

#define IIC_GPIO_PORT	GPIOB			    	 // GPIO端口 
#define IIC_SCL_PIN		GPIO_PIN_9			 // 连接到SCL时钟线的GPIO引脚
#define IIC_SDA_PIN		GPIO_PIN_8			 // 连接到SDA数据线的GPIO引脚
 
#define IIC_SCL_1()  IIC_GPIO_PORT->BSRR = IIC_SCL_PIN											// SCL = 1 
#define IIC_SCL_0()  IIC_GPIO_PORT->BSRR = (uint32_t)IIC_SCL_PIN << 16U  		// SCL = 0 
 
#define IIC_SDA_1()  IIC_GPIO_PORT->BSRR = IIC_SDA_PIN   										// SDA = 1 
#define IIC_SDA_0()  IIC_GPIO_PORT->BSRR = (uint32_t)IIC_SDA_PIN << 16U  		// SDA = 0 
 
#define IIC_SDA_READ()  (IIC_GPIO_PORT->IDR & IIC_SDA_PIN)									// 读SDA引脚 
#define IIC_SCL_READ()  (IIC_GPIO_PORT->IDR & IIC_SCL_PIN)									// 读SCL引脚
 
 
void iic_start(void); //开始信号

void iic_stop(void); //停止信号

void iic_send_byte(uint8_t _ucByte); //发送一个字节

void iic_ack(void); //应答信号

uint8_t iic_read_byte(void); //读取一个字节

uint8_t iic_wait_ack(void); //等待应答信号


#endif

.m文件

#include "iic.h"
 
 void delay_us(__IO uint32_t delay) {
    int last, curr, val;
    int temp;

    while (delay != 0) { 
        temp = delay > 900 ? 900 : delay;
        last = SysTick->VAL;
        curr = last - CPU_FREQUENCY_MHZ * temp;
        if (curr >= 0){
            do{
                val = SysTick->VAL;
            }
            while ((val < last) && (val >= curr));
        } else{
            curr += CPU_FREQUENCY_MHZ * 1000;
            do{
                val = SysTick->VAL;
            }
            while ((val <= last) || (val > curr));
        }
        delay -= temp;
    }
}
 
// IIC 至少0.6us,1us即可
void iic_delay_1us(void) {
	delay_us(1);
}

// SCL保持高电平期间,SDA由高电平变成低电平,产生一个下降沿。
void iic_start(void) {
	IIC_SDA_1();
	IIC_SCL_1();
	iic_delay_1us();
	IIC_SDA_0();
	iic_delay_1us();
}
  
// SCL保持高电平期间,SDA由低电平变成高电平,产生一个上升沿。
void iic_stop(void){
	IIC_SDA_0();
	IIC_SCL_1();
	iic_delay_1us();
	IIC_SDA_1();
	iic_delay_1us();
}

void iic_send_byte(uint8_t _ucByte){
	uint8_t i;
	for (i = 0; i < 8; i++) {
		IIC_SCL_0();
		if (_ucByte & 0x80){
			IIC_SDA_1();
		} else{
			IIC_SDA_0();
		}
		iic_delay_1us();
		IIC_SCL_1();
		iic_delay_1us();
		IIC_SCL_0();
		// 发送最后一位
		if (i == 7) {
			 IIC_SDA_1(); 	// 释放总线
		}
		_ucByte <<= 1;		// 左移一个bit 
		iic_delay_1us();
	}
}

uint8_t iic_read_byte(void){
	uint8_t i;
	uint8_t value = 0;
	for (i = 0; i < 8; i++) {
		value <<= 1;
		IIC_SCL_1();
		iic_delay_1us();
		if (IIC_SDA_READ()) {
			value++;
		}
		IIC_SCL_0();
		iic_delay_1us();
	}
	return value;
}

uint8_t iic_wait_ack(void){
	uint8_t result;

	IIC_SCL_1();	
	iic_delay_1us();
	result = IIC_SDA_READ() ? 1 :0;
	IIC_SCL_0();
	iic_delay_1us();
	return result;
}

void iic_ack(void){
	IIC_SDA_0();	
	iic_delay_1us();
	IIC_SCL_1();	
	iic_delay_1us();
	IIC_SCL_0();
	iic_delay_1us();
	IIC_SDA_1();	
}
 
 
uint8_t iic_CheckDevice(uint8_t _Address){
	uint8_t ucAck;
 
	if (IIC_SDA_READ() && IIC_SCL_READ()){
		iic_start();		/* 发送启动信号 */
 
		/* 发送设备地址+读写控制bit(0 = w, 1 = r) bit7 先传 */
		iic_send_byte(_Address | 0);
		ucAck = iic_wait_ack();	
 
		iic_stop();			
 
		return ucAck;
	}
	return 1;	
}
 
 
void Device_WriteData(uint8_t DeciveAddr,uint8_t *Data,int size){
    int count=size;
		uint8_t *pData=Data;
		//起始信号
    iic_start();    
    //发送器件地址                         
    iic_send_byte(DeciveAddr);       
    //等待应答
    iic_wait_ack();                          
    while(count--)
		{
			//发送数据
			iic_send_byte(*pData++);                     
			//等待应答
			iic_wait_ack();   
		}			 
                       
    //结束信号
    iic_stop();     
}



二、CubeMX配置

模拟iic程序,stm32,嵌入式硬件,单片机

 实验用了PB8和PB9,设置的都是开漏输出式,因为在这个模式下有如下说明:

模拟iic程序,stm32,嵌入式硬件,单片机

在配置成开漏输出时,可以读IDR寄存器。 

三、源码分析

整个源码的格式写法和之前手撸51中的IIC的类似,包括start,stop, ack等的时序。

这里是直接操作的寄存器来输出/输入数据。输出时比如SDA,设置BSRR,读取状态时,比如SDA中的ack,直接读取IDR寄存器。

#define IIC_SCL_1()  IIC_GPIO_PORT->BSRR = IIC_SCL_PIN											// SCL = 1 
#define IIC_SCL_0()  IIC_GPIO_PORT->BSRR = (uint32_t)IIC_SCL_PIN << 16U  		// SCL = 0 
 
#define IIC_SDA_1()  IIC_GPIO_PORT->BSRR = IIC_SDA_PIN   										// SDA = 1 
#define IIC_SDA_0()  IIC_GPIO_PORT->BSRR = (uint32_t)IIC_SDA_PIN << 16U  		// SDA = 0 
 
#define IIC_SDA_READ()  (IIC_GPIO_PORT->IDR & IIC_SDA_PIN)									// 读SDA引脚 
#define IIC_SCL_READ()  (IIC_GPIO_PORT->IDR & IIC_SCL_PIN)									// 读SCL引脚

其它地方就没什么分析的了,和51的代码都一致,O(∩_∩)O哈哈~

完整代码文章来源地址https://www.toymoban.com/news/detail-729884.html

到了这里,关于stm32之软件模拟IIC的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 嵌入式Linux裸机开发(七)UART串口、IIC、SPI通信

    大概学完这三种通信后,之后就先去学系统移植,其他的先暂时放下 串口全称叫做串行接口,通常也叫做 COM 接口。 UART:(Universal Asynchronous Receiver/Trasmitter)通用异步串行收发器。 USART:(Universal Synchronous/Asynchronous Receiver/Transmitter)通用同步/异步串行收发器,相比 UART多了

    2024年02月07日
    浏览(78)
  • STM32软件模拟实现IIC写入和读取AT24C02(STM32CubeMx配置)

    IIC:Inter Integrated Circuit,集成电路总线,是一种 同步 串行 半双工 通信总线。 在使用IIC时分为硬件IIC以及软件IIC,下图为两者的区别: 在使用IIC前先来了解一下IIC总线结构图,即下图: 从图中可以看出IIC有两个双向信号线,一根是数据线SDA,一根是时钟线SCL,并且都接上拉

    2024年02月04日
    浏览(62)
  • STM32 Cube MX 之hal库软件模拟IIC 可直接移植使用

    此为软件模拟IIC,可以直接移植到HAL库使用。.h文件需要自己做函数声明这里就不再放出,如有问题大家可以讨论。 使用的时候只需要更改SDA 和SCL引脚的宏定义就可以移植使用,当然IIC协议其实就是根据IIC的时序图编写代码,主要内容就是包括开始信号,停止信号以及发送数

    2024年02月15日
    浏览(59)
  • HAL库&STM32cubeMX工程软件模拟IIC,改改引脚即可直接使用

    c文件如下 h文件如下

    2024年02月14日
    浏览(58)
  • SPI、UART、RS232、RS485、IIC 5种嵌入式经典通信总线协议

      UART即通用异步收发器,是一种通用的串行、异步通信总线。该总线有两条数据线,可以实现全双工的发送和接收。在嵌入式系统种常用于主机与辅助设备之间的通信。UART就是串口,也是一种通信协议/总线协议。 电脑上已经逐步没有了,换成了usb,但是在嵌入式领域是最

    2024年01月16日
    浏览(61)
  • 蓝桥杯嵌入式(G4系列)HAL:IIC通信之AT24C02与MCP4017

    目录 前言: IIC协议简介: 1、起始信号和停止信号: 2、应答信号: 3、读写字节: AT24C02: 字节写操作: 页写操作: 读操作: MCP4017: 写操作: 读操作:         本篇文章主要介绍IIC通信协议,同时给大家介绍一下蓝桥杯嵌入式的模块的AT24C02和MCP4017,此外本篇博客会采

    2023年04月09日
    浏览(92)
  • 【嵌入式Linux内核驱动】05_IIC子系统 | 硬件原理与常见面试问题 | 应用编程 | 内核驱动 | 总体框架

    1.1 IIC 基础 IIC协议简介—学习笔记_iic标准协议_越吃越胖的黄的博客-CSDN博客 I2C(Inter-Integrated Circuit)是一种串行通信协议,用于连接微控制器、传感器、存储器和其他外设。 I2C使用两条线(SDA和SCL)进行通信,可以连接多个设备,每个设备都有一个唯一的地址。I2C总线上的

    2024年02月09日
    浏览(64)
  • [嵌入式软件][启蒙篇] 搭建在线仿真平台(STM32)

    进入官方,进行注册: 在线仿真地址 ① 新建项目 ② 搭建一个电路 ③ 用STM32F103搭建一个简单电路 ④ 进入编码界面 ⑤ 编译,并进行仿真。 红框是必看文档,新手建议先看中文数据手册,不用看太多,可以边学边看。 至此,环境搭建完毕,后面将在这个平台教学。 在线学

    2024年01月23日
    浏览(41)
  • 模拟IIC通讯协议(stm32)(硬件iic后面在补)

            1、IIC通讯需要两条线就可以,SCL、SDA。         2、IIC的数据传输的速率,不同的ic是不同的,根据电平维持的延时函数的时间来确定IIC数据传输的速率.         3、IIC的延时函数可以使用延时函数,延时函数一般使用系统滴答时钟产生延时,也是在Sysclk频率总线的

    2024年04月15日
    浏览(59)
  • 【嵌入式开发工具】STM32+Keil实现软件工程搭建与开发调试

    本篇文章介绍了使用Keil来对STM32F103C8芯片进行初始工程搭建,以及开发与工程调试的完整过程,帮助读者能够在实战中体会到Keil这个开发环境的使用方法,了解一个嵌入式工程从无到有的过程,并且具备快速搭建一个全新芯片对应最小软件工程的基本能力思路。文章首先介绍

    2024年02月05日
    浏览(66)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包