目录:

  • 一、I2C协议简介
  • 二、STM32的I2C
  • 三、I2C读取EEPROM

一、I2C协议简介

  I2C(IIC,Inter-Integrated Circuit),两线式串行总线,由飞利浦(PHILIPS)公司开发用于连接微控制器及其外围设备。它是由数据线SDA和时钟SCL构成的半双工串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbps以上。

1.功能特点
  1)它只使用两条总线线路:一条双向串行数据线(SDA),一条串行时钟线(SCL)。
  2)每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备之间的访问。
  3)多主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定由哪个设备占用总线。
  4)具有三种传输模式:标准模式的传输速率为100 Kbit/s", 快速模式为400 Kbit’s ,高速模式下可达3.4 Mbit/s,但目前大多I2C设备尚不支持高速模式。
  5)片上的滤波器可以滤去总线数据线上的毛刺波以保证数据完整。
  6)连接到相同总线的IC数量受到总线的最大电容400 pF限制。
2.信号时序
  I2C 总线在传送数据中有空闲状态、开始信号、停止信号、应答信号、数据的有效性判断、数据传输等信号机过程。
1)空闲状态
  I2C总线总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。
2)起始信号与停止信号
  ⚫ 起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
  ⚫ 停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。

3)应答信号ACK
  发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。 应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。对于反馈有效应答位ACK的要求是,接收器在第9个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。 如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器结束数据发送,并释放SDA线,以便主控接收器发送一个停止信号P。

4)数据有效性
  I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。即:数据在SCL的上升沿到来之前就需准备好。并在在下降沿到来之前必须稳定。

5)数据的传送
  在I2C总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。数据位的传输是边沿触发。
4)地址及数据方向
  I2C 总线上的每个设备都有自己的独立地址,主机发起通讯时,通过 SDA 信号线发送设备地址(SLAVE_ADDRESS)来查找从机。I2C 协议规定设备地址可以是 7 或 10 位,实际中 7 位的地址应用比较广泛。紧跟设备地址的一个数据位用来表示数据传输方向,它是数据方向位(R/W),第 8位或第 11位。数据方向位为“1”时表示主机由从机读数据,该位为“0”时表示主机向从机写数据。
3.工作流程
  I2C的协议包括起始和停止条件、数据有效性、响应、仲裁、时钟同步和地址广播等环节。

  上图表示的是主机和从机通信时SDA线的数据包序列。
  其中S表示由主机的IC接口产生的传输起始信号(S), 这时连接到I2C总线上的所有从机都会接收到这个信号。
  起始信号产生后,所有从机就开始等待主机紧接下来广播的从机地址信号(SLAVE_ADDRESS),在I2C总线上,每个设备的地址都是唯一的。当主机广播的地址与某个设备地址相同时,这个设备就被选中了,没被选中的设备将会忽略之后的数据信号。根据I2C协议,这个从机地址可以是7位或10位。
 在地址位之后,是传输方向的选择位,该位为0时,表示后面的数据传输方向是由主机传输至从机。该位为1时,则相反。
 从机接收到匹配的地址后,主机或从机会返回一一个应答(A)或非应答(A)信号,只有接收到应答信号后,主机才能继续发送或接收数据。
 若配置的方向传输位为写数据,广播完地址,接收到应答信号后,主机开始正式向从机传输数据(DATA),数据包的大小为8位。主机每发送完-一个数据,都要等待从机的应答信号(A,重复这个过程,可以向从机传输N个数据,这个N没有大小限制。当数据传输结束时,主机向从机发送一个停止传输信号(P),表示不再传输数据。
 若配置的方向传输位为读数据,广播完地址,接收到应答信号后,从机开始向主机返回数据(DATA),数据包大小也为8位。从机每发送完一个数据,都会等待主机的应答信号(A),重复这个过程,可以返回N个数据,这个N也没有大小限制。当主机希望停止接收数据时,就向从机返回一个非应答信号(A),则从机自动停止数据传输。

二、STM32的I2C

1.I2C接口特性
  1) STM32的中等容量和大容量型号的芯片均有多达两个的rc总线接口。
  2)能够工作于多主模式或从模式,分别为主接收器、主发送器、从接收器及从发送器。
  3)支持标准模式100 Kbit/s和快速模式400 Kbit/s,不支持高速模式。
  4)支持7位或10位寻址。
  5)内置了硬件CRC发生器/校验器。
  6) I2C 的接收和发送都可以使用DMA操作。
  7)支持系统管理总线(SMBus) 2.0 版。
