当前位置:首页 > 单片机 > 单片机
[导读]I2C总线是由NXP(原PHILIPS)公司设计,有十分简洁的物理层定义,其特性如下:· 只要求两条总线线路:一条串行数据线SDA,一条串行时钟线SCL;· 每个连接到总线的器件都可以通过唯一的地址和一直存在的简

I2C总线是由NXP(原PHILIPS)公司设计,有十分简洁的物理层定义,其特性如下:

·  只要求两条总线线路:一条串行数据线SDA,一条串行时钟线SCL;

·  每个连接到总线的器件都可以通过唯一的地址和一直存在的简单的主机/从机关系软件设定地址,主机可以作为主机发送器或主机接收器;

·  它是一个真正的多主机总线,如果两个或更多主机同时初始化,数据传输可以通过冲突检测和仲裁防止数据被破坏;

·  串行的8 位双向数据传输位速率在标准模式下可达100kbit/s,快速模式下可达400kbit/s,高速模式下可达3.4Mbit/s;

·  连接到相同总线的IC 数量只受到总线的最大电容400pF 限制。

其典型的接口连线如下:

I2C的协议很简单:

数据的有效性

在传输数据的时候,SDA线必须在时钟的高电平周期保持稳定,SDA的高或低电平状态只有在SCL 线的时钟信号是低电平时才能改变 。

起始和停止条件

SCL 线是高电平时,SDA 线从高电平向低电平切换,这个情况表示起始条件;

SCL 线是高电平时,SDA 线由低电平向高电平切换,这个情况表示停止条件。

字节格式

发送到SDA 线上的每个字节必须为8 位,每次传输可以发送的字节数量不受限制。每个字节后必须处理一个响应位。

应答响应

数据传输必须带响应,相关的响应时钟脉冲由主机产生。在响应的时钟脉冲期间发送器释放SDA 线(高)。

在响应的时钟脉冲期间,接收器必须将SDA 线拉低,使它在这个时钟脉冲的高电平期间保持稳定的低电平。

也就是说主器件发送完一字节数据后要接收一个应答位(低电平),从器件接收完一个字节后要发送一个低电平。

寻址方式(7位地址方式)

第一个字节的头7 位组成了从机地址,最低位(LSB)是第8 位,它决定了传输的 普通的和带重复开始条件的7位地址格式方向。第一个字节的最低位是

“0”,表示主机会写信息到被选中的从机;

“1”表示主机会向从机读信息。

当发送了一个地址后,系统中的每个器件都在起始条件后将头7 位与它自己的地址比较,如果一样,器件会判定它被主机寻址,至于是从机接收器还是从机发送器,都由R/W 位决定。

仲裁

I2C是所主机总线,每个设备都可以成为主机,但任一时刻只能有一个主机。

stm32至少有一个I2C接口,提供多主机功能,可以实现所有I2C总线的时序、协议、仲裁和定时功能,支持标准和快速传输两种模式,同时与SMBus 2.0兼容。

本实验直接操作寄存器实现对I2C总线结构的EEPROM AT24c02的写入和读取。AT24c02相关操作详见 单片机读取EEPROM(AT24C02)。

库函数实现使用stm32的两个I2C模拟I2C设备间的数据收发,并通过串口查看数据交换情况。

直接操作寄存器

首先需要配置I2C接口的时钟,相关寄存器如下:

I2C_CR2寄存器低五位:

FREQ[5:0]:I2C模块时钟频率 ,必须设置正确的输入时钟频率以产生正确的时序,允许的范围在2~36MHz之间:

000000:禁用 000001:禁用 000010:2MHz ... 100100:36MHz 大于100100:禁用。

用于设置I2C设备的输入时钟,本例使用的是PLCK1总线上的时钟所以为36Mhz;

时钟控制寄存器(I2C_CCR)低12位:

CCR[11:0]:快速/标准模式下的时钟控制分频系数(主模式),该分频系数用于设置主模式下的SCL时钟。

