STM32 IIC通用程序

合集下载

STM32IIC双机通信——HAL库硬件IIC版

STM32IIC双机通信——HAL库硬件IIC版

STM32IIC双机通信——HAL库硬件IIC版 关于IIC的原理这⾥我就不多说了,⽹上有很多很好的解析,如果要看我个⼈对IIC的理解的话,,这⾥主要讲⼀下怎样利⽤STM32CubeMx实现IIC的通讯,经过个⼈实践,感觉HAL库的硬件IIC要⽐标准库的稳定。

好了,下⾯就从STM32CubeMx 配置开始⼀步步实现IIC通讯。

STM32CubeMx的配置,这⾥关于新建⼯程的步骤我就不细说了,如果还不会操作STM32CubeMx 的可以,这⾥主要对IIC的配置进⾏说明。

了解IIC的都知道,IIC通信有主从机之分,⽤两⽚STM32进⾏IIC通信当然也不例外,不过使⽤STM32CubeMx 配置有⼀个好处,就是不⽤分别配置主从机,在STM32CubeMx 配置⾥⾯,主从机的配置是⼀样,唯⼀不同的就是IIC的地址如上图,这个地址很重要,只要配置好了,基本就成功了。

还有⼀个要注意的,就是IIC的SDA、SCK引脚要配置成NPP模式,不然容易出现信号线忙,检测不到从机的情况。

