![shequ.stmicroelectronics.cn](./template/st_v1/static/img/logo2.png)
最近一直在研究STM32F0的IIC,因为项目要用到IIC,master/slave mode都需要,实现数据通信和IAP功能。 网上有关于这部分资料特别少,所以共享一下,只晒出初始化和中断部分的代码的框架。代码在附件 .c里面, 如果有不对的地方,欢迎指正,大家互相学习一下!$ z( P y! Y6 F5 i* E+ w0 S# d STM32F0相对于STM32F1和STM8S 有很大变化,支持时钟延长即I2C_CR1_NOSTRETCH,并且支持SMBUS。. X* G$ \; r. D8 ?, f$ i 1,初始化部分:配置时钟和引脚,不使用时钟延长的功能 2,I2C1_IRQHandler 主要处理中断事件 在I2C_ISR_ADDR事件时,如果设置了多个地址,要判断是那个地址,并且要清除中断标志位。 根据I2C1->ISR&I2C_ISR_DIR 的结果判断是发送数据还是接收数据。) \3 _7 ?6 k* H* { (1)发送数据,流程如下 ![]() 这里要区别一下I2C_ISR_TXIS,I2C_ISR_TXE,描述如下7 D) N- D/ I( i: h# }# L ![]() (2) 接收数据,流程如下4 J8 f( c# \5 ^! [5 ~ ![]() |
IIC SLAVE mode.zip
下载1.84 KB, 下载次数: 899
分享STM32F051中文参考手册(重制书签版)
STM32固件库分享,超全系列整理
三创电子(Tcreate)-STM32F030调试之I2C篇
基于STM32F0的FOC5.2库PMSM驱动:程序+原理图+BOM等全部开源分享
【MCU实战经验】+STM32F030的步进电机加减速
【管管推荐】STM32经验分享篇
三创电子(Tcreate)-STM32F030核心板代码
STM32F0 ADC(DMA中断)多通道,注释超详细
FreeRTOS在STM32F030上的移植
基于STM32移植而引发的疑问经验分享
我在网上找到你们的代码。我复制了一下。有些问题想了解一下, S/ c' ?6 V# O1 `* n6 P# _
void I2C_GPIO_Configuration(void)7 u& V6 h) w @% ?- l0 H
{ |) d' z. Y7 ?. ?$ `; F% h
GPIO_InitTypeDef GPIO_InitStruct;
. B: F# _. S/ P/ f- t6 I* Y
/* Enable GPIOA clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/*!< sEE_I2C Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE);, G% H. J# t& b8 ?! W$ s( o
/*!< GPIO configuration */ 1 C) z1 m& x: h0 K. E1 @) {% L
/*!< Configure sEE_I2C pins: SCL */5 E5 N) x2 P3 {" M' b
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;//GPIO_Mode_IN
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_3; n# Q: ]3 x! l. H) u/ U
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;//open-drain! u4 G% H' h; ], G; j
GPIO_Init(GPIOA , &GPIO_InitStruct);
/*!< Configure sEE_I2C pins: SDA */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;5 ?1 G# Y4 X) b7 n2 E1 t# q1 [
GPIO_Init(GPIOA, &GPIO_InitStruct);3 S) {& E+ F" A5 V
/* Connect PXx to I2C_SCL*/
GPIO_PinAFConfig( GPIOA , GPIO_PinSource9, GPIO_AF_4); ; V. B% G9 A$ Q! a! N
/* Connect PXx to I2C_SDA*/) h7 W! o5 [# v, |
GPIO_PinAFConfig( GPIOA ,GPIO_PinSource10, GPIO_AF_4);
}
! O% x) @3 ^0 x5 z7 p
//IIC从模式配置,在配置时,需要设置地址,在这里设置为0XA0,而从设备的时钟属于被动模式,有IIC的主端确定。0 x1 V0 c) ^9 L) c/ a! R
R7 F( q: l- n9 g
void I2C_Configuration(void)
{
I2C_InitTypeDef I2C_InitStruct;
NVIC_InitTypeDef NVIC_InitStructure;" m" d) I- d" }4 d2 f
/* I2C configuration */
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_InitStruct.I2C_DigitalFilter = 0x00;4 i1 Z! ?6 C" O, C- W* ^
I2C_InitStruct.I2C_OwnAddress1 = ADDR;
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; 4 `* Y8 w& d# j% y5 g X, S
I2C_InitStruct.I2C_Timing = 0xb0420f13; //100Kbits
/* I2C Peripheral Enable */
I2C_Cmd(I2C1, ENABLE);
/* Apply I2C configuration after enabling it */
I2C_Init(I2C1, &I2C_InitStruct);
6 H4 h1 s2 T# b# @
I2C1->CR1 |= (I2C_CR1_ADDRIE | I2C_CR1_STOPIE | I2C_CR1_TXIE | I2C_CR1_RXIE);
//---------------------------- Peripheral and DMA interrupts Initialization ------------------' x( V! m9 |" ^1 u* r" m
// Initialize I2C1 interrupts
/* Enable the IRQ channel */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
' t5 L- K; V2 b; T* A
/* Configure NVIC for I2C1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = I2C1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 2;$ Y2 j: A7 |# O0 q7 X# @
NVIC_Init(&NVIC_InitStructure); 7 \- V9 r* b+ K6 J7 i; n" I
% C. ~! c0 ~; K! z) L1 q
}/ c" H X2 ~9 e# M- ?$ s2 g
; W; k- H, x# b9 Q: s1 G" ^
//下面是IIC中断函数的实现8 n! X/ V! i, C0 Z& p y
void I2c_Init(void)3 ?4 ?) T8 w( {' w, ]2 k% I7 v
{8 v3 B. w/ V* n9 }
I2C_GPIO_Configuration();6 a! a- _7 C* i8 Y
I2C_Configuration();
}
. ?1 h! H& E9 Q, ^" f; E4 e/ S
void I2C1_IRQHandler(void)7 Z' E* j+ |% N) W0 j9 ]
{
u32 AddCode;
// I2C_ClearITPendingBit(I2C1, I2C_ISR_ADDR | I2C_ISR_STOPF |I2C_ISR_ADDCODE );
__IO uint32_t I2CFlagStatus = 0x00000000;
I2CFlagStatus = (uint32_t)(I2C1->ISR & (uint16_t)0x0000100FE);
5 {% Y9 ] @; ~: z7 k) B2 N0 g. K4 A
// printf("recv data\r\n");* E' _6 {. ~: q
if ((I2CFlagStatus & I2C_ISR_ADDR) != 0)" X) w1 h1 Q( i2 _9 B
{) B7 ?& N/ H2 W1 I$ s1 Z
AddCode = (I2C1->ISR & 0xfe0000); //读取ADDCODE 32:17位9 i9 S9 M9 b l! ?4 `. ^6 D7 j
printf("匹配地址2 0x%x: \r\n",AddCode >> 17 );
if(I2C1->ISR&I2C_ISR_DIR) //tx mode* @. e8 h; ]/ N: M
{
printf("发送模式 \r\n");
Tx_count = 0;. [" D) h% W' b; v) c
I2C1->ISR |= I2C_ISR_TXE;) G: @& y% J$ H
I2C1->ICR |= I2C_ICR_ADDRCF; ; x5 \, {# k( `! o/ A
if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0), L3 M6 J+ l/ x! x. G& C( o
{, B q# i2 i( v2 K* J6 f8 z: q" g
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);+ L5 W* h/ o4 e3 [% J# u% X
if(Rx_count>=Rx_MAX) C! z) Y" E' N# A
{
Rx_count=0;$ z0 n2 V; G$ u
//rx ok
}
printf("Rx_buffer : %s\r\n",Rx_buffer);
}
} 0 c8 b% h. D8 F3 u
if((I2C1->ISR&I2C_ISR_DIR)==0) //rx mode
{
printf("接收模式 \r\n");0 I* G2 z9 D+ j6 X& i! L R
Rx_count= 0;! h- R( E# ^2 @) S
I2C1->ICR |= I2C_ICR_ADDRCF; & y3 G" V4 _% }! p& ?, G! g0 U
}
}
else if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)& g* W3 S# C3 A
{- N, u7 W! |4 Q1 E' O& P
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);3 {# k) U$ x p, q. w! A% G5 R
if(Rx_count>=Rx_MAX)4 t+ Z- Y9 O0 M; l+ a2 a
{
Rx_count=0;
//rx ok+ e0 |) {! b- w3 W
}
printf("Rx_buffer : %s\r\n",Rx_buffer);! L2 [ W1 Z* {$ A
}
else if ((I2CFlagStatus & I2C_ISR_TXIS) != 0)
{
I2C_SendData(I2C1,Tx_buffer[Tx_count++]);
if(Tx_count >= Tx_MAX): R0 B2 b8 n. s0 M9 C# U0 v
{) t* \! Y1 K! z- ~. W/ x5 s# ?( g
Tx_count = 0;
//tx ok
}
}
else if ((I2CFlagStatus & I2C_ISR_STOPF) != 0)- @6 |5 v8 G* q/ |, J6 }' h- V
{
printf("停止检查标志位 \r\n");
I2C1->ICR |= I2C_ICR_STOPCF;
Rx_count = 0;/ S$ ]" J! F+ L
Tx_count = 0;) d- J$ X# V2 [7 N) g
}' y3 U3 d# S( A# `7 O j( E
}6 a! ]* D6 L& `7 q1 h
这个是可以匹配到ADDCODE ,但是没有接收到数据的,我没仔细看这个时序寄存器的配置。不知道是不是由于时序不匹配造成没有接收到数据,还是因为ack没有给出造成读不到数据的。
void I2C_GPIO_Configuration(void)/ {8 C8 [9 f1 b( `6 g
{
GPIO_InitTypeDef GPIO_InitStruct;
/* Enable GPIOA clock */- x5 ], u- Z5 Y) q
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); 1 L* c0 N% n5 }9 p) J
/*!< sEE_I2C Periph clock enable */' l0 i+ z; Y7 ^7 n Q# x2 W
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE);
/*!< GPIO configuration */
/*!< Configure sEE_I2C pins: SCL */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;//GPIO_Mode_IN9 G: a$ h% n7 P, Y' d
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_3;
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;//open-drain, O) g [+ N+ Q! O; g. O$ G
GPIO_Init(GPIOA , &GPIO_InitStruct);
/*!< Configure sEE_I2C pins: SDA */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;0 S4 B( Q* }6 u: t" F# O. N% B
GPIO_Init(GPIOA, &GPIO_InitStruct);
S( M8 ~8 {/ s" x. X' X
/* Connect PXx to I2C_SCL*/
GPIO_PinAFConfig( GPIOA , GPIO_PinSource9, GPIO_AF_4);
/* Connect PXx to I2C_SDA*/
GPIO_PinAFConfig( GPIOA ,GPIO_PinSource10, GPIO_AF_4);4 p2 X5 q; f. w
}8 G4 {2 X6 D- [+ a/ Z. S
4 x; `0 V3 T9 o' o% X# j1 p' `7 S
//IIC从模式配置,在配置时,需要设置地址,在这里设置为0XA0,而从设备的时钟属于被动模式,有IIC的主端确定。# I8 S7 R$ M; H. K2 j4 a% v- `
void I2C_Configuration(void)2 A4 y9 G0 _. g$ R$ l
{7 j. S! K( b6 b' b" h0 g, e! ^4 @! E
I2C_InitTypeDef I2C_InitStruct; : v& M: z" F' A) C4 b% \, u; B
NVIC_InitTypeDef NVIC_InitStructure;
& `- Q& k, \) R# G# A$ H! I+ y: h; X
/* I2C configuration */# |6 q3 h. N7 y2 L2 e
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;0 u: R! L0 O6 R n( Y; k
I2C_InitStruct.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_InitStruct.I2C_DigitalFilter = 0x00;3 e! F& P' E! `) ?" u
I2C_InitStruct.I2C_OwnAddress1 = ADDR;: c! ^& n6 _. X3 \
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; . o0 F# ? O% ]" ~& J$ @
I2C_InitStruct.I2C_Timing = 0xb0420f13; //100Kbits
/* I2C Peripheral Enable *// u8 r9 }0 v; _6 {8 f+ d
I2C_Cmd(I2C1, ENABLE);
/* Apply I2C configuration after enabling it */
I2C_Init(I2C1, &I2C_InitStruct);2 U6 h, {8 F$ y0 T8 @
. i) M" y; M; v- P1 m- M
I2C1->CR1 |= (I2C_CR1_ADDRIE | I2C_CR1_STOPIE | I2C_CR1_TXIE | I2C_CR1_RXIE);
//---------------------------- Peripheral and DMA interrupts Initialization ------------------5 N6 B( J$ }* L$ Q$ ^' v
// Initialize I2C1 interrupts
/* Enable the IRQ channel */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
, a& C; q* k; @( b
/* Configure NVIC for I2C1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = I2C1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 2;
NVIC_Init(&NVIC_InitStructure); - x" t4 \+ i: X+ s6 M6 S, a- Z
}% E& W1 `9 ?- E7 z
//下面是IIC中断函数的实现8 V9 f0 V% M' [ _6 {; z
1 r. k7 j: V, I
void I2c_Init(void)
{
I2C_GPIO_Configuration();+ h; p) s" B7 }: Q! U" b7 ~/ E
I2C_Configuration();
}
void I2C1_IRQHandler(void)
{5 Y2 a0 }# |* Z4 S& Z3 X' B
u32 AddCode;
// I2C_ClearITPendingBit(I2C1, I2C_ISR_ADDR | I2C_ISR_STOPF |I2C_ISR_ADDCODE );
__IO uint32_t I2CFlagStatus = 0x00000000;
I2CFlagStatus = (uint32_t)(I2C1->ISR & (uint16_t)0x0000100FE);
// printf("recv data\r\n");
if ((I2CFlagStatus & I2C_ISR_ADDR) != 0)
{
AddCode = (I2C1->ISR & 0xfe0000); //读取ADDCODE 32:17位
printf("匹配地址2 0x%x: \r\n",AddCode >> 17 );' i7 L4 m! q/ i# u8 s
2 q/ i, a. I8 l; \/ e8 h
if(I2C1->ISR&I2C_ISR_DIR) //tx mode7 N7 Z1 z6 A7 d- r
{
printf("发送模式 \r\n");
Tx_count = 0;
I2C1->ISR |= I2C_ISR_TXE;0 M1 i+ K/ q- `7 Z6 v0 A8 ]
I2C1->ICR |= I2C_ICR_ADDRCF; 0 x7 D. s& B5 w$ a O) H6 x
5 P1 P) N- a" W& d- Q
if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)
{ H; D k( ]4 d3 a6 z: i# w# A$ Q5 @
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);
if(Rx_count>=Rx_MAX)
{
Rx_count=0;
//rx ok! h. \* W4 `% d
}! m) \% ^% ~+ a1 g2 Z& X
printf("Rx_buffer : %s\r\n",Rx_buffer);
}8 k9 _9 d+ c4 e! n3 B3 v7 ^5 O
} 1 y# K- p# t8 E4 z. `8 a/ v% E
if((I2C1->ISR&I2C_ISR_DIR)==0) //rx mode) a* v1 v, j1 A/ n) B
{8 f9 j8 o9 G" ^6 p4 I% X L
printf("接收模式 \r\n");
Rx_count= 0;+ O0 b. T3 ]0 e) C2 n& E
I2C1->ICR |= I2C_ICR_ADDRCF;
}
}
else if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)
{
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);* r! j$ A- V5 L8 t7 d" [
if(Rx_count>=Rx_MAX). }: I6 x0 S5 H' x' L& K% a
{
Rx_count=0;5 V- d1 i% H# G# W4 d
//rx ok
}7 w5 Q% R( P2 K3 L/ T
printf("Rx_buffer : %s\r\n",Rx_buffer);; H% m3 Q* I/ J* b6 A6 D+ }
}
else if ((I2CFlagStatus & I2C_ISR_TXIS) != 0)
{
I2C_SendData(I2C1,Tx_buffer[Tx_count++]);3 h. k3 ^" r5 A3 m ~ y
if(Tx_count >= Tx_MAX)
{
Tx_count = 0;
//tx ok' b4 s" d9 X6 X* b% g/ T! z! u
}; s# d, x O0 I- W) o
}+ J* i$ q8 }- X: A6 r; Y
else if ((I2CFlagStatus & I2C_ISR_STOPF) != 0)( a; [7 U! l: l. [7 g
{
printf("停止检查标志位 \r\n");
I2C1->ICR |= I2C_ICR_STOPCF;
Rx_count = 0;- E6 m: B; m/ r2 i. P0 G+ D
Tx_count = 0;+ W3 a: s6 |7 e7 F$ |
}/ k' Z! [+ b7 P- }
}
& W- D( e7 Q9 t' p5 y
! y; _) E! e9 ^2 ^1 s