在I2C标准模式或SMBus模式下:

Thigh = CCR ×TPCLK1

Tlow = CCR ×TPCLK1

时钟周期为 T = Thigh + Tlow;

例如:在标准模式下,FREQR = 36 即36Mhz,产生200kHz的SCL的频率

时钟控制分频系数 = Freqr /2/f f 为想得到的频率

配置好时钟,还需要配置本机地址,I2C支持7位地址和10位地址,这里用的是7位地址:

自身地址寄存器1(I2C_OAR1)[7:1]:接口地址,地址的7~1位。

其他相关操作参见代码,有详细注释:(system.h 和 stm32f10x_it.h 等相关代码参照 stm32 直接操作寄存器开发环境配置)

User/main.c

01 #include <stm32f10x_lib.h>    
02 #include "system.h"
03 #include "usart.h" 
04 #include "i2c.h"
05   
06 #define LED1 PAout(4)
07 #define LED2 PAout(5)
08 #define LED3 PAout(6)
09 #define LED4 PAout(7)
10   
11 void Gpio_Init(void);
12   
13 int main(void)
14 {             
15   
16     Rcc_Init(9);                          //系统时钟设置
17   
18     Usart1_Init(72,9600);
19   
20     Nvic_Init(1,0,I2C1_EV_IRQChannel,4);      //设置抢占优先级为1,响应优先级为0,中断分组为4
21   
22     Nvic_Init(0,0,I2C1_ER_IRQChannel,4);      //设置I2C错误中断抢占优先级为0
23   
24     Gpio_Init();
25   
26     I2c_Init(0x30);                           //设置I2C1地址为0x30                    
27   
28     I2c_Start();
29   
30     while(1);       
31 }
32   
33   
34 void Gpio_Init(void)
35 {
36     RCC->APB2ENR |= 1<<2;          //使能PORTA时钟     
37     RCC->APB2ENR |= 1<<3;          //使能PORTB时钟;    
38   
39   
40     GPIOA->CRL &= 0x0000FFFF;        // PA0~3设置为浮空输入,PA4~7设置为推挽输出
41     GPIOA->CRL |= 0x33334444; 
42   
43   
44     GPIOB->CRL &= 0x00FFFFFF;        //PB6 I2C1_SCL ,PB7  I2C1_SDL
45     GPIOB->CRL |= 0xFF000000;        //复用开漏输出
46       
47     //USART1 串口I/O设置
48   
49     GPIOA -> CRH &= 0xFFFFF00F;      //设置USART1 的Tx(PA.9)为第二功能推挽,50MHz;Rx(PA.10)为浮空输入
50     GPIOA -> CRH |= 0x000008B0;    
51   
52 }

User/stm32f10x_it.c