配置配好后我们⽣成代码,就可以进⾏通信了,主从机核⼼代码如下: 下⾯是主机的重要代码:/* I2C2 init function IIC配置*/static void MX_I2C2_Init(void){hi2c2.Instance = I2C2;hi2c2.Init.Timing = 0x10805D88;hi2c2.Init.OwnAddress1 = 20; //⽤户⾃⼰配置的地址hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;hi2c2.Init.OwnAddress2 = 0;hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK;hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;if (HAL_I2C_Init(&hi2c2) != HAL_OK){_Error_Handler(__FILE__, __LINE__);}/**Configure Analogue filter*/if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != HAL_OK){_Error_Handler(__FILE__, __LINE__);}/**Configure Digital filter*/if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK){_Error_Handler(__FILE__, __LINE__);}}while(HAL_I2C_Master_Transmit_IT(&hi2c2 ,0x0b,&BUFF[0], 1)!= HAL_OK){}//IIC主机发送函数,主要IIC配置好了,这个可以添加到main函数⾥⾯测试 关于STM32CubeMx的HAL库IIC收发有⼏种函数,⽤户可以根据⾃⼰不同的需求进⾏选择,以下就是主要的⼏个HAL库IIC收发函数:/* 第1个参数为I2C操作句柄第2个参数为从机设备地址第3个参数为从机寄存器地址第4个参数为从机寄存器地址长度第5个参数为发送的数据的起始地址第6个参数为传输数据的⼤⼩第7个参数为操作超时时间 */HAL_I2C_Mem_Write(&hi2c2,salve_add,0,0,PA_BUFF,sizeof(PA_BUFF),0x10);HAL_I2C_Mem_Write_IT();HAL_I2C_Mem_Read();HAL_I2C_Mem_Read_IT();HAL_I2C_Mem_Read_DMA();HAL_I2C_Mem_Write_DMA();/* 不需要⽤到寄存器地址的主机HAL库IIC收发函数 */HAL_I2C_Master_Receive(); //STM32 主机接收,不需要⽤到寄存器地址HAL_I2C_Master_Transmit();HAL_I2C_Master_Receive_IT(); //中断IIC接收HAL_I2C_Master_Receive_DMA(); //DMA ⽅式的IIC接收HAL_I2C_Master_Transmit_IT(); //中断IIC发送HAL_I2C_Master_Transmit_DMA(); //DMA ⽅式的IIC发送HAL_I2C_Master_Transmit(&hi2c2,0x0B,PA_BUFF,sizeof(PA_BUFF),0x10); //STM32 主机发送/* 不需要⽤到寄存器地址的从机HAL库IIC收发函数 */HAL_I2C_Slave_Receive(); //STM32 从机机接收,不需要⽤到寄存器地址HAL_I2C_Slave_Transmit(); //STM32 从机机发送,不需要⽤到寄存器地址HAL_I2C_Slave_Receive_IT();HAL_I2C_Slave_Receive_DMA();HAL_I2C_Slave_Transmit_IT();HAL_I2C_Slave_Transmit_DMA(); 我这⾥因为只是做两个STM32间的单向通⾏⽽已,不需要对寄存器进⾏写数据。

stm32IIC程序

stm32IIC程序

}
/**************************************************************************
函数名称: IIC_NAck()

能: 不产生应答信号,主机接收到从机的数据后,不发出应答信号
第3页
IIC.txt

数:None
返回值 : None
第1页
IIC.txt
11:保留
在输出模式(MODE[1:0]>00):
00:通用推挽输出模式
01:通用开漏输出模式
10:复用功能推挽输出模式
11:复用功能开漏输出模式
***************************************************************************/
据,避免在SCL为高电平期间,再次发出起始信号或者停止信号
delay_us(2);
}
/**************************************************************************
函数名称: IIC_Stop(void)

能: 产生IIC停止信号(SP)

明:IIC起始信号定义为当SCL为高电平(HIGH)时,SDA线从高到低的跳变
***************************************************************************/
void IIC_Start(void)
{
SDA_OUT();
//SDA线输出
{
SDA_OUT();
//SDA线输出

STM32系列 的IIC通信例程

STM32系列 的IIC通信例程

=
=
}while((ui_stateflag == ERROR) && (-- ui_cnt)); if(ui_stateflag == SUCCESS) { ui_stateflag = ERROR; //write a byte data I2C_SendData(I2C1, data); ui_cnt = I2C1_TIME; do { ui_stateflag = I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED); }while((ui_stateflag == ERROR) && (-- ui_cnt)); //send stop I2C_GenerateSTOP(I2C1,ENABLE); } } } } } } //--------------------------------------------------------------------------------------------------------------------//Function Name: void I2C_EEPROM_WritePage(unsigned short WordAddress, unsigned char *data, unsigned int length) //Function Discription: write page data //Function Parameters: // INPUT: WordAddress:地址 *data:数据 length:长度 // OUTPUT: //Return Value: //--------------------------------------------------------------------------------------------------------------------void I2C_EEPROM_WritePage(unsigned short WordAddress, unsigned char *data, unsigned int length) { unsigned int ui_cnt, ui_i, ui_stateflag; I2C_AcknowledgeConfig(I2C1, ENABLE); ui_cnt = I2C1_TIME; do { ui_stateflag = I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY); } while ((ui_stateflag == SET) && (-- ui_cnt)); if(ui_stateflag==RESET) { ui_stateflag = ERROR; I2C_GenerateSTART(I2C1,ENABLE);

STM32模拟IIC读写24C02程序代码

STM32模拟IIC读写24C02程序代码

STM32模拟IIC读写24C02程序代码STM32 模拟IIC读写24C02程序代码最近用到STM32F103V来读写A T24C02 EEPROM 于是从原来51单片机的程序代码的基础上修改了下,移植到了STM32,测试工作正常。

引脚定义和配置:#define SCL GPIO_Pin_6 //24C02 SCL#define SDA GPIO_Pin_7 //24C02 SDAvoid GPIO_Configuration(void){RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1 |RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD |RCC_APB2Periph_GPIOE, ENABLE);GPIO_InitStructure.GPIO_Pin = SCL; //24C02 SC LGPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = SDA; //24C02 SDA 作为输出GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);}void AT24C02_SDA_IO_SET(unsigned char io_set) //SDA引脚输入输出设置{if(io_set==0){GPIO_InitStructure.GPIO_Pin = SDA; //24C02 SDA 作为输出GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);else if(io_set==1){GPIO_InitStructure.GPIO_Pin = SDA; //24C02 SDA 作为输入GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入GPIO_Init(GPIOB, &GPIO_InitStructure);}else{;}}////////////////////////////////////主程序////////////////////////////////////////////////////////////////////// ////////int main(void){ uchar i;uchar data_24c02;RCC_Configuration(); //时钟配置GPIO_Configuration();//GPIO配置USARTx_configuration();//串口配置WIN24C02_init();delayms(5000);//延时for(i=0;i<20;i++) //写EEPROM数据{ WIN24C02_write(0x00+i,i);delayms(100);}//存数据到EEPROMdelayms(1000);//延时while(1)//串口3发送读取的EEPROM的数据{for(i=0;i<20;i++){ data_24c02=WIN24C02_read(0x00+i);//读取24C02数据USART_SendData(USART3 ,data_24c02);while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET);}delayms(5000);//延时}/////////////////////////////////////////////////////////////////// //////////////////////////////////////////////WIN_24C02.H头文件/**********************中文版本*******************************//*****功能描述: STM32 24C02 读写程序*****//*****作者: 郑文(ClimberWin) *****//*****编写日期: 2013年1月21日*****//*****版本信息: V1.0 *****//*****修改日期: *****//*************************************************************/ #ifndef __WIN24C02_H__#define __WIN24C02_H__#include"STM32_Config.h"#define uchar unsigned char#define uint unsigned intuchar WIN24C02_read(uchar address); //从24c02的地址address中读取一个字节数据void WIN24C02_write(uchar address,uchar info); //向24c02的address地址中写入一字节数据infovoid WIN24C02_init(); //24c02初始化子程序void delay_nop(void);void delay2(uint x);void start();void stop();void writex(uchar j);uchar readx();void clock();void delay2(uint x){uint i;for(i=0;i<x;i++);< p="">}void delay_nop(void){uint8_t i=10; //i=10延时1.5us//这里可以优化速度,经测试最低到5还能写入while(i--);}void WIN24C02_init(){//SCL=1;GPIO_SetBits(GPIOB,SCL);delay_nop();//SDA=1;GPIO_SetBits(GPIOB,SDA);delay_nop();}void start(){//SDA=1;GPIO_SetBits(GPIOB,SDA);delay_nop();//SCL=1;GPIO_SetBits(GPIOB,SCL); delay_nop();//SDA=0;GPIO_ResetBits(GPIOB, SDA); delay_nop();//SCL=0;GPIO_ResetBits(GPIOB, SCL); delay_nop();}void stop(){//SDA=0;GPIO_ResetBits(GPIOB, SDA); delay_nop();//SCL=1;GPIO_SetBits(GPIOB,SCL); delay_nop();//SDA=1;GPIO_SetBits(GPIOB,SDA); delay_nop();}void writex(uchar j){uchar i,temp,temp1;temp=j;//A T24C02_SDA_IO_SET(0); for (i=0;i<8;i++){temp1=temp & 0x80;temp=temp<<1;//SCL=0;GPIO_ResetBits(GPIOB, SCL);delay_nop();//SDA=CY;if(temp1==0x80){GPIO_SetBits(GPIOB, SDA);} else {GPIO_ResetBits(GPIOB, SDA);} delay_nop(); // SCL=1;GPIO_SetBits(GPIOB,SCL);delay_nop();}//A T24C02_SDA_IO_SET(0);//SCL=0;GPIO_ResetBits(GPIOB, SCL);delay_nop();//SDA=1;GPIO_SetBits(GPIOB,SDA);delay_nop();}uchar readx(){uchar i,j,k=0;//SCL=0;GPIO_ResetBits(GPIOB, SCL);delay_nop();//SDA=1;GPIO_SetBits(GPIOB,SDA);AT24C02_SDA_IO_SET(1);for (i=0;i<8;i++){delay_nop();//SCL=1;GPIO_SetBits(GPIOB,SCL);delay_nop();//if (SDA==1) j=1;if( GPIO_ReadInputDataBit(GPIOB,SDA)==1 ) {j=1;}else{j=0;}k=(k<<1)|j;//SCL=0;GPIO_ResetBits(GPIOB, SCL);}AT24C02_SDA_IO_SET(0);delay_nop();return(k);}{uint i=0;AT24C02_SDA_IO_SET(1);//SCL=1;GPIO_SetBits(GPIOB,SCL);delay_nop();while((GPIO_ReadInputDataBit(GPIOB,SDA)==1)&&(i<5000))i++;//SCL=0;GPIO_ResetBits(GPIOB, SCL);delay_nop();AT24C02_SDA_IO_SET(0);}uchar WIN24C02_read(uchar address){uchar i;start();writex(0xa0);clock();writex(address);clock();start();writex(0xa1);clock();i=readx();stop();//delay2(10);delay2(50);return(i);}void WIN24C02_write(uchar address,uchar info) {start();writex(0xa0);clock();writex(address);writex(info);clock();stop();//delay2(50);delay2(250); }#endif</x;i++);<>。

基于STM32的IIC_EEPROM案例说明

基于STM32的IIC_EEPROM案例说明

基于STM32的IIC_EEPROM案例说明STM32是一系列由STMicroelectronics开发的32位ARM Cortex-M处理器的微控制器。

它具有高性能、低功耗和丰富的外设。

其中一个外设是I2C接口,可以用于连接外部器件,如EEPROM。

EEPROM(Electrically Erasable Programmable Read-Only Memory)是一种非易失性存储器,可以通过电量抹除并重新编程。

本文将说明如何在STM32微控制器上使用I2C接口来读取和写入EEPROM的数据。

以下是一个I2CEEPROM案例的步骤:1.硬件连接:找到适当的引脚连接STM32和EEPROM。

根据STM32型号和EEPROM的规格书,将SCL引脚连接到STM32的相应引脚,将SDA引脚连接到STM32的相应引脚。

确保EEPROM上的地址引脚正确连接到STM32的引脚,以选择EEPROM的地址。

另外,确保STM32的引脚配置正确。

2.初始化I2C外设:在STM32的代码中,首先需要初始化I2C外设。

这可以通过配置I2C控制器的寄存器来完成。

这些寄存器包含有关时钟速度、地址模式和使能I2C控制器的设置选项。

3.选择EEPROM地址:通过向I2C总线发送一个特定的命令字节,可以选择EEPROM的地址。

这个命令字节包含I2C总线上的设备地址和寻址模式。

4.读取EEPROM数据:为了从EEPROM读取数据,STM32将发送一个读取命令字节,将该命令字节传送到EEPROM,然后从EEPROM读取数据。

在读取数据之前,需要设置读取数据的长度和目标缓冲区。

5.写入EEPROM数据:为了向EEPROM写入数据,STM32将发送一个写入命令字节,将该命令字节传送到EEPROM,然后将数据写入EEPROM。

在写入数据之前,需要设置写入数据的长度和源缓冲区。

6.处理错误和超时:在进行I2CEEPROM读取和写入操作时,可能会出现错误和超时。

stm32的i2c读写程序的详细讲解

stm32的i2c读写程序的详细讲解

一、概述STMicroelectronics瑞士意法半导体公司的STM32系列微控制器被广泛应用于各种嵌入式系统中,其强大的性能和丰富的外设功能受到了众多开发者的青睐。

其中,STM32的I2C总线通信功能在实际应用中具有重要意义,本文将对STM32的I2C读写程序进行详细讲解。

二、I2C总线介绍I2C(Inter-Integrated Circuit)总线是一种串行通信接口协议,由Philips公司推出。

它具有双向传输数据线(SDA)、时钟线(SCL)、起始条件、停止条件、数据传输的应答信号等特点。

I2C总线在各种传感器、存储器、外设等设备之间进行通信时,具有简单高效的优势。

三、STM32的I2C外设1. STM32的I2C外设功能STM32系列微控制器内置了丰富的外设功能,其中包括了I2C总线通信。

STM32的I2C外设支持主机和从机模式,可以实现与各种I2C设备的通信和数据交换。

2. STM32的I2C外设配置在使用STM32的I2C外设之前,需要对其进行配置,包括设置时钟、GPIO、寄存器参数等。

通过正确的配置,可以使STM32的I2C外设正常工作,并与其他设备进行可靠的通信。

四、STM32的I2C读写程序详解1. 初始化I2C外设在使用I2C总线进行读写操作之前,首先需要对STM32的I2C外设进行初始化设置。

具体步骤包括设置GPIO管脚为I2C功能模式、配置时钟、设置I2C的工作模式、设定传输速率等。

2. 发送起始信号当I2C通信开始时,主机会发送起始信号(Start),表明要开始一次通信过程。

起始信号的发送方式是通过在SDA线上拉低电平,同时保持SCL线处于高电平状态。

3. 选择设备位置区域在发送起始信号后,主机需要选择要通信的设备位置区域。

针对每个I2C设备,都有唯一的位置区域标识,主机需要向目标设备发送其位置区域信息。

位置区域信息由设备的7位位置区域和读写方向位组成。

4. 数据传输经过起始信号和设备位置区域选择后,接下来进行数据的传输。

STM32系列IIC使用总结

STM32系列IIC使用总结

STM32系列IIC使用总结STM32系列是意法半导体公司推出的一款32位ARM Cortex-M微控制器系列产品,广泛应用于各类嵌入式系统中。

其中,IIC总线是STM32系列产品中常用的通信接口之一,用于连接各种外部设备,如传感器、存储器、LCD显示屏等。

下面是对STM32系列IIC使用的总结。

一、STM32IIC硬件功能1. IIC接口引脚:STM32的IIC接口引脚有两个,分别是SDA(Serial Data)和SCL(Serial Clock)。

2.多主机模式支持:STM32的IIC接口支持多主机模式,可以实现多个主机同时操作同一个从机设备。

3. 速率控制:STM32的IIC接口支持多种速率配置,包括标准模式(100Kbps)、快速模式(400Kbps)和高速模式(1Mbps)等。

4.IIC总线协议支持:STM32的IIC接口遵循I2C总线协议,支持7位或10位设备地址,支持字节读写、页写、设备寻址等操作。

二、STM32IIC软件开发步骤1.初始化IIC接口:使用STM32提供的库函数,配置IIC引脚为复用功能,并初始化IIC控制器的寄存器,包括速率设置、硬件过滤器配置等。

2.开启IIC总线:调用库函数,使能IIC总线,准备进行通信。

3.生成起始位和停止位:调用库函数,发送起始位和停止位信号,控制IIC总线的起始和停止状态。

4.发送器件地址:调用库函数,发送要操作的设备的地址信息,用于将总线上的控制权交给该设备。

5.发送数据或接收数据:调用库函数,根据需要发送数据或接收数据,并处理数据的传输错误等异常情况。

6.关闭IIC总线:调用库函数,关闭IIC总线,释放总线资源。

三、处理IIC通信中的常见问题1.电源电压:STM32的IIC接口对电源电压要求较高,通常工作电压为3.3V,要确保供电电压稳定。

2.设备地址:在使用IIC接口时,需要正确设置设备的地址信息,确保与从机设备进行正常通信。

3.速率设置:根据实际需求,选择合适的通信速率,避免传输错误和数据丢失。

STM32 硬件IIC中断使用方法

STM32 硬件IIC中断使用方法

STM32 硬件IIC中断使用方法--中北大学:马政贵本文详细描述了STM32硬件IIC的中断使用方法,包含流程图和对应代码,以及调试过程中的问题记录和分析解决。

之前,一直听说STM32的硬件IIC有问题,加之以前写好的模拟IIC模块用着一直没问题,就没有去使用STM32的硬件IIC。

后面项目中需要实时读取三个传感器的数据,三个传感器并在一起共用一个IIC口,通过地址进行区分通信,一个传感器要读取8字节数据。

采用模拟IIC方式,很多时间都浪费在高低电平的等待时间上,导致其他任务时间很紧迫。

于是想到使用硬件IIC的中断方式,来提升效率。

查看了下库自带的例程,使用的是查询方式,使用了大量的while来等待状态标志完成。

移植过来,虽然可以跑通,但使用的是查询方式,效率本质上和模拟IIC是一样的。

于是自己便把手册里的IIC模块看了一遍,自己根据手册来写硬件IIC的中断模式。

上图是传感器的通讯时序,属于标准的IIC通信,这里不做进一步展开,详细可以参看IIC总线规范。

应用中,MCU做主机,传感器做从机。

MCU先工作在主发送器模式,然后工作在主接收器模式。

在默认状态下,MCU接口工作于从模式。

接口在生成起始条件后自动地从从模式切换到主模式;当仲裁丢失或产生停止信号时,则从主模式切换到从模式。

在应用手册中,详细给出了IIC主模式的操作要求及顺序:这里需要注意的是怎样结束通信,然后重启通信,以便获取下一个传感器的数据。

应用手册根据情况分为了三种,我这里使用的是第一种方式,也就是把IIC的中断优先级设置为最高。

下面我以流程图的方式,把整个过程表示出来,然后再据此给出相应的代码,代码在中断中以状态机的方式进行。

先进行IIC管脚GPIO的配置:接着进行IIC的配置(中断先不使能,在初始化完传感器之后再使能。

我这里把IIC的事件中断优先级设置为最高,若不是,IIC的结束操作需参照应用手册中相应的情况进行):中断中的状态机如下:void I2C2_EV_IRQHandler(void){switch(IIC2_State){case 0:if(I2C_GetINTStatus(I2C2, I2C_INT_STARTF)){I2C_ClearITPendingBit(I2C2, I2C_INT_STARTF);(void)(I2C2->STS1);I2C_Send7bitAddress(I2C2, ALS31300_ADR[IIC_Device], I2C_Direction_Transmit);IIC2_State++;}else{I2C2->STS1 = 0;}break;case 1:if(I2C_GetINTStatus(I2C2, I2C_INT_ADDRF)){I2C_ClearITPendingBit(I2C2, I2C_INT_ADDRF);(void)(I2C2->STS1);(void)(I2C2->STS2);I2C_SendData(I2C2, 0x28);IIC2_State++;}else{I2C2->STS1 = 0;}break;case 2:if(I2C_GetINTStatus(I2C2, I2C_INT_TDE)){I2C_ClearITPendingBit(I2C2, I2C_INT_TDE);I2C_ClearITPendingBit(I2C2, I2C_INT_BTFF);(void)(I2C2->STS1);I2C_GenerateSTART(I2C2, ENABLE); /* Send STRAT condition a second time */IIC2_State++;}else{I2C2->STS1 = 0;}break;case 3:if(I2C_GetINTStatus(I2C2, I2C_INT_STARTF)){I2C_ClearITPendingBit(I2C2, I2C_INT_STARTF);(void)(I2C2->STS1);I2C_Send7bitAddress(I2C2, ALS31300_ADR[IIC_Device],I2C_Direction_Receive);IIC2_State++;}else{I2C2->STS1 = 0;}break;case 4:if(I2C_GetINTStatus(I2C2, I2C_INT_ADDRF)){I2C_ClearITPendingBit(I2C2, I2C_INT_ADDRF);(void)(I2C2->STS1);(void)(I2C2->STS2);IIC2_State++;}else{I2C2->STS1 = 0;}break;case 5:if(I2C_GetINTStatus(I2C2, I2C_INT_RDNE)){I2C_ClearITPendingBit(I2C2, I2C_INT_RDNE);(void)(I2C2->STS1);ALS31300_Reg_Data[IIC_Device][IIC_Rec_Num] = I2C_ReceiveData(I2C2);IIC_Rec_Num++;if(IIC_Rec_Num >= 6){IIC2_State++;}}else{I2C2->STS1 = 0;}break;case 6:if(I2C_GetINTStatus(I2C2, I2C_INT_RDNE)){I2C_ClearITPendingBit(I2C2, I2C_INT_RDNE);(void)(I2C2->STS1);ALS31300_Reg_Data[IIC_Device][IIC_Rec_Num] = I2C_ReceiveData(I2C2);I2C_AcknowledgeConfig(I2C2, DISABLE);I2C_GenerateSTOP(I2C2, ENABLE);IIC_Rec_Num++;IIC2_State++;}else{I2C2->STS1 = 0;}break;case 7:if(I2C_GetINTStatus(I2C2, I2C_INT_RDNE)){I2C_ClearITPendingBit(I2C2, I2C_INT_RDNE);(void)(I2C2->STS1);ALS31300_Reg_Data[IIC_Device][IIC_Rec_Num] =I2C_ReceiveData(I2C2);IIC_Device++;if(IIC_Device >= 3){IIC_Device = 0;IIC_Rec_OK = 1;}I2C_AcknowledgeConfig(I2C2, ENABLE);I2C_GenerateSTART(I2C2, ENABLE);IIC_Rec_Num = 0;IIC2_State = 0;}else{I2C2->STS1 = 0;}break;default:I2C2->STS1 = 0;break;}}初始化之后,产生开始信号之后,使能中断,此后就一直在中断的状态机中往复进行了:#define IIC_TIMEOUT 1000IIC2_GPIO_Config();IIC2_Config();time_count = IIC_TIMEOUT;while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSYF)){time_count--;if(0 == time_count){IIC_Wrong_Count++;return;}}I2C_AcknowledgeConfig(I2C2, ENABLE);I2C_GenerateSTART(I2C2, ENABLE);//初始化之后再开中断,只在读操作中使用中断I2C_INTConfig(I2C2, I2C_INT_EVT | I2C_INT_BUF | I2C_INT_ERR, ENABLE);编译调试,咦,状态机一直停留在0状态,也就是卡在总线一直BUSY。

stm32hal iic函数详解

stm32hal iic函数详解

stm32hal iic函数详解STM32是意法半导体公司推出的一系列32位微控制器,广泛应用于各种嵌入式系统中。

在STM32系列中,HAL库是官方提供的一套库函数,用于简化开发人员对硬件的操作。

本文将详细介绍STM32HAL 库中的I2C函数,包括函数的功能和使用方法。

I2C(Inter-Integrated Circuit)是一种常用的串行通信协议,用于连接微控制器和外部设备。

在STM32中,I2C接口被称为I2C总线,能够同时连接多个外设。

HAL库提供了一系列函数,用于配置和控制I2C总线。

我们需要通过引用相应的头文件来包含I2C函数的定义。

在使用HAL库时,我们需要引用stm32f4xx_hal.h头文件。

在此基础上,我们还需要引用stm32f4xx_hal_i2c.h头文件,该头文件包含了I2C函数的声明。

一般而言,使用I2C通信需要以下几个步骤:1. 初始化I2C总线;2. 配置I2C总线的参数;3. 发送开始信号;4. 发送或接收数据;5. 发送停止信号。

在HAL库中,这些步骤对应了一系列的函数。

下面我们将详细介绍这些函数的功能和使用方法。

1. I2C初始化函数I2C总线初始化函数是HAL_I2C_Init()。

该函数用于初始化I2C总线,并配置相关的时钟、引脚和模式等参数。

函数声明如下:HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c);其中,hi2c是一个I2C_HandleTypeDef类型的结构体指针,用于存储I2C总线的相关参数。

在使用该函数前,我们需要先定义一个I2C_HandleTypeDef类型的结构体变量,并对其成员进行配置。

2. I2C速度配置函数I2C总线的速度配置函数是HAL_I2C_MspInit()。

该函数用于配置I2C总线的时钟频率和占空比等参数。

函数声明如下:void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c);在该函数中,我们需要根据具体的硬件平台和需求来配置I2C总线的时钟源和分频系数等参数。

