C++例程:使用I/O模拟IIC接口(6)

news/2025/1/11 12:29:45/

完整的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.ppmy.cn/news/1562234.html

相关文章

php.ini配置中有10处设置不当,会使网站存在安全问题

在 php.ini 配置文件中,有一些设置如果配置不当,可能会导致网站面临安全风险。PHP 的安全性很大程度上依赖于这些配置选项的正确设置。以下是 10 个可能存在安全问题的 PHP 配置项,如果配置不当,可能会导致网站存在安全漏洞: 1. display_errors 问题: 启用错误显示时,…

【Oracle篇】深入了解执行计划中的访问路径(含表级别、B树索引、位图索引、簇表四大类访问路径)

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;从事IT领域✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长阿里云AnalyticDB for MySQL(分布式数据仓库)、Oracle、MySQL、Linux、prometheus监控&#xff1b;并对SQLserver、NoSQL(…

Word表格内容批量写入Excel

在日常办公中&#xff0c;Word表格是记录和整理信息的常用工具&#xff0c;但面对需要将Word中的表格数据批量转入Excel的场景&#xff0c;手动操作往往既耗时又容易出错。如果你正在寻找一款能够快速将Word表格内容批量写入Excel的工具&#xff0c;“我爱Excel”将是你不可或缺…

银河麒麟编译QXlsx,使用Qt5.14.2

一、环境准备 系统&#xff1a;银河麒麟V10 QT&#xff1a;5.14.2 QXlsx源码&#xff1a;QtXlsxWriter-master.zip 下载地址&#xff1a;QXlsx Qt环境的安装配置此处不再赘述。 二、开始构建 先将源码压缩包解压 进入到文件夹内 在此处打开终端 输入qmake&#xff0c;回车…

后端技术选型 sa-token校验学习 上 登录校验复习

sa-token 的官网 Sa-Token 复习 首先我们要明确一下 cookie 是什么 登录校验 Sa-Token 官方文档里面的 对于一些登录之后才能访问的接口&#xff08;例如&#xff1a;查询我的账号资料&#xff09;&#xff0c;我们通常的做法是增加一层接口校验&#xff1a; 如果校验通过…

Java爬取1688商品详情API接口

在当今的电商时代&#xff0c;1688平台凭借其庞大的商品种类和丰富的供应商资源&#xff0c;成为了众多企业和个人获取商品信息的重要渠道。对于开发者而言&#xff0c;能够通过API接口爬取1688商品的详细信息&#xff0c;将极大地助力于数据分析、市场调研、价格监控等多方面的…

npm-npm install时rollbackFailedOptional: verb npm-session ce210dc17dd264aa报错

1.前言 npm install的时候卡着不动&#xff0c;安装失败。 2.解决 2.1清除代理 npm config rm proxy npm config rm https-proxy #权限问题记得加sudo2.2修改镜像资源为淘宝镜像资源 npm config set registry http://registry.npm.taobao.org2.3查看镜像资源是否切换成功 …

【漫话机器学习系列】041.信息丢失(dropout)

信息丢失&#xff08;Dropout&#xff09; Dropout 是一种广泛应用于神经网络训练中的正则化技术&#xff0c;旨在减少过拟合&#xff08;overfitting&#xff09;&#xff0c;提高模型的泛化能力。虽然"信息丢失"&#xff08;dropout&#xff09;这个术语在某些情况…