001 #include "stm32f10x_it.h"
002 #include "system.h"
003 #include "stdio.h"
004 #include "i2c.h"
005   
006 #define LED1 PAout(4)
007 #define LED2 PAout(5)
008 #define LED3 PAout(6)
009 #define LED4 PAout(7)
010   
011 #define  ADDRS_R  0xA1    //读操作地址
012 #define  ADDRS_W  0xA0    //写操作地址
013   
014 u8  go = 0;               //操作步骤标记
015   
016 void I2C1_EV_IRQHandler(void)     //I2C1 Event Interrupt 
017 {
018     u16 clear = 0;
019   
020     if(I2C1 -> SR1 & 1<<0 )          //已发送起始条件,写数据寄存器的操作将清除该位
021     {
022         printf("\r\n I2C1 Start .. \r\n");
023   
024         switch(go)
025         {
026             case 0:{ 
027                 I2c_Write(ADDRS_W);        //写入从机地址,写指令操作地址
028                 break;
029             }
030             case 1:{
031                 I2c_Write(ADDRS_W);        //写入从机地址,写指令操作地址
032                 break;
033             }
034             case 2:{
035                 I2c_Write(ADDRS_R);        //写入从机地址,读数据操作地址
036                 break;
037            }
038         }
039   
040     }
041   
042     if(I2C1 -> SR1 & 1<<1 )        //从机地址已发送
043     {
044         printf("\r\n I2C1 has send address .. \r\n");
045         clear = I2C1 -> SR2; //读取SR2可以清除该位中断
046   
047         switch(go)
048         {
049             case 0:{ 
050                 I2c_Write(0x01);    //写入待写入的EEPROM单元地址
051                 break;
052             }
053   
054             case 1:{
055                 I2c_Write(0x01);    //写入待写入的EEPROM单元地址
056                 break;
057             }
058             case 2:{
059                 delay(100000);
060                 printf("\r\n Read 0x%X from At24c02 ,Address 0x01 ..  \r\n",I2c_Read());
061                 I2c_Stop();
062                 break;
063            }
064         }
065   
066     }
067   
068     if(I2C1 -> SR1 & 1<<2 )        //字节发送结束  发送地址字节时,不触发此中断
069     {
070           
071         //printf("\r\n I2C1 send byte success .. \r\n");
072         switch(go)
073         {
074             case 0:{ 
075                 I2c_Write(0x86);            //写入数据
076                 printf("\r\n Write 0x%X to At24c02 ,Address 0x01 ..  \r\n",0x86);           
077                 //I2c_Stop();
078       
079                 delay(10000);
080                 go = 1;
081                 I2c_Start(); 
082                 break;
083             }
084   
085             case 1:{
086   
087                 delay(10000);
088                 go = 2;
089                 I2c_Start();
090                 break;
091             }
092             case 2:{
093   
094                 break;
095            }
096         }
097   
098     }
099   
100     delay(100000);
101     LED3 = 1;
102   
103     //I2C1 -> CR2 &= ~(1<<9);          //事件中断关闭
104 }
105   
106 void I2C1_ER_IRQHandler(void)       //I2C1 Error Interrupt 
107 {
108     delay(100000);
109     LED4 = 1;   
110   
111     if(I2C1->SR1 & 1<<10)          //应答失败
112     {
113         printf("\r\n ACK ERROR .. \r\n");
114   
115         I2C1->SR1 &=~(1<<10);      //清除中断
116     }
117   
118     if(I2C1->SR1 & 1<<14)          //超时
119     {
120         printf("\r\n Timeout .. \r\n");
121   
122         I2C1->SR1 &=~(1<<14);      //清除中断
123     }
124   
125     if(I2C1->SR1 & 1<<11)          //过载/欠载
126     {
127         printf("\r\n Overrun/Underrun .. \r\n");
128         I2C1->SR1 &=~(1<<11);      //清除中断
129     }
130   
131     if(I2C1->SR1 & 1<<9)           //仲裁丢失
132     {
133         printf("\r\n Arbitration lost .. \r\n");
134         I2C1->SR1 &=~(1<<9);       //清除中断
135     }
136   
137     if(I2C1->SR1 & 1<<8)           //总线出错
138     {
139         printf("\r\n Bus error .. \r\n");
140         I2C1->SR1 &=~(1<<8);       //清除中断
141     }
142   
143   
144 }

Library/src/i2c.c

view sourceprint?