iic标准程序

iic标准程序

IIC(Inter-Integrated Circuit)是一种串行通信协议,用于连接微控制器、传感器、存储器和其他外围设备。

以下是IIC标准程序的示例代码,用于在微控制器和外围设备之间进行通信:#include <stdio.h>#include <stdint.h>#include <unistd.h>#include <fcntl.h>#include <sys/ioctl.h>#include <linux/i2c-dev.h>int main(){int file;char *filename = "/dev/i2c-1"; // I2C bus 1 的设备文件路径uint8_t address = 0x50; // I2C 设备的地址char *buffer = malloc(2); // 用于存储从I2C 设备读取的数据的缓冲区// 打开I2C 总线设备文件file = open(filename, O_RDWR);if (file < 0) {perror("Failed to open i2c bus");return -1;}// 设置I2C 总线设备的地址和速率if (ioctl(file, I2C_SLAVE, address) < 0) {perror("Failed to acquire bus access and/or talk to slave");return -1;}// 向I2C 设备写入数据buffer[0] = 0x01; // 要写入的数据的第一个字节buffer[1] = 0x0A; // 要写入的数据的第二个字节int n = write(file, buffer, 2); // 将数据写入I2C 设备if (n < 1) {perror("Write failed");return -1;}// 从I2C 设备读取数据n = read(file, buffer, 1); // 从I2C 设备读取一个字节的数据到缓冲区中if (n < 1) {perror("Read failed");return -1;}printf("Read data: %x\n", buffer[0]); // 打印读取的数据的十六进制表示形式// 关闭I2C 总线设备文件close(file);free(buffer);return 0;}以上代码使用了Linux下的I2C-dev驱动,需要包含`<linux/i2c-dev.h>`头文件。

