C++例程:使用I/O模拟IIC接口(6)
完整的STM32F405代码工程I2C驱动源代码跟踪
一)myiic.c
#include "myiic.h"
#include "delay.h"
#include "stm32f4xx_rcc.h"
//初始化IIC
void IIC_Init(void)
{ GPIO_InitTypeDef GPIO_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟//SCL_1->GPIOA0,SDA_1->GPIOA1GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHzGPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化SCL_1=1;SDA_1=1;
}//产生IIC1起始信号
void IIC1_Start(void)
{SDA1_OUT(); //sda线输出SDA_1=1; SCL_1=1;delay_us(4);delay_us(4);SDA_1=0;//START:when CLK is high,DATA change form high to low delay_us(4);delay_us(4);SCL_1=0;//钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
void IIC1_Stop(void)
{SDA1_OUT();//sda线输出SCL_1=0;SDA_1=0;//STOP:when CLK is high DATA change form low to highdelay_us(4);delay_us(4);SCL_1=1; delay_us(4);delay_us(4);SDA_1=1;//发送I2C总线结束信号delay_us(4);delay_us(4);
}
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
u8 IIC1_Wait_Ack(void)
{u8 ucErrTime=0;SDA1_IN(); //SDA设置为输入 SDA_1=1;delay_us(1); SCL_1=1;delay_us(1); while(READ_SDA1){ucErrTime++;if(ucErrTime>250){IIC1_Stop();return 1;}}SCL_1=0;//时钟输出0 return 0;
} //产生ACK应答
void IIC1_Ack(void)
{SCL_1=0;SDA1_OUT();SDA_1=0;delay_us(2);delay_us(2);SCL_1=1;delay_us(2);delay_us(2);SCL_1=0;
}//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void IIC1_Send_Byte(u8 txd)
{ u8 t; SDA1_OUT(); SCL_1=0;//拉低时钟开始数据传输for(t=0;t<8;t++){ SDA_1=(txd&0x80)>>7;txd<<=1; delay_us(2); //对TEA5767这三个延时都是必须的delay_us(2);SCL_1=1;delay_us(2); delay_us(2);SCL_1=0; delay_us(2);delay_us(2);}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
u8 IIC1_Read_Byte(unsigned char ack)
{unsigned char i,receive=0;SDA1_IN();//SDA设置为输入for(i=0;i<8;i++ ){SCL_1=0; delay_us(2);delay_us(2);SCL_1=1;receive<<=1;if(READ_SDA1)receive++; delay_us(1); delay_us(1);} if (!ack)IIC1_NAck();//发送nACKelseIIC1_Ack(); //发送ACK return receive;
}
二) myiic.h
#ifndef __MYIIC_H
#define __MYIIC_H
#include "sys.h"
//
//PA1输入模式 输出模式
#define SDA1_IN() {GPIOA->MODER&=~(3<<(1*2));GPIOA->MODER|=0<<1*2;}
#define SDA1_OUT() {GPIOA->MODER&=~(3<<(1*2));GPIOA->MODER|=1<<1*2;}
//IO操作函数
#define SCL_1 PAout(0) //SCL
#define SDA_1 PAout(1) //SDA
#define READ_SDA1 PAin(1) //输入SDA
//IIC所有操作函数
void IIC_Init(void); //初始化IIC的IO口
void IIC1_Start(void); //发送IIC开始信号
void IIC1_Stop(void); //发送IIC停止信号
void IIC1_Send_Byte(u8 txd); //IIC发送一个字节
u8 IIC1_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 IIC1_Wait_Ack(void); //IIC等待ACK信号
void IIC1_Ack(void); //IIC发送ACK信号
void IIC1_NAck(void); //IIC不发送ACK信号
void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);
#endif
三) sys.h
#ifndef __SYS_H
#define __SYS_H
#include "stm32f4xx.h"
//
//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).M4同M3类似,只是寄存器地址变了.
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+20) //0x40020014
#define GPIOA_IDR_Addr (GPIOA_BASE+16) //0x40020010
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入
#endif
四)stm32f4xx.h
#ifndef __STM32F4xx_H
#define __STM32F4xx_H#ifdef __cplusplusextern "C" {
#endif /* __cplusplus */typedef struct
{/*!< GPIO port mode register, Address offset: 0x00 */__IO uint32_t MODER; /*!< GPIO port output type register, Address offset: 0x04 */__IO uint32_t OTYPER; /*!< GPIO port output speed register, Address offset: 0x08 */ __IO uint32_t OSPEEDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */__IO uint32_t PUPDR; /*!< GPIO port input data register, Address offset: 0x10 */__IO uint32_t IDR; /*!< GPIO port output data register, Address offset: 0x14 */ __IO uint32_t ODR; /*!< GPIO port bit set/reset low register, Address offset: 0x18 */ __IO uint16_t BSRRL; /*!< GPIO port bit set/reset high register, Address offset: 0x1A */ __IO uint16_t BSRRH; /*!< GPIO port configuration lock register, Address offset: 0x1C */ __IO uint32_t LCKR; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */__IO uint32_t AFR[2];
} GPIO_TypeDef;
/*!< Peripheral base address in the alias region */
#define PERIPH_BASE ((uint32_t)0x40000000)
/*!< Peripheral memory map */
#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000)
/*!< AHB1 peripherals */
#define GPIOA_BASE (AHB1PERIPH_BASE + 0x0000)#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)#ifdef __cplusplus
}
#endif /* __cplusplus */#endif /* __STM32F4xx_H */
五)stm32f4xx_rcc.h
#ifndef __STM32F4xx_RCC_H
#define __STM32F4xx_RCC_H#ifdef __cplusplusextern "C" {
#endif#define RCC_AHB1Periph_GPIOD ((uint32_t)0x00000008)void RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState);#ifdef __cplusplus
}
#endif#endif /* __STM32F4xx_RCC_H */
六)stm32f4xx_rcc.c
#include "stm32f4xx_rcc.h"
/*** @brief Enables or disables the AHB1 peripheral clock.* @note After reset, the peripheral clock (used for registers read/write access)* is disabled and the application software has to enable this clock before * using it. * @param RCC_AHBPeriph: specifies the AHB1 peripheral to gates its clock.* This parameter can be any combination of the following values:* @arg RCC_AHB1Periph_GPIOA: GPIOA clock* @arg RCC_AHB1Periph_GPIOB: GPIOB clock * @arg RCC_AHB1Periph_GPIOC: GPIOC clock* @arg RCC_AHB1Periph_GPIOD: GPIOD clock* @arg RCC_AHB1Periph_GPIOE: GPIOE clock* @arg RCC_AHB1Periph_GPIOF: GPIOF clock* @arg RCC_AHB1Periph_GPIOG: GPIOG clock* @arg RCC_AHB1Periph_GPIOG: GPIOG clock* @arg RCC_AHB1Periph_GPIOI: GPIOI clock* @arg RCC_AHB1Periph_GPIOJ: GPIOJ clock (STM32F42xxx/43xxx devices) * @arg RCC_AHB1Periph_GPIOK: GPIOK clock (STM32F42xxx/43xxx devices) * @arg RCC_AHB1Periph_CRC: CRC clock* @arg RCC_AHB1Periph_BKPSRAM: BKPSRAM interface clock* @arg RCC_AHB1Periph_CCMDATARAMEN CCM data RAM interface clock* @arg RCC_AHB1Periph_DMA1: DMA1 clock* @arg RCC_AHB1Periph_DMA2: DMA2 clock* @arg RCC_AHB1Periph_DMA2D: DMA2D clock (STM32F429xx/439xx devices) * @arg RCC_AHB1Periph_ETH_MAC: Ethernet MAC clock* @arg RCC_AHB1Periph_ETH_MAC_Tx: Ethernet Transmission clock* @arg RCC_AHB1Periph_ETH_MAC_Rx: Ethernet Reception clock* @arg RCC_AHB1Periph_ETH_MAC_PTP: Ethernet PTP clock* @arg RCC_AHB1Periph_OTG_HS: USB OTG HS clock* @arg RCC_AHB1Periph_OTG_HS_ULPI: USB OTG HS ULPI clock* @param NewState: new state of the specified peripheral clock.* This parameter can be: ENABLE or DISABLE.* @retval None*/
void RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState)
{/* Check the parameters */assert_param(IS_RCC_AHB1_CLOCK_PERIPH(RCC_AHB1Periph));assert_param(IS_FUNCTIONAL_STATE(NewState));if (NewState != DISABLE){RCC->AHB1ENR |= RCC_AHB1Periph;}else{RCC->AHB1ENR &= ~RCC_AHB1Periph;}
}
七)delay.h
#ifndef __DELAY_H
#define __DELAY_H
#include <sys.h>
void delay_init(u8 SYSCLK);
void delay_ms(u16 nms);
void delay_us(u32 nus);#endif
相关文章:
C++例程:使用I/O模拟IIC接口(6)
完整的STM32F405代码工程I2C驱动源代码跟踪 一)myiic.c #include "myiic.h" #include "delay.h" #include "stm32f4xx_rcc.h" //初始化IIC void IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure;RCC_AHB1PeriphCl…...
58.在 Vue 3 中使用 OpenLayers 绘制点、线、圆、多边形
前言 在现代 Web 开发中,地图功能已经成为许多应用的重要组成部分。OpenLayers 是一个强大的开源地图库,支持多种地图源和地图操作。结合 Vue 3 的响应式特性,我们可以轻松实现地图的交互功能。本文将详细介绍如何在 Vue 3 中使用 OpenLayer…...
如何快速上手一个鸿蒙工程
作为一名鸿蒙程序猿,当你换了一家公司,或者被交接了一个已有的业务。前辈在找你之前十分钟写了一个他都看不懂的交接文档,然后把一个鸿蒙工程交接给你了,说以后就是你负责了。之后几天你的状态大概就是下边这样的,一堆…...
c++入门之 命名空间与输入输出
1、命名空间 1.1使用命名空间的原因 先看一个例子: #include <iostream>int round 0;int main() {printf("%d", round);return 0; }请问,这个程序能跑起来吗? 答案是否定的 原因是,当我们想创建一个全局变量 …...
GRE技术的详细解释
GRE(Generic Routing Encapsulation,通用路由封装)是一种隧道协议,主要用于在不同网络之间封装和传输其他网络层协议的数据包。它最常用于在IP网络上建立虚拟点到点的隧道连接,是实现VPN的一项关键技术。 下面从原理、…...
Mysql--基础篇--多表查询(JOIN,笛卡尔积)
在MySQL中,多表查询(也称为联表查询或JOIN操作)是数据库操作中非常常见的需求。通过多表查询,你可以从多个表中获取相关数据,并根据一定的条件将它们组合在一起。MySQL支持多种类型的JOIN操作,每种JOIN都有…...
Java 泛型的用法
1. 泛型类 泛型类是指在类定义时使用类型参数来指定类的类型。这样可以在类的内部使用这些类型参数来定义字段、方法的返回类型和参数类型。 public class Box<T> {private T t;public void set(T t) {this.t t;}public T get() {return t;} }在这个例子中,…...
人工智能与物联网:智慧城市的未来
引言 清晨6点,智能闹钟根据你的睡眠状态和天气情况,自动调整叫醒时间;窗帘缓缓打开,阳光洒满房间;厨房里的咖啡机已经为你准备好热饮,而无人驾驶公交车正按时抵达楼下站点。这不是科幻电影的场景ÿ…...
Python标准库之SQLite3
包含了连接数据库、处理数据、控制数据、自定义输出格式及处理异常的各种方法。 官方文档:sqlite3 --- SQLite 数据库的 DB-API 2.0 接口 — Python 3.13.1 文档 官方文档SQLite对应版本:3.13.1 SQLite主页:SQLite Home Page SQL语法教程&a…...
力扣 二叉树的最大深度
树的遍历,dfs与bfs基础。 题目 注意这种题要看根节点的深度是0还是1。 深度优先遍历dfs,通过递归分别计算左子树和右子树的深度,然后返回左右子树深度的最大值再加上 1。递归会一直向下遍历树,直到达到叶子节点或空节点。在回溯…...
Linux_进程间通信_共享内存
什么是共享内存? 对于两个进程,通过在内存开辟一块空间(操作系统开辟的),进程的虚拟地址通过页表映射到对应的共享内存空间中,进而实现通信;物理内存中的这块空间,就叫做共享内存。…...
ubuntu 下生成 core dump
在Ubuntu下,发现程序崩溃后不生成core dump文件, 即使设置了ulimit -c unlimited后仍然无效。 1.ulimit -c unlimited 输出的的含义是核心转储文件的大小限制,单位是blocks,默认是0,表示不生成core dump文件。 2. 重设core_pattern ulimit -c unlimited后,核心转储文件…...
学习HLS.js
前言 HTTP 实时流(也称为HLS(.m3u8))是一种基于HTTP的自适应比特率流通信协议。HLS.js依靠HTML5视频和MediaSource Extensions进行播放,其特点:视频点播和直播播放列表、碎片化的 MP4 容器、加密媒体扩展 …...
2025年华为OD上机考试真题(Java)——判断输入考勤信息能否获得出勤奖
题目: 公司用一个字符串来表示员工的出勤信息: absent:缺勤late:迟到leaveearly:早退present:正常上班 现需根据员工出勤信息,判断本次是否能获得出勤奖,能获得出勤奖的条件如下&am…...
空对象模式
在空对象模式(Null Object Pattern)中,一个空对象取代 NULL 对象实例的检查。Null 对象不是检查空值,而是反应一个不做任何动作的关系。这样的 Null 对象也可以在数据不可用的时候提供默认的行为。 在空对象模式中,我…...
开启Excel导航仪,跨表跳转不迷路-Excel易用宝
都2025年了,汽车都有导航了,你的表格还没有导航仪吗?那也太OUT了。 面对着一个工作簿中有N多个工作表,工作表中又有超级表,数据透视表,图表等元素,如何快速的切换跳转到需要查看的数据呢&#…...
年度技术突破奖|中兴微电子引领汽车芯片新变革
随着以中央计算区域控制为代表的新一代整车电子架构逐步成为行业主流,车企在电动化与智能化之后,正迎来以架构创新为核心的新一轮技术竞争。中央计算SoC,作为支撑智驾和智舱高算力需求的核心组件,已成为汽车电子市场的重要新增量。…...
Ubuntu 如何查看盘是机械盘还是固态盘
在 Ubuntu 系统中,您可以通过以下方法来确定硬盘是机械硬盘(HDD)还是固态硬盘(SSD): 使用 lsblk 命令: 打开终端,输入以下命令: lsblk -d -o name,rota该命令将列出所…...
计算机网络(三)——局域网和广域网
一、局域网 特点:覆盖较小的地理范围;具有较低的时延和误码率;使用双绞线、同轴电缆、光纤传输,传输效率高;局域网内各节点之间采用以帧为单位的数据传输;支持单播、广播和多播(单播指点对点通信…...
STM32F4分别驱动SN65HVD230和TJA1050进行CAN通信
目录 一、CAN、SN65HVD230DR二、TJA10501、TJA1050 特性2、TJA1050 引脚说明 三、硬件设计1、接线说明2、TJA1050 模块3、SN65HVD230 模块 四、程序设计1、CAN_Init:CAN 外设初始化函数2、CAN_Send_Msg、CAN_Receive_Msg 五、功能展示1、接线图2、CAN 数据收发测试 …...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...