01 #include "i2c.h" 
02   
03 void I2c_Init(u16 Addr )
04 {
05   
06     RCC -> APB1ENR |= 1<<21;           //打开I2C1时钟
07     //RCC -> APB1ENR |= 1<<22;         //打开I2C2时钟
08   
09     RCC->APB1RSTR  |= 1<<21;           //复位I2C1
10     RCC->APB1RSTR  &= ~(1<<21);            //复位结束I2C1
11     //RCC->APB1RSTR  |= 1<<22;         //复位I2C2
12   
13     //I2C1 -> CR1 |=  1<<15;               //复位寄存器
14   
15     //I2C模块时钟频率,2~36MHz之间
16     I2C1 -> CR2 |=   36 ;                //000000:禁用 000001:禁用 000010:2MHz ... 100100:36MHz
17   
18   
19     I2C1 -> CCR |= 0<<15;              //I2C主模式  0:标准模式的I2C    1:快速模式的I2C
20     //I2C1 -> CCR |= 1<<14;                //快速模式时的占空比 0 Tlow/Thigh = 2    1   Tlow/Thigh = 16/9
21   
22     //得到200kHz频率
23     I2C1 -> CCR |= 90<<0;              //时钟控制分频系数  = PCLK1 /2/f    f 为想得到的频率
24   
25     //主模式最大上升时间
26     I2C1 -> TRISE |= 37;             //最大允许SCL上升时间为1000ns,故TRISE[5:0]中必须写入(1us/(1/36)us = 36+1)。
27   
28     I2C1 -> CR1 |=  1<<10;             //打开ACK应答,在接收到一个字节后返回一个应答
29     I2C1 -> CR1 |= 1<<6;               //广播呼叫使能
30   
31     I2C1 -> OAR1 |= 0<<15;             //寻址模式   1 响应10位地址  0  响应7位地址   
32   
33     I2C1 -> OAR1 |= 1<<14;             //必须始终由软件保持为 1
34   
35     I2C1 -> OAR1 |=  Addr <<1 ;            //设置接口地址的 7~1位
36   
37     //I2C1 -> OAR1 |=  0 ;           //设置10位地址模式时地址第0位 
38     //I2C1 -> OAR1 |= 0<<8;                //设置10位地址模式时地址第9~8位
39   
40     //I2C1 -> CR2 |=  1<<10;               //缓冲器中断使能
41     I2C1 -> CR2 |=  1<<9;              //事件中断使能
42     I2C1 -> CR2 |=  1<<8;              //出错中断使能
43   
44     I2C1 -> CR1 |=   1<<0;             //开启I2C1
45 }
46   
47   
48 void  I2c_Start()
49 {
50   
51     I2C1 -> CR1 |=   1<<8;             //I2C1产生起始条件
52 }
53   
54 void  I2c_Stop()
55 {
56     I2C1 -> CR1 |=   1<<9;             //I2C1产生停止条件
57 }
58   
59   
60 void  I2c_Write(u8 data)
61 {
62     I2C1 -> DR = data;
63 }
64   
65 u8  I2c_Read()
66 {
67     while(!(I2C1 -> SR1 & 1<<6));      //接收到数据标志位
68   
69     return I2C1 -> DR;
70 }
71   
72 void  I2c_End()                         //关闭I2C
73 {
74     I2C1 -> CR1 &=   ~(1<<0);      
75 }

Library/inc/i2c.h

1 #include <stm32f10x_lib.h>
2   
3 void I2c_Init(u16 Addr );   
4   
5 void  I2c_Start(void);
6 void  I2c_Stop(void);
7 void  I2c_Write(u8 data);
8 u8    I2c_Read(void);
9 void  I2c_End(void);

串口接收数据如下:

I2C1 Start ..

I2C1 has send address ..

Write 0x86 to At24c02 ,Address 0x01 ..

I2C1 Start ..

I2C1 has send address ..

I2C1 Start ..

I2C1 has send address ..

Read 0x86 from At24c02 ,Address 0x01 ..

库函数操作

main.c