STM32中的模拟IIC使用

STM32中的模拟IIC使用
停止信号:SCLK为高的时候,SDA从低向高跳变。 SDA_OUT();//sda输出 IIC_SCL=0; IIC_SDA=0;//STOP:when CLK is high DATA change form low to high delay_us(4); IIC_SCL=1; IIC_SDA=1;//·发送结束信号 delay_us(4);
u8 IIC_Read_Byte(unsigned char ack) { unsigned char i,receive=0; SDA_IN();//SDA输入 for(i=0;i<8;i++ ) {
IIC_SCL=0; delay_us(2); IIC_SCL=1; receive<<=1; if(READ_SDA)receive++; delay_us(1); } if (!ack) IIC_NAck();//发送nACK else IIC_Ack(); //发送ACK return receive; }
hehe
数据有效性::
void IIC_Send_Byte(u8 txd) { u8 t; SDA_OUT(); IIC_SCL=0;// for(t=0;t<8;t++) { //IIC_SDA=(txd&0x80)>>7; if((txd&0x80)>>7) IIC_SDA=1; else IIC_SDA=0; txd<<=1; delay_us(2); //延时是必须的 IIC_SCL=1; delay_us(2); IIC_SCL=0ቤተ መጻሕፍቲ ባይዱ delay_us(2); } }
void IIC_NAck(void) { IIC_SCL=0; SDA_OUT(); IIC_SDA=1; delay_us(2); IIC_SCL=1; delay_us(2); IIC_SCL=0; }

STM32用GPIO模拟IIC(I2C)通讯C语言源码 实测可用

STM32用GPIO模拟IIC(I2C)通讯C语言源码 实测可用

/******************************************************************************
*
* Function Name : I2C_NoAck
* Description : Master Send No Acknowledge Single
SDA_IN();//SDA 设置为输入
for(i=0;i<8;i++ )
{
IIC_SCL=0;
Delay_us(I2C_Delayus);
IIC_SCL=1;
receive<<=1;
if(READ_SDA)receive++;
Delay_us(I2C_Delayus);
}
return receive;
IIC_SDA=(dat&0x80)>>7; dat<<=1; Delay_us(I2C_Delayus); //对 TEA5767 这三个延时都是必须的 IIC_SCL=1; Delay_us(I2C_Delayus); IIC_SCL=0; Delay_us(I2C_Delayus); } IIC_RecvACK(); #endif } //************************************** //从 IIC 总线接收一个字节数据 //************************************** u8 IIC_RecvByte(void) { #ifdef BMI160 u8 i=8; u8 ReceiveByte=0;
if(!IIC_RecvACK()){IIC_Stop();return FALSE;} IIC_SendByte((u8) REG_Address); //设置低起始地址 IIC_RecvACK(); IIC_Start(); IIC_SendByte(SlaveAddress+1); IIC_RecvACK();

基于STM32的IIC-DAC6571程序设计

基于STM32的IIC-DAC6571程序设计
the com munication between the accuracy and stability of the equipm ent is very important.Based on the STM 32F 1 03 fam ily of m icrocontrollers, this paper provides two m ethods for comm unicating IIC and DAC657 1. Respectively, through STM 32 internal hardware logic and general— purpose GPIO port simulation in two ways, using C language program m ing, IIC protocol standard control data lines and clock lines f o r program m ing, and to achieve the com munication between the two.In this paper, the comm unication process between STM 32 and DAC657 1 is analyzed in detail, and the key program is given.The experimental results are verified and analyzed. K ey words:DAC657 1;IIC bus;STM 32 m icrocontroller;hardware IIC ;analog IIC
DAC6571进 行 通 信 ,使 其 具 有 一定 的适 用 范 围 。本 文将 基 于 STM32F103系 列单 片机 ,通过 IIC总线 协议 与 DAC6571通信 ,从 硬 件 IIC与 IO口模 拟 IIC两种 方 式 提 出 了详 细 的设 计方 案 ,对用 IIC协 议进 行外 设 间 的通信 很有 参考 意义 。

stm32 之 IIC应用

stm32 之 IIC应用

stm32 之IIC应用iic协议是比较简单的双线协议,时钟线CLK和数据线SDA。

一般我们常见的还有spi总线,这种总线可以可以根据需要扩展,还有单总线等等这次还以at240c2为例进行操作!PS:这就是传说中的iic时序图硬件构造我们不过多的分析,今天用到库了!我们先从库函数硬件iic初始化说起!PB6 -- CLKPB7 -- SDA[cpp]view plaincopyprint?1. void i2c_init(u8 addr,u32 clock)2. {3. I2C_InitTypeDef i2c;4. RCC->APB2ENR |= 1<<3;5. GPIOB->CRL |= (u32)0xff<<(6*4);6.7. RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);8. i2c.I2C_Ack = I2C_Ack_Enable;9. i2c.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;10. i2c.I2C_ClockSpeed = clock*1000;11. i2c.I2C_DutyCycle = I2C_DutyCycle_2;12. i2c.I2C_Mode = I2C_Mode_I2C;13. i2c.I2C_OwnAddress1 = addr;14.15. I2C_Cmd(I2C1,ENABLE);16. I2C_Init(I2C1,&i2c);17. }在配置管脚方面,我还是喜欢用寄存器配置,因为我的两行代码可以解决库函数的N多行代码的问题!还有在结构体变量命名方面也是属于我自己的独创吧,这样反正我觉得是既容易识别,也少打几个字!typedef struct{uint32_t I2C_ClockSpeed; //I2C时钟频率设置uint16_t I2C_Mode; //I2C模式设置uint16_t I2C_DutyCycle; //高低电平时间之比uint16_t I2C_OwnAddress1; //主设备地址设置,也就是自己的地址uint16_t I2C_Ack; //Checkuint16_t I2C_AcknowledgedAddress; //地址长度,可以为7bit的也可以为10bit的}I2C_InitTypeDef;IIC初始化完之后,我们开始来研究eeprom看完这个写一个字节的协议之后,我们应该对这个写已经没有什么问题了,很简单的。

两片STM32之间I2C通信

两片STM32之间I2C通信
两片STM32之间I2C通信
硬件平台:master:stm32f401reslave:stm32f401ce
开发平台:keil 5.18
操作系统:win7
如上篇所讲,将401CE配置为I2C从机,并设置为从发送模式。
主机的I2C与从机相同,同样配置即可。同时增加uart设置,方便将接收到
的数据打印出来。
while (1)
{
}
注:这里I2C_ADDRESS为与我们设置的从机地址相同
将两篇STM的板子I2C连接起来,我们会在串口调试助手里发现从机发送
过来的数据,即上篇的”…helloworld…“。
tips:感谢大家的阅读,文由我司收集整编。仅供参阅!
(uint8_t *)aRxBuffer, RXBUFFERSIZE,10000) != HAL_OK)
{
/*Error_Handler()functioniscalledwhenTimeouterroroccurs.When
Acknowledgefailureoccurs(Slavedon&#39;tacknowledgeit&#39;saddress)
Master restarts communication */
if (HAL_I2C_GetError(&I2cHandle) != HAL_I2C_ERROR_AF)
{
printf(“\n\rReceivefailed\n”);
}
}
printf(“\n\r%s\n\r”,aRxBuffer);
/* Infinite loop */
主机的设置为主接收:
printf(“\n\rStart....\n\r”);

