微控制器GPIO軟體模擬I2C通訊程式
阿新 • • 發佈:2018-11-19
文章原始地址:http://feotech.com/?p=98
本程式主要用於使用可程式設計晶片自身的IO管腳,模擬I2C通訊的協議,實現I2C匯流排資料的傳輸.
/** ****************************************************************************** * @file Virtual_I2C.C * @author Ryan Zhao * @version V1.0.0 * @date 2017-04-20 * @brief 軟體I/O模擬I2C匯流排通訊. ****************************************************************************** * @attention Null * ****************************************************************************** */ /** * @brief I2C引腳初始化. * @param None. * @retval None. */ void I2C_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );//使能GPIOB時鐘 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推輓輸出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7); //PB6,PB7 輸出高 } /** * @brief 產生I2C開始訊號. * @param None. * @retval None. */ void I2C_Start(void) { SDA_OUT(); //SDA引腳設定為輸出模式 I2C_SDA_H; //SDA引腳設定為高電平 I2C_SCL_H; //SCL引腳設定為高電平 Delay(); //軟體延時 I2C_SDA_L; Delay(); //軟體延時 I2C_SCL_L; //準備傳送或接收資料 } /** * @brief 產生I2C停止訊號. * @param None. * @retval None. */ void I2C_Stop(void) { SDA_OUT();//SDA引腳設定為輸出模式 I2C_SCL_l; I2C_SDA_l; Delay(); //軟體延時 I2C_SCL_H; I2C_SDA_H; Delay(); } /** * @brief 等待ACK訊號. * @param None. * @retval 1:接收應答成功; 0:接收應答失敗; */ unsigned char I2C_Wait_Ack(void) { unsigned char ucErrTime=0; SDA_IN(); //SDA引腳設定為輸入模式 I2C_SDA_H; Delay(); I2C_SCL_H; Delay(); while(READ_SDA)//讀取SDA引腳電平狀態 { ucErrTime++; if(ucErrTime>250) { I2C_Stop(); return 0; //接收應答失敗 } } I2C_SCL_L; return 1; //接收應答成功 } /** * @brief 產生ACK訊號. * @param None. * @retval None. */ void I2C_Ack(void) { I2C_SCL_L; SDA_OUT(); //SDA引腳設定為輸出模式 I2C_SDA_L; Delay(); I2C_SCL_H; Delay(); I2C_SCL_L; } /** * @brief 不產生ACK訊號. * @param None. * @retval None. */ void I2C_NAck(void) { I2C_SCL_L; SDA_OUT(); I2C_SDA_H; Delay(); I2C_SCL_H; Delay(); I2C_SCL_L; } /** * @brief I2C傳送一個位元組. * @param None. * @retval None. */ void I2C_Send_Byte(unsigned char txd) { unsigned char i; SDA_OUT(); I2C_SCL_L; for(i=0;i<8;i++) { if((txd&0x80)>>7) { I2C_SDA_H; } else { I2C_SDA_L; } txd = txd<<1; Delay(); I2C_SCL_H; Delay(); I2C_SCL_L; Delay(); } } /** * @brief I2C讀取一個位元組. * @param None. * @retval 讀取到的資料 */ unsigned char I2C_Read_Byte(unsigned char ack) { unsigned char i,receive=0; SDA_IN();//SDA設定為輸入 for(i=0;i<8;i++ ) { I2C_SCL=0; Delay(); I2C_SCL=1; receive<<=1; if(READ_SDA) { receive++; } Delay(); } if (!ack) { I2C_NAck();//傳送nACK } else { I2C_Ack(); //傳送ACK } return receive; }