1. 程式人生 > >STM32自帶的IIC配置

STM32自帶的IIC配置

以下是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