STM32調試MIPI RFFE協議

目錄

一、前言

二、RFFE總線

三、協議時序

四、器件狀態

五、更改USID

六、程序代碼

七、參考資料


一、前言

前陣子手裏有幾個天線調諧器芯片,1.5x1mm的BGA封裝非常小,通信控制協議是MIPI RFFE協議,這個協議網上資料比較少,搜了一下搜到了一個標準的MIPI協議文檔,裏面各種控制時序和介紹都寫的非常詳細了,其實就和I2C這類的協議差不多吧,然後在CSDN上又找到了一個STM32用GPIO模擬MIPI RFFE協議的文檔資料作參考,稍微改了改,調試的時候遇到了一些問題,然後用邏輯分析儀抓了抓波形改了改代碼,然後調試成功了,本文進行調試總結。

 

二、RFFE總線

RFFE總線定義如下:

https://files.sekorm.com/opt/fileStore/portal/ecnew/editor/new/20160620/1466401433395087932th.jpg

 

VIORFFE接口的基準電壓,也可以作爲復位和使能輸入。一個施加到VIO 信號的邏輯低電平可以將RFFE接口關斷。

SCLKRFFE 總線時鐘輸入。通常被連接至RF 或基帶IC 上的RFFE 主機。當未施加VIO 時,SCLK 必須爲低電平。時鐘頻率範圍爲32KHz到26MHz。

SDATARFFE 總線數據輸入/輸出。通常被連接至RF 或基帶IC 上的RFFE 主機。當未施加VIO 時,SCLK 必須爲低電平。

MIPI RFFE協議和I2C協議真的共性很多,都是一條數據線(SDATA)和一條時鐘線(SCLK),然後所有的從設備都通過這兩條線掛接到總線上,所有的從設備都可以設置獨立的從設備地址,Master可以通過從設備地址來單獨控制多個從設備中的單個設備,RFFE總線高電平爲1.2到1.8V,VIO供電也是1.2到1.8V,注意不要用3.3V單片機IO直接驅動,要接個電平轉換芯片。RFFE設備連接框圖如下:

 

三、協議時序

時序操作基本上可以歸爲兩類操作,寄存器寫和寄存器讀,其中寄存器寫又分爲寄存器0寫入、普通寄存器寫入和擴展寄存器寫入;讀可以分爲普通寄存器讀和擴展寄存器讀。從機寄存器尋址如下。

https://files.sekorm.com/opt/fileStore/portal/ecnew/editor/new/20160620/1466401649058019994th.jpg

寫寄存器命令分好幾種,區別就是可以訪問的寄存器地址區間不一樣,我手頭上這個IC的有用數據都是定義在寄存器0到31上的,之後的地址沒定義,所以用不到擴展寄存器寫命令。不管是哪種操作,都可以歸類爲:SSC頭+命令幀+數據幀+停止幀。

https://files.sekorm.com/opt/fileStore/portal/ecnew/editor/new/20160620/1466401671314017211th.jpg

1、基本命令幀

(1)SSC(Sequence Start Condition)

 

 SSC具體時序是SCLK爲低電平時,SDATA0變爲兩個週期的1,然後變爲0。SSC相當於是啓動信號,每次命令操作都需要先發送該時序。

(2)命令幀

命令幀前4bit爲從機地址,接下來是8bit的命令+1bit的奇校驗位(對前12bit數據進行奇校驗),

(3)數據幀

8bit的數據+1bit的奇校驗。

(4)Bus Park幀

最後在SCLK的一個下降沿SDATA保持一個以上週期的0電平來使總線掛起也就是Bus park

 

2、寄存器寫操作

(1)寄存器0寫入

SA0到SA3是從機地址,一般和器件的4位USID值是一致的,寄存器0寫入命令的命令幀前8bit的最高位D7是固定爲1的,剩下的D0到D6是寫入到寄存器0的數據,實際上也就只能修改寄存器0的D0到D6的數據。

(2)非0寄存器寫入

命令幀的前3位D7,D6,D5固定爲0,1,0,剩下的5位表示寄存器地址,實際上能夠尋址的寄存器範圍只有0到31,命令幀接下來是數據幀,D0到D7是要寫入到相應寄存器的數據。

