最近一直在研究STM32F0的IIC,因为项目要用到IIC,master/slave mode都需要,实现数据通信和IAP功能。( W$ {% [2 P* L! ?1 h6 B, c: V 网上有关于这部分资料特别少,所以共享一下,只晒出初始化和中断部分的代码的框架。代码在附件 .c里面, 如果有不对的地方,欢迎指正,大家互相学习一下! STM32F0相对于STM32F1和STM8S 有很大变化,支持时钟延长即I2C_CR1_NOSTRETCH,并且支持SMBUS。6 Q: K, w$ {9 ? w) u. p 1,初始化部分:配置时钟和引脚,不使用时钟延长的功能' _" h- A! z' R6 ~, T 2,I2C1_IRQHandler 主要处理中断事件 在I2C_ISR_ADDR事件时,如果设置了多个地址,要判断是那个地址,并且要清除中断标志位。 根据I2C1->ISR&I2C_ISR_DIR 的结果判断是发送数据还是接收数据。* h8 L1 k: A/ B- U3 z2 ]6 ^/ a O1 y (1)发送数据,流程如下 这里要区别一下I2C_ISR_TXIS,I2C_ISR_TXE,描述如下 4 \4 k9 g# j! ~$ F3 i: }! \ (2) 接收数据,流程如下7 H# _ _* Q G6 }! c/ D |
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移植而引发的疑问经验分享
. [4 `1 o6 A# m( m
我在网上找到你们的代码。我复制了一下。有些问题想了解一下
void I2C_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
! p3 ]5 |( X0 V/ R& k
/* Enable GPIOA clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/*!< sEE_I2C Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE);) p+ g5 B( _, ^4 a9 ?; `+ n
/*!< GPIO configuration */ 0 ~, l! e l) Y
/*!< Configure sEE_I2C pins: SCL */
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;
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;//open-drain
GPIO_Init(GPIOA , &GPIO_InitStruct);
/*!< Configure sEE_I2C pins: SDA */6 \, a% `- i, K, _
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;7 a7 W5 i5 |5 ?& v: o9 q% ?
GPIO_Init(GPIOA, &GPIO_InitStruct);, X. P) T) e' k
4 _- w& F& a5 F$ B& z0 k& h& E
/* Connect PXx to I2C_SCL*/2 J/ W, X/ S$ m% r; P
GPIO_PinAFConfig( GPIOA , GPIO_PinSource9, GPIO_AF_4);
/* Connect PXx to I2C_SDA*/5 N/ v+ |3 @ E$ l9 D/ K
GPIO_PinAFConfig( GPIOA ,GPIO_PinSource10, GPIO_AF_4);+ v! E ~: L/ Q8 E5 F
}- ~+ _1 ]8 s! U; j; p7 w4 m
0 f" y/ X$ B# R+ a$ r
//IIC从模式配置,在配置时,需要设置地址,在这里设置为0XA0,而从设备的时钟属于被动模式,有IIC的主端确定。- U) x( q7 N7 D0 F
! [) ^: t H4 i3 w
void I2C_Configuration(void)" A$ c n( G' {) J
{
I2C_InitTypeDef I2C_InitStruct; . ?' ^/ e* P8 J& S; p: g) D/ M$ Y
NVIC_InitTypeDef NVIC_InitStructure;0 Q* `" s: p; j
/* I2C configuration */
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_AnalogFilter = I2C_AnalogFilter_Enable;/ x6 O4 G/ j! V0 a" W
I2C_InitStruct.I2C_DigitalFilter = 0x00;
I2C_InitStruct.I2C_OwnAddress1 = ADDR;7 b/ q+ B+ c: s. T4 M( T4 R
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; 9 e# I" l+ a( |$ F, U
I2C_InitStruct.I2C_Timing = 0xb0420f13; //100Kbits# X! j; g5 |9 j. N. \- |
/* I2C Peripheral Enable */
I2C_Cmd(I2C1, ENABLE);7 T% [% O e+ D d+ Y3 N
/* Apply I2C configuration after enabling it */4 I; ~& N7 w v7 d# ]
I2C_Init(I2C1, &I2C_InitStruct); A4 d: V7 K: U7 O% I' O
, H8 X+ L1 T% J$ i x- P
I2C1->CR1 |= (I2C_CR1_ADDRIE | I2C_CR1_STOPIE | I2C_CR1_TXIE | I2C_CR1_RXIE);- l$ C+ L5 d8 K) c+ x' T2 ^: F V
//---------------------------- Peripheral and DMA interrupts Initialization ------------------
// Initialize I2C1 interrupts
/* Enable the IRQ channel */6 k g* ]& h* M1 M6 @+ U' h
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/* Configure NVIC for I2C1 Interrupt */5 Y) a9 R' ^% r5 G+ \
NVIC_InitStructure.NVIC_IRQChannel = I2C1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 2;
NVIC_Init(&NVIC_InitStructure);
. [- V# y) Q4 C+ [7 z, { t
}0 F. L5 A" Y: A8 ~" j" i5 K, E+ d
3 u) E, d I) D+ ~! c# n# ~* U
//下面是IIC中断函数的实现) e9 W4 K. u$ Z* k+ F- y& s5 P
void I2c_Init(void)
{) _' Q: q% S6 N6 u6 n& \5 z
I2C_GPIO_Configuration();3 O; A T, V' @8 f. z, s8 V
I2C_Configuration();
}
" z! Y) R# V% T6 E5 f& X
void I2C1_IRQHandler(void)! v! O. M% u" ]* }3 L
{
u32 AddCode;
// I2C_ClearITPendingBit(I2C1, I2C_ISR_ADDR | I2C_ISR_STOPF |I2C_ISR_ADDCODE );
__IO uint32_t I2CFlagStatus = 0x00000000;& W2 J' p$ j/ n7 V
I2CFlagStatus = (uint32_t)(I2C1->ISR & (uint16_t)0x0000100FE);. q) F' l: \& T7 j$ f$ v2 j& J
// printf("recv data\r\n");
if ((I2CFlagStatus & I2C_ISR_ADDR) != 0)# p% K- d S& x8 y. w1 p& q
{4 u* R) i9 `- g" X$ O& B) L- J
AddCode = (I2C1->ISR & 0xfe0000); //读取ADDCODE 32:17位
printf("匹配地址2 0x%x: \r\n",AddCode >> 17 );
5 r' M' p \1 V' F! f, T. A
if(I2C1->ISR&I2C_ISR_DIR) //tx mode
{1 d4 t W. n5 i* n
printf("发送模式 \r\n");
Tx_count = 0;& O+ X ?! r2 e" l5 l
I2C1->ISR |= I2C_ISR_TXE;9 T1 ?1 D* M" t2 h; [
I2C1->ICR |= I2C_ICR_ADDRCF;
if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)
{
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);
if(Rx_count>=Rx_MAX)
{
Rx_count=0;! g2 E7 [. Z9 `4 i1 o$ D- |
//rx ok
}
printf("Rx_buffer : %s\r\n",Rx_buffer);0 l4 i: x5 _5 S' _, f6 m
}
} 2 g) @9 ~+ i' G6 }" j2 n
if((I2C1->ISR&I2C_ISR_DIR)==0) //rx mode+ ^! A! B1 n8 ~ v3 ?, m8 X
{, H, m1 U$ Y" _4 A9 I G! T& |9 }) W( U
printf("接收模式 \r\n");+ _/ r; p, N* C7 J% d' I6 G4 \
Rx_count= 0;
I2C1->ICR |= I2C_ICR_ADDRCF; Z' e% m6 o1 N4 @! x8 R' l
}! ^9 S; Z. X8 t/ h$ e$ p& _
}1 P! \" |* J9 y" Z/ J) O5 Z
else if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)1 A$ l n2 I! f n5 q5 O
{
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);
if(Rx_count>=Rx_MAX)2 B- t8 |) i2 n# u9 U5 Q; M# K8 r
{5 B8 ?, J0 Z0 }9 r6 ?/ n& s c
Rx_count=0;
//rx ok! Z! n% o1 x6 t5 x) v3 _
}
printf("Rx_buffer : %s\r\n",Rx_buffer);
}3 L X( e2 s# O$ { q: U# E
else if ((I2CFlagStatus & I2C_ISR_TXIS) != 0)
{3 \% C: k# _0 u6 S
I2C_SendData(I2C1,Tx_buffer[Tx_count++]);( ^5 T* K o; g. K
if(Tx_count >= Tx_MAX)1 d' }* j9 w* [
{: q2 Q& N- ?. ]3 ?3 f
Tx_count = 0; V/ X3 c: s7 t. @4 @" n
//tx ok% w5 n; B m* a8 F
}
}
else if ((I2CFlagStatus & I2C_ISR_STOPF) != 0)0 W1 T, B0 G8 j3 u/ i8 F4 Y. M% w9 t9 e0 Q
{8 A ?. a# X4 C0 P1 U& k2 q
printf("停止检查标志位 \r\n");+ n3 }" c/ x! ?* k# v, O0 Q, i
I2C1->ICR |= I2C_ICR_STOPCF;
Rx_count = 0;
Tx_count = 0; C, H5 R' _1 j! _4 u7 ?5 d
}
}( J9 D+ _2 J- C( t& x# |; N/ N; S
这个是可以匹配到ADDCODE ,但是没有接收到数据的,我没仔细看这个时序寄存器的配置。不知道是不是由于时序不匹配造成没有接收到数据,还是因为ack没有给出造成读不到数据的。
void I2C_GPIO_Configuration(void)- F p; U8 F9 n* o1 P1 E6 I
{
GPIO_InitTypeDef GPIO_InitStruct;
/* Enable GPIOA clock */4 D% _- n) Q. a& y! ?, \9 m
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); 6 M5 P7 R; L, b3 \2 H3 @
/*!< sEE_I2C Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE);3 z" k1 n, O* c9 l5 I
/*!< GPIO configuration */ 5 t( S8 a1 G7 }# b$ L$ g
/*!< Configure sEE_I2C pins: SCL */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; z) i1 U3 Y) K) P4 o3 c
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;//GPIO_Mode_IN
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_3;
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;//open-drain) y, d, L& Y( L7 G0 Q4 ` i
GPIO_Init(GPIOA , &GPIO_InitStruct); h. C. Q9 O, w- \. X q
/*!< Configure sEE_I2C pins: SDA */- e. h- K( T8 B6 {6 T% K* O
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStruct);# c! G3 F A8 v' x" `
& S2 D9 [' c* d/ u9 |" e" V
/* Connect PXx to I2C_SCL*/) H/ T* p/ u& O' e
GPIO_PinAFConfig( GPIOA , GPIO_PinSource9, GPIO_AF_4); ' C, c+ d) `1 \6 W6 j
/* Connect PXx to I2C_SDA*/
GPIO_PinAFConfig( GPIOA ,GPIO_PinSource10, GPIO_AF_4);
}
//IIC从模式配置,在配置时,需要设置地址,在这里设置为0XA0,而从设备的时钟属于被动模式,有IIC的主端确定。
void I2C_Configuration(void)
{
I2C_InitTypeDef I2C_InitStruct;
NVIC_InitTypeDef NVIC_InitStructure;
" W/ |- q( h/ e2 i1 H$ u
/* I2C configuration */
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_InitStruct.I2C_DigitalFilter = 0x00;
I2C_InitStruct.I2C_OwnAddress1 = ADDR;& q+ C" [1 W0 J: `2 ?
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;* w M. {: N. T* f P( p ]
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStruct.I2C_Timing = 0xb0420f13; //100Kbits
/* I2C Peripheral Enable */) ]: M& N3 J5 E$ q
I2C_Cmd(I2C1, ENABLE);
/* Apply I2C configuration after enabling it */2 P/ P6 q! B: w$ e/ ?
I2C_Init(I2C1, &I2C_InitStruct);
I2C1->CR1 |= (I2C_CR1_ADDRIE | I2C_CR1_STOPIE | I2C_CR1_TXIE | I2C_CR1_RXIE);
//---------------------------- Peripheral and DMA interrupts Initialization ------------------ R: n0 E. m4 {" B8 T
// Initialize I2C1 interrupts4 {* b2 l- }" \; M& W# l
/* Enable the IRQ channel */7 N+ N# n7 G9 }$ u, A
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;) S2 k) E6 _& g! `
/* Configure NVIC for I2C1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = I2C1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 2;
NVIC_Init(&NVIC_InitStructure);
# H$ H! r& }6 Y% V `1 [& e; E8 Y' g1 x
}
//下面是IIC中断函数的实现
void I2c_Init(void)1 ]+ u# z2 C- k0 X9 `; t
{) P- i w5 h0 X* z; O1 v
I2C_GPIO_Configuration();: J+ v0 l! {, \9 b/ r. D& n* s; B/ W
I2C_Configuration();
}) K5 p" W8 ?8 y6 D2 v+ M8 x
4 O- R X* i; Q5 J
void I2C1_IRQHandler(void)9 w% W, c. V1 R4 S" s3 w0 ^
{
u32 AddCode;0 I1 n5 O5 ?$ Z: K
// I2C_ClearITPendingBit(I2C1, I2C_ISR_ADDR | I2C_ISR_STOPF |I2C_ISR_ADDCODE );
__IO uint32_t I2CFlagStatus = 0x00000000;% s8 C, H) k0 w9 i# f6 i
I2CFlagStatus = (uint32_t)(I2C1->ISR & (uint16_t)0x0000100FE);; r8 o; Y; [; B' u$ @7 v
" y V o4 {7 R
// printf("recv data\r\n");
if ((I2CFlagStatus & I2C_ISR_ADDR) != 0)
{4 R K O/ R8 N
AddCode = (I2C1->ISR & 0xfe0000); //读取ADDCODE 32:17位
printf("匹配地址2 0x%x: \r\n",AddCode >> 17 );7 [. L0 B$ ~" G7 {3 L O9 V
if(I2C1->ISR&I2C_ISR_DIR) //tx mode# h% \8 c2 t8 W! i5 |! w
{
printf("发送模式 \r\n");) W$ z* a# g$ ^% X, D8 j) x6 D
Tx_count = 0;
I2C1->ISR |= I2C_ISR_TXE;/ S/ T; |0 B F! o2 Z! r
I2C1->ICR |= I2C_ICR_ADDRCF; 2 _2 v+ {/ ^' L+ W. S
! N0 u7 y h M
if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)- N$ }& m% B% Y" n. ?
{
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);& r/ `: N- s; ~
if(Rx_count>=Rx_MAX)0 C- r E2 c/ \; }3 B i0 _: x3 K ]
{8 C* b" B' |8 q: ^( m
Rx_count=0;
//rx ok" ^/ v2 \+ Z$ [" R9 ~; @& z3 F$ f) M9 z
}1 f* O8 k b4 r- b" Y
printf("Rx_buffer : %s\r\n",Rx_buffer);/ `) p/ Y B2 Q' [' W. G
}
}
if((I2C1->ISR&I2C_ISR_DIR)==0) //rx mode
{% ], Z% v6 j+ j0 i; [, @
printf("接收模式 \r\n");( E" z$ D- {8 I# n
Rx_count= 0;
I2C1->ICR |= I2C_ICR_ADDRCF; , m0 } ?6 L H
}
}
else if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0) t8 l9 V/ h: p# X
{7 S+ @* b7 p5 }; j5 {( @' H, a3 ~
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);# K. ^$ k6 f d3 q# R+ o- w( E
if(Rx_count>=Rx_MAX)! B7 g5 i9 Y, H B# @
{
Rx_count=0;4 h+ S" I( y2 Y# U0 N
//rx ok8 {8 z7 U$ r/ c0 m% Y* `% S/ F
}9 G: R6 V. T' b( w% B9 {. h7 j
printf("Rx_buffer : %s\r\n",Rx_buffer);
}
else if ((I2CFlagStatus & I2C_ISR_TXIS) != 0)
{# d/ L. V: x2 j) b% i9 y) f7 \
I2C_SendData(I2C1,Tx_buffer[Tx_count++]);+ y2 O" V" e: g: f1 W1 `1 |
if(Tx_count >= Tx_MAX)1 Z" B q; }* i! B1 u: K
{7 k7 {& h% y* {# q; w
Tx_count = 0;
//tx ok* Q' j5 }( M5 ]* a! I$ s3 o* {
}
}* R& i7 I8 Y6 s
else if ((I2CFlagStatus & I2C_ISR_STOPF) != 0)% _2 j u4 w6 s0 R4 S! _
{
printf("停止检查标志位 \r\n");0 i- w( x6 u+ M9 M8 ]
I2C1->ICR |= I2C_ICR_STOPCF;9 E/ e' W+ D, e5 \, P& L
Rx_count = 0;/ V/ u- A3 A7 l4 g9 [
Tx_count = 0;6 j6 {8 b+ E& O
}
}
# @( C n; l4 }
1 b; f& P- H3 d K( H2 P2 \ b