使用GPIO引脚模拟SDA和SCL总线实现软件模拟IIC通信,IIC的具体通信协议层和物理层链接:IIC

#ifndef __BSP_IIC_H
#define __BSP_IIC_H #include "stm32f10x.h" #define SCL_PORT GPIOA
#define SCL_PIN GPIO_Pin_2
#define SCL_MOOD GPIO_Mode_Out_OD
#define SCL_SPEED GPIO_Speed_50MHz #define SDA_PORT GPIOA
#define SDA_PIN GPIO_Pin_3
#define SDA_MOOD GPIO_Mode_Out_OD
#define SDA_SPEED GPIO_Speed_50MHz #define SDA_1() GPIO_SetBits(SDA_PORT, SDA_PIN)
#define SDA_0() GPIO_ResetBits(SDA_PORT, SDA_PIN) #define SCL_1() GPIO_SetBits(SCL_PORT, SCL_PIN)
#define SCL_0() GPIO_ResetBits(SCL_PORT, SCL_PIN) #define SDA_READ GPIO_ReadInputDataBit(SDA_PORT, SDA_PIN) /* ACK原型为acknowledge,意为:报告已收到 */
void Delay(void);
void IIC_START(void);
void IIC_STOP(void);
void IIC_ACK(void);
void IIC_NACK(void);
uint8_t IIC_ReadACK(void);
void IIC_SendByte(uint8_t data) ;
uint8_t IIC_ReadByte(void);
void IIC_GPIO_Config(void); #endif /* __BSP_IIC_H */


void Delay(void)
{
uint8_t i; /* 
下面的时间是通过逻辑分析仪测试得到的。
工作条件:CPU主频72MHz ,MDK编译环境,1级优化 循环次数为10时,SCL频率 = 205KHz
循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us
循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us
*/
for (i = 0; i < 10; i++);
} /* SCL高电平时期SDA产生下降沿表示起始信号 */
void IIC_START(void)
{
SDA_1();
SCL_1();
Delay(); SDA_0();
Delay();
SCL_0();
Delay();
} /* SCL高电平时期SDA产生上升沿表示停止信号 */
void IIC_STOP(void)
{
SDA_0();
SCL_1();
Delay(); SDA_1();
Delay();
/* 停止信号后SDA和SCL都为高电平 */
} /* SCL高电平时期 SDA保持低电平代表 应答信号 */
void IIC_ACK(void)
{
SDA_0();
Delay();
SCL_1();
Delay(); SCL_0();
Delay();
SDA_1();
/* 随后释放SDA总线 */
} /* SCL高电平时期 SDA保持高电平代表 非应答信号 */
void IIC_NACK(void)
{
SDA_1();
Delay();
SCL_1();
Delay(); SCL_0();
/* SDA已经为高电平,无需释放 */
} /* CPU产生一个SCL时钟,读取应答 ACK:0 NACK:1*/
/* 因为SDA平时为高电平,所以没有收到应答时,SDA还为高电平,即读取到 1 为非应答 */
uint8_t IIC_ReadACK(void)
{
uint8_t k;
/* 释放SDA总线 */
SDA_1();
Delay();
/* SCL为高电平时,才会读取有效数据 */
SCL_1();
Delay(); /* 读取信号 */
if(SDA_READ==1)
k=1;
else
k=0;
/* 收到信号后SCL要拉低 */
SCL_0();
Delay();
return k;
} /* 发送一个字节,先发送高位 */
void IIC_SendByte(uint8_t data)
{
uint8_t n=0x01;
int i;
SCL_0();
Delay();
for(i=7;i>=0;i--)
{
if(n&(data>>i))
{
SDA_1();
Delay();
SCL_1();
Delay();
}
else
{
SDA_0();
Delay();
SCL_1();
Delay();
}
SCL_0();
Delay();
}
/* 发送完一个字节后释放SDA总线 */
SDA_1();
Delay(); } /* 读取一个字节,在CPU产生的SCL高电平时期读取 */
uint8_t IIC_ReadByte(void)
{
// uint8_t i,data=0;
// for(i=0;i<8;i++)
// {
// SCL_1();
// Delay();
// if(SDA_READ)
// {
// data++; /* 利用自增实现对最低位写 1 */
// }
// data<<=1;
// SCL_0();
// Delay();
//
// }
// return data;
// uint8_t i; uint8_t temp = 0; for(i=0;i<8;i++)
{
temp<<=1; SCL_1();
Delay(); if( SDA_READ==1 )
{
temp += 1;
} SCL_0();
Delay();
} return temp;
} /* 配置SCL和SDA对应的GPIO引脚,模式都为开漏输出 */
void IIC_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStruct.GPIO_Pin = SCL_PIN;
GPIO_InitStruct.GPIO_Mode = SCL_MOOD;
GPIO_InitStruct.GPIO_Speed = SCL_SPEED;
GPIO_Init(SCL_PORT, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = SDA_PIN;
GPIO_InitStruct.GPIO_Mode = SDA_MOOD;
GPIO_InitStruct.GPIO_Speed = SDA_SPEED;
GPIO_Init(SDA_PORT, &GPIO_InitStruct); /* 给一个停止信号,使IIC总线上所有设备处于复位 */
IIC_STOP(); }