(3)擴展寄存器寫入

命令幀的前4位固定爲全0,只剩下BC0~BC3是可以自己填的,這4位表示要寫入多少個字節的數據,0表示寫一個字節,0xF表示寫16個字節,其實一個寄存器只能寫1個字節,多寫的字節會根據當前寄存器的地址開始向後寫入到後面的寄存器中。數據幀那裏的8位用來填寫寄存器的地址,之後的很多個幀根據BC0~BC3的值追加多個要寫入的字節數據。

3、寄存器讀操作

(1)寄存器讀

讀寄存器跟寫寄存器一樣的套路,先給4位從機地址,然後因爲是普通讀,命令幀的高三位定死了是0,1,1,剩下的5位可以自己填,實際只能尋址0到31這些寄存器,然後後面接8位的數據讀取操作,這裏讀取操作的時候主機要把SDATA設爲下拉模式,即默認電平爲低電平,然後從機輸出數據的話如果是1會把SDATA拉高,8位寄存器數據之後是1位寄校驗(對前面8位數據校驗),注意編程的時候還是要判斷下器件給的奇校驗位P,看下是不是校驗能夠通過,否則讀到的數據是錯的。

 

(2)擴展寄存器讀

BC0到BC3表示讀取的字節數目,爲0時表示都1個字節,爲0xF時表示讀16個字節,讀超過1個字節會返回當前寄存器地址往後的寄存器地址的內容,和擴展寄存器寫套路一樣的。

 

四、器件狀態

以下是器件狀態切換圖:

RFFE的器件有幾種狀態可以切換,分別爲STARTUP、ACTIVE、LOW POWER、SHUTDOWN。通過VIO電平狀態切換和往PWR_MODE寄存器寫值來跳轉這些狀態。操作IC的時候發現不激活IC的狀態只能讀寄存器,寫寄存器時無效。

 

五、更改USID

單獨更改USID寄存器的值是改不了USID的,發現讀回來的數據還是原來的。改USID要同時更改PRODUCT_ID、MANUFACTURER_ID和USID,這樣才能改動USID的值,然後從機地址就跟着一起變了,下次給SA0~SA3的時候記得要替換回新的從機地址。具體時序如下:

看着那麼長一段,其實就是三個寄存器寫命令拼在一起。

 

六、程序代碼

代碼是基於STM32F103XX調試的,如下:

MIPI.h

#ifndef _MIPI_H_
#define _MIPI_H_

#include "stm32f10x.h"
#include "public.h"
#include "systick.h"

#define REG_PAC_SPST_STATE  0x00
#define REG_VBODY_TIMERS    0x01
#define REG_VVAR            0x02
#define REG_CUSTOMER_SRATCH 0x17
#define REG_RFFE_STATUS     0x1A
#define REG_GROUP_SID       0x1B
#define REG_PM_TRIG         0x1C
#define REG_PRODUCT_ID      0x1D
#define REG_MANUFACTURER_ID 0x1E
#define REG_MAN_USID        0x1F
#define REG_CMOS_VERSION_ID 0x21
#define REG_SDATA_DRV_LVL   0x2B

#define CHECK_OK 	1
#define CHECK_FAIL 	0

#define RFFE_SDATA_PORT	GPIOA
#define RFFE_SDATA_PIN	GPIO_Pin_0

#define RFFE_SCLK_PORT	GPIOA
#define RFFE_SCLK_PIN	GPIO_Pin_1

#define RFFE_SDATA_HIGH GPIO_SetBits(RFFE_SDATA_PORT, RFFE_SDATA_PIN)
#define RFFE_SDATA_LOW	GPIO_ResetBits(RFFE_SDATA_PORT, RFFE_SDATA_PIN)

#define RFFE_SDATA_READ	GPIO_ReadInputDataBit(RFFE_SDATA_PORT, RFFE_SDATA_PIN)

#define RFFE_SCLK_HIGH GPIO_SetBits(RFFE_SCLK_PORT, RFFE_SCLK_PIN)
#define RFFE_SCLK_LOW	GPIO_ResetBits(RFFE_SCLK_PORT, RFFE_SCLK_PIN)

