1. 程式人生 > >STM32軟體IIC的實現

STM32軟體IIC的實現

接上篇,LIS331的例程終於可以正常運行了,接下來就是將其移植到STM32上了,不過第一次接觸STM32的IIC,看例程比較簡單,直接複製到工程後卻讀不出資料,一直停在等待從裝置回覆ACK的死迴圈。

經過一天的修改之後,終於還是捨去了硬體IIC改成了用軟體實現,最終程式碼如下:

.h檔案

#include "stm32f10x.h"
#define ANO_GPIO_I2C    GPIOB
#define I2C_Pin_SCL     GPIO_Pin_3
#define I2C_Pin_SDA     GPIO_Pin_4
#define ANO_RCC_I2C     RCC_APB2Periph_GPIOB
/*********************************************/

#define SCL_H         ANO_GPIO_I2C->BSRR = I2C_Pin_SCL
#define SCL_L         ANO_GPIO_I2C->BRR  = I2C_Pin_SCL
#define SDA_H         ANO_GPIO_I2C->BSRR = I2C_Pin_SDA
#define SDA_L         ANO_GPIO_I2C->BRR  = I2C_Pin_SDA
#define SCL_read      ANO_GPIO_I2C->IDR  & I2C_Pin_SCL
#define SDA_read      ANO_GPIO_I2C->IDR  & I2C_Pin_SDA

#define EEPROM_DEV_ADDR           0x3a           //??(????)
#define EEPROM_WR                 0x00                     //?
#define EEPROM_RD                 0x01                     //?
#define EEPROM_WORD_ADDR_SIZE      8
extern u8 databuff[3];
extern u8 x,y,z;
int I2C_Start(void);
void I2C_Stop(void);
void I2C_Ack(void);
void I2C_NoAck(void);
void I2C_SDA_OUT(void);
void I2C_SDA_IN(void);
uint8_t I2C_GetAck(void);
void I2C_SendByte(uint8_t Data);
uint8_t I2C_ReadByte(uint8_t ack);
void I2C_delay(void);
int EEPROM_ReadByte(uint16_t Addr, uint8_t *Data);
int EEPROM_WriteByte(uint16_t Addr, uint8_t Data);
void I2C_Initializes(void);
u8 Sanzhou_Start(void);
u8 Who_Am_I(void);
int Read_XYZ(void);
#endif

.c檔案

#include "tb_delay.h"
#include "i2c.h"
void I2C_delay(void)
{
	u8 t = 2;
	while(t--);
	return;
}
int I2C_Start(void)
{
	I2C_SDA_OUT();
	
	SDA_H;
	SCL_H;
	I2C_delay();
	if(!SDA_read)
	{
		return DISABLE;
	}
	SDA_L;
	I2C_delay();
	if(SDA_read)
	{
		return DISABLE;
	}
	SCL_L;
	return ENABLE;
}
void I2C_Stop(void)
{
	I2C_SDA_OUT();	
	SCL_L;
	SDA_L;	
	SCL_H;
	I2C_delay();
	SDA_H;
	I2C_delay();
}

static void I2C_Ack()
{
	SCL_L;
	I2C_SDA_OUT();	
	
	SDA_L;
	I2C_delay();
	SCL_H;
	I2C_delay();
	SCL_L;
}
 
static void I2C_NoAck()
{
	SCL_L;
	I2C_SDA_OUT();
	
	I2C_delay();
	SDA_H;
	I2C_delay();
	SCL_H;
	I2C_delay();
	SCL_L;
}
uint8_t I2C_GetAck(void)
{
  uint8_t time = 0;
	I2C_SDA_IN();
	SDA_H;
	I2C_delay();
	SCL_H;
	I2C_delay();
	while(SDA_read)
	{
		time++;
		if(time > 250)
		{			
			SCL_L;
			return DISABLE;
		}
	}
	SCL_L;
	return ENABLE;
}
void I2C_SendByte(uint8_t Data)
{
  uint8_t cnt;
  I2C_SDA_OUT();	
  for(cnt=0; cnt<8; cnt++)
  {
    SCL_L;                              
    I2C_delay();
 
    if(Data & 0x80)
    {
      SDA_H;                         
    }
    else
    {
      SDA_L;                         
    }
    Data <<= 1;
    SCL_H;                              
    I2C_delay();
  }
  SCL_L;                                   
  I2C_delay();
}
 

