高手經(jīng)驗!STM32單片機學(xué)習(xí)I2C通信
I2C總線是由NXP(原PHILIPS)公司設(shè)計,有十分簡潔的物理層定義,其特性如下:
· 只要求兩條總線線路:一條串行數(shù)據(jù)線SDA,一條串行時鐘線SCL;
· 每個連接到總線的器件都可以通過唯一的地址和一直存在的簡單的主機/從機關(guān)系軟件設(shè)定地址,主機可以作為主機發(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é)后必須處理一個響應(yīng)位。
應(yīng)答響應(yīng)
數(shù)據(jù)傳輸必須帶響應(yīng),相關(guān)的響應(yīng)時鐘脈沖由主機產(chǎn)生。在響應(yīng)的時鐘脈沖期間發(fā)送器釋放SDA 線(高)。
在響應(yīng)的時鐘脈沖期間,接收器必須將SDA 線拉低,使它在這個時鐘脈沖的高電平期間保持穩(wěn)定的低電平。
也就是說主器件發(fā)送完一字節(jié)數(shù)據(jù)后要接收一個應(yīng)答位(低電平),從器件接收完一個字節(jié)后要發(fā)送一個低電平。
尋址方式(7位地址方式)
第一個字節(jié)的頭7 位組成了從機地址,最低位(LSB)是第8 位,它決定了傳輸?shù)?普通的和帶重復(fù)開始條件的7位地址格式方向。第一個字節(jié)的最低位是
“0”,表示主機會寫信息到被選中的從機;
“1”表示主機會向從機讀信息。
當(dāng)發(fā)送了一個地址后,系統(tǒng)中的每個器件都在起始條件后將頭7 位與它自己的地址比較,如果一樣,器件會判定它被主機尋址,至于是從機接收器還是從機發(fā)送器,都由R/W 位決定。
仲裁
I2C是所主機總線,每個設(shè)備都可以成為主機,但任一時刻只能有一個主機。
stm32至少有一個I2C接口,提供多主機功能,可以實現(xiàn)所有I2C總線的時序、協(xié)議、仲裁和定時功能,支持標準和快速傳輸兩種模式,同時與SMBus 2.0兼容。
本實驗直接操作寄存器實現(xiàn)對I2C總線結(jié)構(gòu)的EEPROM AT24c02的寫入和讀取。AT24c02相關(guān)操作詳見 單片機讀取EEPROM(AT24C02)。
庫函數(shù)實現(xiàn)使用stm32的兩個I2C模擬I2C設(shè)備間的數(shù)據(jù)收發(fā),并通過串口查看數(shù)據(jù)交換情況。
直接操作寄存器
首先需要配置I2C接口的時鐘,相關(guān)寄存器如下:
I2C_CR2寄存器低五位:
FREQ[5:0]:I2C模塊時鐘頻率 ,必須設(shè)置正確的輸入時鐘頻率以產(chǎn)生正確的時序,允許的范圍在2~36MHz之間:
000000:禁用 000001:禁用 000010:2MHz ... 100100:36MHz 大于100100:禁用。
用于設(shè)置I2C設(shè)備的輸入時鐘,本例使用的是PLCK1總線上的時鐘所以為36Mhz;
時鐘控制寄存器(I2C_CCR)低12位:
CCR[11:0]:快速/標準模式下的時鐘控制分頻系數(shù)(主模式),該分頻系數(shù)用于設(shè)置主模式下的SCL時鐘。
在I2C標準模式或SMBus模式下:
Thigh = CCR ×TPCLK1
Tlow = CCR ×TPCLK1
時鐘周期為 T = Thigh + Tlow;
例如:在標準模式下,F(xiàn)REQR = 36 即36Mhz,產(chǎn)生200kHz的SCL的頻率
時鐘控制分頻系數(shù) = Freqr /2/f f 為想得到的頻率
配置好時鐘,還需要配置本機地址,I2C支持7位地址和10位地址,這里用的是7位地址:
自身地址寄存器1(I2C_OAR1)[7:1]:接口地址,地址的7~1位。
其他相關(guān)操作參見代碼,有詳細注釋:(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è)置 |
17 |
|
18 |
Usart1_Init(72,9600); |
19 |
|
20 |
Nvic_Init(1,0,I2C1_EV_IRQChannel,4); //設(shè)置搶占優(yōu)先級為1,響應(yīng)優(yōu)先級為0,中斷分組為4 |
21 |
|
22 |
Nvic_Init(0,0,I2C1_ER_IRQChannel,4); //設(shè)置I2C錯誤中斷搶占優(yōu)先級為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時鐘 |
37 |
RCC->APB2ENR |= 1<<3; //使能PORTB時鐘; |
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; //操作步驟標記 |
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ā)送結(jié)束 發(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); //事件中斷關(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) //超時 |
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; //復(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模塊時鐘頻率,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應(yīng)答,在接收到一個字節(jié)后返回一個應(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位地址模式時地址第0位 |
38 |
//I2C1 -> OAR1 |= 0<<8; //設(shè)置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產(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ù)標志位 |
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 ..
庫函數(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è)置*/ |
114 |
RCC_DeInit(); |
115 |
/* 開啟HSE*/ |
116 |
RCC_HSEConfig(RCC_HSE_ON); |
117 |
/* 等待HSE起振并穩(wěn)定*/ |
118 |
HSEStartUpStatus = RCC_WaitForHSEStartUp(); |
119 |
/* 判斷HSE起是否振成功,是則進入if()內(nèi)部 */ |
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 |
/* 設(shè)置FLASH延時周期數(shù)為2 */ |
129 |
FLASH_SetLatency(FLASH_Latency_2); |
130 |
/* 使能FLASH預(yù)取緩存 */ |
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: //收到結(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 |
} |