當前位置:首頁 > 單片機 > 單片機
[導讀]I2C總線是由NXP(原PHILIPS)公司設計,有十分簡潔的物理層定義,其特性如下:· 只要求兩條總線線路:一條串行數(shù)據(jù)線SDA,一條串行時鐘線SCL;· 每個連接到總線的器件都可以通過唯一的地址和一直存在的簡

I2C總線是由NXP(原PHILIPS)公司設計,有十分簡潔的物理層定義,其特性如下:

·  只要求兩條總線線路:一條串行數(shù)據(jù)線SDA,一條串行時鐘線SCL;

·  每個連接到總線的器件都可以通過唯一的地址和一直存在的簡單的主機/從機關系軟件設定地址,主機可以作為主機發(fā)送器或主機接收器;

·  它是一個真正的多主機總線,如果兩個或更多主機同時初始化,數(shù)據(jù)傳輸可以通過沖突檢測和仲裁防止數(shù)據(jù)被破壞;

·  串行的8 位雙向數(shù)據(jù)傳輸位速率在標準模式下可達100kbit/s,快速模式下可達400kbit/s,高速模式下可達3.4Mbit/s;

·  連接到相同總線的IC 數(shù)量只受到總線的最大電容400pF 限制。

其典型的接口連線如下:

I2C的協(xié)議很簡單:

數(shù)據(jù)的有效性

在傳輸數(shù)據(jù)的時候,SDA線必須在時鐘的高電平周期保持穩(wěn)定,SDA的高或低電平狀態(tài)只有在SCL 線的時鐘信號是低電平時才能改變 。

起始和停止條件

SCL 線是高電平時,SDA 線從高電平向低電平切換,這個情況表示起始條件;

SCL 線是高電平時,SDA 線由低電平向高電平切換,這個情況表示停止條件。

字節(jié)格式

發(fā)送到SDA 線上的每個字節(jié)必須為8 位,每次傳輸可以發(fā)送的字節(jié)數(shù)量不受限制。每個字節(jié)后必須處理一個響應位。

應答響應

數(shù)據(jù)傳輸必須帶響應,相關的響應時鐘脈沖由主機產生。在響應的時鐘脈沖期間發(fā)送器釋放SDA 線(高)。

在響應的時鐘脈沖期間,接收器必須將SDA 線拉低,使它在這個時鐘脈沖的高電平期間保持穩(wěn)定的低電平。

也就是說主器件發(fā)送完一字節(jié)數(shù)據(jù)后要接收一個應答位(低電平),從器件接收完一個字節(jié)后要發(fā)送一個低電平。

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

第一個字節(jié)的頭7 位組成了從機地址,最低位(LSB)是第8 位,它決定了傳輸?shù)?普通的和帶重復開始條件的7位地址格式方向。第一個字節(jié)的最低位是

“0”,表示主機會寫信息到被選中的從機;

“1”表示主機會向從機讀信息。

當發(fā)送了一個地址后,系統(tǒng)中的每個器件都在起始條件后將頭7 位與它自己的地址比較,如果一樣,器件會判定它被主機尋址,至于是從機接收器還是從機發(fā)送器,都由R/W 位決定。

仲裁

I2C是所主機總線,每個設備都可以成為主機,但任一時刻只能有一個主機。

stm32至少有一個I2C接口,提供多主機功能,可以實現(xiàn)所有I2C總線的時序、協(xié)議、仲裁和定時功能,支持標準和快速傳輸兩種模式,同時與SMBus 2.0兼容。

本實驗直接操作寄存器實現(xiàn)對I2C總線結構的EEPROM AT24c02的寫入和讀取。AT24c02相關操作詳見 單片機讀取EEPROM(AT24C02)。

庫函數(shù)實現(xiàn)使用stm32的兩個I2C模擬I2C設備間的數(shù)據(jù)收發(fā),并通過串口查看數(shù)據(jù)交換情況。

直接操作寄存器