001 #include "stm32f10x.h"
002 #include "stdio.h"
003   
004 #define  PRINTF_ON  1
005   
006 void RCC_Configuration(void);
007 void GPIO_Configuration(void);
008 void USART_Configuration(void);
009 void I2C_Configuration(void);
010 void NVIC_Configuration(void);
011   
012   
013 u8 I2C1_ADDRESS = 0x30;   //7位 I2C 地址
014 u8 I2C2_ADDRESS = 0x31;
015   
016 #define Size 4
017   
018 vu8 I2C1_Buffer_Tx[Size] = {1,2,3,4};
019 vu8 I2C2_Buffer_Rx[Size] = {0};
020   
021 u32 BufferSize = Size ;
022   
023 int main(void)
024 {
025     RCC_Configuration();
026     GPIO_Configuration();
027     USART_Configuration();
028     I2C_Configuration();
029     NVIC_Configuration();
030   
031     I2C_GenerateSTART(I2C1,ENABLE);
032   
033     while(1);   
034 }
035   
036 void I2C_Configuration(void)
037 {
038     I2C_InitTypeDef I2C_InitStructure;
039   
040     I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
041     I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
042     I2C_InitStructure.I2C_OwnAddress1 = I2C1_ADDRESS;
043     I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
044     I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
045     I2C_InitStructure.I2C_ClockSpeed = 200000;
046     I2C_Init(I2C1,&I2C_InitStructure);
047   
048     I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
049     I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
050     I2C_InitStructure.I2C_OwnAddress1 = I2C2_ADDRESS;
051     I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
052     I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
053     I2C_InitStructure.I2C_ClockSpeed = 200000;
054     I2C_Init(I2C2,&I2C_InitStructure);
055   
056   
057     I2C_ITConfig(I2C1,I2C_IT_EVT|I2C_IT_BUF,ENABLE);
058     I2C_ITConfig(I2C2,I2C_IT_EVT|I2C_IT_BUF,ENABLE);
059       
060     I2C_Cmd(I2C1,ENABLE);
061     I2C_Cmd(I2C2,ENABLE);
062 }
063   
064 void NVIC_Configuration(void)
065 {
066     NVIC_InitTypeDef NVIC_InitStructure;
067   
068     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
069   
070     NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;
071     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
072     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
073     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
074     NVIC_Init(&NVIC_InitStructure);
075   
076     NVIC_InitStructure.NVIC_IRQChannel = I2C2_EV_IRQn;
077     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
078     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
079     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
080     NVIC_Init(&NVIC_InitStructure);
081 }
082   
083 void GPIO_Configuration(void)
084 {
085     GPIO_InitTypeDef    GPIO_InitStructure;
086   
087     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
088   
089     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
090     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;         
091     GPIO_Init(GPIOB , &GPIO_InitStructure); 
092   
093     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;      
094     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
095     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; 
096     GPIO_Init(GPIOB , &GPIO_InitStructure); 
097   
098   
099     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
100     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;         
101     GPIO_Init(GPIOA , &GPIO_InitStructure); 
102       
103     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
104     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;           
105     GPIO_Init(GPIOA , &GPIO_InitStructure); 
106 }
107   
108 void RCC_Configuration(void)
109 {
110     /* 定义枚举类型变量 HSEStartUpStatus */
111     ErrorStatus HSEStartUpStatus;
112   
113     /* 复位系统时钟设置*/
114     RCC_DeInit();
115     /* 开启HSE*/
116     RCC_HSEConfig(RCC_HSE_ON);
117     /* 等待HSE起振并稳定*/
118     HSEStartUpStatus = RCC_WaitForHSEStartUp();
119     /* 判断HSE起是否振成功,是则进入if()内部 */
120     if(HSEStartUpStatus == SUCCESS)
121     {
122         /* 选择HCLK(AHB)时钟源为SYSCLK 1分频 */
123         RCC_HCLKConfig(RCC_SYSCLK_Div1); 
124         /* 选择PCLK2时钟源为 HCLK(AHB) 1分频 */
125         RCC_PCLK2Config(RCC_HCLK_Div1); 
126         /* 选择PCLK1时钟源为 HCLK(AHB) 2分频 */
127         RCC_PCLK1Config(RCC_HCLK_Div2);
128         /* 设置FLASH延时周期数为2 */
129         FLASH_SetLatency(FLASH_Latency_2);
130         /* 使能FLASH预取缓存 */
131         FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
132         /* 选择锁相环(PLL)时钟源为HSE 1分频,倍频数为9,则PLL输出频率为 8MHz * 9 = 72MHz */
133         RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
134         /* 使能PLL */ 
135         RCC_PLLCmd(ENABLE);
136         /* 等待PLL输出稳定 */
137         while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
138         /* 选择SYSCLK时钟源为PLL */
139         RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
140         /* 等待PLL成为SYSCLK时钟源 */
141         while(RCC_GetSYSCLKSource() != 0x08);
142     
143     /* 打开APB2总线上的GPIOA时钟*/
144     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_USART1, ENABLE);
145   
146     //RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
147   
148     RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1|RCC_APB1Periph_I2C2,ENABLE);
149     //RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP|RCC_APB1Periph_WWDG|RCC_APB1Periph_SPI2, ENABLE);
150           
151 }
152   
153    
154 void USART_Configuration(void)
155 {
156     USART_InitTypeDef USART_InitStructure;
157     USART_ClockInitTypeDef USART_ClockInitStructure;
158   
159     USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
160     USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
161     USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;                                                                                                                                                      
162     USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
163     USART_ClockInit(USART1 , &USART_ClockInitStructure);
164   
165     USART_InitStructure.USART_BaudRate = 9600;
166     USART_InitStructure.USART_WordLength = USART_WordLength_8b;
167     USART_InitStructure.USART_StopBits = USART_StopBits_1;
168     USART_InitStructure.USART_Parity = USART_Parity_No;
169     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
170     USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
171     USART_Init(USART1,&USART_InitStructure);
172   
173     USART_Cmd(USART1,ENABLE);
174 }
175   
176 #if  PRINTF_ON
177   
178 int fputc(int ch,FILE *f)
179 {
180     USART_SendData(USART1,(u8) ch);
181     while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);
182     return ch;
183 }
184   
185 #endif