2.I2C架构

  上图中我们可以看到,I2C的所有硬件架构就是根据SCL线和SDA线展开的(其中SMBALERT线用于SMBus)。
  SCL线的时序即为I2C协议中的时钟信号,它由IC接口根据时钟控制寄存器(CCR)控制,控制的参数主要为时钟频率。
  而SDA线的信号则通过一系列数据控制架构,在将要发送的数据的基础上,根据协议添加各种起始信号、应答信号、地址信号,实现以I2C协议的方式发送出去。读取数据时则从SDA线上的信号中取出接收到的数据值。发送和接收的数据都被保存在数据寄存器(DR)上。

三、I2C读取EEPROM

1.发送读写流程
(1)主发送器发送流程:
  ⚫ 控制产生起始信号(S),当发生起始信号后,它产生事件“EV5”,并会对 SR1 寄存器的“SB”位置 1,表示起始信号已发送;
  ⚫ 接着发送设备地址并等待应答信号,若有从机应答,则产生事件“EV6”及“EV8”,这时 SR1 寄存器的“ADDR”位及“TXE”位被置 1,ADDR 为 1表示地址已经发送,TXE 为 1表示数据寄存器为空;
  ⚫ 以上步骤正常执行并对 ADDR 位清零后,我们往 I2C 的“数据寄存器 DR”写入要发送的数据,这时TXE位会被重置0,表示数据寄存器非空,I2C外设通过SDA信号线一位位把数据发送出去后,又会产生“EV8”事件,即 TXE 位被置 1,重复这个过程,就可以发送多个字节数据了;
  ⚫ 当我们发送数据完成后,控制 I2C 设备产生一个停止信号( P ),这个时候会产生EV8_2 事件,SR1 的 TXE位及 BTF位都被置 1,表示通讯结束。
  ⚫假如我们使能了 I2C 中断,以上所有事件产生时,都会产生 I2C 中断信号,进入同一个中断服务函数,到 I2C中断服务程序后,再通过检查寄存器位来判断是哪一个事件。
(2)主接收器接收流程:
  ⚫ 同主发送流程,起始信号(S)是由主机端产生的,控制发生起始信号后,它产生事件“EV5”,并会对 SR1寄存器的“SB”位置 1,表示起始信号已经发送;
  ⚫ 紧接着发送设备地址并等待应答信号,若有从机应答,则产生事件“EV6”这时SR1 寄存的“ADDR”位被置 1,表示地址已经发送。
  ⚫ 从机端接收到地址后,开始向主机端发送数据。当主机接收到这些数据后,会产生“EV7”事件,SR1寄存器的 RXNE被置 1,表示接收数据寄存器非空,我们读取该寄存器后,可对数据寄存器清空,以便接收下一次数据。此时我们可以控制I2C 发送应答信号(ACK)或非应答信号(NACK),若应答,则重复以上步骤接收数据,若非应答,则停止传输;
  ⚫ 发送非应答信号后,产生停止信号( P ),结束传输。
  在发送和接收过程中,有的事件不只是标志了我们上面提到的状态位,还可能同时标志主机状态之类的状态位,而且读了之后还需要清除标志位,比较复杂。我们可使用STM32标准库函数来直接检测这些事件的复合标志,降低编程难度。
2.I2C初始化函数

I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = I2C1_OWN_ADDRESS7;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgeAddress = I2C_AcknowledgeAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;
I2C_Init(I2C1,ENABLE);

(1)I2C_ Mode :
  本成员是选择I2C的使用方式,有I2C模式(I2C_ Mode_I2C)和SMBus模式(I2C_ Mode_SMBusDevice、I2C Mode_ SMBus_Host )。