首先需要配置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]:快速/標準模式下的時鐘控制分頻系數(shù)(主模式),該分頻系數(shù)用于設置主模式下的SCL時鐘。

在I2C標準模式或SMBus模式下:

Thigh = CCR ×TPCLK1

Tlow = CCR ×TPCLK1

時鐘周期為 T = Thigh + Tlow;

例如:在標準模式下,F(xiàn)REQR = 36 即36Mhz,產生200kHz的SCL的頻率

時鐘控制分頻系數(shù) = Freqr /2/f f 為想得到的頻率

配置好時鐘,還需要配置本機地址,I2C支持7位地址和10位地址,這里用的是7位地址:

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

其他相關操作參見代碼,有詳細注釋:(system.h 和 stm32f10x_it.h 等相關代碼參照 stm32 直接操作寄存器開發(fā)環(huán)境配置)

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);                          //系統(tǒng)時鐘設置
17   
18     Usart1_Init(72,9600);
19   
20     Nvic_Init(1,0,I2C1_EV_IRQChannel,4);      //設置搶占優(yōu)先級為1,響應優(yōu)先級為0,中斷分組為4
21   
22     Nvic_Init(0,0,I2C1_ER_IRQChannel,4);      //設置I2C錯誤中斷搶占優(yōu)先級為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 )          //已發(fā)送起始條件,寫數(shù)據(jù)寄存器的操作將清除該位
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);        //寫入從機地址,讀數(shù)據(jù)操作地址
036                 break;
037            }
038         }
039   
040     }
041   
042     if(I2C1 -> SR1 & 1<<1 )        //從機地址已發(fā)送
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 )        //字節(jié)發(fā)送結束  發(fā)送地址字節(jié)時,不觸發(fā)此中斷
069     {
070           
071         //printf("\r\n I2C1 send byte success .. \r\n");
072         switch(go)
073         {
074             case 0:{ 
075                 I2c_Write(0x86);            //寫入數(shù)據(jù)
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;              //時鐘控制分頻系數(shù)  = 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應答,在接收到一個字節(jié)后返回一個應答
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));      //接收到數(shù)據(jù)標志位
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);

串口接收數(shù)據(jù)如下:

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 ..

庫函數(shù)操作

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     /* 復位系統(tǒng)時鐘設置*/
114     RCC_DeInit();
115     /* 開啟HSE*/
116     RCC_HSEConfig(RCC_HSE_ON);
117     /* 等待HSE起振并穩(wěn)定*/
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延時周期數(shù)為2 */
129         FLASH_SetLatency(FLASH_Latency_2);
130         /* 使能FLASH預取緩存 */
131         FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
132         /* 選擇鎖相環(huán)(PLL)時鐘源為HSE 1分頻,倍頻數(shù)為9,則PLL輸出頻率為 8MHz * 9 = 72MHz */
133         RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
134         /* 使能PLL */ 
135         RCC_PLLCmd(ENABLE);
136         /* 等待PLL輸出穩(wěn)定 */
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: //已發(fā)送啟始條件
18         {
19             I2C_Send7bitAddress(I2C1,I2C2_ADDRESS,I2C_Direction_Transmitter);   
20             break;
21         }
22         case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED: //已發(fā)送從機地址
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: //第一個數(shù)據(jù)已發(fā)送
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);  //計數(shù)發(fā)送的個數(shù)
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: //收到匹配的地址數(shù)據(jù)
52         {
53             break;
54         }
55         case I2C_EVENT_SLAVE_BYTE_RECEIVED: //收到數(shù)據(jù)
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++]); //計數(shù)收到的個數(shù)               
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 }

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或將催生出更大的獨角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產業(yè)博覽會開幕式在貴陽舉行,華為董事、質量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯(lián)合牽頭組建的NVI技術創(chuàng)新聯(lián)盟在BIRTV2024超高清全產業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術創(chuàng)新聯(lián)...

關鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉
關閉