高手經(jīng)驗(yàn)!STM32單片機(jī)學(xué)習(xí)I2C通信
I2C總線是由NXP(原PHILIPS)公司設(shè)計(jì),有十分簡(jiǎn)潔的物理層定義,其特性如下:
· 只要求兩條總線線路:一條串行數(shù)據(jù)線SDA,一條串行時(shí)鐘線SCL;
· 每個(gè)連接到總線的器件都可以通過唯一的地址和一直存在的簡(jiǎn)單的主機(jī)/從機(jī)關(guān)系軟件設(shè)定地址,主機(jī)可以作為主機(jī)發(fā)送器或主機(jī)接收器;
· 它是一個(gè)真正的多主機(jī)總線,如果兩個(gè)或更多主機(jī)同時(shí)初始化,數(shù)據(jù)傳輸可以通過沖突檢測(cè)和仲裁防止數(shù)據(jù)被破壞;
· 串行的8 位雙向數(shù)據(jù)傳輸位速率在標(biāo)準(zhǔn)模式下可達(dá)100kbit/s,快速模式下可達(dá)400kbit/s,高速模式下可達(dá)3.4Mbit/s;
· 連接到相同總線的IC 數(shù)量只受到總線的最大電容400pF 限制。
其典型的接口連線如下:
I2C的協(xié)議很簡(jiǎn)單:
數(shù)據(jù)的有效性
在傳輸數(shù)據(jù)的時(shí)候,SDA線必須在時(shí)鐘的高電平周期保持穩(wěn)定,SDA的高或低電平狀態(tài)只有在SCL 線的時(shí)鐘信號(hào)是低電平時(shí)才能改變 。
起始和停止條件
SCL 線是高電平時(shí),SDA 線從高電平向低電平切換,這個(gè)情況表示起始條件;
SCL 線是高電平時(shí),SDA 線由低電平向高電平切換,這個(gè)情況表示停止條件。
字節(jié)格式
發(fā)送到SDA 線上的每個(gè)字節(jié)必須為8 位,每次傳輸可以發(fā)送的字節(jié)數(shù)量不受限制。每個(gè)字節(jié)后必須處理一個(gè)響應(yīng)位。
應(yīng)答響應(yīng)
數(shù)據(jù)傳輸必須帶響應(yīng),相關(guān)的響應(yīng)時(shí)鐘脈沖由主機(jī)產(chǎn)生。在響應(yīng)的時(shí)鐘脈沖期間發(fā)送器釋放SDA 線(高)。
在響應(yīng)的時(shí)鐘脈沖期間,接收器必須將SDA 線拉低,使它在這個(gè)時(shí)鐘脈沖的高電平期間保持穩(wěn)定的低電平。
也就是說主器件發(fā)送完一字節(jié)數(shù)據(jù)后要接收一個(gè)應(yīng)答位(低電平),從器件接收完一個(gè)字節(jié)后要發(fā)送一個(gè)低電平。
尋址方式(7位地址方式)
第一個(gè)字節(jié)的頭7 位組成了從機(jī)地址,最低位(LSB)是第8 位,它決定了傳輸?shù)?普通的和帶重復(fù)開始條件的7位地址格式方向。第一個(gè)字節(jié)的最低位是
“0”,表示主機(jī)會(huì)寫信息到被選中的從機(jī);
“1”表示主機(jī)會(huì)向從機(jī)讀信息。
當(dāng)發(fā)送了一個(gè)地址后,系統(tǒng)中的每個(gè)器件都在起始條件后將頭7 位與它自己的地址比較,如果一樣,器件會(huì)判定它被主機(jī)尋址,至于是從機(jī)接收器還是從機(jī)發(fā)送器,都由R/W 位決定。
仲裁
I2C是所主機(jī)總線,每個(gè)設(shè)備都可以成為主機(jī),但任一時(shí)刻只能有一個(gè)主機(jī)。
STM32至少有一個(gè)I2C接口,提供多主機(jī)功能,可以實(shí)現(xiàn)所有I2C總線的時(shí)序、協(xié)議、仲裁和定時(shí)功能,支持標(biāo)準(zhǔn)和快速傳輸兩種模式,同時(shí)與SMBus 2.0兼容。
本實(shí)驗(yàn)直接操作寄存器實(shí)現(xiàn)對(duì)I2C總線結(jié)構(gòu)的EEPROM AT24c02的寫入和讀取。AT24c02相關(guān)操作詳見 單片機(jī)讀取EEPROM(AT24C02)。
庫(kù)函數(shù)實(shí)現(xiàn)使用STM32的兩個(gè)I2C模擬I2C設(shè)備間的數(shù)據(jù)收發(fā),并通過串口查看數(shù)據(jù)交換情況。
直接操作寄存器
首先需要配置I2C接口的時(shí)鐘,相關(guān)寄存器如下:
I2C_CR2寄存器低五位:
FREQ[5:0]:I2C模塊時(shí)鐘頻率 ,必須設(shè)置正確的輸入時(shí)鐘頻率以產(chǎn)生正確的時(shí)序,允許的范圍在2~36MHz之間:
000000:禁用 000001:禁用 000010:2MHz ... 100100:36MHz 大于100100:禁用。
用于設(shè)置I2C設(shè)備的輸入時(shí)鐘,本例使用的是PLCK1總線上的時(shí)鐘所以為36Mhz;
時(shí)鐘控制寄存器(I2C_CCR)低12位:
CCR[11:0]:快速/標(biāo)準(zhǔn)模式下的時(shí)鐘控制分頻系數(shù)(主模式),該分頻系數(shù)用于設(shè)置主模式下的SCL時(shí)鐘。
在I2C標(biāo)準(zhǔn)模式或SMBus模式下:
Thigh = CCR ×TPCLK1
Tlow = CCR ×TPCLK1
時(shí)鐘周期為 T = Thigh + Tlow;
例如:在標(biāo)準(zhǔn)模式下,F(xiàn)REQR = 36 即36Mhz,產(chǎn)生200kHz的SCL的頻率
時(shí)鐘控制分頻系數(shù) = Freqr /2/f f 為想得到的頻率
配置好時(shí)鐘,還需要配置本機(jī)地址,I2C支持7位地址和10位地址,這里用的是7位地址:
自身地址寄存器1(I2C_OAR1)[7:1]:接口地址,地址的7~1位。
其他相關(guān)操作參見代碼,有詳細(xì)注釋:(system.h 和 stm32f10x_it.h 等相關(guān)代碼參照 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)時(shí)鐘設(shè)置 |
17 | |
18 | Usart1_Init(72,9600); |
19 | |
20 | Nvic_Init(1,0,I2C1_EV_IRQChannel,4); //設(shè)置搶占優(yōu)先級(jí)為1,響應(yīng)優(yōu)先級(jí)為0,中斷分組為4 |
21 | |
22 | Nvic_Init(0,0,I2C1_ER_IRQChannel,4); //設(shè)置I2C錯(cuò)誤中斷搶占優(yōu)先級(jí)為0 |
23 | |
24 | Gpio_Init(); |
25 | |
26 | I2c_Init(0x30); //設(shè)置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時(shí)鐘 |
37 | RCC->APB2ENR |= 1<<3; //使能PORTB時(shí)鐘; |
38 | |
39 | |
40 | GPIOA->CRL &= 0x0000FFFF; // PA0~3設(shè)置為浮空輸入,PA4~7設(shè)置為推挽輸出 |
41 | GPIOA->CRL |= 0x33334444; |
42 | |
43 | |
44 | GPIOB->CRL &= 0x00FFFFFF; //PB6 I2C1_SCL ,PB7 I2C1_SDL |
45 | GPIOB->CRL |= 0xFF000000; //復(fù)用開漏輸出 |
46 | |
47 | //USART1 串口I/O設(shè)置 |
48 | |
49 | GPIOA -> CRH &= 0xFFFFF00F; //設(shè)置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; //操作步驟標(biāo)記 |
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); //寫入從機(jī)地址,寫指令操作地址 |
028 | break ; |
029 | } |
030 | case 1:{ |
031 | I2c_Write(ADDRS_W); //寫入從機(jī)地址,寫指令操作地址 |
032 | break ; |
033 | } |
034 | case 2:{ |
035 | I2c_Write(ADDRS_R); //寫入從機(jī)地址,讀數(shù)據(jù)操作地址 |
036 | break ; |
037 | } |
038 | } |
039 | |
040 | } |
041 | |
042 | if (I2C1 -> SR1 & 1<<1 ) //從機(jī)地址已發(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ā)送結(jié)束 發(fā)送地址字節(jié)時(shí),不觸發(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); //事件中斷關(guān)閉 |
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) //應(yīng)答失敗 |
112 | { |
113 | printf ( "\r\n ACK ERROR .. \r\n" ); |
114 | |
115 | I2C1->SR1 &=~(1<<10); //清除中斷 |
116 | } |
117 | |
118 | if (I2C1->SR1 & 1<<14) //超時(shí) |
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) //總線出錯(cuò) |
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時(shí)鐘 |
07 | //RCC -> APB1ENR |= 1<<22; //打開I2C2時(shí)鐘 |
08 | |
09 | RCC->APB1RSTR |= 1<<21; //復(fù)位I2C1 |
10 | RCC->APB1RSTR &= ~(1<<21); //復(fù)位結(jié)束I2C1 |
11 | //RCC->APB1RSTR |= 1<<22; //復(fù)位I2C2 |
12 | |
13 | //I2C1 -> CR1 |= 1<<15; //復(fù)位寄存器 |
14 | |
15 | //I2C模塊時(shí)鐘頻率,2~36MHz之間 |
16 | I2C1 -> CR2 |= 36 ; //000000:禁用 000001:禁用 000010:2MHz ... 100100:36MHz |
17 | |
18 | |
19 | I2C1 -> CCR |= 0<<15; //I2C主模式 0:標(biāo)準(zhǔn)模式的I2C 1:快速模式的I2C |
20 | //I2C1 -> CCR |= 1<<14; //快速模式時(shí)的占空比 0 Tlow/Thigh = 2 1 Tlow/Thigh = 16/9 |
21 | |
22 | //得到200kHz頻率 |
23 | I2C1 -> CCR |= 90<<0; //時(shí)鐘控制分頻系數(shù) = PCLK1 /2/f f 為想得到的頻率 |
24 | |
25 | //主模式最大上升時(shí)間 |
26 | I2C1 -> TRISE |= 37; //最大允許SCL上升時(shí)間為1000ns,故TRISE[5:0]中必須寫入(1us/(1/36)us = 36+1)。 |
27 | |
28 | I2C1 -> CR1 |= 1<<10; //打開ACK應(yīng)答,在接收到一個(gè)字節(jié)后返回一個(gè)應(yīng)答 |
29 | I2C1 -> CR1 |= 1<<6; //廣播呼叫使能 |
30 | |
31 | I2C1 -> OAR1 |= 0<<15; //尋址模式 1 響應(yīng)10位地址 0 響應(yīng)7位地址 |
32 | |
33 | I2C1 -> OAR1 |= 1<<14; //必須始終由軟件保持為 1 |
34 | |
35 | I2C1 -> OAR1 |= Addr <<1 ; //設(shè)置接口地址的 7~1位 |
36 | |
37 | //I2C1 -> OAR1 |= 0 ; //設(shè)置10位地址模式時(shí)地址第0位 |
38 | //I2C1 -> OAR1 |= 0<<8; //設(shè)置10位地址模式時(shí)地址第9~8位 |
39 | |
40 | //I2C1 -> CR2 |= 1<<10; //緩沖器中斷使能 |
41 | I2C1 -> CR2 |= 1<<9; //事件中斷使能 |
42 | I2C1 -> CR2 |= 1<<8; //出錯(cuò)中斷使能 |
43 | |
44 | I2C1 -> CR1 |= 1<<0; //開啟I2C1 |
45 | } |
46 | |
47 | |
48 | void I2c_Start() |
49 | { |
50 | |
51 | I2C1 -> CR1 |= 1<<8; //I2C1產(chǎn)生起始條件 |
52 | } |
53 | |
54 | void I2c_Stop() |
55 | { |
56 | I2C1 -> CR1 |= 1<<9; //I2C1產(chǎn)生停止條件 |
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ù)標(biāo)志位 |
68 | |
69 | return I2C1 -> DR; |
70 | } |
71 | |
72 | void I2c_End() //關(guān)閉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 ..
庫(kù)函數(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 | /* 復(fù)位系統(tǒng)時(shí)鐘設(shè)置*/ |
114 | RCC_DeInit(); |
115 | /* 開啟HSE*/ |
116 | RCC_HSEConfig(RCC_HSE_ON); |
117 | /* 等待HSE起振并穩(wěn)定*/ |
118 | HSEStartUpStatus = RCC_WaitForHSEStartUp(); |
119 | /* 判斷HSE起是否振成功,是則進(jìn)入if()內(nèi)部 */ |
120 | if (HSEStartUpStatus == SUCCESS) |
121 | { |
122 | /* 選擇HCLK(AHB)時(shí)鐘源為SYSCLK 1分頻 */ |
123 | RCC_HCLKConfig(RCC_SYSCLK_Div1); |
124 | /* 選擇PCLK2時(shí)鐘源為 HCLK(AHB) 1分頻 */ |
125 | RCC_PCLK2Config(RCC_HCLK_Div1); |
126 | /* 選擇PCLK1時(shí)鐘源為 HCLK(AHB) 2分頻 */ |
127 | RCC_PCLK1Config(RCC_HCLK_Div2); |
128 | /* 設(shè)置FLASH延時(shí)周期數(shù)為2 */ |
129 | FLASH_SetLatency(FLASH_Latency_2); |
130 | /* 使能FLASH預(yù)取緩存 */ |
131 | FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); |
132 | /* 選擇鎖相環(huán)(PLL)時(shí)鐘源為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時(shí)鐘源為PLL */ |
139 | RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); |
140 | /* 等待PLL成為SYSCLK時(shí)鐘源 */ |
141 | while (RCC_GetSYSCLKSource() != 0x08); |
142 | } |
143 | /* 打開APB2總線上的GPIOA時(shí)鐘*/ |
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ā)送從機(jī)地址 |
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: //第一個(gè)數(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); //計(jì)數(shù)發(fā)送的個(gè)數(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++]); //計(jì)數(shù)收到的個(gè)數(shù) |
61 | } |
62 | break ; |
63 | } |
64 | case I2C_EVENT_SLAVE_STOP_DETECTED: //收到結(jié)束條件 |
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 | } |
編輯:admin 最后修改時(shí)間:2018-05-18