最近一直在研究STM32F0的IIC,因为项目要用到IIC,master/slave mode都需要,实现数据通信和IAP功能。 网上有关于这部分资料特别少,所以共享一下,只晒出初始化和中断部分的代码的框架。代码在附件 .c里面,0 r2 k+ ]+ {4 o* }- V 如果有不对的地方,欢迎指正,大家互相学习一下!! ]- |& P5 ^# p0 |8 E' R + P+ d% x* o6 g% s' k STM32F0相对于STM32F1和STM8S 有很大变化,支持时钟延长即I2C_CR1_NOSTRETCH,并且支持SMBUS。8 e6 L) }' }% ~' ?3 y% i 1,初始化部分:配置时钟和引脚,不使用时钟延长的功能 2,I2C1_IRQHandler 主要处理中断事件 在I2C_ISR_ADDR事件时,如果设置了多个地址,要判断是那个地址,并且要清除中断标志位。8 u, R8 A2 s" d8 T% ? 根据I2C1->ISR&I2C_ISR_DIR 的结果判断是发送数据还是接收数据。 (1)发送数据,流程如下& Q" I9 q" O4 p, m2 g6 h 这里要区别一下I2C_ISR_TXIS,I2C_ISR_TXE,描述如下( b6 q8 H1 a; S; q4 T & k, ]1 ]8 E+ d0 P. L (2) 接收数据,流程如下5 l" ~: |: R* {+ l5 }) j) N |
IIC SLAVE mode.zip
下载1.84 KB, 下载次数: 899
STM32F0F1F4内部flash擦写时间和寿命
游名:STM32F030+FT1610FF1高精度超声波测距模块测距教程及参...
分享STM32F051中文参考手册(重制书签版)
STM32固件库分享,超全系列整理
三创电子(Tcreate)-STM32F030调试之I2C篇
基于STM32F0的FOC5.2库PMSM驱动:程序+原理图+BOM等全部开源分享
【MCU实战经验】+STM32F030的步进电机加减速
【管管推荐】STM32经验分享篇
三创电子(Tcreate)-STM32F030核心板代码
STM32F0 ADC(DMA中断)多通道,注释超详细
我在网上找到你们的代码。我复制了一下。有些问题想了解一下% O% E7 h3 P; P
void I2C_GPIO_Configuration(void)) Z2 l3 f9 O# Z( |) \; Y! Z* S
{
GPIO_InitTypeDef GPIO_InitStruct;
/* Enable GPIOA clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/*!< sEE_I2C Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE);9 s1 G, e. y R1 {
/*!< GPIO configuration */ ' U; e# O% S& \8 Z8 b
/*!< Configure sEE_I2C pins: SCL */. N+ e, {' K! N/ P
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;//GPIO_Mode_IN8 [5 q# w/ }) X% d) U( T
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_3;/ H. y( ~2 D* n. v
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;//open-drain
GPIO_Init(GPIOA , &GPIO_InitStruct);4 k9 Q: |$ T s) @* O
5 |6 X* H# s3 x! w( M* a) o! o
/*!< Configure sEE_I2C pins: SDA */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;3 ]; Z7 O( f* S! Q
GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Connect PXx to I2C_SCL*/& j/ R0 I- H% E; q, l
GPIO_PinAFConfig( GPIOA , GPIO_PinSource9, GPIO_AF_4);
/* Connect PXx to I2C_SDA*/
GPIO_PinAFConfig( GPIOA ,GPIO_PinSource10, GPIO_AF_4);
}
//IIC从模式配置,在配置时,需要设置地址,在这里设置为0XA0,而从设备的时钟属于被动模式,有IIC的主端确定。4 a4 z* P. a8 W& Z4 m% |
void I2C_Configuration(void)
{
I2C_InitTypeDef I2C_InitStruct;
NVIC_InitTypeDef NVIC_InitStructure;0 v- b9 U( t: u/ _& w. x# A2 |
) w( E; U0 T& \) g7 Y
/* I2C configuration */6 |9 u t1 Y G
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;; G) S5 P/ j$ @4 S+ t, Q
I2C_InitStruct.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_InitStruct.I2C_DigitalFilter = 0x00;
I2C_InitStruct.I2C_OwnAddress1 = ADDR;
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;1 I' c. U. i- U, M4 v
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStruct.I2C_Timing = 0xb0420f13; //100Kbits, a' {' ]6 b5 O
/* I2C Peripheral Enable */
I2C_Cmd(I2C1, ENABLE);
/* Apply I2C configuration after enabling it */
I2C_Init(I2C1, &I2C_InitStruct);! g% ?( i4 ]% _; h* n% k
I2C1->CR1 |= (I2C_CR1_ADDRIE | I2C_CR1_STOPIE | I2C_CR1_TXIE | I2C_CR1_RXIE);8 W. J9 E7 i4 X" j
//---------------------------- Peripheral and DMA interrupts Initialization ------------------ I' o" {8 t5 J+ e: w
// Initialize I2C1 interrupts; |1 N' |4 D, q2 D( z
/* Enable the IRQ channel */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- ?9 [# q1 l, h. O/ h
/* Configure NVIC for I2C1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = I2C1_IRQn;5 f2 T% n: `" ?1 Y
NVIC_InitStructure.NVIC_IRQChannelPriority = 2;7 x1 `- Y+ T+ q, g# u: A; \1 h f
NVIC_Init(&NVIC_InitStructure); ! `* ]9 v3 {2 h8 ]. c
/ A5 `( ?0 d: X* q
}" J6 a- h- d% b/ I! q
* _; V; ^* b0 w9 D8 w$ V, T
//下面是IIC中断函数的实现( @* }0 D. Q$ U, O- ?+ K
void I2c_Init(void)
{1 ^, @( @' j5 u( ^* j
I2C_GPIO_Configuration();
I2C_Configuration();& h, d9 M: Z) u
}/ s, M$ C0 A$ D
void I2C1_IRQHandler(void)) O) e4 B4 W2 w: Q
{* j& s4 V) B; f# V% N# Z8 g
u32 AddCode;
// I2C_ClearITPendingBit(I2C1, I2C_ISR_ADDR | I2C_ISR_STOPF |I2C_ISR_ADDCODE );
__IO uint32_t I2CFlagStatus = 0x00000000;0 p% g( }9 e) ~
I2CFlagStatus = (uint32_t)(I2C1->ISR & (uint16_t)0x0000100FE);, d3 ]2 e- E$ `
: l; z/ m8 ~- B4 y# H
// printf("recv data\r\n");4 l7 s8 P0 p, u- T
if ((I2CFlagStatus & I2C_ISR_ADDR) != 0)# v& D! M4 Q& v+ T" s% m- I
{* r' E' o" C0 X7 a6 J) q* f
AddCode = (I2C1->ISR & 0xfe0000); //读取ADDCODE 32:17位
printf("匹配地址2 0x%x: \r\n",AddCode >> 17 );$ p M9 c* v5 P
if(I2C1->ISR&I2C_ISR_DIR) //tx mode
{
printf("发送模式 \r\n"); ?1 d% Y S* n* Z
Tx_count = 0;. o w+ ?" e; ?# P8 B6 G# T# r- V
I2C1->ISR |= I2C_ISR_TXE;4 c/ R; w6 L: J; e& m
I2C1->ICR |= I2C_ICR_ADDRCF; 9 h5 D- D# q- X/ @+ q
if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)
{' T1 W5 Z* @- d* |! e
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);6 P% U- f/ k2 I" E- E- t
if(Rx_count>=Rx_MAX)- m/ e. x4 P0 @; x* C
{5 p& L# B4 l1 T8 F
Rx_count=0;4 D L) K3 Q- Y: I7 p6 G$ g- U
//rx ok
}; A. h7 u, I) h2 G
printf("Rx_buffer : %s\r\n",Rx_buffer);) R! X' n) Q( e1 H$ j6 ~8 r8 x; N
}% E, w2 F% v: v' i
}
if((I2C1->ISR&I2C_ISR_DIR)==0) //rx mode4 s L' C3 R0 P. l
{; g+ }* J, Q: _0 v7 Y9 x5 T
printf("接收模式 \r\n");
Rx_count= 0;0 r' q N3 `( E1 W
I2C1->ICR |= I2C_ICR_ADDRCF;
}
}6 ]! Z3 c3 | S) H s
else if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)
{$ b% {& C. E' H
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);
if(Rx_count>=Rx_MAX)
{
Rx_count=0;" ~- S$ H$ w0 x9 G) M
//rx ok
}& X$ A* V+ d+ m
printf("Rx_buffer : %s\r\n",Rx_buffer);4 y8 v `( M: I
}
else if ((I2CFlagStatus & I2C_ISR_TXIS) != 0); I' v5 h# E) b3 f. ^, ^: i
{
I2C_SendData(I2C1,Tx_buffer[Tx_count++]);
if(Tx_count >= Tx_MAX)
{
Tx_count = 0;" e" Y4 R8 b: x9 E4 N1 z
//tx ok8 P6 R6 [6 [( d: {
}5 C. o1 e. |/ c: @* g6 C( j e: R
}9 I4 x+ L7 p1 z9 _) T
else if ((I2CFlagStatus & I2C_ISR_STOPF) != 0)4 Y0 W) V3 `* X8 o
{
printf("停止检查标志位 \r\n");
I2C1->ICR |= I2C_ICR_STOPCF;/ J" L3 X7 K2 c
Rx_count = 0;
Tx_count = 0;1 ?9 M% K# J9 R" @5 X; v
}# D, F! c- i; h% f* e
}
. j: K9 m& p9 S+ E5 i m
这个是可以匹配到ADDCODE ,但是没有接收到数据的,我没仔细看这个时序寄存器的配置。不知道是不是由于时序不匹配造成没有接收到数据,还是因为ack没有给出造成读不到数据的。
void I2C_GPIO_Configuration(void)0 p2 i6 }! a; ~1 y- M0 I* E; _
{
GPIO_InitTypeDef GPIO_InitStruct; : _" s0 ~8 a) M9 m: B
( V( T U( O& W9 ~+ d
/* Enable GPIOA clock */0 Q" r0 b4 c/ S0 I2 l( I, `
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); $ U A8 p- y( B8 T$ w1 y @
/*!< sEE_I2C Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE); ~- l1 d! o3 N' [2 ~& o% n% i
/*!< GPIO configuration */ : Q! A% `9 o8 I4 r7 Q6 n
/*!< Configure sEE_I2C pins: SCL */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;//GPIO_Mode_IN( A2 b3 i2 H" v8 {0 \! y8 I( Z `- L
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_3;9 _9 K# X' y$ n1 S
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;//open-drain8 s; g* o/ k. ^9 A& V4 d
GPIO_Init(GPIOA , &GPIO_InitStruct);
' l% B( i( ]9 W& A
/*!< Configure sEE_I2C pins: SDA */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStruct);- g; Y1 c" i' f8 {9 [5 p
/* Connect PXx to I2C_SCL*/5 E. c5 h) ?2 G% p, R) `+ @
GPIO_PinAFConfig( GPIOA , GPIO_PinSource9, GPIO_AF_4);
/* Connect PXx to I2C_SDA*/" `7 L$ Q: Q8 E6 ]" ?" N1 Q
GPIO_PinAFConfig( GPIOA ,GPIO_PinSource10, GPIO_AF_4);
}: O% x' l( }7 o( d& ]0 U
" v4 T; Y# {& H9 W# g/ u- [0 a
//IIC从模式配置,在配置时,需要设置地址,在这里设置为0XA0,而从设备的时钟属于被动模式,有IIC的主端确定。
6 {3 s; q* [5 q, u) J" y* K: N
void I2C_Configuration(void)4 N2 V6 ?6 v' r H
{
I2C_InitTypeDef I2C_InitStruct;
NVIC_InitTypeDef NVIC_InitStructure;
/* I2C configuration */
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;/ X9 h, T6 x& F1 H+ i
I2C_InitStruct.I2C_AnalogFilter = I2C_AnalogFilter_Enable;( ~8 r: D' D/ J0 x% v7 Q9 g
I2C_InitStruct.I2C_DigitalFilter = 0x00;" S( p/ m% ?! b+ w: z$ S& j8 ~
I2C_InitStruct.I2C_OwnAddress1 = ADDR;
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; ( y! S2 l9 `$ E2 q5 b! G
I2C_InitStruct.I2C_Timing = 0xb0420f13; //100Kbits
/* I2C Peripheral Enable */% X1 N, R* \- {7 b0 a. M# ~
I2C_Cmd(I2C1, ENABLE);$ o& r* f6 Z2 z+ V- o9 n
/* Apply I2C configuration after enabling it */
I2C_Init(I2C1, &I2C_InitStruct);4 m+ v. {" R6 K) W S3 V
I2C1->CR1 |= (I2C_CR1_ADDRIE | I2C_CR1_STOPIE | I2C_CR1_TXIE | I2C_CR1_RXIE);
//---------------------------- Peripheral and DMA interrupts Initialization ------------------
// Initialize I2C1 interrupts
/* Enable the IRQ channel */+ m' V# N/ Y; ]. K8 Y- N, Y. z2 B
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/* Configure NVIC for I2C1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = I2C1_IRQn;! ?) ~0 z1 q3 c! I* Z: w- S
NVIC_InitStructure.NVIC_IRQChannelPriority = 2;, B6 \9 o# R& g
NVIC_Init(&NVIC_InitStructure); ) i7 V+ A& A! G8 C A7 s9 n+ l
( j% Z3 q8 C3 m4 u% n$ Y$ ~* b( i' j
}
" ?0 n$ E- g: K1 i7 }/ O
//下面是IIC中断函数的实现, a( a* L: q' q+ S
void I2c_Init(void)
{
I2C_GPIO_Configuration();2 i# V" J7 {9 T# U
I2C_Configuration();
}
' M( N" T: f, B& v7 w
void I2C1_IRQHandler(void)
{
u32 AddCode;% Q& z6 ?8 m, ^: e6 a; o( Y* Q3 e
// I2C_ClearITPendingBit(I2C1, I2C_ISR_ADDR | I2C_ISR_STOPF |I2C_ISR_ADDCODE );/ H8 v: A# D9 s1 h" C
__IO uint32_t I2CFlagStatus = 0x00000000;
I2CFlagStatus = (uint32_t)(I2C1->ISR & (uint16_t)0x0000100FE);% ~4 z5 b, i% H' v" r- X( p+ F
// printf("recv data\r\n");* Y: J* b8 X) c' m% |2 O
if ((I2CFlagStatus & I2C_ISR_ADDR) != 0)
{
AddCode = (I2C1->ISR & 0xfe0000); //读取ADDCODE 32:17位
printf("匹配地址2 0x%x: \r\n",AddCode >> 17 );% c$ w; R& z# f
) ]; Q" P9 J- _7 g
if(I2C1->ISR&I2C_ISR_DIR) //tx mode
{4 t% J0 f( G* N7 I1 N5 l9 p* H1 `
printf("发送模式 \r\n");
Tx_count = 0;. B+ g% |4 Q" m) }0 d( U
I2C1->ISR |= I2C_ISR_TXE;4 p# [, p6 ?8 B# x B4 ?7 }6 e
I2C1->ICR |= I2C_ICR_ADDRCF; # ]$ s, m+ |& B* z* _
( Z7 r) z9 D2 F# \- R0 l+ A
if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)! Y L% y, V7 t! {' O1 m
{: G' K8 t' ^) [, H7 N+ p
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);
if(Rx_count>=Rx_MAX)
{1 W L1 g& ~0 p7 T2 b# H8 }6 {! b* m
Rx_count=0;
//rx ok3 r3 b* |% L3 ^
}
printf("Rx_buffer : %s\r\n",Rx_buffer);
}( E* F* u. \2 E4 e/ J6 u9 ^
} % [5 t2 B2 z% Q2 S( Q* V6 c/ l
if((I2C1->ISR&I2C_ISR_DIR)==0) //rx mode9 I o X8 |6 ^# g* B, ]
{" K9 ~8 b2 G6 X+ Y
printf("接收模式 \r\n");
Rx_count= 0;
I2C1->ICR |= I2C_ICR_ADDRCF; 7 h- B" K! Z) j1 {+ W+ w
}7 ~1 E6 D( @* d) @
}' M! l& l* f5 m% V7 {8 ~
else if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)
{
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);
if(Rx_count>=Rx_MAX)
{
Rx_count=0;) ?3 @7 q& ^" i2 `% M8 c
//rx ok
}
printf("Rx_buffer : %s\r\n",Rx_buffer);! [9 R1 ?& v3 L2 u
}# z& S+ ^7 K: G: y, S( q: e1 ~
else if ((I2CFlagStatus & I2C_ISR_TXIS) != 0)
{
I2C_SendData(I2C1,Tx_buffer[Tx_count++]);0 k8 x( M: A9 h- C
if(Tx_count >= Tx_MAX)$ b8 U4 `% k0 C4 L1 m
{
Tx_count = 0;$ w) f5 P5 q: `! Z. i" _+ s5 w
//tx ok
}
}
else if ((I2CFlagStatus & I2C_ISR_STOPF) != 0)
{1 H: [' j; y: K( E# B
printf("停止检查标志位 \r\n");# Z( K2 u, f# n0 A
I2C1->ICR |= I2C_ICR_STOPCF;0 ~+ e6 M& K7 D/ x& `
Rx_count = 0;
Tx_count = 0;, n/ s1 B( \' R/ V, Y- l2 L
}
}
$ W; \6 [$ F9 E% Q- [4 P9 w
& h% c2 e; @2 y. y; D' _
2 U; l" l5 I2 Z0 K7 Q
0 ]; K$ ^5 ]/ a2 q# \; n