#define Delay_nop(x) delay_us(x);

//#define Delay_nop(x) {;;;;;};

#define Bus_Park()	RFFE_SDATA_LOW

//GPIO初始化
extern void RFFE_Init(void);
//寄存器讀
extern unsigned char Register_Read(unsigned char USID_Address, unsigned char Reg_address, unsigned char *Reg_Value);
//0寄存器寫
extern void Register_0_Write(unsigned char USID_Address, unsigned char Reg_data);
//非0寄存器寫,實驗中發現寫0寄存器也生效
extern void Register_Write(unsigned char USID_Address, unsigned char Reg_Address, unsigned char Reg_data);
//器件使能
extern void Active_Product(unsigned char USID_Address);
//必須連續一起修改Product_ID、MANUFACTURER_ID、USID才能使新的USID生效,單獨修改USID寄存器不生效
extern void Register_Write_USID(unsigned char Old_USID_Address, unsigned char Product_ID, unsigned short MANUFACTURER_ID, unsigned char MAN_USID);
//寫一個字節到擴展寄存器,擴展寄存器指地址大於0x1F的寄存器
extern void Extended_Register_Write(unsigned char USID_Address, unsigned char Reg_Address, unsigned char Reg_data);
//擴展寄存器讀一個字節
extern unsigned char Extended_Register_Read(unsigned char USID_Address, unsigned char Reg_address, unsigned char *Reg_Value);

#endif

MIPI.c

#include "MIPI.h"

void RFFE_SDATA_Output_Mode(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;	

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 
		
	GPIO_InitStructure.GPIO_Pin = RFFE_SDATA_PIN;	 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	  
	GPIO_Init(RFFE_SDATA_PORT, &GPIO_InitStructure); 

	RFFE_SDATA_LOW;
}

void RFFE_SDATA_Input_Mode(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;	

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 
		
	GPIO_InitStructure.GPIO_Pin = RFFE_SDATA_PIN;	 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	  
	GPIO_Init(RFFE_SDATA_PORT, &GPIO_InitStructure); 

	//RFFE_SDATA_LOW;
}

void RFFE_SCLK_Output_Mode(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;	

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 
		
	GPIO_InitStructure.GPIO_Pin = RFFE_SCLK_PIN;	 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	  
	GPIO_Init(RFFE_SCLK_PORT, &GPIO_InitStructure); 

	RFFE_SCLK_LOW;
}

void RFFE_Init(void)
{
	RFFE_SCLK_Output_Mode();
	RFFE_SDATA_Output_Mode();
	
}

void SSC_Head(void)
{
	RFFE_SCLK_LOW;
	RFFE_SDATA_LOW;
	Delay_nop(10);

	RFFE_SDATA_HIGH;
	Delay_nop(1);
	Delay_nop(1);
	Delay_nop(1);

	RFFE_SDATA_LOW;
	Delay_nop(1);
}

// void Bus_Park()
// {
// 	RFFE_SDATA_LOW;
// 	// Delay_nop(1);
// 	// RFFE_SCLK_HIGH;
// }

void Register_0_Write(unsigned char USID_Address, unsigned char Reg_data)
{
	int i;
	unsigned char P_Bit = 1;
	unsigned char Reg_frame_13bit[13];

	//前四位爲USID地址
	for(i = 0; i < 4; i++)
	{
		if(USID_Address & 0x80)
		{
			Reg_frame_13bit[i] = 1;
		}
		else
		{
			Reg_frame_13bit[i] = 0;
		}
		USID_Address = USID_Address << 1;
	}

	//八位數據位,首位1爲寄存器0寫入標誌位
	Reg_data = Reg_data | 0x80;  //加入1000b的0寄存器寫入標誌位
	for(i = 0; i < 8; i++)
	{
		if(Reg_data & 0x80)
		{
			Reg_frame_13bit[i + 4] = 1;
		}
		else
		{
			Reg_frame_13bit[i + 4] = 0;
		}
		Reg_data = Reg_data << 1;
	}

	//前12位進行奇校驗
	P_Bit = 1;
	for(i = 0; i < 12; i++)
	{
		if(Reg_frame_13bit[i])
		{
			P_Bit ^= 0x01;
		}
	}
	Reg_frame_13bit[12] = P_Bit;

	//開始發送總線時序
	RFFE_SDATA_Output_Mode();
	//SSC_Head
	SSC_Head();
	RFFE_SCLK_HIGH;
	//data frame寫入
	for(i = 0; i < 13; i++)
	{
		if(Reg_frame_13bit[i])
		{
			RFFE_SDATA_HIGH;
		}
		else
		{
			RFFE_SDATA_LOW;
		}

		Delay_nop(1);
		RFFE_SCLK_HIGH;
		Delay_nop(1);
		RFFE_SCLK_LOW;
		//Delay_nop(1);
		//RFFE_SCLK_HIGH;
	}

	//bus park
	Bus_Park();
	Delay_nop(1);
	RFFE_SCLK_HIGH;
	Delay_nop(1);
	RFFE_SCLK_LOW;
}