uint8_t I2C_ReadByte(uint8_t ack)
{
  uint8_t cnt;
  uint16_t data;
  I2C_SDA_IN();	
	
  for(cnt=0; cnt<8; cnt++)
  {
    SCL_L;                                
    I2C_delay();
		
    SCL_H;                             
    data <<= 1;
    if(SDA_read)
    {
      data |= 0x01;                              
    }
    I2C_delay();
  }
  if(ack == 1)
  {
     I2C_NoAck();
  }
  else
  {
     I2C_Ack();
  }
  return data;                                  
}
void I2C_GPIO_Configuration(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
 
  GPIO_InitStructure.GPIO_Pin = I2C_Pin_SCL;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(ANO_GPIO_I2C,&GPIO_InitStructure);
	
  GPIO_InitStructure.GPIO_Pin = I2C_Pin_SDA;
  GPIO_Init(ANO_GPIO_I2C, &GPIO_InitStructure);
}
 
 
void I2C_SDA_IN()
{
   GPIO_InitTypeDef  GPIO_InitStructure;
   GPIO_InitStructure.GPIO_Pin = I2C_Pin_SDA;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 
   GPIO_Init(ANO_GPIO_I2C, &GPIO_InitStructure);	
}
 
void I2C_SDA_OUT()
{
   GPIO_InitTypeDef  GPIO_InitStructure;
   GPIO_InitStructure.GPIO_Pin = I2C_Pin_SDA;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
   GPIO_Init(ANO_GPIO_I2C, &GPIO_InitStructure);	
}
void I2C_Initializes(void)
{
	I2C_GPIO_Configuration();
  SCL_H; 
	SDA_H;
}
int EEPROM_WriteByte(uint16_t Addr, uint8_t Data)
{
	I2C_Start();
	I2C_SendByte(EEPROM_DEV_ADDR | EEPROM_WR);
  if(!I2C_GetAck())
  {
	I2C_Stop();
	return DISABLE;
  }
  #if (8 == EEPROM_WORD_ADDR_SIZE)
  I2C_SendByte((uint8_t)(Addr&0x00FF));   
  #else
  I2C_SendByte((uint8_t)(Addr>>8));     
  I2C_SendByte((uint8_t)(Addr&0x00FF));
  #endif
  I2C_GetAck();
  I2C_SendByte(Data);
  I2C_Stop();
	return 1;
}

int EEPROM_ReadByte(uint16_t Addr, uint8_t *Data)
{
  I2C_Start(); 
	I2C_SendByte(EEPROM_DEV_ADDR | EEPROM_WR);
  if(!I2C_GetAck())
  {
	I2C_Stop();
	return DISABLE;
  }
  #if (8 == EEPROM_WORD_ADDR_SIZE)
  I2C_SendByte((uint8_t)(Addr&0x00FF)); 
  #else
  I2C_SendByte((uint8_t)(Addr>>8));   
	I2C_SendByte((uint8_t)(Addr&0x00FF));
  #endif
  I2C_Start();
	I2C_SendByte(EEPROM_DEV_ADDR | EEPROM_RD);
	
	if(!I2C_GetAck())
	{
	I2C_Stop();
	return DISABLE;
  }
  *Data = I2C_ReadByte(0); 
	I2C_Stop();
	return 1;
}
u8 Who_Am_I(void)
{
	u8 who;
	EEPROM_ReadByte(0x20, &who);
	return who;
}
u8 Sanzhou_Start()
{
	u8 id;
	id = Who_Am_I();
	if(id)
	{
		EEPROM_WriteByte(0x20, 0xE7);
		return ENABLE;
	}
	else
		return DISABLE;
}
int Read_XYZ(void)
{
 	EEPROM_ReadByte(0x29, &x);
	databuff[0] = x;
 	EEPROM_ReadByte(0x2b, &y);
	databuff[1] = y;
 	EEPROM_ReadByte(0x2d, &z);
	databuff[2] = z;
	return ENABLE;
}

