STM32 IIC 学习笔记总结
STM32自学笔记

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(电可擦可编程只读存储器)中的程序。
STM32学习笔记及勘误手册

/******************************************************************* 文件名:书写程序中一些特别需要留意的地方文件编辑人:张恒编辑日期: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细节的把握-配置正确顺序的错误。
I2C学习笔记

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自学笔记共20页

•
LED0=1;
•
LED1=0;
•
delay_ms(300);
•
}
•}
第二章 跑马灯实验
• Led.c函数
• void LED_Init(void)
•{
•
RCC->APB2ENR|=1<<2; //使能PORTA时钟
•
GPIOA->CRH|=0XFFFFFFFF3;//PA8 推挽输出
•
GPIOA->ODR|=1<<8; //PA8 输出高
• JTAG_Set(JTAG_SWD_DISABLE);//关闭JTAG和SWD,在原理图上可以看 到PA13和PA15为键盘和JTAG与SWD所共用,而这两种方针接口,他们 和普通的IO口公用,当想使用普通IO口时,必须先把他们关闭。在这 个函数里面设置参数,如果为二进制数00,则代表全部使能,如果是 二进制数01,则是能SWD,如果是10,则表示全部关闭。JTAG是一种 国际标准测试协议,主要用于芯片内部的测试。
• }要想实现一个点亮led小灯的功能,最少只需对3个寄存器进行设 置,第一步是设置外设时钟使能先把PORTA时钟使能,接下来把IO
口设置为输出,在接下来设置输出为高电平还是低电平,这里使用 推挽输出(3.3v),推挽输出主要是增强驱动能力,为外部提供大电 流。
第二章 跑马灯实验
• #ifndef __LED_H • #define __LED_H • #include "sys.h" • #define LED0 PAout(8)// PA8 • #define LED1 PDout(2)// PD2 • void LED_Init(void);//初始化
STM32各模块学习笔记

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

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 )]通信协议,这意味着总线中的只有一支中心设备能发起通信。
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串口通信学习总结

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的配置进行检查,包括校验位、停止位、数据位等的设置是否正确。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
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的读写时序,对应主机只需要知道怎么检测标志就可以了,而从机的数据需要一定的时序才能读出或写入;五、其他。