(2)I2C_DutyCycle:
  本成员设置的是I2C的SCL线时钟的占空比。SCL线的时钟信号的高电平时间与低电平时间不必相同,由于SDA线在SCL线维持在高电平时读取或写入数据,而在SCL的低电平期间SDA的数据发生变化,所以高电平时间较长就不容易出现数据错误。根据I2C协议,在快速模式和高速模式下SCL的高低电平时间可以不同。在STM32的rC占空比配置中有两个选择,分别为高电平时间和低电平时间之比为16:9 (I2C_DutyCycle_16_9)和2: 1 ( I2C_DutyCycle_2)。
(3) I2C_OwnAddress1 :
  本成员配置的是STM32的IC设备自己的地址,每个连接到I2C总线上的设备都要有一个自己的地址,作为主机也不例外。就如同前面介绍的连接到IFC的EEPROM的设备地址一样,只不过STM32的I2C地址可软件编程。这个地址可以被配置为7位和10位地址。
(4)I2C_AckEnable:
  本成员关于FC应答设置,设置为使能则每接收到一个字节就返回一个应答信号。本实验配置为允许应答(I2C_Ack_ Enable), 这是绝大多数遵循I2C标准的设备通信的要求,改为禁止应答(I2C_Ack_Disable) 往往会导致通信错误。
(5)I2C_AcknowledgeAddress :
  本成员选择I2C的寻址模式是7位还是10位地址。这需要根据实际连接到IC总线上设备的地址进行选择。本实验是与EEPROM进行通信,使用的为7位寻址模式(I2C_AcknowledgedAddress_7bit)。
(6)I2C_ClockSpeed :
  本成员设置的是FC的传输速率,在调用初始化函数时,函数会根据我们输入的数值经过运算后把分频值写人到FC的时钟控制寄存器。而我们写人的这个参数值不得高于400KHZ。本实验向这个成员写人参数为400000 (自定义密I2C Speed)。实际上由于IC使用的APB1时钟为36 MHz,不是10 MHz的整数倍,因此最终分频后输出的SCL线时钟并不是精确的400KHz。
  对结构体成员赋值完成后,我们调用库函数I2C_ Init()根据我们的配置对IFC进行初始化,并调用库函数I2C_Cmd()使能I2C外设。
3.实验程序
  这里我们不使用STM32的硬件IIC来读写24C02,而是通过软件模拟IIC来读写24C02。STM32的硬件IIC非常复杂,更重要的是不稳定,故不推荐使用。
(1)IIC初始化函数

//初始化 IIC
void IIC_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;
//RCC->APB2ENR|=1<<4;//先使能外设 IO PORTC 时钟
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
IIC_SCL=1;
IIC_SDA=1;
}
//产生 IIC 起始信号
void IIC_Start(void)
{SDA_OUT(); //sda 线输出
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;//START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL=0;//钳住 I2C 总线,准备发送或接收数据
}
//产生 IIC 停止信号
void IIC_Stop(void)
{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;//发送 I2C 总线结束信号
delay_us(4);
}
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
u8 IIC_Wait_Ack(void)
{u8 ucErrTime=0;
SDA_IN(); //SDA 设置为输入
IIC_SDA=1;delay_us(1);
IIC_SCL=1;delay_us(1);
while(READ_SDA)
{ucErrTime++;
if(ucErrTime>250)
{IIC_Stop();
return 1;
}
}
IIC_SCL=0;//时钟输出 0
return 0;
}
//产生 ACK 应答
void IIC_Ack(void)
{IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
//不产生 ACK 应答
void IIC_NAck(void)
{IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
//IIC 发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void IIC_Send_Byte(u8 txd)
{u8 t;
SDA_OUT();IIC_SCL=0;//拉低时钟开始数据传输for(t=0;t<8;t++){IIC_SDA=(txd&0x80)>>7;txd<<=1;
delay_us(2); //对 TEA5767 这三个延时都是必须的
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);}
}
//读 1 个字节,ack=1 时,发送 ACK,ack=0,发送 nACK
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();//发送 nACKelseIIC_Ack(); //发送 ACKreturn receive;
}

  该部分为IIC初始化代码,实现包括IIC的初始化(IO口)、IIC开始、IIC结束、ACK、IIC读写等功能,在其他函数里面,只需要调用相关的IIC函数就可以和外部IIC器件通信了,这里并不局限于24C02,该段代码可以用在任何IIC设备上。