void Register_Write(unsigned char USID_Address, unsigned char Reg_Address, unsigned char Reg_data)
{
	int i;
	unsigned char P_Bit = 1;
	unsigned char Reg_frame_13bit[13];
	unsigned char Reg_data_frame_9Bit[9];

	//前四位爲USID地址
	for(i = 0; i < 4; i++)
	{
		if(USID_Address & 0x80)
		{
			Reg_frame_13bit[i] = 1;
		}
		else
		{
			Reg_frame_13bit[i] = 0;
		}
		USID_Address = USID_Address << 1;
	}

	//八位數據位,首位1爲寄存器0寫入標誌位
	Reg_Address &= ~((unsigned char)7 << 5);
	Reg_Address = Reg_Address | 0x40;  //加入010b的0寄存器寫入標誌位
	for(i = 0; i < 8; i++)
	{
		if(Reg_Address & 0x80)
		{
			Reg_frame_13bit[i + 4] = 1;
		}
		else
		{
			Reg_frame_13bit[i + 4] = 0;
		}
		Reg_Address = Reg_Address << 1;
	}

	//前12位進行奇校驗
	P_Bit = 1;
	for(i = 0; i < 12; i++)
	{
		if(Reg_frame_13bit[i])
		{
			P_Bit ^= 0x01;
		}
	}
	Reg_frame_13bit[12] = P_Bit;
	
	//處理寫入寄存器的數據
	for(i = 0; i < 8; i++)
	{
		if(Reg_data & 0x80)
		{
			Reg_data_frame_9Bit[i] = 1;
		}
		else
		{
			Reg_data_frame_9Bit[i] = 0;
		}
		Reg_data = Reg_data << 1;
	}

	//前8位進行奇校驗
	P_Bit = 1;
	for(i = 0; i < 8; i++)
	{
		if(Reg_data_frame_9Bit[i])
		{
			P_Bit ^= 0x01;
		}
	}
	Reg_data_frame_9Bit[8] = P_Bit;

	//開始發送總線時序
	RFFE_SDATA_Output_Mode();
	//SSC_Head
	SSC_Head();

	//Reg frame寫入
	for(i = 0; i < 13; i++)
	{
		if(Reg_frame_13bit[i])
		{
			RFFE_SDATA_HIGH;
		}
		else
		{
			RFFE_SDATA_LOW;
		}

		Delay_nop(1);
		RFFE_SCLK_HIGH;
		Delay_nop(1);
		RFFE_SCLK_LOW;
		//Delay_nop(1);
	}

	//data frame寫入
	for(i = 0; i < 9; i++)
	{
		if(Reg_data_frame_9Bit[i])
		{
			RFFE_SDATA_HIGH;
		}
		else
		{
			RFFE_SDATA_LOW;
		}

		Delay_nop(1);
		RFFE_SCLK_HIGH;
		Delay_nop(1);
		RFFE_SCLK_LOW;
		//Delay_nop(1);
	}
	
	//bus park
	Bus_Park();
	Delay_nop(1);
	RFFE_SCLK_HIGH;
	Delay_nop(1);
	RFFE_SCLK_LOW;
}