另外;

原始碼本是IF,可能是寫錯了否則進不了迴圈,我改成了while。在通訊過程中可能因兩裝置接受與傳送頻率的不同,造成從裝置在接受到資料時會發送應答,而主裝置檢測應答訊號時,總線上並沒有將測到訊號。該段程式碼的目的正是延長一段時間等待從裝置的回覆。

iic裝置都有一個裝置型別碼,儲存在相應暫存器中。編寫程式時可讀取該暫存器檢測程式正確與否。

相關推薦

STM32軟體IIC實現

接上篇,LIS331的例程終於可以正常運行了,接下來就是將其移植到STM32上了,不過第一次接觸STM32的IIC,看例程比較簡單,直接複製到工程後卻讀不出資料,一直停在等待從裝置回覆ACK的死迴圈。 經過一天的修改之後,終於還是捨去了硬體IIC改成了用軟體實現,最終程

STM32軟體模擬IIC

                               IIC匯流排 一、與IIC有關的知識 (1)IIC屬於半雙工通訊方式 (2)IIC的協議     1.空閒狀態:IIC的SCL和SDA兩條線均處於高電平狀態,此時即釋放匯流排     2.起始訊號(Start):

STM32 IO模擬實現軟體串列埠

最近專案中STM32的串列埠資源緊張,於是使用IO口進行模擬串列埠,現進行整理記錄。 1. 實現思路 IO口模擬串列埠的思路也比較簡單,一切按照串列埠協議進行操作即可。 對於傳送,計算好不同波特率對應的延時時間進行資料傳送。 對於接收,稍微複雜。通過外部中斷檢測

stm32IIC通信協議

art code strong typedef col 上傳 bps eight 系統結構 1 //3?ê??ˉIIC 2 void IIC_Init(void) 3 { 4 GPIO_InitTy

STM32+IAP方案 實現網絡升級應用固件

註釋 tail 啟動 href net stm32 sdn tar log 源:STM32+IAP方案 實現網絡升級應用固件 IAR + STM32固件庫 啟動文件startup_stm32f10x_hd.s功用及註釋STM32+IAP方案 實現網絡升級應用固件

oa管理軟體如何實現全面的協同辦公管理?

隨著科技的不斷髮展,市場上oa管理軟體廠商越來越多,要想在眾多oa管理軟體廠商中脫穎而出,必須要有其“過人之處”。新一代oa管理軟體,加強企業業務監管、推動企業提升執行力,助領導做出快速、準確的決策等。那麼oa管理軟體如何實現全面的協同辦公管理? 1.全面的功能和流程oa管理軟體具有多種功能模組,如目標

智點進銷存軟體如何實現不同操作員管理不同客戶

在使用智點進銷存軟體過程中,經常會遇到不同操作員需要管理不同的客戶資訊,操作員自己只能管理自己的客戶,不能看到其他操作員的客戶資訊,當然其他操作員也看不到自己的的客戶資訊,這樣要怎麼操作才能實現呢? 很簡單,只要建立不同的營銷區域,然後不同操作員繫結不同的營銷區域即可。具體操作如下: 1.首先建立營銷區域

不用無限路由器 不用任何軟體輕鬆實現 發射無線訊號的功能

單擊開始按鈕,輸入“cmd”並按下回車。依次輸入以下兩個命令(其中網路連線名和金鑰自行設定) 命令1:netsh wlan set hostednetwork mode=allow ssid=網路連線名 key=金鑰(至少八位) 命令2:netsh wlan start hostednet