(2)IIC.h

#define SDA_IN() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=8<<12;}
#define SDA_OUT() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=3<<12;}

(3)24C02代码

#include "24cxx.h"
#include "delay.h"
//初始化 IIC 接口
void AT24CXX_Init(void)
{IIC_Init();
}
//在 AT24CXX 指定地址读出一个数据
//ReadAddr:开始读数的地址
//返回值 :读到的数据
u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{u8 temp=0;IIC_Start();
if(EE_TYPE>AT24C16)
{IIC_Send_Byte(0XA0); //发送写命令
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr>>8);//发送高地址
}else IIC_Send_Byte(0XA0+((ReadAddr/256)<<1)); //发送器件地址 0XA0,写数据
IIC_Wait_Ack(); IIC_Send_Byte(ReadAddr%256); //发送低地址
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(0XA1); //进入接收模式
IIC_Wait_Ack();temp=IIC_Read_Byte(0);IIC_Stop();//产生一个停止条件
return temp;
}
//在 AT24CXX 指定地址写入一个数据
//WriteAddr :写入数据的目的地址
//DataToWrite:要写入的数据
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{IIC_Start();
if(EE_TYPE>AT24C16)
{IIC_Send_Byte(0XA0); //发送写命令
IIC_Wait_Ack();
IIC_Send_Byte(WriteAddr>>8);//发送高地址
}else IIC_Send_Byte(0XA0+((WriteAddr/256)<<1)); //发送器件地址 0XA0,写数据
IIC_Wait_Ack();IIC_Send_Byte(WriteAddr%256); //发送低地址
IIC_Wait_Ack();
IIC_Send_Byte(DataToWrite); //发送字节
IIC_Wait_Ack();IIC_Stop(); //产生一个停止条件
delay_ms(10); //对于 EEPROM 器件,每写一次要等待一段时间,否则写失败!
}
//在 AT24CXX 里面的指定地址开始写入长度为 Len 的数据
//该函数用于写入 16bit 或者 32bit 的数据.
//WriteAddr :开始写入的地址
//DataToWrite:数据数组首地址
//Len :要写入数据的长度 2,4
void AT24CXX_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len)
{u8 t;
for(t=0;t<Len;t++) AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff);
}
//在 AT24CXX 里面的指定地址开始读出长度为 Len 的数据
//该函数用于读出 16bit 或者 32bit 的数据.
//ReadAddr :开始读出的地址
//返回值 :数据
//Len :要读出数据的长度 2,4
u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len)
{u8 t; u32 temp=0;
for(t=0;t<Len;t++)
{temp<<=8;
temp+=AT24CXX_ReadOneByte(ReadAddr+Len-t-1);
}
return temp;
}
//检查 AT24CXX 是否正常
//这里用了 24XX 的最后一个地址(255)来存储标志字.
//如果用其他 24C 系列,这个地址要修改
//返回 1:检测失败
//返回 0:检测成功
u8 AT24CXX_Check(void)
{u8 temp;
temp=AT24CXX_ReadOneByte(255);//避免每次开机都写 AT24CXX
if(temp==0X55)return 0;
else//排除第一次初始化的情况
{AT24CXX_WriteOneByte(255,0X55);temp=AT24CXX_ReadOneByte(255);
if(temp==0X55)return 0;
}
return 1;
}
//在 AT24CXX 里面的指定地址开始读出指定个数的数据
//ReadAddr :开始读出的地址 对 24c02 为 0~255
//pBuffer :数据数组首地址
//NumToRead:要读出数据的个数
void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)
{while(NumToRead)
{*pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);
NumToRead--;
}
}
//在 AT24CXX 里面的指定地址开始写入指定个数的数据
//WriteAddr :开始写入的地址 对 24c02 为 0~255
//pBuffer :数据数组首地址
//NumToWrite:要写入数据的个数
void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
{while(NumToWrite--)
{AT24CXX_WriteOneByte(WriteAddr,*pBuffer);
WriteAddr++;
pBuffer++;
}
}

