STM32自帶的IIC配置
阿新 • • 發佈:2019-02-02
以下是main.c中的內容:
//********************************************************** // 使用STM32F103自帶的IIC,利用IIC2實現STM32與EEPROM晶片 // AT24C02間的資料傳輸。傳輸成功在LCD上顯示。 // 試驗平臺為正點原子的ALIENTEK戰艦開發板 //********************************************************** #include "sys.h" #include "delay.h" #include "usart.h" #include "lcd.h" #include "iic.h" int main(void) { u8 data = 0; //測試的資料變數 delay_init(); //延時函式初始化 uart_init(9600); //通用非同步首發傳輸器初始化 LCD_Init(); //TFTLCD液晶初始化 I2C2_Init(); //STM32硬體自帶IIC2初始化 NVIC_Configuration(); //設定NVIC中斷分組2:2位搶佔優先順序,2位響應優先順序 I2C2_WriteByte( AT24C02_ADDRESS, 1, 0x89 ); //往EEPROM的第1個地址裡寫入0X89 data = I2C2_ReadByte( AT24C02_ADDRESS, 1 ); //讀取EEPROM第1個地址裡的資料,賦給data if (data==0x89) //如果data = 0X89,證明EEPROM寫、讀成功,STM32的IIC2寫、讀成功 { POINT_COLOR = RED; //設定字型為紅色 LCD_ShowString(35,50,200,16,16,"STM32 IIC2 READ/WRITE"); LCD_ShowString(70,70,200,16,16,"SUCCESSFULLY"); } while (1); }
以下是iic.c中的內容:
#include "iic.h" //***************************************************** // IIC2初始化函式:初始化STM32硬體自帶的IIC2 // IIC2_SCL對應GPIO.B10 // IIC2_SDA對應GPIO.B11 //***************************************************** void I2C2_Init(void) { /*GPIO與IIC初始化結構體*/ GPIO_InitTypeDef GPIO_InitStructure; I2C_InitTypeDef I2C_InitStructure; /*GPIO與IIC時鐘使能*/ RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); //GPIOB時鐘使能 RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C2, ENABLE ); //IIC2時鐘使能 /*初始化GPIO*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; //初始化GPIO.B10(IIC2_SCL),GPIO.B11(IIC2_SDA) GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //最高輸出速度50Hz GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //輸入輸出模式為複用功能開漏輸出 GPIO_Init( GPIOB, &GPIO_InitStructure ); //根據GPIO初始化結構體初始化GPIOB /*初始化IIC2*/ I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; //設定為IIC模式 I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //設定IIC的佔空比,低電平除以高電平值為2 I2C_InitStructure.I2C_OwnAddress1 = AT24C02_ADDRESS; //指定第一個裝置的地址為7位地址 I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //使能ACK訊號 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //指定7位地址 I2C_InitStructure.I2C_ClockSpeed = 400000; //時鐘頻率,必須小於等於400KHz I2C_Cmd( I2C2, ENABLE ); //使能IIC2 I2C_Init( I2C2, &I2C_InitStructure ); //根據IIC初始化結構體初始化IIC2 /*允許一位元組一應答模式*/ I2C_AcknowledgeConfig( I2C2, ENABLE ); //使能IIC2應答狀態 } //***************************************************** // IIC2寫函式 :往IIC裝置寫入一個BYTE的data // id :IIC裝置的id // write_address:資料要寫入IIC裝置的地址 // data :需要寫入的資料 //***************************************************** void I2C2_WriteByte( u8 id, u8 write_address, u8 data ) { while (I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY)); //當IIC2狀態為BUSY時,一直停在這裡死迴圈 /*傳送START之後要等待,意味著START條件被正確釋放,此時IIC總線上沒有其它外設*/ I2C_GenerateSTART( I2C2, ENABLE ); //一旦不為BUSY,跳出迴圈,產生START條件 while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT)); //如果主機被選中(死迴圈等待ACK訊號) /*主機發送地址聯絡從機後,主機要等待從機的ACK,如果主機設定為發射,*/ /*則收到ACK訊號時 I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED 被置1 */ I2C_Send7bitAddress( I2C2, id, I2C_Direction_Transmitter ); //傳送從機地址以選擇從機,主機為傳送模式 while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //如果主機發射模式被選中(死迴圈等待ACK訊號) /*通訊建立(生成START過程與從機地址被承認)以後,主機發送資料,*/ /*如果資料被轉移並輸出IIC匯流排,則 I2C_EVENT_MASTER_BYTE_TRANSMITTED 被置1*/ I2C_SendData( I2C2, write_address ); //將write_address,即要寫的地址通過IIC2傳送出去 while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //如果地址已經從IIC2成功發射出去(死迴圈等待ACK訊號) /*往暫存器傳送資料data*/ I2C_SendData( I2C2, data ); while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); I2C_GenerateSTOP( I2C2, ENABLE ); //IIC2產生STOP條件 /*迴圈確保IIC裝置與主機的通訊建立*/ do { I2C_GenerateSTART( I2C2, ENABLE ); //IIC2產生START條件 I2C_Send7bitAddress( I2C2, AT24C02_ADDRESS, I2C_Direction_Transmitter );//傳送EEPROM地址0XA0 } while (!(I2C_ReadRegister(I2C2,I2C_Register_SR1)&0x0002)); //讀取IIC2->SR1的值,當IIC2->SR1[1] = 1時跳出迴圈 //此時地址傳送結束 I2C_ClearFlag( I2C2, I2C_FLAG_AF ); //IIC2清除應答錯誤標誌位 I2C_GenerateSTOP( I2C2, ENABLE ); //IIC2產生STOP條件 } //***************************************************** // IIC2讀函式 :從IIC裝置的指定地址中讀出一個BYTE的資料 // id :IIC裝置的id // read_address :需要讀取IIC資料的裝置的地址 // 返回值 :讀出的資料 //***************************************************** u8 I2C2_ReadByte( u8 id, u8 read_address ) { u8 data; /***主機發送地址***/ while (I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY)); //當IIC2狀態為BUSY時,一直停在這裡死迴圈 /*傳送START之後要等待,意味著START條件被正確釋放,此時IIC總線上沒有其它外設*/ I2C_GenerateSTART( I2C2, ENABLE ); //一旦不為BUSY,跳出迴圈,產生START條件 while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT)); //如果主機被選中(死迴圈等待ACK訊號) /*主機發送地址聯絡從機後,主機要等待從機的ACK,如果主機設定為發射,*/ /*則收到ACK訊號時 I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED 被置1 */ I2C_Send7bitAddress( I2C2, id, I2C_Direction_Transmitter ); //傳送從機地址以選擇從機,主機為傳送模式 while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //如果主機發射模式被選中(死迴圈等待ACK訊號) /*通訊建立(生成START過程與從機地址被承認)以後,主機發送資料,*/ /*如果資料被轉移並輸出IIC匯流排,則 I2C_EVENT_MASTER_BYTE_TRANSMITTED 被置1*/ I2C_Cmd( I2C2, ENABLE ); //使能IIC2 I2C_SendData( I2C2, read_address ); //將write_address,即要讀的地址通過IIC2傳送出去 while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //如果地址已經從IIC2成功發射出去(死迴圈等待ACK訊號? I2C_GenerateSTART( I2C2, ENABLE ); //產生START條件 while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT)); //如果主機被選中(死迴圈等待ACK訊號) /***主機接收資料***/ I2C_Send7bitAddress( I2C2, id, I2C_Direction_Receiver ); //主機設定為接收模式 while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); //如果主機接收模式被選中(死迴圈等待ACK訊號) I2C_AcknowledgeConfig( I2C2, DISABLE ); //失能IIC2的應答狀態 I2C_GenerateSTOP( I2C2, ENABLE ); //產生STOP條件 while (!(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED))); //如果主機接收資料成功(死迴圈等待ACK訊號) data = I2C_ReceiveData(I2C2); //返回IIC2接收的資料,賦給temp I2C_AcknowledgeConfig( I2C2, ENABLE ); //再一次使能IIC2的應答狀態 return data; //返回接收到的資料 }
以下是iic.h中的內容:
#ifndef _IIC_H
#define _IIC_H
#include "sys.h"
/*EEPROM晶片AT24C02的晶片地址*/
#define AT24C02_ADDRESS 0XA0
void I2C2_Init(void);
void I2C2_WriteByte( u8 id, u8 write_address, u8 data );
u8 I2C2_ReadByte( u8 id, u8 read_address );
#endif
以上iic部分程式碼參考了:http://www.amobbs.com/thread-5492914-1-1.html