STM32系列 IIC 使用总结

STM32系列 IIC 使用总结

信号线负载电容(对地)由多方面组成,包括器件引脚、PCB 信号线、连接器等。如果信号线上挂 有多个器件,负载电容也会增大。比如总线规定,对于的 400kbps 速率应用,信号上升时间应小于 300ns; 假设线上 CL 为 20PF,可计算出对应的 RP 值为 15KΩ。
如果 RC 充电时间常数过大,将使得信号上升沿变化缓慢,达不到数据传输的要求。 因此一般应用中选取的都是几 KΩ量级的上拉电阻,比如都选取 4K7 的电阻。 小阻值的 RP 电阻增大了端口 Sink 电流,故在可能的情况下,RP 取值应稍大一点,以减少耗电。另 外,通产情况下,SDA,SCL 两条线上的上拉电阻取值是一致的,并上拉到同一电源上。 PCB 布局布线与抗干扰设计 I2C 信号线属于低速控制线,在手机 PCB 设计时,按通常的控制 IO 对待即可,无需做特别的保护设 计,一般不用担心受到噪声源干扰。 但在一些特定的情况下,比如折叠、滑盖机型中,I2C 的两根信号线需要通过转轴或滑轨处的 FPC, 此时由于信号路径比较长,距离天线比较近,而且 Open drain 的输出级对地阻抗大,对干扰比较敏感,因 此比较容易受到 RF 信号源的干扰。在这种情况下,就应适当注意对 I2C 信号线的保护。比如 I2C 两条信 号线(SDA,SCL)等长度地平行走线,两边加地线进行保护,避免临近层出现高速信号线等。 上拉电阻应安置在 OD 输出端附近。当 I2C 总线上主从器件(Master & Slave)两端均为 OD 输出时, 电阻放置在信号路径的中间位置。当主设备端是软件模拟时序,而从设备是 OD 输出时,应将电阻安置在 靠近从设备的位置。 I2C 协议还定义了串联在 SDA、SCL 线上电阻 Rs。该电阻的作用是,有效抑制总线上的干扰脉冲进 入从设备,提高可靠性。这个电阻的选择一般在 100~200ohm 左右。当然,这个电阻并不是必须的,在恶 劣噪声环境中,可以选用。