unsigned char Register_Read(unsigned char USID_Address, unsigned char Reg_address, unsigned char *Reg_Value)
{
	int i = 0;
	unsigned char P_Bit = 1;
	unsigned char Reg_frame_13bit[13];
	unsigned char Receive_Bit9_frame[9];

	//實驗發現需要先拉高SDATA和SCLK才能讀正確
	RFFE_SDATA_Output_Mode();
	RFFE_SCLK_HIGH;
	RFFE_SDATA_HIGH;
	Delay_nop(10);
	
	RFFE_SCLK_LOW;
	Delay_nop(1);
	RFFE_SDATA_LOW;
	Delay_nop(10);
	
	//前四位爲USID地址
	for(i = 0; i < 4; i++)
	{
		if(USID_Address & 0x80)
		{
			Reg_frame_13bit[i] = 1;
		}
		else
		{
			Reg_frame_13bit[i] = 0;
		}
		USID_Address = USID_Address << 1;
	}

	//八位寄存器地址轉換
	Reg_address = Reg_address | 0x60;  //加入0110b讀取指令標誌位

	for(i = 4; i < 12; i++)
	{
		if(Reg_address & 0x80)
		{
			Reg_frame_13bit[i] = 1;
		}
		else
		{
			Reg_frame_13bit[i] = 0;
		}
		Reg_address = Reg_address << 1;
	}

	//前12位進行奇校驗P
	P_Bit = 1;
	for(i = 0; i < 12; i++)
	{
		if(Reg_frame_13bit[i])
		{
			P_Bit ^= 0x01;
		}
	}

	Reg_frame_13bit[12] = P_Bit;

	//開始發送總線時序
	RFFE_SDATA_Output_Mode();
	//SSC_Head
	SSC_Head();

	//data frame寫入
	for(i = 0; i < 13; i++)
	{
		if(Reg_frame_13bit[i])
		{
			RFFE_SDATA_HIGH;
		}
		else
		{
			RFFE_SDATA_LOW;
		}

		Delay_nop(1);
		RFFE_SCLK_HIGH;
		Delay_nop(1);
		RFFE_SCLK_LOW;
		//Delay_nop(1);
	}

	//bus park
	Bus_Park();
	Delay_nop(1);
	RFFE_SCLK_HIGH;
	Delay_nop(1);
	RFFE_SCLK_LOW;
	RFFE_SDATA_Input_Mode();

	//read data數據讀出,同時對數據進行奇校驗
	P_Bit = 1;

	for(i = 0; i < 9; i++)
	{
		Delay_nop(2);
		RFFE_SCLK_HIGH;
		Delay_nop(2);
		RFFE_SCLK_LOW;

		if(RFFE_SDATA_READ)
		{
			Receive_Bit9_frame[i] = 1;
			P_Bit ^= 0x01;
		}
		else
		{
			Receive_Bit9_frame[i] = 0;
		}
	}

	*Reg_Value = 0;
	for(i = 0; i < 8; i++)
	{
		*Reg_Value <<= 1;
		*Reg_Value |=  Receive_Bit9_frame[i] ? 1 : 0;
	}

	//bus park
	RFFE_SDATA_Output_Mode();
	Bus_Park();
	Delay_nop(2);
	RFFE_SCLK_HIGH;
	Delay_nop(2);
	RFFE_SCLK_LOW;
	
	if(P_Bit)
	{
		//奇校驗失敗
		return CHECK_FAIL;
	}
	else
	{
		//奇校驗成功
		return CHECK_OK;
	}
}

//器件使能
void Active_Product(unsigned char USID_Address)
{
	Register_Write(USID_Address, 0x1C, 0x38);
	Register_Write(USID_Address, 0x02, 0x02);
}

//必須連續一起修改Product_ID、MANUFACTURER_ID、USID才能使新的USID生效,單獨修改USID寄存器不生效
void Register_Write_USID(unsigned char Old_USID_Address, unsigned char Product_ID, unsigned short MANUFACTURER_ID, unsigned char MAN_USID)
{
	Register_Write(Old_USID_Address, 0x1D, Product_ID);
	Register_Write(Old_USID_Address, 0x1E, MANUFACTURER_ID);
	Register_Write(Old_USID_Address, 0x1F, MAN_USID);
}