stm32f10x_it.c

view sourceprint?

01 #include "stm32f10x_it.h"
02 #include "stdio.h"
03   
04 extern u32 BufferSize ;
05 extern u8 I2C1_ADDRESS ;
06 extern u8 I2C2_ADDRESS ;
07   
08 extern vu8 I2C1_Buffer_Tx[];
09 extern vu8 I2C2_Buffer_Rx[];
10 vu32 Tx_Counter = 0;
11 vu32 Rx_Counter = 0;
12   
13 void I2C1_EV_IRQHandler(void)
14 {
15     switch(I2C_GetLastEvent(I2C1))
16     {
17         case I2C_EVENT_MASTER_MODE_SELECT: //已发送启始条件
18         {
19             I2C_Send7bitAddress(I2C1,I2C2_ADDRESS,I2C_Direction_Transmitter);   
20             break;
21         }
22         case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED: //已发送从机地址
23         {
24             printf("\r\n The I2C1 has send data %d \r\n",I2C1_Buffer_Tx[Rx_Counter]);
25             I2C_SendData(I2C1,I2C1_Buffer_Tx[Tx_Counter++]);
26             break;
27         }
28         case I2C_EVENT_MASTER_BYTE_TRANSMITTED: //第一个数据已发送
29         {
30             if(Tx_Counter<BufferSize)
31             {
32                 printf("\r\n The I2C1 has send data %d \r\n",I2C1_Buffer_Tx[Rx_Counter]);
33                 I2C_SendData(I2C1,I2C1_Buffer_Tx[Tx_Counter++]);                
34   
35             }else{
36                 I2C_GenerateSTOP(I2C1,ENABLE);
37                 I2C_ITConfig(I2C1,I2C_IT_EVT|I2C_IT_BUF,DISABLE);  //计数发送的个数
38             }
39   
40             break;
41         }
42         default: {break;}
43     }
44 }
45   
46   
47 void I2C2_EV_IRQHandler(void)
48 {
49     switch(I2C_GetLastEvent(I2C2))
50     {
51         case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED: //收到匹配的地址数据
52         {
53             break;
54         }
55         case I2C_EVENT_SLAVE_BYTE_RECEIVED: //收到数据
56         {   
57             if(Rx_Counter < BufferSize )
58             {
59                 I2C2_Buffer_Rx[Rx_Counter] = I2C_ReceiveData(I2C2);
60                 printf("\r\n The I2C2 has received data %d \r\n",I2C2_Buffer_Rx[Rx_Counter++]); //计数收到的个数               
61             }
62             break;
63         }
64         case I2C_EVENT_SLAVE_STOP_DETECTED: //收到结束条件
65         {
66             I2C_ClearFlag(I2C2,I2C_FLAG_STOPF);
67             I2C_ITConfig(I2C1,I2C_IT_EVT|I2C_IT_BUF,DISABLE);
68   
69             break;
70         }
71         default: {break;}
72     }
73 }

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