Scrapy爬蟲 -- 編寫下載中介軟體實現隨機User-Agent

Scrapy爬蟲 -- 編寫下載中介軟體,實現隨機User-Agent 實現步驟: 1. 在middlewares.p中,新建一個下載中介軟體; 2. 建立process_request方法(引擎傳送request物件到下載器時的回撥函式),實現隨機User-Agent的功能; 3.

Django - 使用自定義中介軟體實現登陸驗證

目錄 一、中介軟體 mymiddelware.py 檔案 二、檢視檔案 三、前端提交資料   一、中介軟體 mymiddelware.py 檔案 from django.utils.deprecation import MiddlewareMixin

知識管理,oa辦公軟體如何實現

在資訊時代裡,知識已成為最主要的財富來源,組織和個人的最重要的任務就是對知識進行管理。知識管理將使組織和個人具有更強的競爭實力,並做出更好地決策。 那麼,oa辦公軟體能不能做到?又是如何實現的呢? 1、oa辦公軟體可以幫助企業快速積累知識 oa辦公軟體可以幫助

MySQL中介軟體proxysql實現讀寫分離

環境說明: IP 角色 應用 平臺 192.168.161.96 讀寫分離解析主機 proxysql rhel7.4 19

stm32軟體觸發的按鍵長按與短按區分

/* ------------------------------------------------------------------------------------------------  * @fn          KeyCoolPressTimeHandle

使用淘寶中介軟體cobar實現mysql分庫分表

cobar 編譯安裝配置筆記 https://github.com/alibaba/cobar windows下使用eclipse匯入cobar專案,eclipse File -> Import -> Git https://github.com/alibab

STM32使用systick實現精確延時

SYSTICK暫存器初始化 void SysTick_Configuration(void) {     if (SysTick_Config(SystemCoreClock / 100))          {         while (1);   }     NVIC_SetPriority(

Windows系統下安裝深度學習Caffe軟體實現MATLAB呼叫的詳細步

下載Caffe,並解壓出原始碼資料夾caffe-master,轉到該資料夾下的windows資料夾下,將CommonSettings.props.example檔案複製到該目錄下並重命名為CommonSettings.props。用文字方式或者VS 2013單獨開啟,修改如下

雲合同電子合同合作矩陣軟體實現遠端稱重智慧電子簽約

近日,雲合同(yunhetong.com)與“稱重物聯網第一股”公司——山東矩陣軟體工程股份有限公司(以下簡稱“矩陣軟體”)達成戰略合作,為矩陣軟體生態鏈提供專業的第三方電子合同服務。 隨著電商行業的客單量越來越大,物流業物品稱重、分揀的效率受到很大阻礙,因每個物品的

CRC的校驗原理及硬體、軟體演算法實現

轉自:http://blog.163.com/yucheng_xiao/blog/static/76600192201393092918776/  一、基本原理     CRC檢驗原理實際上就是在一個p位二進位制資料序列之後附加一個r位二進位制檢驗碼(序列),從而構成一個總長為n=p+r位的二進位制序

stm32 web伺服器實現

最近在做stm32 web伺服器的東西,忙了一段時間終於弄完了,把這幾天關於stm32伺服器的工作記錄一下。 剛接到這個任務的時候,不知道怎麼下手,網上資料似乎不是很多,於是在下載了一個官方demo測試了一下,看了一下程式碼,不是很懂,於是繼續百度找資料,找到一個比較有

中國象棋軟體-引擎實現(六)局面評估

前面已經講過了棋局表示、著法生成、搜尋演算法(包括搜尋輔助), 在象棋程式中如果說搜尋演算法是心臟,那麼局面評估就是大腦。搜尋演算法負責驅動整個程式,而局面評估則負責對搜尋的內容進行判斷評價。因而搜尋與局面評估是整個程式的核心。 首先,先介紹一下在局面評估中需要考慮的因素。就不同的棋類可能要考慮的因素略有差