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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/505640.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电脑提示directx错误导致玩不了游戏怎么办?dx出错的解决方法

想必大家都有过这样的崩溃瞬间&#xff1a;满心欢喜打开心仪的游戏&#xff0c;准备在虚拟世界里大杀四方或者畅游冒险&#xff0c;结果屏幕上突然弹出个 DirectX 错误的提示框&#xff0c;紧接着游戏闪退&#xff0c;一切美好戛然而止。DirectX 作为 Windows 系统下游戏运行的…

汽车基础软件AutoSAR自学攻略(三)-AutoSAR CP分层架构(2)

汽车基础软件AutoSAR自学攻略(三)-AutoSAR CP分层架构(2) 下面我们继续来介绍AutoSAR CP分层架构&#xff0c;下面的文字和图来自AutoSAR官网目前最新的标准R24-11的分层架构手册。该手册详细讲解了AutoSAR分层架构的设计&#xff0c;下面让我们来一起学习一下。 Introductio…

消息中间件类型介绍

消息中间件是一种在分布式系统中用于实现消息传递的软件架构模式。它能够在不同的系统或应用之间异步地传输数据&#xff0c;实现系统的解耦、提高系统的可扩展性和可靠性。以下是几种常见的消息中间件类型及其介绍&#xff1a; 1.RabbitMQ 特点&#xff1a; • 基于AMQP&#…

WEB攻防-通用漏洞_文件上传_黑白盒审计流程

目录 前置知识点 Finecms-CMS文件上传 ​编辑 Cuppa-Cms文件上传 Metinfo-CMS 文件上传 前置知识点 思路&#xff1a; 黑盒就是寻找一切存在文件上传的功能应用 1 、个人用户中心是否存在文件上传功能 2 、后台管理系统是否存在文件上传功能 3 、字典目录扫描探针文件上传构…

“深入浅出”系列之FFmpeg:(1)音视频开发基础

我的音视频开发大部分内容是跟着雷霄骅大佬学习的&#xff0c;所以笔记也是跟雷老师的博客写的。 一、音视频相关的基础知识 首先播放一个视频文件的流程如下所示&#xff1a; FFmpeg的作用就是将H.264格式的数据转换成YUV格式的数据&#xff0c;然后SDL将YUV显示到电脑屏幕上…

搭建docker私有化仓库Harbor

Docker私有仓库概述 Docker私有仓库介绍 Docker私有仓库是个人、组织或企业内部用于存储和管理Docker镜像的存储库。Docker默认会有一个公共的仓库Docker Hub,而与Docker Hub不同,私有仓库是受限访问的,只有授权用户才能够上传、下载和管理其中的镜像。这种私有仓库可以部…

fast-crud select下拉框 实现多选功能及下拉框数据动态获取(通过接口获取)

教程 fast-crud select示例配置需求:需求比较复杂 1. 下拉框选项需要通过后端接口获取 2. 实现多选功能 由于这个前端框架使用逻辑比较复杂我也是第一次使用,所以只记录核心问题 环境:vue3,typescript,fast-crud ,elementPlus 效果 代码 // crud.tsx文件(/.ts也行 js应…

在Windows环境下搭建无人机模拟器

最近要开发无人机地面站&#xff0c;但是没有无人机&#xff0c;开发无人机对我来说也是大姑娘坐花轿——头一回。我们要用 MAVLink 和无人机之间通信&#xff0c;看了几天 MAVLink&#xff0c;还是不得劲儿&#xff0c;没有实物实在是不好弄&#xff0c;所以想先装一个无人机模…

HTB:Topology[WriteUP]

目录 连接至HTB服务器并启动靶机 信息收集 使用rustscan对靶机TCP端口进行开放扫描 提取并保存靶机TCP开放端口号 使用nmap对靶机TCP开放端口进行脚本、服务扫描 使用nmap对靶机TCP开放端口进行漏洞、系统扫描 使用nmap对靶机常用UDP端口进行开放扫描 使用浏览器访问靶…

【 Verdi实用技巧-Part-3】

