最近一直在研究STM32F0的IIC,因为项目要用到IIC,master/slave mode都需要,实现数据通信和IAP功能。 网上有关于这部分资料特别少,所以共享一下,只晒出初始化和中断部分的代码的框架。代码在附件 .c里面, 如果有不对的地方,欢迎指正,大家互相学习一下! 8 n* a) ~: i3 ?* o* q& E STM32F0相对于STM32F1和STM8S 有很大变化,支持时钟延长即I2C_CR1_NOSTRETCH,并且支持SMBUS。 1,初始化部分:配置时钟和引脚,不使用时钟延长的功能( z) o2 E" S1 M+ S, P7 c& w/ h 2,I2C1_IRQHandler 主要处理中断事件; D# q/ y' _+ h. p4 \$ ] y& b' S 在I2C_ISR_ADDR事件时,如果设置了多个地址,要判断是那个地址,并且要清除中断标志位。 根据I2C1->ISR&I2C_ISR_DIR 的结果判断是发送数据还是接收数据。& H6 g, b# z8 P5 O (1)发送数据,流程如下 l1 G' x! |- F% ^3 G- Z6 ] 这里要区别一下I2C_ISR_TXIS,I2C_ISR_TXE,描述如下 5 ~; ?$ W$ Q, s6 F (2) 接收数据,流程如下 L" g' W0 @' x% g3 q3 t |
IIC SLAVE mode.zip
下载1.84 KB, 下载次数: 897
分享STM32F051中文参考手册(重制书签版)
STM32固件库分享,超全系列整理
三创电子(Tcreate)-STM32F030调试之I2C篇
基于STM32F0的FOC5.2库PMSM驱动:程序+原理图+BOM等全部开源分享
【MCU实战经验】+STM32F030的步进电机加减速
【管管推荐】STM32经验分享篇
三创电子(Tcreate)-STM32F030核心板代码
STM32F0 ADC(DMA中断)多通道,注释超详细
FreeRTOS在STM32F030上的移植
基于STM32移植而引发的疑问经验分享
我在网上找到你们的代码。我复制了一下。有些问题想了解一下5 q, u) ~2 I; ?$ g- q
void I2C_GPIO_Configuration(void)7 ?3 W u* p2 u! S; V
{1 ` z7 }% ^0 @+ Y" v
GPIO_InitTypeDef GPIO_InitStruct; 6 T; S; K! m: x. G. o8 _3 b ^8 A1 v
/* Enable GPIOA clock */5 [4 P# N2 F! u" U8 K
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/*!< sEE_I2C Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE);
/*!< GPIO configuration */
/*!< Configure sEE_I2C pins: SCL */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;" _* ?4 }2 x. Q# y/ ~/ ~
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;//GPIO_Mode_IN1 M2 r, Q" u5 R3 t; Y; b5 {
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_3;
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;//open-drain3 m2 |/ ?9 a$ r" n6 l) t r9 D L
GPIO_Init(GPIOA , &GPIO_InitStruct);! S/ z/ u. X4 N+ q
. p q+ h6 t) D+ l6 E
/*!< Configure sEE_I2C pins: SDA */& M/ ?0 Y. @, q* a5 d3 V
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStruct);- h+ z7 u+ `2 |& f
/* Connect PXx to I2C_SCL*/
GPIO_PinAFConfig( GPIOA , GPIO_PinSource9, GPIO_AF_4); 4 R, Q/ X5 ]( G. K' Q2 l
/* Connect PXx to I2C_SDA*/
GPIO_PinAFConfig( GPIOA ,GPIO_PinSource10, GPIO_AF_4);
}) Z% N1 D; ]8 Z
//IIC从模式配置,在配置时,需要设置地址,在这里设置为0XA0,而从设备的时钟属于被动模式,有IIC的主端确定。) D. e1 i, `% E
" }% u( I9 I* t u8 Z. o
void I2C_Configuration(void)# R* ?6 v8 I% E; C
{
I2C_InitTypeDef I2C_InitStruct; ! ?1 }/ K2 c8 D" V# E$ `
NVIC_InitTypeDef NVIC_InitStructure;0 C. F' y' i3 \' h; H! r6 ^- s
9 n* v6 L! [: P! O
/* I2C configuration */
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;9 c/ z: P+ {4 o+ Z7 c
I2C_InitStruct.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_InitStruct.I2C_DigitalFilter = 0x00;) t# z6 k0 ]7 |: E% d( T
I2C_InitStruct.I2C_OwnAddress1 = ADDR;' L5 n- J a9 W6 |. i5 C% x2 S& k' K( ?
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStruct.I2C_Timing = 0xb0420f13; //100Kbits9 h* ~! w: N, W. A& V& v
/* I2C Peripheral Enable */( F8 k- r# I9 y; o1 s2 o
I2C_Cmd(I2C1, ENABLE);% ]0 ]6 F% V/ o% `2 m& t# u- }6 {
/* Apply I2C configuration after enabling it */
I2C_Init(I2C1, &I2C_InitStruct);5 C! {- ~3 {8 C8 j4 ]8 `; V
; ~# _0 {/ D$ A4 o) L5 F# O( N
I2C1->CR1 |= (I2C_CR1_ADDRIE | I2C_CR1_STOPIE | I2C_CR1_TXIE | I2C_CR1_RXIE);4 H4 B5 n; X7 z( q w
//---------------------------- Peripheral and DMA interrupts Initialization ------------------
// Initialize I2C1 interrupts
/* Enable the IRQ channel */5 I. o* i& D4 J$ i
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
% |. N9 P7 O7 n* L) W h
/* Configure NVIC for I2C1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = I2C1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 2;
NVIC_Init(&NVIC_InitStructure); 9 }6 d/ t1 n ]( ~2 c
}
//下面是IIC中断函数的实现
% G1 f" K) k3 q j3 ^6 A& x
void I2c_Init(void)
{: t7 @, B, D- @; z: U: l
I2C_GPIO_Configuration();
I2C_Configuration();
}9 O; v$ P6 j- E* D* M5 p5 \
7 _4 H1 l# m$ ]" G o
void I2C1_IRQHandler(void)4 X% l( H: } B& H- s# x
{
u32 AddCode;
// I2C_ClearITPendingBit(I2C1, I2C_ISR_ADDR | I2C_ISR_STOPF |I2C_ISR_ADDCODE );
__IO uint32_t I2CFlagStatus = 0x00000000;) e9 E2 O( h# W% C8 O: t' S6 Z" ~1 Q
I2CFlagStatus = (uint32_t)(I2C1->ISR & (uint16_t)0x0000100FE);3 i7 e4 i H/ T) _ J' l
// printf("recv data\r\n");
if ((I2CFlagStatus & I2C_ISR_ADDR) != 0); d( Z9 R( L8 W, a9 j
{
AddCode = (I2C1->ISR & 0xfe0000); //读取ADDCODE 32:17位
printf("匹配地址2 0x%x: \r\n",AddCode >> 17 );
8 P! t( |6 ~) b/ m* b* z5 M
if(I2C1->ISR&I2C_ISR_DIR) //tx mode
{/ x! k5 r- \5 G9 z7 B
printf("发送模式 \r\n");
Tx_count = 0;
I2C1->ISR |= I2C_ISR_TXE;& v1 e& r* C0 d7 g3 s
I2C1->ICR |= I2C_ICR_ADDRCF; Q. k6 [' b& n* W1 A0 g
" I$ g2 V& x* s
if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0) T+ j: N1 C6 v! ]5 |( o& j, h+ c
{# N: G' Z) X9 t4 M2 z. c3 f7 c- L
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);
if(Rx_count>=Rx_MAX): I2 T* ~! b1 _: ]* a! H/ X) o
{
Rx_count=0;! S0 R$ A, t7 W- ^
//rx ok
}0 x6 u3 K9 F5 N0 i& _1 Y& D
printf("Rx_buffer : %s\r\n",Rx_buffer);( W6 v. j% g. u% [$ R/ q
}
} 7 [; w% e% G* C, y5 `, A
if((I2C1->ISR&I2C_ISR_DIR)==0) //rx mode
{
printf("接收模式 \r\n"); f. C# I* h$ W# v3 C. m% E
Rx_count= 0;
I2C1->ICR |= I2C_ICR_ADDRCF; + p! W) S) ]( B) p
}
}
else if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)
{
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);
if(Rx_count>=Rx_MAX)
{
Rx_count=0;8 L5 @: r0 |" p4 M0 U& j: g7 q
//rx ok; T/ A* u% E9 |4 f" B% \) M
}
printf("Rx_buffer : %s\r\n",Rx_buffer);
}7 {5 t" r0 H0 n. x- R. U
else if ((I2CFlagStatus & I2C_ISR_TXIS) != 0) H, }/ S- m6 ]8 ]
{
I2C_SendData(I2C1,Tx_buffer[Tx_count++]);
if(Tx_count >= Tx_MAX)3 n8 q' y6 ]' }; q& B: x# e
{% [! w7 m2 f$ r2 f+ C
Tx_count = 0;
//tx ok4 d# t. f) P- O9 g
}
}
else if ((I2CFlagStatus & I2C_ISR_STOPF) != 0)
{
printf("停止检查标志位 \r\n");, b/ Q1 L6 i9 x0 G
I2C1->ICR |= I2C_ICR_STOPCF;
Rx_count = 0;/ p. P9 U( |7 H5 Z5 P: x% M
Tx_count = 0;, g. Q" H: O, V, [- F
}8 @& Q* h" d1 d0 }! D- u" M
}# w+ ?" V/ ^2 s# y- Y9 B+ ?& t
( R7 T4 @, t/ Z, r; z, }1 [
这个是可以匹配到ADDCODE ,但是没有接收到数据的,我没仔细看这个时序寄存器的配置。不知道是不是由于时序不匹配造成没有接收到数据,还是因为ack没有给出造成读不到数据的。% p- f- \# a7 t: e' k6 d
void I2C_GPIO_Configuration(void)
{/ G3 ^4 i; e' s. \3 x4 ?
GPIO_InitTypeDef GPIO_InitStruct; 7 ]8 f3 D1 O0 y/ V
2 W4 o. E6 y8 f) Y8 H" W
/* Enable GPIOA clock */% P7 X* w- B% D. x- q0 Z7 ?2 o
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/*!< sEE_I2C Periph clock enable */# T+ m7 a- C0 B9 }9 ~
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE);2 A" d$ o1 l& k* o$ _- w
/*!< GPIO configuration */ & Q* w9 J) X, k
/*!< Configure sEE_I2C pins: SCL */" ~; _* x6 ^' O, t
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;7 {. L( e7 @' z$ }6 i
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);% V: `. N9 D/ {; p% c2 @
/*!< Configure sEE_I2C pins: SDA */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStruct);( R6 z- s0 |+ X# e. j6 [' h
2 }/ B1 |7 t p
/* Connect PXx to I2C_SCL*/0 g+ U$ x; o* D" h/ e$ ?- ]5 g
GPIO_PinAFConfig( GPIOA , GPIO_PinSource9, GPIO_AF_4); ' ^! F# ^/ }' O2 z
/* Connect PXx to I2C_SDA*/+ Z" h' a* V/ i* ?; T7 c
GPIO_PinAFConfig( GPIOA ,GPIO_PinSource10, GPIO_AF_4);
}) ^. n: D- u; d
" s: C8 H, m% _ {, |
//IIC从模式配置,在配置时,需要设置地址,在这里设置为0XA0,而从设备的时钟属于被动模式,有IIC的主端确定。
void I2C_Configuration(void)
{, v P& p* Y" m3 X
I2C_InitTypeDef I2C_InitStruct; 0 ~3 m3 c+ R9 R: V% f
NVIC_InitTypeDef NVIC_InitStructure;
; C( i6 c+ Z" c4 U, Z. D. J6 X9 B. o4 D
/* I2C configuration */) U) \. @' M& I4 e
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;' |+ U' `( g1 a- e
I2C_InitStruct.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_InitStruct.I2C_DigitalFilter = 0x00;
I2C_InitStruct.I2C_OwnAddress1 = ADDR;$ `0 C& F' V- a4 f) c
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; 6 Q9 @+ ~% h* s3 P* D: I* V" `7 `( B
I2C_InitStruct.I2C_Timing = 0xb0420f13; //100Kbits
/* I2C Peripheral Enable */7 F: q6 ^& W' o- t* G
I2C_Cmd(I2C1, ENABLE);
/* Apply I2C configuration after enabling it */
I2C_Init(I2C1, &I2C_InitStruct);
2 Z" J: A: ~$ Z$ Q5 Y% l' V2 K
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 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
5 R4 r8 a; o, ^ n
/* Configure NVIC for I2C1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = I2C1_IRQn;# R# N2 d3 U" J7 {8 K+ j2 n
NVIC_InitStructure.NVIC_IRQChannelPriority = 2;! ?+ S- u, ]3 M( `/ b
NVIC_Init(&NVIC_InitStructure); ) C) I+ f- V: z1 T( B
: y) {0 ^9 S$ o; s$ P& v
}
//下面是IIC中断函数的实现" y2 X9 y# L6 e7 T2 b1 S
# t1 G5 Q& z! e W+ W1 u6 {
void I2c_Init(void)& H! f% m+ c- B9 `; d
{- U. t& H% \( V% N; C9 Q( z
I2C_GPIO_Configuration();
I2C_Configuration();
}
8 F4 ^; R% c2 i8 \& {& s* W
void I2C1_IRQHandler(void)) Z) l S( o% ^) d* q# i
{
u32 AddCode;
// I2C_ClearITPendingBit(I2C1, I2C_ISR_ADDR | I2C_ISR_STOPF |I2C_ISR_ADDCODE );
__IO uint32_t I2CFlagStatus = 0x00000000;: L, c3 E( W2 O+ c; U
I2CFlagStatus = (uint32_t)(I2C1->ISR & (uint16_t)0x0000100FE);
$ i) u9 f" O) ?
// printf("recv data\r\n");
if ((I2CFlagStatus & I2C_ISR_ADDR) != 0)) Q) C5 y* v& W% Y( N& W
{
AddCode = (I2C1->ISR & 0xfe0000); //读取ADDCODE 32:17位
printf("匹配地址2 0x%x: \r\n",AddCode >> 17 );3 w& n/ s" c- t
if(I2C1->ISR&I2C_ISR_DIR) //tx mode
{
printf("发送模式 \r\n");
Tx_count = 0;0 Q/ \6 t" K+ Q# Q a- E# m: {! x
I2C1->ISR |= I2C_ISR_TXE;
I2C1->ICR |= I2C_ICR_ADDRCF; + I: T& s1 f6 i& C
" _/ V( p5 T; R6 [: v$ ~- L- y
if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)
{
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);# `1 E% M9 @5 J3 S% K
if(Rx_count>=Rx_MAX)1 S! p8 W' w t- |3 p$ k, {
{( [3 F- a, w* C- x
Rx_count=0;
//rx ok. u* j% j+ ?: a, q0 E$ q7 D
}
printf("Rx_buffer : %s\r\n",Rx_buffer);
}6 ^$ h9 u S: j" m: N7 o- N0 o
} 1 d! d. S7 O2 S# K: t
if((I2C1->ISR&I2C_ISR_DIR)==0) //rx mode
{
printf("接收模式 \r\n");. v) \8 X2 l! p' u$ M! S: V
Rx_count= 0;
I2C1->ICR |= I2C_ICR_ADDRCF;
}
}; b, M5 h, t! ?/ i# d
else if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)$ X# F2 s. n+ i5 x# [
{% }5 b4 E) a; ?1 }8 V
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);
if(Rx_count>=Rx_MAX)$ F& o, C+ D! j4 H/ [, D
{) a2 a0 a( G/ O" ]/ I& g3 Z/ G1 Y1 d
Rx_count=0; s+ ^6 P1 j$ j9 m
//rx ok2 A$ P. @3 r- Z* C* ]9 k" x
}# o3 V! H; {% f1 H1 H" _( q5 P
printf("Rx_buffer : %s\r\n",Rx_buffer);
}
else if ((I2CFlagStatus & I2C_ISR_TXIS) != 0)& `# _& y1 V0 ] r: w
{/ X; u+ d+ \ w D2 v0 z9 @. y, F4 r
I2C_SendData(I2C1,Tx_buffer[Tx_count++]);
if(Tx_count >= Tx_MAX)) i- L* y1 \9 `* D v0 D8 J' y
{% C" O( S( a7 E/ d- |
Tx_count = 0;
//tx ok7 t6 v# O9 }" j' W) ?. N+ u+ }
}$ B! n0 y* t; ?" O2 W6 U
}% K) Y6 b' [) h: Q. d
else if ((I2CFlagStatus & I2C_ISR_STOPF) != 0)
{
printf("停止检查标志位 \r\n");
I2C1->ICR |= I2C_ICR_STOPCF; u7 ^5 ^% Q% Z' I
Rx_count = 0;4 B/ \% D) }9 k! c1 R' z$ H/ ?
Tx_count = 0;( \' H; N2 m" l/ R
}5 j8 R* G* b! S/ ?* u2 A
}
6 E* v! S/ }3 x' h1 ^) H