基于STM32F10x-一看两看就懂的IIC教程

基于STM32F10x-一看两看就懂的IIC教程

废话不多说,下面简单介绍一下IIC:IIC(IIC,inter-Integrated circuit),两线式串行总线,用于MCU和外设间的通信。

又俗称I2C IIC只需两根线:时钟线SCL和数据线SDA。

以半双工方式实现外设和MCU之间数据传输,速度可达400kbps。

这里以芯片型号为STM32F103RCT6为例.我们在这里只是概括的讲,详细的内容,可以在稍微熟悉以后再去看STM32中文参考手册。

总线空闲状态包括:SDA :高电平SCL :高电平总线信号包括:SDA :串行数据线SCL :串行时钟起始位:SCL为高电平期间,SDA出现下降沿终止位:SCL为高电平期间,SDA出现上升沿IIC时钟频率:一般不高于400K数据传输:SDA的数据在SCL高电平期间被写入从机。

所以SDA的数据变化要发生在SCL 低电平期间。

应答:当IIC主机(不一定是发送端还是接受端)将8位数据或命令传出后,会将SDA信号设置为输入,等待从机应答(等待SDA由高电平拉为低电平)若从机正确应答,表明数据或者命令传输成功,否则传输失败,注意,应答信号是数据接收方发送给数据发送方的。

IIC器件地址:每一个IIC器件都有一个器件地址,有的器件地址在出厂时地址就设定好了,用户不可以更改。

有的器件例如EEPROM,前四个地址已经确定为1010,后三个地址是由硬件链接确定的,所以一个IIC总线最多能连8个EEPROM芯片。

多主从的系统结构以上为简单原理介绍,以下是具体代码实现:初始化:void IIC_Config(void){GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitStructure.GPIO_Pin = SDA_Pin | SCL_Pin;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(I2C_PORT, &GPIO_InitStructure);}void SDA_Input(void){GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = SDA_Pin;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;GPIO_Init(I2C_PORT,&GPIO_InitStructure);}void SDA_Output(void){GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = SDA_Pin;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(I2C_PORT,&GPIO_InitStructure);}SDA的输出读取配置:uint8_t SDA_ReadIn(){uint8_t bitstatus = 0x00;if ((I2C_PORT->IDR & SDA_Pin) != (uint32_t)Bit_RESET){bitstatus = (uint8_t)Bit_SET;}else{bitstatus = (uint8_t)Bit_RESET;}return bitstatus;}设置SDA SCL高低电平:void SDA_(u8 n){n != Low ? (I2C_PORT->BSRR = SDA_Pin): (I2C_PORT->BRR = SDA_Pin); }void SCL_(u8 n){n != Low ? (I2C_PORT->BSRR = SCL_Pin): (I2C_PORT->BRR = SCL_Pin); }I2C开始:void IIC_Start(void){SDA_H;delay;SCL_H;delay;SDA_L;delay;SCL_L;delay;}I2C停止:void IIC_Stop(void){SCL_L;delay;SDA_L;delay;SCL_H;delay;SDA_H;delay;}等待应答:unsigned char IIC_WaitAck(void){u8 ErrorTime = 5;SDA_Input();delay;SCL_H;delay;while((uint8_t)SDA_ReadIn()){ErrorTime--;delay;if(0 ==ErrorTime){SDA_Output();IIC_Stop();return FAILURE;}}SDA_Output();SCL_L;delay;return SUCCESS;}发送应答:void IIC_SendAck(void){SDA_L;delay;delay;SCL_H;delay;SCL_L;delay;}不产生应答:void IIC_SendNoAck(void){SDA_H;delay;delay;SCL_H;delay;SCL_L;delay;}发送字节:void IIC_SendByte(unsigned char byte){ unsigned char t = 8;for(;t>0;t--){SCL_L;delay;SDA_(byte & 0x80);delay;byte+=byte;delay;SCL_H;delay;}SCL_L;delay;}读取字节:unsigned char IIC_RecByte(void){unsigned char t = 8;unsigned char RevByte = 0;SDA_Input();for(;t>0;t--){RevByte+=RevByte;SCL_L;delay;delay;SCL_H;delay;RevByte|= SDA_ReadIn();}SCL_L;delay;SDA_Output();return RevByte;}C文件具体结构:#include "stm32f10x.h"#define I2C_PORT GPIOB#define SDA_Pin GPIO_Pin_7#define SCL_Pin GPIO_Pin_6#define FAILURE 0#define SUCCESS 1#define High 1#define Low 0#define delay {unsigned int i = 0 ; for(;i<500;++i);} #define SDA_H SDA_(High)#define SDA_L SDA_(Low)#define SCL_H SCL_(High)#define SCL_L SCL_(Low)void IIC_Config(void);void SDA_Input(void);void SDA_Output(void);void SDA_(u8 n);void SCL_(u8 n);void IIC_Start(void);void IIC_Stop(void);unsigned char IIC_WaitAck(void);void IIC_SendAck(void);void IIC_SendNoAck(void);void IIC_SendByte(unsigned char byte);unsigned char IIC_RecByte(void);。

