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 数据收发测试 …...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...

如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...

selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...