在现代电子技术的快速发展中,单片机以其高度的集成性、稳定性和可靠性,在工业自动化、智能家居、医疗设备、航空航天等诸多领域得到了广泛应用。S32单片机,作为其中的佼佼者,其引脚功能丰富多样,是实现与外部设备通信、控制、数据...

关键字: s32单片机引脚 单片机

在微控制器领域,MSP430与STM32无疑是两颗璀璨的明星。它们各自凭借其独特的技术特点和广泛的应用领域,在市场上占据了重要的位置。本文将深入解析MSP430与STM32之间的区别,探讨它们在不同应用场景下的优势和局限...

关键字: MSP430 STM32 单片机

该系列产品有助于嵌入式设计人员在更广泛的系统中轻松实现USB功能

关键字: 单片机 嵌入式设计 USB

单片机编程语言是程序员与微控制器进行交流的桥梁,它们构成了单片机系统的软件开发基石,决定着如何有效、高效地控制和管理单片机的各项资源。随着微控制器技术的不断发展,针对不同应用场景的需求,形成了丰富多样的编程语言体系。本文...

关键字: 单片机 微控制器

单片机,全称为“单片微型计算机”或“微控制器”(Microcontroller Unit,简称MCU),是一种高度集成化的电子器件,它是现代科技领域的关键组件,尤其在自动化控制、物联网、消费电子、汽车电子、工业控制等领域...

关键字: 单片机 MCU

STM32是由意法半导体公司(STMicroelectronics)推出的基于ARM Cortex-M内核的32位微控制器系列,以其高性能、低功耗、丰富的外设接口和强大的生态系统深受广大嵌入式开发者喜爱。本文将详细介绍S...

关键字: STM32 单片机

在当前的科技浪潮中,单片机作为嵌入式系统的重要组成部分,正以其强大的功能和广泛的应用领域受到越来越多行业的青睐。在众多单片机中,W79E2051以其卓越的性能和稳定的工作特性,成为市场上的明星产品。本文将深入探讨W79E...

关键字: 单片机 w79e2051单片机

单片机,又称为微控制器或微处理器,是现代电子设备中的核心部件之一。它集成了中央处理器、存储器、输入输出接口等电路,通过外部信号引脚与外部设备进行通信,实现对设备的控制和管理。本文将详细介绍单片机的外部信号引脚名称及其功能...

关键字: 单片机 微控制器 中央处理器

随着科技的飞速发展,单片机和嵌入式系统在现代电子设备中的应用越来越广泛。它们不仅提高了设备的智能化水平,还推动了各行各业的创新与发展。在单片机和嵌入式系统的开发中,编程语言的选择至关重要。本文将深入探讨单片机和嵌入式系统...

关键字: 单片机 嵌入式系统 电子设备

STM32与51单片机之间有什么差异呢?两者可以说是一场科技与性能的较量了。在科技飞速发展的今天,微控制器(MCU)已广泛应用于各类电子设备和系统中,发挥着举足轻重的作用。其中,STM32和51单片机作为两种常见的微控制...

关键字: STM32 51单片机 MCU
关闭
关闭