STM32-软件模拟I2C

STM32-软件模拟I2C

STM32-软件模拟I2C⼀、SCL和SDA引脚说明 I2C的两个引脚(SCL引脚和SDA引脚)需要既能输出⼜能输⼊,为了避免复杂的配置操作需要把该引脚配置为开漏输出模式,该模式的说明如下图所⽰: 当单⽚机的SDA引脚配置为低电平时,SDA线被拉低;当单⽚机的SDA引脚配置为⾼电平时,引脚端⼝为⾼阻态,SDA线通过上拉电阻被VCC 拉⾼。

因此⼀定要注意在进⾏I2C通讯时确保SDA线和SCL线外接上拉电阻。

三、代码实现 1、I2C软件延时/*** @brief 模拟I2C延时* @retval none* @author Mr.W* @date 2020-10-12*/static void analog_i2c_delay(void){volatile uint8_t i;for (i = 0; i < 10; i++);} 2、I2C引脚初始化/*** @brief 软件模拟I2C初始化* @author Mr.W* @date 2020-10-12*/void bsp_analog_i2c_init(void){GPIO_InitTypeDef GPIO_InitStruct = {0};__HAL_RCC_GPIOB_CLK_ENABLE();/*Configure GPIO pins : PB6 PB7 */GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);bsp_analog_i2c_stop();} 3、I2C开始/*** @brief I2C 开始,SCL为⾼电平的时候SDA产⽣⼀个下降沿信号 * @retval none* @author Mr.W* @date 2020-10-12*/void bsp_analog_i2c_start(void){/* _____*SDA \_____________* __________*SCL \________*/i2c_sda_high();i2c_scl_high();analog_i2c_delay();i2c_sda_low();analog_i2c_delay();i2c_scl_low();analog_i2c_delay();} 4、I2C停⽌/*** @brief I2C 停⽌,SCL为⾼电平的时候SDA产⽣⼀个上升沿信号 * @retval none* @author Mr.W* @date 2020-10-12*/void bsp_analog_i2c_stop(void){/* _______*SDA __________/* ____________*SCL _____/*/i2c_sda_low();i2c_scl_high();analog_i2c_delay();i2c_sda_high();analog_i2c_delay();} 5、I2C等待响应/*** @brief I2C 等待响应* @retval none* @author Mr.W* @date 2020-10-12*/uint8_t bsp_analog_i2c_wait_ack(void){uint32_t timeout = 0;i2c_sda_high();analog_i2c_delay();i2c_scl_high();analog_i2c_delay();while(i2c_read_sda()){if(timeout > 2000){return0;}}i2c_scl_low();analog_i2c_delay();return1;} 6、I2C响应/*** @brief I2C 响应* @retval none* @author Mr.W* @date 2020-10-12*/void bsp_analog_i2c_ack(void){/* ____*SCL ______/ \______* ____ _____*SDA \_______/*/i2c_sda_low();analog_i2c_delay();i2c_scl_high();analog_i2c_delay();i2c_scl_low();analog_i2c_delay();i2c_sda_high();} 7、I2C不响应/*** @brief I2C 不响应* @retval none* @author Mr.W* @date 2020-10-12*/void bsp_analog_i2c_nack(void){/* ____*SCL ______/ \______* __________________*SDA*/i2c_sda_high();analog_i2c_delay();i2c_scl_high();analog_i2c_delay();i2c_scl_low();analog_i2c_delay();} 8、I2C发送⼀个字节数据/*** @brief I2C 发送⼀个字节数据* @retval none* @author Mr.W* @date 2020-10-12*/void bsp_analog_i2c_send_byte(uint8_t data) {uint8_t i;for(i = 0; i < 8; i++){if(data & 0x80){i2c_sda_high();}else{i2c_sda_low();}analog_i2c_delay();i2c_scl_high();analog_i2c_delay();i2c_scl_low();if(i == 7){i2c_sda_high();}data <<= 1;analog_i2c_delay();}} 9、I2C接收⼀个字节数据/*** @brief I2C 读⼀个字节数据* @retval none* @author Mr.W* @date 2020-10-12*/uint8_t bsp_analog_i2c_read_byte(void) {uint8_t i, data = 0;for(i = 0; i < 8; i++ ){data <<= 1;i2c_scl_high();analog_i2c_delay();if(i2c_read_sda()){data++;}i2c_scl_low();analog_i2c_delay();}return data;}#endif。

STM32F0系列软件模拟i2c接口

STM32F0系列软件模拟i2c接口

STM32F0系列软件模拟i2c接口#ifndef _I2C_H_#define _I2C_H_#include "stm32f0xx.h"#define WRITE_MASK 0xFE#define READ_MASK 0x01/************************* SDA-->PA10(输出) ** SCL-->PA9(输出) *************************///I2C输入端口定义#define SDA GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_10) //I2C输出端口定义#define SDA_0 GPIO_ResetBits(GPIOA, GPIO_Pin_10)#define SDA_1 GPIO_SetBits(GPIOA, GPIO_Pin_10)#define SCL_0 GPIO_ResetBits(GPIOA, GPIO_Pin_9)#define SCL_1 GPIO_SetBits(GPIOA, GPIO_Pin_9)/*********************************************函数功能:初始化硬件I2C2接口**参数:无**返回值:无*********************************************/void I2C_Configuration(void);void I2C_Start(void);void I2C_Stop(void);void I2C_Write_Byte(u8 data);u8 I2C_Read_Byte(u8 flag);/*************************************************************函数功能:通过I2C2接口向从机写数据函数* *参数:addr:从机的设备地址,buff:数据缓冲区,length:数据长度**返回值:无*************************************************************/ void I2C_Write_Data(u8 addr,u8 *buff,u16 length);/*************************************************************函数功能:通过I2C从从机读数据函数* *参数:addr:从机的设备地址,buff:数据缓冲区,length:数据长度* *返回值:无* ************************************************************/ void I2C_Read_Data(u8 addr,u8 *buff,u16 length);#endif//以下是源文件#include "i2c.h"/*********************************************函数功能:初始化模拟I2C接口**参数:无**返回值:无*********************************************/void I2C_Configuration(void){/************************* SDA-->PA10(输出) ** SCL-->PA9(输出) *************************/GPIO_InitTypeDef GPIO_InitStructure;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//输出GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;//开漏GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_SetBits(GPIOA,GPIO_Pin_9|GPIO_Pin_10);}void I2C_Start(void){SCL_1;SDA_0;}void I2C_Stop(void){SCL_1;SDA_1;}void I2C_Write_Byte(u8 data){u8 i;for(i=0;i<8;i++){SCL_0;(data&0x80)?SDA_1:SDA_0;SCL_1;data = data<<1;}SCL_0;SDA_1;//输出高电平,可以读取外设的输出SCL_1;while(SDA);//等待应答SCL_0;SDA_0;}u8 I2C_Read_Byte(u8 flag){u8 i;u8 data = 0x00;SCL_0;SDA_1;//输出高电平,可以读取外设的输出for(i=0;i<8;i++){data = data<<1;SCL_1;if(SDA){data |= 0x01;}else{data &= ~0x01;}SCL_0;}(flag)?SDA_0:SDA_1;//应答/不应答SCL_1;SCL_0;SDA_0;return data;}/************************************************************ *函数功能:通过I2C接口向从机写数据函数* *参数:addr:从机的设备地址,buff:数据缓冲区,length:数据长度**返回值:无*************************************************************/ void I2C_Write_Data(u8 addr,u8 *buff,u16 length){u16 i;addr = addr<<1;addr &= WRITE_MASK;I2C_Start();I2C_Write_Byte(addr);//写地址并判断是否写成功for(i=0;i<="">{I2C_Write_Byte(buff[i]);}I2C_Stop();}/************************************************************ *函数功能:通过I2C从从机读数据函数**参数:addr:从机的设备地址,buff:数据缓冲区,length:数据长度**返回值:无*************************************************************/ void I2C_Read_Data(u8 addr,u8 *buff,u16 length){u16 i;addr = addr<<1;addr |= READ_MASK;I2C_Start();I2C_Write_Byte(addr);for(i=0;i<length;i++)< bdsfid="203" p=""></length;i++)<> {if(i==(length-1))//是否为最后一个字节{buff[i] = I2C_Read_Byte(0);//读且不应答} else{buff[i] = I2C_Read_Byte(1);//读且应答} }I2C_Stop();}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