STM32—IIC通信(软件实现底层函数)的更多相关文章

  1. 半吊子的STM32 — IIC通信

    半双工通信模式:以字节模式发送(8位): 两线式串行总线,SDA(数据信号)和SCL(时钟信号)两条信号线都为高电平时,总线为空闲状态:起始时,SCL稳定为高电平,SDA电平由高向低跳变:停止时,SC ...

  2. STM32 IIC双机通信—— HAL库硬件IIC版

    参考传送门 关于IIC的原理这里我就不多说了,网上有很多很好的解析,如果要看我个人对IIC的理解的话,可以点击查看,这里主要讲一下怎样利用STM32CubeMx实现IIC的通讯,经过个人实践,感觉HA ...

  3. 基于51单片机IIC通信的PCF8591学习笔记

    引言 PCF8591 是单电源,低功耗8 位CMOS 数据采集器件,具有4 个模拟输入.一个输出和一个串行I2C 总线接口.3 个地址引脚A0.A1 和A2 用于编程硬件地址,允许将最多8 个器件连接 ...

  4. 基于51单片机IIC通信的AT24C02学习笔记

    引言 最近在学习几种串行通信协议,感觉收获很多,这篇文章是学习IIC总线协议的第一篇文章,以后还会再写一篇关于PCF8591 IIC通信的ADDA转换芯片的文章. 关于IIC总线 IIC 即Inter ...

  5. Stm32串口通信(USART)

    Stm32串口通信(UART) 串口通信的分类 串口通信三种传递方式 串口通信的通信方式 串行通信的方式: 异步通信:它用一个起始位表示字符的开始,用停止位表示字符的结束.其每帧的格式如下: 在一帧格 ...

  6. STM32串口通信UART使用

    STM32串口通信UART使用 uart使用的过程为: 1. 使能GPIO口和UART对应的总线时钟 2. 配置GPIO口的输出模式 3. 配置uart口相关的基本信息 4. 使能uart口的相关的中 ...

  7. 【Java】Java socket通信使用read,readline函数的阻塞问题

    Socket通信是Java网络编程中比较基础的部分,其原理其实就是源ip,源端口和目的ip,目的端口组成的套接字通信.其底层还设及到了TCP协议的通信. Java中的Socket通信可以通过客户端的S ...

  8. STM32 对内部FLASH读写接口函数(转)

    源:STM32 对内部FLASH读写接口函数 因为要用内部FLASH代替外部EEPROM,把参数放在STM32的0x08000000+320K处,其中20K是bootloader,300K是应用程序. ...

  9. STM32 串口通信使用奇偶校验

    STM32串口通信如果使用奇偶校验,需要设置数据位长度为9bit USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USAR ...

随机推荐

  1. 2shell中处理字符串,字符串的截取、替换

    0.字符串的小知识点 1.字符串的截取 1.1从指定位置开始截取 1.2 从指定字符(子字符串)开始截取 1.3字符串截取的总结 1.4 按指定要求截取 2.字符串的拼接 3.字符串的替换 0.字符串 ...

  2. 文末送书四本 | 这篇Java反射机制太经典!不看后悔!

    先看再点赞,给自己一点思考的时间,如果对自己有帮助,微信搜索[程序职场]关注这个执着的职场程序员. 价值:Java技能,面试经验指导,简历优化,职场规划指导,技能提升方法,讲不完的职场故事,个人成长经 ...

  3. 「CF585E」 Present for Vitalik the Philatelist

    「CF585E」 Present for Vitalik the Philatelist 传送门 我们可以考虑枚举 \(S'=S\cup\{x\}\),那么显然有 \(\gcd\{S'\}=1\). ...

  4. GitBook在Windows上安装及使用

    GitBook是基于Nodejs,使用Git/Github和Markdown制作电子书的命令行工具. 1.安装Nodejs 首先,安装Nodejs,官网地址:https://nodejs.org/en ...

  5. asp.net web.config数据库连接字符串加密与解密

    在WEB网站开发过程中,如果我们将数据库连接字符串封装到.DLL文件中,将会给数据库和程序的迁移带来麻烦,因为万一服务器地址或者数据库发生变更,那么我们就不得不修改源程序并重新将其编译.最好的解决方法 ...

  6. python基础之多线程的操作

    # 多线程实例# 例1.单线程from time import sleep,ctimedef task1(taskName): for i in range(2): print("正在执行 ...

  7. Requests方法 --- post 请求body的四种类型

    常见的 post 提交数据类型有四种: 1.第一种:application/json:这是最常见的 json 格式,也是非常友好的深受小伙伴喜欢的一种,如下{"input1":&q ...

  8. Leetcode:面试题55 - II. 平衡二叉树

    Leetcode:面试题55 - II. 平衡二叉树 Leetcode:面试题55 - II. 平衡二叉树 Talk is cheap . Show me the code . /** * Defin ...

  9. 扩展中国剩余定理(exCRT)

    我 tm--CRT 没看懂 exCRT 却看懂了--emmmm-- 而且这名字完全就是国内的 OI 带师胡起的吧-- 考虑一次同余方程组 \[\begin{cases} x \equiv a_1\ ( ...

  10. Ubuntu 19.10安装Wine软件

    ======================================== 我使用的操作系统版本为Ubuntu 19.10 64位,如果是32位Ubuntu19.10则可以跳过步骤一 1.添加 ...