//寫一個字節到擴展寄存器,擴展寄存器指地址大於0x1F的寄存器
void Extended_Register_Write(unsigned char USID_Address, unsigned char Reg_Address, unsigned char Reg_data)
{
	int i;
	unsigned char P_Bit = 1;
	unsigned char Byte_len = 0;  //0代表寫一個字節
	unsigned char Reg_frame_22bit[22];
	unsigned char Reg_data_frame_9Bit[9];

	//前四位爲USID地址
	for(i = 0; i < 4; i++)
	{
		if(USID_Address & 0x80)
		{
			Reg_frame_22bit[i] = 1;
		}
		else
		{
			Reg_frame_22bit[i] = 0;
		}
		USID_Address = USID_Address << 1;
	}

	//默認寫一個字節,可以改成寫多個字節,多個字節會順推寫到後面的寄存器地址,最多連續寫16個字節
	Byte_len &= 0x0F;
	Byte_len = Byte_len | 0x00;  
	for(i = 0; i < 8; i++)
	{
		if(Byte_len & 0x80)
		{
			Reg_frame_22bit[i + 4] = 1;
		}
		else
		{
			Reg_frame_22bit[i + 4] = 0;
		}
		Byte_len = Byte_len << 1;
	}

	//前12位進行奇校驗
	P_Bit = 1;
	for(i = 0; i < 12; i++)
	{
		if(Reg_frame_22bit[i])
		{
			P_Bit ^= 0x01;
		}
	}
	Reg_frame_22bit[12] = P_Bit;

	//八位寄存器地址
	for(i = 0; i < 8; i++)
	{
		if(Reg_Address & 0x80)
		{
			Reg_frame_22bit[i + 13] = 1;
		}
		else
		{
			Reg_frame_22bit[i + 13] = 0;
		}
		Reg_Address = Reg_Address << 1;
	}

	//第13 ~ 20位進行奇校驗
	P_Bit = 1;
	for(i = 0; i < 8; i++)
	{
		if(Reg_frame_22bit[i + 13])
		{
			P_Bit ^= 0x01;
		}
	}
	Reg_frame_22bit[21] = P_Bit;
	
	//處理寫入寄存器的數據
	for(i = 0; i < 8; i++)
	{
		if(Reg_data & 0x80)
		{
			Reg_data_frame_9Bit[i] = 1;
		}
		else
		{
			Reg_data_frame_9Bit[i] = 0;
		}
		Reg_data = Reg_data << 1;
	}

	//前8位進行奇校驗
	P_Bit = 1;
	for(i = 0; i < 8; i++)
	{
		if(Reg_data_frame_9Bit[i])
		{
			P_Bit ^= 0x01;
		}
	}
	Reg_data_frame_9Bit[8] = P_Bit;

	//開始發送總線時序
	RFFE_SDATA_Output_Mode();
	//SSC_Head
	SSC_Head();

	//Reg frame寫入
	for(i = 0; i < 22; i++)
	{
		if(Reg_frame_22bit[i])
		{
			RFFE_SDATA_HIGH;
		}
		else
		{
			RFFE_SDATA_LOW;
		}

		Delay_nop(1);
		RFFE_SCLK_HIGH;
		Delay_nop(1);
		RFFE_SCLK_LOW;
		//Delay_nop(1);
	}

	//data frame寫入
	for(i = 0; i < 9; i++)
	{
		if(Reg_data_frame_9Bit[i])
		{
			RFFE_SDATA_HIGH;
		}
		else
		{
			RFFE_SDATA_LOW;
		}

		Delay_nop(1);
		RFFE_SCLK_HIGH;
		Delay_nop(1);
		RFFE_SCLK_LOW;
		//Delay_nop(1);
	}
	
	//bus park
	Bus_Park();
	Delay_nop(1);
	RFFE_SCLK_HIGH;
	Delay_nop(1);
	RFFE_SCLK_LOW;
}