typedef struct
{GPIO_TypeDef* GPIOx;
u16 GPIO_Pin;
}I2C_SCL;
I2C_SCL SCL;
typedef struct
{GPIO_TypeDef* GPIOx;
u16 GPIO_Pin;
}I2C_SDA;
I2C_SDA SDA;
#ifndef __I2C_Configuration_H
#define __I2C_Configuration_H
#include<stm32f10x_lib.h>
#include"GPIO_Configuration.h"
#include"RCC_Configuration.h"
#include"Delay_Configuration.h"
}
#endif
{ACK = FALSE;}
GPIO_ResetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=0;
return(ACK);
}
/*主机发送IIC总线上一个字节数据*/
void I2C_SendByte(u8 data) //发送一个字节
delay_us(10);
GPIO_ResetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=0;
delay_us(10);
}
/*IIC总线结束*/
void I2C_Stop () //I2C结束
{
GPIO_Output_I2C_Configuration(SDA.GPIOx,SDA.GPIO_Pin); //SDA置输出
/*IIC总线启动*/
void I2C_Start ()//I2C开始
{GPIO_Output_I2C_Configuration(SCL.GPIOx,SCL.GPIO_Pin); //SCL置输出
GPIO_Output_I2C_Configuration(SDA.GPIOx,SDA.GPIO_Pin); //SDA置输出
if(bitcount1-1)
{temp1=temp1<<1;}
bitcount1--;
}while(bitcount1);
return(temp1);
}
/*主机向IC总线发送连续读信号*/
void I2C_ack(void) // 发送连续读信号
void I2C_nack(void) // 发送不连续读信号
{
GPIO_Output_I2C_Configuration(SDA.GPIOx,SDA.GPIO_Pin); //SDA置输出 ;
GPIO_ResetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=0;
if(s1) //读 1
{temp1=temp1|0x01;}
else //读 0
{temp1=temp1&0xfe;}
delay_us(10);
GPIO_ResetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=0;
{ bool ACK;
u8 s1;
GPIO_Input_I2C_Configuration(SDA.GPIOx,SDA.GPIO_Pin); //SDA置输入
GPIO_ResetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=0;
GPIO_ResetBits(SDA.GPIOx, SDA.GPIO_Pin);//SDA=0;
delay_us(10);
GPIO_SetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=1;
delay_us(10);
GPIO_SetBits(SDA.GPIOx, SDA.GPIO_Pin);//SDA=1;
delay_us(10); //在时钟大于4u秒期间写数据
GPIO_ResetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=0;
bitcount--;
{
GPIO_Output_I2C_Configuration(SDA.GPIOx,SDA.GPIO_Pin); //SDA置输出;
GPIO_ResetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=0;
delay_us(5);
GPIO_ResetBits(SDA.GPIOx, SDA.GPIO_Pin);//SDA=0;
delay_us(10);
GPIO_ResetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=0;
delay_us(10);
}
/*主机检查从机的响应信号*/
bool I2C_Slave_ACK(void) // 检查从机应答信号,返回0有ACK,返回1无ACK
GPIO_SetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=1;
s1=GPIO_ReadInputDataBit(SDA.GPIOx,SDA.GPIO_Pin);
if (s1)
{ACK = TRUE;}
else
GPIO_SetBits(SCL.GPIOx, SCL.GPIO_Pin); //SCL=1;
s1=GPIO_ReadInputDataBit(SDA.GPIOx, SDA.GPIO_Pin);
data=data<<1;
delay_us(10);
GPIO_ResetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=0;
delay_us(10);
GPIO_SetBits(SCL.GPIOx, SCL.GPIO_Pin); //SCL=1;
} while(bitcount);
}
/*主机接收IIC总线上一个字节数据*/
u8 I2C_ReciveByte(void) //接受一个字节
{
u8 s1=0,temp1=0;
u8 bitcount1=8;
delay_us(5);
GPIO_SetBits(SCL.GPIOx, SCL.GPIO_Pin); //SCL=1;
delay_us(5);
GPIO_ResetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=0;
}
/*主机向IC总线发送不连续读信号*/
{GPIO_SetBits(SDA.GPIOx, SDA.GPIO_Pin);}//SDA=1,写 1
else
{GPIO_ResetBits(SDA.GPIOx, SDA.GPIO_Pin);}//SDA=0,写 0
{u8 bitcount=8; //发送8位
GPIO_Output_I2C_Configuration(SDA.GPIOx,SDA.GPIO_Pin); //SDA置输出
do
{ if((data&0x80)==0x80)
delay_us(5);
GPIO_SetBits(SDA.GPIOx, SDA.GPIO_Pin);//SDA=1;
delay_us(5);
GPIO_SetBits(SCL.GPIOx, SCL.GPIO_Pin); //SCL=ResetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=0;
GPIO_Input_I2C_Configuration(SDA.GPIOx,SDA.GPIO_Pin); //SDA置输入
GPIO_ResetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=0;
do
{delay_us(10); //在时钟大于4u秒期间读数据
GPIO_SetBits(SDA.GPIOx, SDA.GPIO_Pin);//SDA=1;
delay_us(10);
GPIO_SetBits(SCL.GPIOx, SCL.GPIO_Pin);//SCL=1;
delay_us(10);
GPIO_ResetBits(SDA.GPIOx, SDA.GPIO_Pin);//SDA=0;
相关文档
最新文档