STM32—IIC通信(软件实现底层函数)
使用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通信(软件实现底层函数)的更多相关文章
- 半吊子的STM32 — IIC通信
半双工通信模式:以字节模式发送(8位): 两线式串行总线,SDA(数据信号)和SCL(时钟信号)两条信号线都为高电平时,总线为空闲状态:起始时,SCL稳定为高电平,SDA电平由高向低跳变:停止时,SC ...
- STM32 IIC双机通信—— HAL库硬件IIC版
参考传送门 关于IIC的原理这里我就不多说了,网上有很多很好的解析,如果要看我个人对IIC的理解的话,可以点击查看,这里主要讲一下怎样利用STM32CubeMx实现IIC的通讯,经过个人实践,感觉HA ...
- 基于51单片机IIC通信的PCF8591学习笔记
引言 PCF8591 是单电源,低功耗8 位CMOS 数据采集器件,具有4 个模拟输入.一个输出和一个串行I2C 总线接口.3 个地址引脚A0.A1 和A2 用于编程硬件地址,允许将最多8 个器件连接 ...
- 基于51单片机IIC通信的AT24C02学习笔记
引言 最近在学习几种串行通信协议,感觉收获很多,这篇文章是学习IIC总线协议的第一篇文章,以后还会再写一篇关于PCF8591 IIC通信的ADDA转换芯片的文章. 关于IIC总线 IIC 即Inter ...
- Stm32串口通信(USART)
Stm32串口通信(UART) 串口通信的分类 串口通信三种传递方式 串口通信的通信方式 串行通信的方式: 异步通信:它用一个起始位表示字符的开始,用停止位表示字符的结束.其每帧的格式如下: 在一帧格 ...
- STM32串口通信UART使用
STM32串口通信UART使用 uart使用的过程为: 1. 使能GPIO口和UART对应的总线时钟 2. 配置GPIO口的输出模式 3. 配置uart口相关的基本信息 4. 使能uart口的相关的中 ...
- 【Java】Java socket通信使用read,readline函数的阻塞问题
Socket通信是Java网络编程中比较基础的部分,其原理其实就是源ip,源端口和目的ip,目的端口组成的套接字通信.其底层还设及到了TCP协议的通信. Java中的Socket通信可以通过客户端的S ...
- STM32 对内部FLASH读写接口函数(转)
源:STM32 对内部FLASH读写接口函数 因为要用内部FLASH代替外部EEPROM,把参数放在STM32的0x08000000+320K处,其中20K是bootloader,300K是应用程序. ...
- STM32 串口通信使用奇偶校验
STM32串口通信如果使用奇偶校验,需要设置数据位长度为9bit USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USAR ...
随机推荐
- Linux之19——Shell编程基础详解
第一部分:Linux Shell 简介 Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 既是一种命令语言,又是一种程序设计语言. Shell 是指一种应用程序, ...
- 管理员的基本防范措施 Linux系统安全及应用
系统安全及应用一.账号安全基本措施① 系统账号清理② 密码安全控制③ 命令历史限制④ 终端自动注销二.SU命令切换用户① 用途及用法② 验证密码③ 限制使用su命令的用户④ 查看su操作记录补充三.L ...
- python encode decode
Python encode()encode() 方法以 encoding 指定的编码格式编码字符串.errors参数可以指定不同的错误处理方案.写法:str.encode(encoding='UTF- ...
- 记录APP 启动ACTIVITITY
a.启动待测apkb.开启日志输出:adb logcat>D:/log.txt c.关闭日志输出:ctrl+cd.查看日志找寻: Displayed com.mm.android.hsy/.ui ...
- Junit测试用例配置Log4j
用Junit测试非常方便,但有时我们想要看日志来方便排除,使用spring+log4j时,用Junit测试看日志很多人都不太会,即如何将Junit与log4j进行整合. 我也是研究了半天,才终于找到了 ...
- tensorflow2 自定义损失函数使用的隐藏坑
Keras的核心原则是逐步揭示复杂性,可以在保持相应的高级便利性的同时,对操作细节进行更多控制.当我们要自定义fit中的训练算法时,可以重写模型中的train_step方法,然后调用fit来训练模型. ...
- Html模板引擎Handlerbars使用demo
1.自定义demo <html> <head> <script src="./handlebars-v4.0.12.js"></scrip ...
- Android系统编程入门系列之界面Activity响应多元的属性动画
在响应丝滑动画一篇文章中,分别介绍了作用于普通视图.绘制视图的绘制对象.和界面这三种对象的动画效果,但是都有一些使用的局限性.比如这些动画都只是以屏幕上绘制更新的方式绘制动画,并没有真实改变作用对象的 ...
- springmvc学习指南 之---第27篇 spring如何实现servlet3.0无web.xml 配置servlet对象的
writedby 张艳涛 基于web.xml配置,有人说麻烦,tomcat给按照servlet3.0,实现了基于注解@WebServlet,有人说springmvc的springmvc.xml配置麻烦 ...
- 【JavaWeb】EL表达式&过滤器&监听器
EL表达式和JSTL EL表达式 EL表达式概述 基本概念 EL表达式,全称是Expression Language.意为表达式语言.它是Servlet规范中的一部分,是JSP2.0规范加入的内容.其 ...