STM32 IIC 学习笔记总结
- 格式:pdf
- 大小:555.44 KB
- 文档页数:7
STM32⾃学笔记⼀、原⼦位操作:原⼦位操作定义在⽂件中。
令⼈感到奇怪的是位操作函数是对普通的内存地址进⾏操作的。
原⼦位操作在多数情况下是对⼀个字长的内存访问,因⽽位号该位于0-31之间(在64位机器上是0-63之间),但是对位号的范围没有限制。
原⼦操作中的位操作部分函数如下:void set_bit(int nr, void *addr)原⼦设置addr所指的第nr位void clear_bit(int nr, void *addr)原⼦的清空所指对象的第nr位void change_bit(nr, void *addr)原⼦的翻转addr所指的第nr位int test_bit(nr, void *addr)原⼦的返回addr位所指对象nr位inttest_and_set_bit(nr, void *addr)原⼦设置addr所指对象的第nr位,并返回原先的值int test_and_clear_bit(nr, void *addr)原⼦清空addr所指对象的第nr位,并返回原先的值int test_and_change_bit(nr, void *addr)原⼦翻转addr所指对象的第nr位,并返回原先的值unsigned long word = 0;set_bit(0, &word); /*第0位被设置*/set_bit(1, &word); /*第1位被设置*/clear_bit(1, &word); /*第1位被清空*/change_bit(0, &word); /*翻转第0位*/⼆、STM32的GPIO锁定:三、中断挂起:因为某种原因,中断不能马上执⾏,所以“挂起”等待。
⽐如有⾼、低级别的中断同时发⽣,就挂起低级别中断,等⾼级别中断程序执⾏完,在执⾏低级别中断。
四、固⽂件:固件(Firmware)就是写⼊EROM(可擦写只读存储器)或EEPROM(电可擦可编程只读存储器)中的程序。
/******************************************************************* 文件名:书写程序中一些特别需要留意的地方文件编辑人:张恒编辑日期:15/11/23功能:快速查阅巩固知识点*******************************************************************/ 版本说明:v1.0版本:1.开始编辑书写整个文档,开始用的为TXT文档的形式,整理了部分学习到的东西和一些在书写常用程序中容易出错的地方,以及经常忽视细节而导致程序运行失败,是巩固知识点,提醒值得注意地方的工具文档。
2.添加的功能上基本涵盖了所有的模块,除了串口通信中的SPI和I2C、I2S等,应用是比较简单后续可能会添加。
3.对一些特定的功能综合应用并未加入进去,这是一个不好的地方,后续应该会随着学习总结更新,每次更新记录为一个版本。
// 2015/11/24;v1.1版本:1.将所有的TXT版本的文档全部转换为DOC模式,并且更新的加入了目录显示,显示为1级目录,方便查阅相关内容。
2.更新了SysTick书写中值得注意的地方3.更新了FSMC的一些细微操作,后续继续追捕更新书写细节。
V1.2版本:1.更新了FSMC部分功能显示,详细了FSMC的使用注意事项2.添加了RTC实时时钟的一些注意事项。
//2015/12/1;V1.3版本:1.更新RTC部分注意事项。
//2015/12/11V1.4版本:1.更新ADC校准标志部分注意事项。
2.更新了TIM1和TIM8的高级定时器特殊功能说明。
//2015/12/13V1.5版本:1.优化了部分注意事项,SysTick的写法上重新的定制写法。
2.优化了ADC在使用过程的一些细节注意地方。
3.面对最近出现的浮点数运算错误,配合AD数据进行总结。
4.RTC细节的把握-配置正确顺序的错误。
1 概述I2C总线以2根信号线(数据线SDA,时钟线SCL)实现双向同步数据传,并且可以连接到总线上的任何一个器件作为一个发送器或接收器。
执行数据传输时可以当作主机或从机。
发送器:传送中发送数据到总线的器件接收器:传送中从总线接收数据的器件主机:用来初始化发送、产生时钟信号和终止发送的器件,可是发送器或接收器从机:被主机寻址的器件,也可以作为发送器或接收器LPC1700有三个接口:I2C0/1/2。
I2C0为标准I2C总线接口(开漏引脚),该接口支持I2C规范中所叙述的功能,运行速度高达1MHz。
支持多主机操作,并允许挂接在I2C总线上运行器件在退出I2C总线功能时掉电;而I2C1和I2C2使用标准I/O引脚,专用于单主机I2C总线,不支持挂接在I2C总线上的运行器件在退出I2C总线功能时掉电,也不支持多主机I2C操作。
三个接口在标准模式下,总线数据传输的速度为0到100Kbit/s;高速模式下的为0到400Kbit/s;总线速率越高,总线上拉电阻要越小。
注意的是只有I2C0总线支持快速plus模式,速度可达1Mbit/s,可通过设置CPADCFG寄存器里的SDADRV0和SCLDRV0来实现。
2 总线特性:标准的I2C总线接口;可配置为主机、从机或主/从机;可编程时钟能够实现通用速率控制;主从之间双向数据传输;多主机总线;通信速率高达1MHZ(快速模式);支持监控模式;只能基于版内通信;3 传输协议(1)寻址字节主机产生起始信号后,发送的第一个字节为寻址字节。
前7位为从机地址,最低位决定报文方向:0表示主机写信息到从机,1表示主机读从机中的信息。
(2)传输格式主机产生起始信号后,发送一个寻址字节,收到应答后紧跟着的就是数据传输,数据传输一般由主机产生的停止位终止。
如果主机仍希望在总线上通讯,它可以产生重复起始信号和寻址另一个从机,而不是首先产生一个停止信号。
4 基本配置利用以下寄存器来配置I2C0/1/2接口:(1)电源:在寄存器PCONP中置位PCI2C0/1/2;(2)时钟:在寄存器PCLK_SEL0中选择PCLK_I2C0;在寄存器PCLK_SEL1中选择PCLK_I2C1/2(3)引脚:通过寄存器PINSEL使能I2C0引脚和选择I2C1/2引脚。
STM32中断优先级和开关总中断一,中断优先级:STM32(Cortex-M3)中的优先级概念STM32(Cortex-M3)中有两个优先级的概念——抢占式优先级和响应优先级,有人把响应优先级称作'亚优先级'或'副优先级',每个中断源都需要被指定这两种优先级。
具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。
当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。
如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。
既然每个中断源都需要被指定这两种优先级,就需要有相应的寄存器位记录每个中断的优先级;在Cortex-M3中定义了8个比特位用于设置中断源的优先级,这8个比特位可以有8种分配方式,如下:所有8位用于指定响应优先级最高1位用于指定抢占式优先级,最低7位用于指定响应优先级最高2位用于指定抢占式优先级,最低6位用于指定响应优先级最高3位用于指定抢占式优先级,最低5位用于指定响应优先级最高4位用于指定抢占式优先级,最低4位用于指定响应优先级最高5位用于指定抢占式优先级,最低3位用于指定响应优先级最高6位用于指定抢占式优先级,最低2位用于指定响应优先级最高7位用于指定抢占式优先级,最低1位用于指定响应优先级这就是优先级分组的概念。
--------------------------------------------------------------------------------Cortex-M3允许具有较少中断源时使用较少的寄存器位指定中断源的优先级,因此STM32把指定中断优先级的寄存器位减少到4位,这4个寄存器位的分组方式如下:第0组:所有4位用于指定响应优先级第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级第4组:所有4位用于指定抢占式优先级可以通过调用STM32的固件库中的函数NVIC_PriorityGroupConfig()选择使用哪种优先级分组方式,这个函数的参数有下列5种:NVIC_PriorityGroup_0 => 选择第0组NVIC_PriorityGroup_1 => 选择第1组NVIC_PriorityGroup_2 => 选择第2组NVIC_PriorityGroup_3 => 选择第3组NVIC_PriorityGroup_4 => 选择第4组接下来就是指定中断源的优先级,下面以一个简单的例子说明如何指定中断源的抢占式优先级和响应优先级:// 选择使用优先级分组第1组NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);// 使能EXTI0中断NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQChannel;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 指定抢占式优先级别1NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 指定响应优先级别0NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);// 使能EXTI9_5中断NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 指定抢占式优先级别0NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 指定响应优先级别1NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);要注意的几点是:1)如果指定的抢占式优先级别或响应优先级别超出了选定的优先级分组所限定的范围,将可能得到意想不到的结果;2)抢占式优先级别相同的中断源之间没有嵌套关系;3)如果某个中断源被指定为某个抢占式优先级别,又没有其它中断源处于同一个抢占式优先级别,则可以为这个中断源指定任意有效的响应优先级别。
stm32学习笔记--spi与iic关于上次说的要改程序的问题,//读ADXL345 寄存器//addr:寄存器地址//返回值:读到的值u8 ADXL345_RD_Reg(u8 addr){u8 temp=0; IIC_Start(); IIC_Send_Byte(ADXL_WRITE); //发送写器件指令temp=IIC_Wait_Ack(); IIC_Send_Byte(addr); //发送寄存器地址temp=IIC_Wait_Ack(); IIC_Start(); //重新启动IIC_Send_Byte(ADXL_READ); //发送读器件指令temp=IIC_Wait_Ack(); temp=IIC_Read_Byte(0); //读取一个字节,不继续再读,发送NAK IIC_Stop(); //产生一个停止条件return temp; //返回读到的值} 这段写寄存器代码,不理解temp 为什么要被频繁的赋值,去掉后,宏观看来对结果没有影响。
第二个不理解的地方是为什么在发送寄存器地址之后要从新启动一次,因为在相似的写寄存器函数中,在相同的位置不存在重启代码。
注释掉该句之后显示ADXL345 error。
这两天主要看了三轴加速度计的程序,虽然例程里的能看懂,但是在四轴里的程序却不那么容易,我甚至不明白为什么他要自己写一个iic 的函数,我打算接下来把它的程序和例程里的程序对照来看,看能不能找到什么头绪。
下面是对以前学过内容的总结:对位的寻址操作为了实现对SARM、I/O 外设空间中某一位的操作,在寻址空间(4GB)另一地方取个别名区空间,从这地址开始,每一个字(32bit)就对应SRAM 或I/O 的一位。
即原来每个字节用一个地址,现在给字节中的每个位一个地址,实现了对位的寻址。
spi 与iic 之间各自的优劣1 硬件连接的优劣SPI 是[单主设备(single-master )]通信协议,这意味着总线中的只有一支中心设备能发起通信。
一、概述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串口通信学习总结STM32是STMicroelectronics推出的一款32位单片机系列,具有高性能、低功耗、丰富的外设等特点,广泛应用于工业控制、消费电子、汽车电子等领域。
其中,串口通信是单片机中常用的通信方式之一,本文将对STM32串口通信学习进行总结。
1.串口通信原理及基础知识在STM32中,USART(通用同步/异步收发器)是负责串口通信的外设。
USART提供了多种模式的串口通信,包括异步模式(Asynchronous)、同步模式(Synchronous)以及单线模式(Single-wire)等。
2.STM32串口通信配置步骤(1)GPIO配置:首先需要配置串口通信所涉及的GPIO引脚,通常需要配置为复用功能,使其具备USART功能。
(2)USART配置:根据需要选择USART1、USART2、USART3等串口进行配置,设置通信模式、波特率等参数。
在配置时需要注意与外部设备的通信标准和参数保持一致。
(3)中断配置(可选):可以选择中断方式来实现串口数据的收发。
通过配置中断,当接收到数据时会触发中断,从而实现接收数据的功能。
(4)发送数据:通过USART的发送寄存器将数据发送出去,可以通过查询方式或者中断方式进行发送。
(5)接收数据:通过读取USART的接收寄存器,获取接收到的数据。
同样可以通过查询方式或者中断方式进行接收。
3.常见问题及解决方法(1)波特率设置错误:在进行串口通信时,波特率设置错误可能会导致通信失败。
需要根据外设的要求,选择适当的波特率设置,并在STM32中进行配置。
(2)数据丢失:在高速通信或大量数据传输时,由于接收速度跟不上发送速度,可能会导致数据丢失。
可以通过增加接收缓冲区大小、优化接收中断处理等方式来解决该问题。
(3)数据帧错误:在数据传输过程中,可能发生数据位错误、校验错误等问题。
可以通过对USART的配置进行检查,包括校验位、停止位、数据位等的设置是否正确。
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应⽤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看完这个写⼀个字节的协议之后,我们应该对这个写已经没有什么问题了,很简单的。
推挽输出与开漏输出的区别推挽输出推挽输出::可以输出高可以输出高,,低电平低电平,,连接数字器件连接数字器件; ;开漏输出开漏输出::输出端相当于三极管的集电极输出端相当于三极管的集电极. . 要得到高电平状态需要上拉电阻才行要得到高电平状态需要上拉电阻才行. . 适合于做电流型的驱动电流型的驱动,,其吸收电流的能力相对强其吸收电流的能力相对强((一般20ma 以内以内). ).推挽结构一般是指两个三极管分别受两互补信号的控制推挽结构一般是指两个三极管分别受两互补信号的控制,,总是在一个三极管导通的时候另一个截止另一个截止. .要实现“线与”需要用OC(open collector)collector)门电路门电路门电路..是两个参数相同的三极管或MOSFET,以推挽方式存在于电路中以推挽方式存在于电路中,,各负责正负半周的波形放大任务各负责正负半周的波形放大任务,,电路工作时,两只对称的功率开关管每次只有一个导通,所以导通损耗小关管每次只有一个导通,所以导通损耗小,,效率高。
输出既可以向负载灌电流,也可以从负载抽取电流。
抽取电流。
问题:问题:很多芯片的供电电压不一样,有3.3v 和5.0v 5.0v,需要把几种,需要把几种IC 的不同口连接在一起,是不是直接连接就可以了?实际上系统是应用在I2C 上面。
上面。
简答:简答:1、部分3.3V 器件有5V 兼容性,可以利用这种容性直接连接兼容性,可以利用这种容性直接连接2、应用电压转换器件,如TPS76733就是5V 输入,转换成3.3V 3.3V、、1A 输出。
输出。
开漏电路特点及应用在电路设计时我们常常遇到开漏(在电路设计时我们常常遇到开漏(open drain open drain )和开集()和开集()和开集(open collector open collector )的概念。
所)的概念。
所谓开漏电路概念中提到的“漏”就是指MOSFET 的漏极。
网上看到很多说STM32的I2C很难用,但我觉得还是理解上的问题,STM32的I2C确实很复杂,但只要基础牢靠,并没有想象中的那么困难。
那么就先从基础说起,只说关键点,不涉及代码。
首先说I2C这个协议:协议包括START、ACK、NACK、STOP。
尽管协议中规定START必须,其他几个非必须,但实际上其他三个仍旧非常重要。
主发从收:主START -> 主发地址-> 从ACK -> (主发数据-> 从ACK (循环)) -> 主STOP 或主START 启动下一次传输这一过程中,主控SCL线,从只在ACK时控SDA线,其他时刻主控SDA线。
主收从发:主START -> 从发地址-> 主ACK -> (从发数据-> 主ACK (循环)) -> 接受至最后一个字节时,主NACK -> 主STOP 或主START 启动下一次传输在这一过程中,主START、主ACK 时,主控总线;从发ACK时,主控SCL线,从控SDA线;在主接受数据时,虽然由主设备产生时钟,但从设备在数据未准备好时,拉低SCL线,这样主设备可知从设备未发送数据,从设备在数据准备好,可以发送的时候,停止拉低SCL线,这时候才开始真正的数据传输,换句话说,虽然时钟是由住设备产生,但在总线上未必就有时钟存在,这期间可以看做是从设备在控总线;当发送到最后一字节的时候,主设备发送NACK,从设备接受后,放弃对总线的控制。
STOP在单主环境下非必要,但在多主环境就非常必要,主控总线的设备发送STOP后,通知总线其他设备总线已经闲置。
以前的老器件很容易导致总线死锁,但现在的产品很多都带有超时机制,所以总线被锁的情况基本不怎么存在了。
下面要说的是STM32的寄存器,状态寄存器有两个,事件、错误状态一堆,看起来确实都算是有用,但实际使用的时候未必都要用到,还是要看情况,那么状态寄存器的清除就是个问题,有两个方法,一个是PE位禁止,不过除非在通讯结束,否则会扰乱总线上的电平,后果未知,争取的方法是:对于普通事件,先读SR1,再读SR2,如果是错误,那么就要再增加一个将SR1写0 。
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总线的时钟源和分频系数等参数。
stm32学习⼼得体会 stm32作为现在嵌⼊式物联⽹单⽚机⾏业中经常要⽤多的技术,相信⼤家都有所接触,今天这篇就给⼤家详细的分析下有关于stm32的出⼝,还不是很清楚的朋友要注意看看了哦,在最后还会为⼤家分享有些关于stm32的视频资料便于学习参考。
什么是串⼝ UART : Universal Asynchronous Receiver/Transmitter 通⽤异步收发器 USART : Universal Synchronous Asynchronous Receiver/Transmitter 通⽤同步/异步收发器 ⼀种是常⽤也是最简单的串⾏数据传输协议。
数据线只需要两根就可以实现全双⼯。
Tx: 发送数据线 Rx: 接收数据线 A B TX -----------> Rx Rx <------------Tx 全双⼯: 两个设备可以同时发送和接收 串⾏数据: 发送只⼀根线,⼀次只能发送⼀bit. ⼀bit接着⼀bit发送和接收。
模块通信: 上位机 下位机 通信⼀般需要两个设备,我们把这两个设备,⼈为叫做上位机, 下位机。
上位机: 把处理性能强的机⼦,上位机。
数据⼤部分处理都在上位机完成。
下位机: 把数据采集的终端,处理性能单⼀的机⼦,下位机。
串⼝只有⼀根发送数据线,假如 A要发送⼀个字符数据 10101010 给B A -------- --------- -------- ------- ... ⾼电平周期是多长?即使是不发送数据Tx线上也有⼀个电平状态,接收⽅ 它怎么知道你是在发送呢?.... UART数据如何传输? UART protocol 串⼝协议。
串⼝发送和接收数据是以帧为单位. Frame 1帧(Frame)= 1 start bit(起始位) + 5-9bits数据位 + 0/1bit 校验位 + stop bits(0.5, 1,1,5,2) 起始位: ⼀个周期的低电平 数据位: 5-9bits数据位,具体是多少bits,需要双⽅协商。
K ing_BingGe的专栏写博客,只为记录学习过程中的点点滴滴。
交流Q851419062,我的进步离不开您的指点!!![置顶] 基于stm32f103zet6的IIC学习分类: stm32 2013-03-16 21:52 108人阅读 评论(0) 收藏举报STM32裸机IIC2402一、先简单了解下所为的IIC协议:IIC(Inter -Integrated Circuit) 总线是一种由PHILIPS 公司开发的两线式串行总线,用于连接微控制器及其外围设备。
它是由数据线 SDA 和时钟SCL 构成的串行总线,可发送和接收数据。
在CPU与被控IC之间、IC 与IC之间进行双向传送,高速IIC 总线一般可达400kbps 以上。
I2C 总线在传送数据过程中共有三种类型信号, 它们分别是:开始信号、结束信号和应答信号。
开始信号:SCL 为高电平时,SDA 由高电平向低电平跳变,开始传送数据。
结束信号:SCL 为高电平时,SDA 由低电平向高电平跳变,结束传送数据。
应答信号:接收数据的IC 在接收到8bit 数据后,向发送数据的IC 发出特定的低电平脉冲,表示已收到数据。
CPU 向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU 接收到应答信号后,根据实际情况作出是否继续传递信号的判断。
若未收到应答信号,由判断为受控单元出现故障。
这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。
我用的是AT24C02的EEPROM,所以这个存储空间应该是256B的(2*1024b)1、明确我的器件地址因为24c02的器件地址高4位固定部分为1010,从图中可以看到A0/A1/A2都拉高,所以我的器件地址应该是1010111= 0x57,但是在操作2402的时候还需要发送方向位(读还是写),读:1,写:0,所以在进行操作的时候需要首先发一字节包含器件地址和方向位的数据最终组合起来就是0xae;2、发送完后释放SDA线并在SCL线上产生第9个时钟信号。
stm32 硬件iic原理STM32是一款广泛应用于嵌入式系统开发的微控制器,具有丰富的外设和强大的处理能力。
其中,硬件IIC(Inter-Integrated Circuit)是一种重要的通信接口,它能够实现微控制器与其他外部设备之间的数据交换。
本文将从STM32硬件IIC的原理入手,介绍其工作原理以及相关应用。
一、STM32硬件IIC简介STM32硬件IIC是指STM32微控制器上集成的硬件IIC接口,它是一种串行通信接口,由两条线路组成:SDA(Serial Data)和SCL(Serial Clock)。
其中,SDA线用于数据传输,而SCL线用于同步时钟信号的传输。
通过这两条线路,STM32可以与其他器件进行数据的收发。
二、STM32硬件IIC的工作原理1. 起始信号和停止信号在IIC通信中,数据的传输始于起始信号,终于停止信号。
起始信号由高电平到低电平的跳变而形成,而停止信号由低电平到高电平的跳变而形成。
2. 数据的传输数据的传输是通过时钟信号来同步的。
在传输一个字节的过程中,STM32作为主设备控制时钟信号的产生和数据的读写。
每当产生一个时钟脉冲,数据线上的数据就会被读取或写入。
3. 数据的确认在每传输一个字节后,接收设备会返回一个应答信号,用于确认数据是否成功接收。
应答信号由接收设备拉低数据线来表示,而主设备通过读取数据线上的电平来判断是否接收到应答信号。
三、STM32硬件IIC的应用STM32硬件IIC广泛应用于各种外设的控制和通信。
以下是一些常见的应用场景:1. 传感器数据采集通过连接传感器到STM32的硬件IIC接口,可以方便地采集传感器的数据。
例如,温湿度传感器、光照传感器等,通过IIC接口将数据传输到STM32,然后进行处理和存储。
2. 外部存储器控制将外部存储器(如EEPROM、Flash等)连接到STM32的硬件IIC 接口,可以实现对存储器的读写操作。
这在数据存储和固件升级等场景下非常有用。
关于STM32的硬件IIC使用问题解决方案最近公司上STM32,对新的东西不太熟悉。
直接上手,平台配置啥的都还算顺利,毕竟八位机平台的东西在。
到硬件IIC 的时候就出大问题了,刚刚上板子的PCF8563(RTC),我也懒,直接就用ST 官方给的库。
刚刚开始几次可以读写PCF8563,后来直接就杯具。
查了两天,发现连STAR 信号都发不出来,直接卡在IIC 时钟使能那个地方。
总线永远是忙!实在没办法。
求助几个朋友,其中一种说法是:STM32 的抗干扰问题,导致IIC 总线有动作,让IIC 器件认为忙。
要在VDD 和VSS,接近管脚的地方加104 的电容。
有可能是这种原因,不过我手头板子限制,我没办法加电容,我没有试,要不谁试一下。
然后到网上一搜,乖乖,原来不只是我碰到这个问题,N 多人都碰到这个问题,官方也出了一个修定基本承认这是一个硬件BUG。
杯具了,很多人都直接用IO 直接模拟了。
我的日程安排也打算,再弄一个早止,如果不成我也直接用IO 模拟了。
继续调,继续搜。
在一个BLOG(实在对不起,由于大量的查看网页,我实不记得那博客是哪的了)里看到有这么一个说法:首先是,应用时序不完全标准。
其次是,IIC 自动ACK 的问题。
受这个启发我从新整理IIC 的时序。
由于是总线一开始就是忙,那我在配置IO 的时候,就先更改IO 状态,让IO 先全部拉高。
想当于强制释放总线,然后再配置IO 和IIC。
一看,嘿嘿,IIC不忙了。
大喜!!!理所当然,接下来的写函数也正确了,至少没有出现STAR 发不出的情况。
到读数据,杯具又出现了!又当在了发STAR 的时候,我都无语了。
郁闷过后,仔细跟踪进去发现:第一次读数据是正确的,而第二次读数据的时候才出现了STAR 不能发的情况。
我又从新组织一个读的IO 配。
STM32系列IIC学习笔记经验总结一、各寄存器内容与组织:控制、地址匹配、数据、状态、时钟控制、上升沿控制二、IIC协议及STM32的master实现EVENT后的第一个符号表示事件发生后对应的标志位的状态,着重看7位地址的通信;三、基础知识(主要讨论起主机模式,从机模式的配置与使用可类比)1.默认工作在从机模式,产生起始信号后自动转为主机模式,产生终止信号或仲裁失权后自动转为从机模式;起止信号由主机模式下的软件实现,地址也只能由主机发送,响应信号由接收器发出(软件实现),要注意区别主机、从机、发送机、接收机;2.数据通信的直接通道,SDA LineShift RegisterDRMemory(数据寄存器与存储器直接的数据交换发生在DMA模式,另外若从机在SDA接收到的是地址则直接会与地址寄存器比较,而不会送入数据寄存器)3.主机产生时钟信号,一串数据总是以起始于start信号,终止于stop信号,一旦SDA线上产生start位信号,主机模式便被选中;9个寄存器的功能分配简单明了:I2C_CR2主要配置时钟与模块中断及DMA使能位,I2C_CR1则主要产生Start等控制信号,I2C_SR2主要是MSL、TRA和BUSY标志位,I2C_SR1则是其他事件的标志位,接下来就是存储数据的I2C_DR,时钟设置的I2C_CC4R和I2C_TRISE,地址匹配的I2C_OAR1和I2C_OAR2;4.主机模式必要操作序列:外围时钟输入最少2M(标准模式)、4M(快速模式)1)配置I2C_CR2寄存器以产生正确时序;2)配置时钟控制寄存器I2C_CCR;3)配置上升时间寄存器I2C_TRISE;4)配置I2C_CR1寄存器以使能接口电路;5)配置I2C_CR1寄存器,置位START位以产生起始信号;5.时序具体解析1)Start信号,置位I2C_CR1的START位以产生起始信号(在总线空闲时,即I2C_SR2的BUSY清零),使转为主机模式(置位I2C_SR2的MSL);在主机模式下,置位START位会在当前字节传输完成后产生一个重启ReStart信号;一旦Start信号送出,I2C_SR1的SB位会由硬件置位并产生中断(前提是ITEVFEN位被置位,貌似文档有误,我认为应是IC2_SR2的ITEVTEN位),然后需要读SR1和写DR以清零SB(这也符合操作时序);2)从机地址发送,7位模式下,地址字节一旦送出,I2C_SR1的ADDR位会由硬件置位并产生中断(前提是ITEVFEN 置位),然后主机等待读取SR1和SR2以清零ADDR(稍微符合,读SR2貌似饶了一步);7位模式下,地址字节最低位若是0则说明主机要进入发送模式,若是1则是接收模式;I2C_SR2的TRA表示主机在发送模式还是接收模式;3)主机发送模式,地址送出且ADDR清零后,主机会将DR中数据发送到SDA line(当然经过Shift Register),主机会等到第一个数据写入DR(EV8_1阶段),若收到响应脉冲,SR1中的TxE位会置位(前提是ITEVFEN和ITBUFEN已置位);在最后一个字节传输结束前的传输过程中,若TxE置位且某数据字节没有写入DR,BTF会置位直到(硬件清零)该数据字节被写入到DR,这个过程中SCL会一直被拉低;4)主机发送模式关闭通信,最后一个字节被写入DR,CR1的STOP位要由软件置位而产生停止信号,接口自动转为从机模式(MSL清零);置位Stop位即对应于EV8_2事件;5)主机接收模式,地址送出且ADDR清零后,主机会进入接收模式,接口会从SDA line中读数据到DR中(同样经过Shift Register);每个字节接收后的操作序列为,产生应答信号(前提是CR1的ACK位置位),RxNE位置位并产生中断(前提是SR2的ITEVFEN和ITBUFEN置位);在最后一个字节传输结束前的传输过程中,若RxNE 置位且某数据未从DR中读取,BTF会置位直到(硬件清零)该数据字节被读出,这个过程SCL会一直被拉低;6)主机接收模式关闭通信,收到最后一个字节后会发送NACK信号给从机,从机收到NACK会释放总线(SDA和SCL),此时主机便可发送一个Stop或Restart信号;在读完倒数第二个字节后(RxNE中断后),要清零ACK 位以产生NACK应答,要置位STOP/START位以产生Stop/Restart信号;在单字节数据接收状况,NACK 要在ADDR清零前(EV6)设置,STOP信号要在ADDR清零后配置;Stop信号产生后,主机自动进入从机模式(SR2的MSL清零);7)最后一字节数据接收的ACK响应前若RxNE清零(ACK清零与Stop请求)没有完成,则建议采取以下步骤以确保ACK位在最后一字节数据接收前被清零,STOP位在最后一字节数据接受完后(没有附加数据)被置位:(1)2字节的数据接收:等到ADDR=1;清零ACK,置位POS;清零ADDR;等到BTF=1(数据1在DR,数据2在Shift Register——即最后一个字节到来时RxNE置位且DR中没有写入最后字节);置位STOP;读取数据1和数据2;(2)N>2字节的数据接收:对前N-2个数据,等到BTF=1(N-2在DR且N-1在Shift Register);清零ACK(永远是对最后一个数据的响应,而且后面跟随的信号是STOP信号);读取N-2;等到BTF=1(N-1在DR且N在Shift Register);STOP置位;读取N-1与N;6.DMA控制1)DMA请求只产生于数据传输过程,当发送时DR为空或接收时DR为满时便会激发DMA请求,DMA请求必须在当前字节传输完前服务,当传输的字节数达到DMA channel通道的程序设定值时,DMA controller控制器会发送EOT(End of Transfer)信号给I2C接口并产生传输完成的中断(若中断已被使能);主机发送模式,在中断程序中要disable DMA requests,然后在编程Stop位前要等待BTF时间;主机接收模式,当接收字节数大于等于2时,DMA controller发送硬件信号EOT_1(对应倒数第2个数据),若在CR2中的LAST置位,I2C 会自动产生NACK以响应EOT_1的下一个字节,用户只需在DMA完成中断中产生一个Stop信号;主机接收模式中,接收单个字节时,NACK必须在EV6(ADDR=1)事件中编程实现即当ADDR=1时令ACK=0,然后可以再清零ADDR(可软件可硬件、选择时参考时序)后发送STOP信号,也可在DMA完成中断程序中(发送EOT 信号时)实现;2)DMA发送模式:CR2的DMAEN置位,当TxE置位时数据会通过DMA外围电路从某个内存单元装载到I2C_DR,为实现一个DMA通道的I2C发送,可以执行以下操作序列,x是选择的通道号:(1)在DMA_CPARx寄存器中设置I2C_DR的地址;在DMA_CMARx寄存器中设置存储单元的地址;随TxE 而访问;(2)在DMA_CNDTRx寄存器中设置字节总数,随TxE而递减;(3)在DMA_CCRx寄存器中用Pl[0:1]配置通道优先级;(4)在DMA_CCRx寄存器中设置DIR位,根据实际需要在传输一半或完成时配置中断;(5)配置DMA_CCRx寄存器的EN位以激活通道;当设置的数目到达时,DMA controller会发送EOT/EOT_1信号到I2C接口,产生DMA完成中断,DMA通道中断允许向量;3)DMA接收模式:DMAEN置位,当接收到数据时数据会通过DMA外围电路从I2C-DR装载到某个没存单元,为实现DMA通道的I2C接收,可以执行以下操作序列,x是选择的通道号:(1)在DMA_CPARx寄存器中设置I2C_DR的地址;在DMA_CMARx寄存器中设置存储单元的地址;随RxNE 而访问;(2)在DMA_CNDTRx寄存器中设置字节总数,随RxNE而递减;(3)在DMA_CCRx寄存器中用Pl[0:1]配置通道优先级;(4)在DMA_CCRx寄存器中设置DIR位,根据实际需要在传输一半或完成时配置中断;(5)配置DMA_CCRx寄存器的EN位以激活通道;当设置的数目到达时,DMA controller会发送EOT/EOT_1信号到I2C接口,产生DMA完成中断,DMA通道中断允许向量;若使用DMA接收,不要使能I2C_CR2寄存器中的ITBUFEN位;4)其他7.中断映射8.补充知识1)POS是对于数据接收的响应或PEC位置,由硬件置位或清零(PE=0时硬件清零),必须在2字节读取时用到(主机接收模式);清零时表示ACK位是对当前Shift Register中所接收数据的响应,置位时表示ACK位是对下一个到Shift Register中的数据的响应;没接收一个字节,数据接收或地址匹配都会引起ACK响应;2)PE是Peripheral Enable,在通信结束前不能使用;CR2中的LAST是在主机接收模式中确保最后一个数据响应为NACK(DMA通信);SR1中的AF在没有响应时置位;3)BTF置位说明某数据字节传输已经成功完成(并不是说所有数据传输已经完成),是在NOSTRETCH=0时由硬件自动置位,由软件通过读写DR清零或起止信号后硬件自动清零;NACK接收到后BTF不会置位,下一个要传输的是PEC时BTF不会置位;9.I2C通信频率不能超过400k,I2C模块的输入频率不能小于2M(标准模式、快速模式是4M),I2C对应的IO口输入频率要高于2/4M,一般取50M;四、编程实现:1.相关库函数:1)按指定参数初始化I2Cx寄存器(x可为1或2),void I2C_Init(I2C_TypeDef*I2Cx,I2C_InitTypeDef *I2C_InitStruct)2)使能或失能I2C外设,void I2C_Cmd(I2C_TypeDef*I2Cx,FunctionalState NewState)3)使能或失能I2C的DMA请求,I2C_DMACmd(I2C_TypeDef*I2Cx,FunctionalState NewState) 4)使下次的DMA传输为最后一次传输,I2C_DMALastTransferCmd(I2C_TypeDef*I2Cx, FunctionalState NewState)5)产生起始条件,void I2C_GenerateSTART(I2C_TypeDef*I2Cx,FunctionalState NewState) 6)产生终止条件,void I2C_GenerateSTOP(I2C_TypeDef*I2Cx,FunctionalState NewState)7)使能或失能I2C的应答:void I2C_AcknowledgeConfig(I2C_TypeDef*I2Cx,FunctionalState NewState)8)设定自身的I2C地址:void I2C_OwnAddress2Config(I2c_TypeDef*I2Cx,u8Address)9)使能或失能指定的I2C中断:void I2C_ITConfig(I2C_TypeDef*I2Cx,u16I2C_IT, FunctionalState NewState)10)通过外设I2C发送一个数据:void I2C_SendData(I2C_TypeDef*I2Cx,u8Data)11)返回通过I2Cx最近接受的数据:u8I2C_ReceiveData(I2C_TypeDef*I2Cx)12)向指定的I2C设备传送地址字:void I2C_Send7bitAddress(I2C_TypeDef*I2Cx,u8Address,u8I2C_Direction)13)读取指定的I2C寄存器并返回其值:u16I2C_ReadRegister(I2C_TypeDef*I2Cx,u8 I2C_Register)14)使能或失能指定的I2C的软件复位:I2C_SoftwareResetCmd(I2C_TypeDef*I2Cx, FunctionalState NewState)15)使能或失能指定的I2C的PEC传输:I2C_TransimitPEC(I2C_TypeDef*I2Cx, FunctionalState NewState)16)使能或失能时钟延展:void I2C_StrechClockCmd(I2C_TypeDef*I2Cx,FunctionalState NewState)17)指定I2C的快速模式的占空比:void I2C_FastModeDutyCycleConfig(I2C_TypeDef*I2Cx,u 16I2C_DutyCycle),其实在初始化中已经有所介绍;18)返回最近一次I2C事件,u32I2C_GetLastEvent(I2C_TypeDef*I2Cx)19)检查最近一次I2C事件是否是输入的事件,ErrorStatus I2C_CheckEvent(I2C_TypeDef*I2C x,u32I2C_EVENT)20)检查指定的I2C标志位设置与否:FlagStatus I2C_GetFlagStatus(I2C_TypeDef*I2Cx,u3 2I2C_FLAG)21)清除I2Cx的待处理标志位:void I2C_ClearFlag(I2C_TypeDef*I2Cx,u32I2C_FLAG)---若不能自动硬件清除的话22)检查指定的I2C中断发生与否:ITStatus I2C_GetITStatus(I2C_TypeDef*I2cx,u32I2C_I T)23)清除I2Cx的中断待处理位:void I2C_ClearITPendingBit(I2C_TypeDef*I2Cx,u32I2C_I T)2.基本思路:1)了解各库函数的功能及其涉及到的数据结构;2)定义枚举状态变量(检测最后状态):typedef enum{FAILED=0;PASSED=!FAILED}TestStatus;定义比变量并初始化volatile TestStatus TransferStatus=FAILEd;3)首先时钟配置,RCC_Configuration();打开端口时钟:RCC_APB2PeriphClockCmd(RCC_APB2P eriph_GPIOB|RCC_APB2Periph_GPIOB,ENABLE);打开APB1总线上的I2C1:RCC_APB1Per iphClockCmd(RCC_APB1Periph_I2C1,ENABLE),即I2C模块与相应I/O口要分别打开;4)其次是中断配置,这里没用到,NVIC_Configuration的中断向量若需要则要合理配置;5)从机的初始化配置,首先是GPIO的配置,然后是I2C的配置;GPIO配置,先定义配置结构体变量(类似I2C),然后对引脚、速率、模式分别赋值,调用GPIO_Init初始化;50MHz上面配置完,下面的C口就不用再重新配置了;I2C配置,定义配置结构体,对个成员赋初值,调用初始化函数,然后使能I2C模块,便可对其进行操作;6)写数据函数(调用有关函数实现将发送数组写入EEPROM)I2C_EE_SequentialWrite(Tx_Buffer, EEPROM_WriteAddress,BufferSize);字节数BufferSize可能超过一页,可能超过一页,用页写函数(根据时序和轮询用库函数来实现);每次操作都要考虑通信芯片的自编程;7)读数据函数:I2C_EE_SequentialWrite(Rx_Buffer,EEPROM_WriteAddress,BufferSize);8)若要用I2C自带中断的话,需要在中断程序中用状态机来实现;3.当确认用主机模式时,接下来要了解的便是要通信的器件的I2C的读写时序,对应主机只需要知道怎么检测标志就可以了,而从机的数据需要一定的时序才能读出或写入;五、其他。