(4)main.c

//要写入到 24c02 的字符串数组
const u8 TEXT_Buffer[]={"MiniSTM32 IIC TEST"};
#define SIZE sizeof(TEXT_Buffer)
int main(void)
{u8 key;
u16 i=0;
u8 datatemp[SIZE];
delay_init(); //延时函数初始化
uart_init(9600); //串口初始化为 9600
LED_Init(); //初始化与 LED 连接的硬件接口
LCD_Init();
KEY_Init(); //按键初始化
AT24CXX_Init(); //IIC 初始化
POINT_COLOR=RED;//设置字体为红色
LCD_ShowString(60,50,200,16,16,"Mini STM32");
LCD_ShowString(60,70,200,16,16,"IIC TEST");
LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(60,110,200,16,16,"2014/3/9");
LCD_ShowString(60,130,200,16,16,"WK_UP:Write KEY0:Read"); //显示提示信息
while(AT24CXX_Check())//检测不到 24c02
{LCD_ShowString(60,150,200,16,16,"24C02 Check Failed!");
delay_ms(500);
LCD_ShowString(60,150,200,16,16,"Please Check! ");
delay_ms(500);
LED0=!LED0;//DS0 闪烁
}
LCD_ShowString(60,150,200,16,16,"24C02 Ready!");
POINT_COLOR=BLUE;//设置字体为蓝色
while(1)
{key=KEY_Scan(0);
if(key==WKUP_PRES)//WK_UP 按下,写入 24C02
{LCD_Fill(0,170,239,319,WHITE);//清除半屏
LCD_ShowString(60,170,200,16,16,"Start Write 24C02....");
AT24CXX_Write(0,(u8*)TEXT_Buffer,SIZE);
LCD_ShowString(60,170,200,16,16,"24C02 Write Finished!");//提示传送完成
}
if(key==KEY0_PRES)//KEY0 按下,读取字符串并显示
{LCD_ShowString(60,170,200,16,16,"Start Read 24C02.... ");
AT24CXX_Read(0,datatemp,SIZE);
LCD_ShowString(60,170,200,16,16,"The Data Readed Is: ");//提示传送完成
LCD_ShowString(60,190,200,16,16,datatemp);//显示读到的字符串
}
i++;
delay_ms(10);
if(i==20)
{LED0=!LED0;//提示系统正在运行
i=0;
}
}
}

  通过KEY_UP按键来控制24C02的写入,通过另外一个按键KEY0来控制24C02的读取。并在LCD模块上面显示相关信息。

参考资料:
1.STM32系统学习——I2C (读写EEPROM)
2.STM32 IIC详解

