近來主要在寫一些STM32上的開發程式,由於STM32的韌體庫中,I2C模組實在是不好用,所以在採用了軟體類比的方法來實現。
具體的代碼如下(在Keil下調試通過):
#include "stm32f10x_lib.h"//條件編譯 1:使用軟體類比I2C//#define PIN_SCL GPIO_Pin_6//#define PIN_SDA GPIO_Pin_7static __inline void TWI_SCL_0(void){ GPIOB->BRR=PIN_SCL; }static __inline void TWI_SCL_1(void) { GPIOB->BSRR=PIN_SCL;}static __inline void TWI_SDA_0(void) { GPIOB->BRR=PIN_SDA; }static __inline void TWI_SDA_1(void) { GPIOB->BSRR=PIN_SDA;}static __inline u8 TWI_SDA_STATE(void) { return (GPIOB->IDR & PIN_SDA) != 0; }//static __inline void TWI_NOP(void) { TWI_Delay(); }static const u8 TWI_ACK =0;static const u8 TWI_READY =0;static const u8 TWI_NACK =1;static const u8 TWI_BUS_BUSY =2;static const u8 TWI_BUS_ERROR =3;static const u8 TWI_RETRY_COUNT = 3; //重試次數extern void Delay_mS(u32 n);static void TWI_Initialize(void);static u8 TWI_START(void);static u8 TWI_START_SHT(void);static void TWI_STOP(void);static u8 TWI_SendByte(u8 Data);static u8 TWI_ReceiveByte(void);static void TWI_SendACK(void);static void TWI_SendNACK(void);/******************************************************************************* * 函數名稱:TWI_Delay * 描 述:延時函數 * * 輸 入:無 * 輸 出:無 * 返 回:無 * 作 者: * 修改日期:2010年6月8日 *******************************************************************************/static void TWI_NOP(void){ vu32 i, j; vu32 sum = 0; i = 20; while(i--) { for (j = 0; j < 10; j++) sum += i; } sum = i;}/******************************************************************************* * 函數名稱:TWI_Initialize * 描 述:I2C初始化函數 * * 輸 入:無 * 輸 出:無 * 返 回:無 * 作 者: * 修改日期:2010年6月8日 *******************************************************************************/static void TWI_Initialize(void){ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD; GPIO_InitStructure.GPIO_Pin = PIN_SDA; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = PIN_SCL; GPIO_Init(GPIOB, &GPIO_InitStructure); TWI_SDA_1(); TWI_SCL_0(); //////DebugPrint("Software TWI Initializing...\n"); }/******************************************************************************* * 函數名稱:TWI_START * 描 述:發送啟動 * * 輸 入:無 * 輸 出:無 * 返 回:無 * 作 者: * 修改日期:2010年6月8日 *******************************************************************************/static u8 TWI_START(void){ TWI_SDA_1(); TWI_NOP(); TWI_SCL_1(); TWI_NOP(); if(!TWI_SDA_STATE()) { ////DebugPrint("TWI_START:BUSY\n"); return TWI_BUS_BUSY; } TWI_SDA_0(); TWI_NOP(); TWI_SCL_0(); TWI_NOP(); if(TWI_SDA_STATE()) { ////DebugPrint("TWI_START:BUS ERROR\n"); return TWI_BUS_ERROR; } return TWI_READY;}/* --------------------------------------------------------------------------*//** * @Brief: TWI_START_SHT * * @Returns: *//* --------------------------------------------------------------------------*/static u8 TWI_START_SHT(void){ TWI_SDA_1(); TWI_SCL_0(); TWI_NOP(); TWI_SDA_1(); TWI_SCL_1(); TWI_NOP(); if(!TWI_SDA_STATE()) { return TWI_BUS_BUSY; } TWI_SDA_0(); TWI_NOP(); TWI_SCL_0(); TWI_NOP(); TWI_SCL_1(); TWI_NOP(); TWI_SDA_1(); TWI_NOP(); TWI_SCL_0(); TWI_NOP(); return TWI_READY;}/* --------------------------------------------------------------------------*//** * @Brief: TWI_STOP *//* --------------------------------------------------------------------------*/static void TWI_STOP(void){ TWI_SDA_0(); TWI_NOP(); TWI_SCL_1(); TWI_NOP(); TWI_SDA_1(); TWI_NOP(); //////DebugPrint("TWI_STOP\n"); }/* --------------------------------------------------------------------------*//** * @Brief: TWI_SendACK *//* --------------------------------------------------------------------------*/static void TWI_SendACK(void){ TWI_SDA_0(); TWI_NOP(); TWI_SCL_1(); TWI_NOP(); TWI_SCL_0(); TWI_NOP(); TWI_SDA_1(); //////DebugPrint("TWI_SendACK\n"); }/* --------------------------------------------------------------------------*//** * @Brief: TWI_SendNACK *//* --------------------------------------------------------------------------*/static void TWI_SendNACK(void){ TWI_SDA_1(); TWI_NOP(); TWI_SCL_1(); TWI_NOP(); TWI_SCL_0(); TWI_NOP(); //////DebugPrint("TWI_SendNACK\n"); }/* --------------------------------------------------------------------------*//** * @Brief: TWI_SendByte * * @Param: Data * * @Returns: *//* --------------------------------------------------------------------------*/static u8 TWI_SendByte(u8 Data){ u8 i; TWI_SCL_0(); for(i=0;i<8;i++) { //---------資料建立---------- if(Data&0x80) { TWI_SDA_1(); } else { TWI_SDA_0(); } Data<<=1; TWI_NOP(); //---資料建立保持一定延時---- //----產生一個上升沿[正脈衝] TWI_SCL_1(); TWI_NOP(); TWI_SCL_0(); TWI_NOP();//延時,防止SCL還沒變成低時改變SDA,從而產生START/STOP訊號 //--------------------------- } //接收從機的應答 TWI_SDA_1(); TWI_NOP(); TWI_SCL_1(); TWI_NOP(); if(TWI_SDA_STATE()) { TWI_SCL_0(); TWI_SDA_1(); //////DebugPrint("TWI_NACK!\n"); return TWI_NACK; } else { TWI_SCL_0(); TWI_SDA_1(); //////DebugPrint("TWI_ACK!\n"); return TWI_ACK; } }/* --------------------------------------------------------------------------*//** * @Brief: TWI_ReceiveByte * * @Returns: *//* --------------------------------------------------------------------------*/static u8 TWI_ReceiveByte(void){ u8 i,Dat; TWI_SDA_1(); TWI_SCL_0(); Dat=0; for(i=0;i<8;i++) { TWI_SCL_1();//產生時鐘上升沿[正脈衝],讓從機準備好資料 TWI_NOP(); Dat<<=1; if(TWI_SDA_STATE()) //讀引腳狀態 { Dat|=0x01; } TWI_SCL_0();//準備好再次接收資料 TWI_NOP();//等待資料準備好 } //////DebugPrint("TWI_Dat:%x\n",Dat); return Dat;}