//擴展寄存器讀一個字節
unsigned char Extended_Register_Read(unsigned char USID_Address, unsigned char Reg_address, unsigned char *Reg_Value)
{
	int i = 0;
	unsigned char P_Bit = 1;
	unsigned char Byte_Len = 0;  //讀一個字節
	unsigned char Reg_frame_22bit[22];
	unsigned char Receive_Bit9_frame[9];

	//實驗發現需要先拉高SDATA和SCLK才能讀正確
	RFFE_SDATA_Output_Mode();
	RFFE_SCLK_HIGH;
	RFFE_SDATA_HIGH;
	Delay_nop(10);
	
	RFFE_SCLK_LOW;
	Delay_nop(1);
	RFFE_SDATA_LOW;
	Delay_nop(10);
	
	//前四位爲USID地址
	for(i = 0; i < 4; i++)
	{
		if(USID_Address & 0x80)
		{
			Reg_frame_22bit[i] = 1;
		}
		else
		{
			Reg_frame_22bit[i] = 0;
		}
		USID_Address = USID_Address << 1;
	}

	//字節數目
	Byte_Len &= 0x0F;
	Byte_Len = Byte_Len | 0x20;  

	for(i = 4; i < 12; i++)
	{
		if(Byte_Len & 0x80)
		{
			Reg_frame_22bit[i] = 1;
		}
		else
		{
			Reg_frame_22bit[i] = 0;
		}
		Byte_Len = Byte_Len << 1;
	}

	//前12位進行奇校驗P
	P_Bit = 1;
	for(i = 0; i < 12; i++)
	{
		if(Reg_frame_22bit[i])
		{
			P_Bit ^= 0x01;
		}
	}
	Reg_frame_22bit[12] = P_Bit;

	//八位寄存器地址轉換
	for(i = 13; i < 21; i++)
	{
		if(Reg_address & 0x80)
		{
			Reg_frame_22bit[i] = 1;
		}
		else
		{
			Reg_frame_22bit[i] = 0;
		}
		Reg_address = Reg_address << 1;
	}

	//進行奇校驗P
	P_Bit = 1;
	for(i = 13; i < 21; i++)
	{
		if(Reg_frame_22bit[i])
		{
			P_Bit ^= 0x01;
		}
	}

	Reg_frame_22bit[21] = P_Bit;

	//開始發送總線時序
	RFFE_SDATA_Output_Mode();
	//SSC_Head
	SSC_Head();

	//data frame寫入
	for(i = 0; i < 22; i++)
	{
		if(Reg_frame_22bit[i])
		{
			RFFE_SDATA_HIGH;
		}
		else
		{
			RFFE_SDATA_LOW;
		}

		Delay_nop(1);
		RFFE_SCLK_HIGH;
		Delay_nop(1);
		RFFE_SCLK_LOW;
		//Delay_nop(1);
	}

	//bus park
	Bus_Park();
	Delay_nop(1);
	RFFE_SCLK_HIGH;
	Delay_nop(1);
	RFFE_SCLK_LOW;
	RFFE_SDATA_Input_Mode();

	//read data數據讀出,同時對數據進行奇校驗
	P_Bit = 1;

	for(i = 0; i < 9; i++)
	{
		Delay_nop(2);
		RFFE_SCLK_HIGH;
		Delay_nop(2);
		RFFE_SCLK_LOW;

		if(RFFE_SDATA_READ)
		{
			Receive_Bit9_frame[i] = 1;
			P_Bit ^= 0x01;
		}
		else
		{
			Receive_Bit9_frame[i] = 0;
		}
	}

	*Reg_Value = 0;
	for(i = 0; i < 8; i++)
	{
		*Reg_Value <<= 1;
		*Reg_Value |=  Receive_Bit9_frame[i] ? 1 : 0;
	}

	//bus park
	RFFE_SDATA_Output_Mode();
	Bus_Park();
	Delay_nop(2);
	RFFE_SCLK_HIGH;
	Delay_nop(2);
	RFFE_SCLK_LOW;
	
	if(P_Bit)
	{
		//奇校驗失敗
		return CHECK_FAIL;
	}
	else
	{
		//奇校驗成功
		return CHECK_OK;
	}
}

 

七、參考資料

《MIPI RFFE協議文檔V1.10》鏈接:https://pan.baidu.com/s/1mnxA9TehKzA8tdSM7bdcOg  提取碼:xdk3

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章