最近一直在研究STM32F0的IIC,因为项目要用到IIC,master/slave mode都需要,实现数据通信和IAP功能。, x5 Z, M5 ?- {' I/ f 网上有关于这部分资料特别少,所以共享一下,只晒出初始化和中断部分的代码的框架。代码在附件 .c里面, 如果有不对的地方,欢迎指正,大家互相学习一下!1 [* l6 d. f: R. X8 m3 X STM32F0相对于STM32F1和STM8S 有很大变化,支持时钟延长即I2C_CR1_NOSTRETCH,并且支持SMBUS。 1,初始化部分:配置时钟和引脚,不使用时钟延长的功能 2,I2C1_IRQHandler 主要处理中断事件" J% D5 Q9 F6 o, t5 X0 Y& J! u 在I2C_ISR_ADDR事件时,如果设置了多个地址,要判断是那个地址,并且要清除中断标志位。0 S$ M, k4 q: w8 D& S 根据I2C1->ISR&I2C_ISR_DIR 的结果判断是发送数据还是接收数据。( \! F4 G3 P$ g3 d" k" l (1)发送数据,流程如下2 X8 g, U/ [6 V. W8 m 这里要区别一下I2C_ISR_TXIS,I2C_ISR_TXE,描述如下 (2) 接收数据,流程如下 |
IIC SLAVE mode.zip
下载1.84 KB, 下载次数: 893
【管管推荐】STM32经验分享篇
STM32固件库分享,超全系列整理
三创电子(Tcreate)-STM32F030核心板代码
STM32F0 ADC(DMA中断)多通道,注释超详细
FreeRTOS在STM32F030上的移植
基于STM32移植而引发的疑问经验分享
分享STM32F051中文参考手册(重制书签版)
游名:STM32F0+Trinamic智能步进驱动芯片TMC5160(最高20A)参考原...
【MCU实战经验】+STM32F030的步进电机加减速
STM32F0的中文技术参考手册(标签处理过)
7 r9 C4 T6 n. O* T- T& J# `
我在网上找到你们的代码。我复制了一下。有些问题想了解一下+ i7 p& G1 T: G6 N. F. U
void I2C_GPIO_Configuration(void)
{+ x( x6 {$ j7 t! L! c% j+ k
GPIO_InitTypeDef GPIO_InitStruct;
/* Enable GPIOA clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/*!< sEE_I2C Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE);
/*!< GPIO configuration */
/*!< Configure sEE_I2C pins: SCL */: G/ s$ Z* A' {/ v9 f7 K
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; d0 W* q$ y0 I' b& Z* ~9 o5 X7 o
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;//GPIO_Mode_IN
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_3;3 |+ F/ g6 K$ s: H1 ]3 q
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;//open-drain
GPIO_Init(GPIOA , &GPIO_InitStruct);3 y0 i, b! K* V
$ j4 O n( d% q9 f) z! Y
/*!< Configure sEE_I2C pins: SDA */8 m2 T$ {) F" e; b
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;2 u0 o9 l4 \" _7 k, a/ I& N- b
GPIO_Init(GPIOA, &GPIO_InitStruct);
2 s$ v0 s1 D6 J& p
/* Connect PXx to I2C_SCL*/' G* b$ o0 m( v4 y& _9 j* d9 H
GPIO_PinAFConfig( GPIOA , GPIO_PinSource9, GPIO_AF_4);
/* Connect PXx to I2C_SDA*/; _, U; o, }- F- {
GPIO_PinAFConfig( GPIOA ,GPIO_PinSource10, GPIO_AF_4);
}" E" R+ P* R1 ]9 v
4 A) o6 G0 [1 n4 z
//IIC从模式配置,在配置时,需要设置地址,在这里设置为0XA0,而从设备的时钟属于被动模式,有IIC的主端确定。
void I2C_Configuration(void)
{( {! S$ L- W9 q! U2 V) u W
I2C_InitTypeDef I2C_InitStruct; 3 S6 t# g& R6 G, M
NVIC_InitTypeDef NVIC_InitStructure;+ K2 c% h' {, v6 q
/* I2C configuration */, q& M( h9 Z5 \/ o. U0 ?
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;& ]6 E. h- I6 P" T0 b- u
I2C_InitStruct.I2C_AnalogFilter = I2C_AnalogFilter_Enable;. y9 d0 `) k9 |& a# V$ \% o
I2C_InitStruct.I2C_DigitalFilter = 0x00;
I2C_InitStruct.I2C_OwnAddress1 = ADDR;' Z- D$ {7 E" K3 u& ?+ W) I8 K
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStruct.I2C_Timing = 0xb0420f13; //100Kbits+ `$ \6 c4 [1 p2 a
/* I2C Peripheral Enable */+ A# S5 P, A$ j& o. M. D; E
I2C_Cmd(I2C1, ENABLE);$ H1 f0 u1 Y. J1 m6 J: H
/* Apply I2C configuration after enabling it */
I2C_Init(I2C1, &I2C_InitStruct);
I2C1->CR1 |= (I2C_CR1_ADDRIE | I2C_CR1_STOPIE | I2C_CR1_TXIE | I2C_CR1_RXIE); u1 h7 O2 X9 Z7 f
//---------------------------- Peripheral and DMA interrupts Initialization ------------------
// Initialize I2C1 interrupts4 n9 S3 L$ O7 S. {5 h7 G
/* Enable the IRQ channel */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;. X: y! B, k3 C( W4 u
3 Z0 d% M/ G k* _ B4 L4 {
/* Configure NVIC for I2C1 Interrupt */( e; \$ N- G8 h
NVIC_InitStructure.NVIC_IRQChannel = I2C1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 2;6 z; m2 l7 d2 X2 Z6 y
NVIC_Init(&NVIC_InitStructure);
}
//下面是IIC中断函数的实现
& r( Y1 t5 ]2 o8 H, y o
void I2c_Init(void)
{
I2C_GPIO_Configuration();! P- B- c% M6 ]" L) h' N8 x$ p9 a& L& W
I2C_Configuration();
}
% }4 Z8 z; {: W9 E) i- s
void I2C1_IRQHandler(void)
{! B! ]4 \" b5 X* B8 P' v4 E
u32 AddCode;! Y4 L! O- [8 g) [8 y3 T
// I2C_ClearITPendingBit(I2C1, I2C_ISR_ADDR | I2C_ISR_STOPF |I2C_ISR_ADDCODE );# T* j* y# L/ P7 d' g$ M9 B
__IO uint32_t I2CFlagStatus = 0x00000000;
I2CFlagStatus = (uint32_t)(I2C1->ISR & (uint16_t)0x0000100FE);
// printf("recv data\r\n");
if ((I2CFlagStatus & I2C_ISR_ADDR) != 0)6 e4 G! r, m) c8 a O. W
{/ l8 G2 Z7 V, Q4 ^! I
AddCode = (I2C1->ISR & 0xfe0000); //读取ADDCODE 32:17位2 B( }0 Q. j4 P8 B. r* B
printf("匹配地址2 0x%x: \r\n",AddCode >> 17 );
if(I2C1->ISR&I2C_ISR_DIR) //tx mode( O5 a6 x+ J0 q
{
printf("发送模式 \r\n");
Tx_count = 0;
I2C1->ISR |= I2C_ISR_TXE;
I2C1->ICR |= I2C_ICR_ADDRCF; ' U; L% n6 q3 b
if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)) S% K: e M2 s! B3 e" U
{
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);5 b" I/ I! ~1 t- L
if(Rx_count>=Rx_MAX)
{: N, ]) U) X( V$ Y
Rx_count=0;
//rx ok
}
printf("Rx_buffer : %s\r\n",Rx_buffer);
}" k- Y9 e5 V, k) }9 w E6 u& E! J/ h
} : t) W% I4 [9 D4 t
if((I2C1->ISR&I2C_ISR_DIR)==0) //rx mode8 H6 O3 ]/ t+ j) Q a3 ~: J
{" Q& b# P- `7 ?( f
printf("接收模式 \r\n");: c4 e' b- j6 ], p& M9 s5 k- h
Rx_count= 0;% ~% j" K! [; F6 q' _" J
I2C1->ICR |= I2C_ICR_ADDRCF;
}0 L& {& P$ l2 e
}) g5 k7 q! |0 M$ ~7 p
else if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)& A* z7 s7 _" Z. Z. t
{1 _/ r5 G6 U$ I/ {6 F
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);
if(Rx_count>=Rx_MAX)1 g2 b# M6 v e$ y1 O
{
Rx_count=0;
//rx ok \ z, u1 X. m/ {3 O- l
}
printf("Rx_buffer : %s\r\n",Rx_buffer);
}
else if ((I2CFlagStatus & I2C_ISR_TXIS) != 0)
{
I2C_SendData(I2C1,Tx_buffer[Tx_count++]);% S) _' [1 s7 E0 R: b* h
if(Tx_count >= Tx_MAX)
{
Tx_count = 0;- `- L9 r! |* `; v, D. J: l
//tx ok
}0 x* d0 f2 W: l4 O6 w
}2 m, [/ s- j' R Q
else if ((I2CFlagStatus & I2C_ISR_STOPF) != 0)0 l- y0 w" e: d0 B3 {2 K
{1 p' x2 y- ?/ V+ X0 B' G
printf("停止检查标志位 \r\n");
I2C1->ICR |= I2C_ICR_STOPCF;
Rx_count = 0;
Tx_count = 0;4 T6 \& R$ h* l# m) v# j
}/ \. D' |1 \' B. U! J
}* H' E8 w* f: p: _ ?7 `
这个是可以匹配到ADDCODE ,但是没有接收到数据的,我没仔细看这个时序寄存器的配置。不知道是不是由于时序不匹配造成没有接收到数据,还是因为ack没有给出造成读不到数据的。
void I2C_GPIO_Configuration(void)( A7 `0 C* t* D7 b# d9 I& l9 n! n3 `$ [
{5 A! k) Z- j3 @* t- V! g) q
GPIO_InitTypeDef GPIO_InitStruct;
0 a4 M- ?) |- K$ O- q3 t
/* Enable GPIOA clock */5 K5 H' }# R8 F8 C" B2 x$ W/ `$ X
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;- x5 A& h3 G4 H) F# T
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& t- Y. E0 A% x# g7 u4 j1 `1 E
GPIO_Init(GPIOA , &GPIO_InitStruct);9 `$ T/ w! W4 }/ e2 p v \- {
/*!< Configure sEE_I2C pins: SDA */' o# q: P. Y5 y X
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;2 J( x. I, `) q
GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Connect PXx to I2C_SCL*/1 p5 u& j9 Z$ @, O" m" v# G- h1 |
GPIO_PinAFConfig( GPIOA , GPIO_PinSource9, GPIO_AF_4);
/* Connect PXx to I2C_SDA*/
GPIO_PinAFConfig( GPIOA ,GPIO_PinSource10, GPIO_AF_4);" v* ^ O1 s' ^2 i
}
//IIC从模式配置,在配置时,需要设置地址,在这里设置为0XA0,而从设备的时钟属于被动模式,有IIC的主端确定。
void I2C_Configuration(void)
{
I2C_InitTypeDef I2C_InitStruct;
NVIC_InitTypeDef NVIC_InitStructure;6 T( |6 }/ i- I( D8 w* X
- F* D( n3 I3 M5 F& a9 L
/* I2C configuration */: |. W! B& i! b1 J5 b$ w* h6 x$ A m
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_AnalogFilter = I2C_AnalogFilter_Enable;3 T z) d* c6 e& U5 n
I2C_InitStruct.I2C_DigitalFilter = 0x00;
I2C_InitStruct.I2C_OwnAddress1 = ADDR;. {# A3 p, p7 M
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStruct.I2C_Timing = 0xb0420f13; //100Kbits* M+ x0 A: w0 R3 z% V
/* I2C Peripheral Enable */
I2C_Cmd(I2C1, ENABLE);2 P0 |2 l& B1 Q
/* Apply I2C configuration after enabling it */6 L( G8 i8 W) t4 W
I2C_Init(I2C1, &I2C_InitStruct);
+ W# i* w: E" v
I2C1->CR1 |= (I2C_CR1_ADDRIE | I2C_CR1_STOPIE | I2C_CR1_TXIE | I2C_CR1_RXIE);- j/ g) S+ g7 @: w
//---------------------------- Peripheral and DMA interrupts Initialization ------------------
// Initialize I2C1 interrupts
/* Enable the IRQ channel */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
( O6 m {$ m/ h/ Y
/* Configure NVIC for I2C1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = I2C1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 2;
NVIC_Init(&NVIC_InitStructure);
}
9 r7 b( ?" Z8 S
//下面是IIC中断函数的实现
void I2c_Init(void)
{
I2C_GPIO_Configuration();
I2C_Configuration();& E+ d2 J: u/ M; l
}9 N# J; Q+ q, S& E d
void I2C1_IRQHandler(void)
{
u32 AddCode;; b2 e( v5 J$ H6 E' k4 y
// I2C_ClearITPendingBit(I2C1, I2C_ISR_ADDR | I2C_ISR_STOPF |I2C_ISR_ADDCODE ); `& v4 \( I9 \1 E3 w; S2 H& ~( A
__IO uint32_t I2CFlagStatus = 0x00000000;! p1 |+ \ n: J4 y: y0 B5 L! @0 e$ p
I2CFlagStatus = (uint32_t)(I2C1->ISR & (uint16_t)0x0000100FE);( M0 P: e+ b# t7 `& |. k$ I
; S; `- y5 j1 r0 I7 z' V0 I
// printf("recv data\r\n");8 [- q% R3 Q/ ~9 r+ M
if ((I2CFlagStatus & I2C_ISR_ADDR) != 0)& p5 Z& o: d' u* h
{
AddCode = (I2C1->ISR & 0xfe0000); //读取ADDCODE 32:17位
printf("匹配地址2 0x%x: \r\n",AddCode >> 17 );0 q7 r# G6 o7 J
if(I2C1->ISR&I2C_ISR_DIR) //tx mode
{' E$ \3 A3 d4 {( n1 k' ^
printf("发送模式 \r\n");) |+ `6 ]6 g- k; r2 K9 C) B- f! \( }
Tx_count = 0;+ w$ R+ {7 k( j) ~( H V
I2C1->ISR |= I2C_ISR_TXE;
I2C1->ICR |= I2C_ICR_ADDRCF;
if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)( B& q$ C1 L( F; a
{* D$ _) S: w( r% e4 @
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);
if(Rx_count>=Rx_MAX)" b" O0 p/ Y8 t; M; [
{5 S+ q' P. p% C, n' _
Rx_count=0;2 |! _$ g) X7 C. B1 _8 G5 k0 q
//rx ok( U0 G9 t6 v; N2 @3 F" v
}
printf("Rx_buffer : %s\r\n",Rx_buffer);( {) p! s6 d) {6 @7 l Z" L
}
}
if((I2C1->ISR&I2C_ISR_DIR)==0) //rx mode* V+ I' y1 t7 U; O8 [
{
printf("接收模式 \r\n");
Rx_count= 0;
I2C1->ICR |= I2C_ICR_ADDRCF;
}0 V \. n8 }, H2 E
}
else if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)
{
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);
if(Rx_count>=Rx_MAX); r0 A0 I+ _: L5 ]" H8 G( e- S) g! @
{9 \! N3 z6 [3 d+ g" B- o( r
Rx_count=0;; ?' ?# E9 c) g" N: u7 ~
//rx ok
}
printf("Rx_buffer : %s\r\n",Rx_buffer);5 Q. H) B1 b$ S) |' H9 p
}) Y' S2 W$ G5 R6 g
else if ((I2CFlagStatus & I2C_ISR_TXIS) != 0)
{. x- ?% b; k, ?! {+ a
I2C_SendData(I2C1,Tx_buffer[Tx_count++]);7 A( Y5 I5 i# r6 {8 f4 ~0 U
if(Tx_count >= Tx_MAX)
{5 s0 r* U1 b; X: ?* V
Tx_count = 0;5 H! L; v9 H6 H) C% b5 f
//tx ok
}
}4 e/ ^ Y: X2 p( z: e% r
else if ((I2CFlagStatus & I2C_ISR_STOPF) != 0)4 A+ b( r$ R! i1 ]- S; K
{
printf("停止检查标志位 \r\n");
I2C1->ICR |= I2C_ICR_STOPCF;
Rx_count = 0;( g* G$ ` i! @0 o9 T- H) @; u
Tx_count = 0;
}: e) t+ ^ n* _$ H1 P% t
}
0 V3 }$ o- }4 N( }$ h0 v
$ \0 S4 w7 F7 P+ I( P