Verdi实用技巧-Part-3 3 Verdi实用技巧-Part-33.1 nWave window(看波形窗口)3.2 收集coverage3.3 nWave window3.4 Verdi-->app3.5 Force信号用Verdi去debug 本篇文章继续介绍Verdi实用技巧–Part-3; 3 Verdi实用技巧-Part-3 3.1 nWave window(看波形窗口) nWave window …

Vue sm3国密 IE模式报错处理

1、sm-crypto 转义错误 查看报错信息包名 在vue.config.js的transpileDependencies中把依赖包添加进去&#xff0c;让babel能够转译sm-crypto包 babel.config.js module.exports {presets: [[vue/app, {useBuiltIns: entry}]] }2、exports.destroy (() &#xff1e; { … }&a…

docker 基本使用

-do1.安装docker: Redirecting… 0. docker内使用gpu, 安装nvidia-docker: https://github.com/NVIDIA/nvidia-docker, 安装后使用&#xff1a;nvidia-container-cli -k -d /dev/tty list&#xff0c; 验证正确&#xff0c;无报错&#xff0c;即为正确 1. docker 启动image,如…

手机的ip地址是根据电话卡归属地定吗

在智能手机普及的今天&#xff0c;IP地址作为我们连接互联网的“门牌号”&#xff0c;其来源和确定方式常常引发用户的好奇。特别是关于手机IP地址是否与电话卡的归属地直接相关&#xff0c;这一话题更是众说纷纭。本文将深入探讨这一问题&#xff0c;为您揭开手机IP地址与电话…

计算机网络 (32)用户数据报协议UDP

前言 用户数据报协议&#xff08;UDP&#xff0c;User Datagram Protocol&#xff09;是计算机网络中的一种重要传输层协议&#xff0c;它提供了无连接的、不可靠的、面向报文的通信服务。 一、基本概念 UDP协议位于传输层&#xff0c;介于应用层和网络层之间。它不像TCP那样提…

YOLOv5改进 | CARAFE提高精度的上采样方法

目录 1 CARAFE模块原理 1.1 上采样的表示 1.2 Motivation 2 YOLOv5中加入CARAFE模块 2.1 ultralytics/nn/modules/block.py文件配置 2.2 ultralytics/nn/tasks.py配置 2.3 创建添加优化点模块的yolov5x-CARAFE.yaml 参考文献 1 CARAFE模块原理 上采样操作可以表示为…

高通,联发科(MTK)等手机平台调优汇总

一、常见手机型号介绍&#xff1a; ISP除了用在安防行业&#xff0c;还有手机市场&#xff0c;以及目前新型的A/VR眼睛&#xff0c;机器3D视觉机器人&#xff0c;医疗内窥镜这些行业。 下面是一些最近几年发布的,,,旗舰SOC型号&#xff1a; 1.联发科&#xff1a;天玑92…

windows从0开始配置llamafactory微调chatglm3-6b

后续会更新 从0学习LLaMaFactory参数解释说明 &#xff0c;请期待~ 文章目录 一、准备工作1、创建python虚拟环境(annoconda)2、配置pytorch傻瓜版3、llamafactory配置4、微调数据准备5、开始微调5.1 webui启动微调5.2 指令启动微调 一、准备工作 1、创建python虚拟环境(annoc…

某漫画网站JS逆向反混淆流程分析

文章目录 1. 写在前面1. 接口分析2. 反混淆分析 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Pyth…

netplan apply报错No module named ‘netifaces‘

Ubuntu 20.04.5 LTS \n \l&#xff0c;ctrlaltf2切换字符登录f1切换图形 处理办法&#xff1a; root登录执行 rootnode37:/disk1/Qwen2.5-72B-Instruct-GPTQ-Int4# cat /etc/netplan/01-network-manager-all.yaml # Let NetworkManager manage all devices on this system …

LabVIEW 系统诊断

LabVIEW 系统诊断是指通过各种工具和方法检测、评估、分析和解决 LabVIEW 程序和硬件系统中可能存在的故障和性能问题。系统诊断不仅涵盖软件层面的调试与优化&#xff0c;还包括硬件交互、数据传输、实时性能等方面的检查和分析。一个成功的系统诊断能够显著提升LabVIEW应用程…