STM32学习笔记--I2C相关推荐

  1. STM32学习笔记(9)——(I2C续)读写EEPROM

    STM32学习笔记(9)--(I2C续)读写EEPROM 一.概述 1. 背景介绍 2. EEPROM简介 二.AT24C02--常用的EEPROM 1. 电路原理图 2. 写操作 (1)按字节写操作 ...

  2. 《STM32学习笔记》4——核心功能电路与编程(下)

    接上文,文中的图片,大多数来自视频的截图(来自洋桃电子). 欢迎大家批评指正! STM32学习笔记-专栏 文章目录 一.蜂鸣器驱动 1.蜂鸣器介绍 2.蜂鸣器电路 3.蜂鸣器程序 二. MIDI 音乐 ...

  3. STM32学习笔记(15)——SPI协议

    STM32学习笔记(15)--SPI协议 一.SPI协议简介 1. 物理层 2. 协议层 (1) 通讯的开始与停止 (2)时钟极性CPOL.时钟相位CPHA 二.STM32的SPI外设 1. 通讯引脚 ...

  4. OpenHarmony学习笔记——I2C驱动0.96OLED屏幕

    文章目录 前言 I2C简介 硬件连接 编程实现 创建代码框架 初始化并复用GPIO 初始化I2C0 初始化OLED 从机地址 OLED初始化配置 功能代码 总结 目录 前言 前面介绍了一些关于在Hi3 ...

  5. STM32学习笔记(三)丨中断系统丨EXTI外部中断(对射式红外传感器计次、旋转编码器计次)

    本篇文章包含的内容 一.中断系统 1.1 中断的定义 1.2 中断优先级 1.3 中断的嵌套 1.4 STM32中的中断系统 1.4.1 STM32的中断资源 1.4.2 嵌套中断向量控制器 NVIC ...

  6. STM32学习笔记 | CAN总线收发数据常见问题分析

    关注+星标公众号,不错过精彩内容 CAN,Controller Area Network(控制器局域网络),在汽车电子.工业控制领域的应用比较多,通常用于局域组网. CAN总线和UART.I2C.SP ...

  7. stm32学习笔记----双串口同时打开时的printf()问题

    stm32学习笔记----双串口同时打开时的printf()问题 最近因为要使用串口2外接PN532芯片实现通信,另一方面,要使用串口1来将一些提示信息输出到上位机,于是重定义了printf(),使其 ...

  8. STM32学习笔记 | 引起电源和系统异常复位的原因

    关注+星标公众号,不错过精彩内容 每一块处理器都有复位的功能,不同处理器复位的类型可能有差异,引起复位的原因也可能有多种. STM32的复位功能非常强大,可通过软件.硬件和一些事件触发系统复位,而且通 ...

  9. 【STM32学习笔记-点亮LED灯】

    STM32学习笔记-点亮LED灯 文章目录 STM32学习笔记-点亮LED灯 一.原理图分析 二.代码分析 1.mian函数 2.led.c函数 3.led.h函数 4.函数文件整理 5.LED_In ...

  10. STM32学习笔记(四)丨TIM定时器及其应用(定时中断、内外时钟源选择)

    本篇文章包含的内容 一.TIM 定时器 1.1 TIM 定时器简介 1.2 TIM 定时器类型及其工作原理简介 1.2.1 基本定时器工作原理及其结构 1.2.2 通用定时器工作原理及其结构 1.2. ...

最新文章

  1. 《HelloGitHub》第 20 期
  2. 安卓SurfaceFlinger框架初探
  3. 微软云平台媒体服务实践系列 1- 使用静态封装为iOS, Android 设备实现点播(VoD)方案...
  4. 信息系统项目管理师-知识管理知识点
  5. 《Adobe Flash CS6中文版经典教程》——导读
  6. 作业32-完成评论功能
  7. [blog摘要]Exploring and Decoding ETW Providers using Event Log Channels
  8. 投屏连接台式计算机,笔记本如何连接一体电脑进行投屏?
  9. idea测试单元错误_不要单元测试错误
  10. 四大必看亮点,2019黄石工业互联网创新发展大会精彩前瞻
  11. Java基础学习总结(19)——Java环境变量配置
  12. id nfc模拟_模拟门禁卡: NFC卡模拟 v3.1.5 清爽版
  13. 新零售全渠道营销,线上经营,线下成长
  14. eclipse mysql 打包_Eclipse+Mysql+打包发布的问题......
  15. 《给后端工程师的前端开发课程》笔记
  16. NET 里序列化可概念。
  17. Android 方向传感器的简单使用
  18. 光功率P和振幅E的平方成正比关系
  19. 代码整洁之道--阅读
  20. java的while、do while循环和案例

热门文章

  1. 正点原子 任天堂_任天堂20年前,任天堂用纸Mario改变了RPG风格
  2. read-shrinkwrap This version of npm is compatible with lockfileVersion@1, but package-lock.json was
  3. 网络文件共享服务(一)
  4. Android 沉浸式体验
  5. Qt 6.2的下载和安装
  6. CenterNet: Keypoint Triplets for Object Detection论文详解
  7. sprintf,snprintf的用法(可以作为linux中itoa函数的补充)
  8. 键盘按键名键码对照表
  9. Tebleau-四象限图
  10. Kaggle 时间序列教程