SN7325 iic程序

本文为CSDN博主「被追杀的晨曦」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/double_lee3/article/details/90205474

#include "SN7326.h"
#include <stdio.h>
#include <string>             // for STL string class
#include "define.h"
 
 
 
extern bool(__stdcall *InitializeWinIo)(void);
extern void(__stdcall *ShutdownWinIo)(void);
extern PBYTE(__stdcall *MapPhysToLin)(PBYTE pbPhysAddr, DWORD dwPhysSize, HANDLE *pPhysicalMemoryHandle);
extern bool(__stdcall *UnmapPhysicalMemory)(HANDLE PhysicalMemoryHandle, PBYTE pbLinAddr);
extern bool(__stdcall *GetPhysLong)(PBYTE pbPhysAddr, PDWORD pdwPhysVal);
extern bool(__stdcall *SetPhysLong)(PBYTE pbPhysAddr, DWORD dwPhysVal);
extern bool(__stdcall *GetPortVal)(WORD wPortAddr, PDWORD pdwPortVal, BYTE bSize);
extern bool(__stdcall *SetPortVal)(WORD wPortAddr, DWORD dwPortVal, BYTE bSize);
extern bool(__stdcall *InstallWinIoDriver)(PSTR pszWinIoDriverPath, bool IsDemandLoaded);
extern bool(__stdcall *RemoveWinIoDriver)(void);
 
/*
*FunctionName: I2CDelay
* Purpose : I2C时序模拟SCL时间间隔(周期),需要根据Slave性能及单片机工作频率调整
* Parameters : 无
*/
static void I2C_Delay(void) {
	__asm {
		nop
		nop
		nop
		nop
	}
}
 
/*
* FunctionName: I2CStart
* Purpose: 模拟I2C开始信号,	SCL电平拉高,SDA由高变低,I2C开始传输数据
* Parameters: 无
*/
static void SN7325_i2c_START(void) {
 
	SN7325_I2C_SCL_H;
	SN7325_I2C_SDA_H;
	I2C_Delay();
	SN7325_I2C_SDA_L;
	SN7325_I2C_SCL_L;
}
 
static void SN7325_i2c_RESTART(void) {
	SN7325_I2C_SCL_L;
 
	SN7325_I2C_SCL_H;
	SN7325_I2C_SDA_H;
	I2C_Delay();
	SN7325_I2C_SDA_L;
	SN7325_I2C_SCL_L;
}
 
/*
* FunctionName: I2CStop
* Purpose: 模拟I2C结束信号,SCL电平拉高,SDA由低边高,I2C停止传输数据
* Parameters: 无
*/
static void SN7325_i2c_STOP(void) {
	int i;
	SN7325_I2C_SCL_H;
	SN7325_I2C_SDA_L;
	I2C_Delay();
	SN7325_I2C_SDA_H;
}
 
/*
* FunctionName: I2CSendNoACK
* Purpose: 模拟I2C无ACK响应
* Parameters: 无
*/
static void SN7325_i2c_NOACK(void) {
 
	SN7325_I2C_SDA_H;
	SN7325_I2C_SCL_H;
	SN7325_I2C_SCL_L;
}
 
/*
* FunctionName: I2CCheckACK
* Purpose:把串口设置为输入模式,测试串口是否有响应
* Parameters: 无
*/
static bool SN7325_i2c_WAITACK(void) {
	unsigned long tempACK = 0;
	unsigned long res = 0;
	unsigned long time_out = 0;
 
	SN7325_I2C_SDA_L;
 
	SetPhysLong((PBYTE)KEY_IO5_ADDR, 0x00908200);//输入模式
	SN7325_I2C_SCL_H;
	do {
		GetPhysLong((PBYTE)KEY_IO5_ADDR, (PDWORD)&tempACK);//获取ack
		if (tempACK)
			res =1;
		else
			res = 0;
 
		time_out++;
 
		if (time_out > 3)//超时处理
		{
			res = 0;
		}
 
	} while (( !res )||(time_out> 3));
 
	SN7325_I2C_SCL_L;
 
	return res;
}
 
/*
* FunctionName: I2CTWRITE8BIT
* Purpose:模拟I2C发送一个字节数据,从低位开始写
* Parameters: sendData-发送的一个字节数据
*/
static void SN7325_i2c_WRITE8B(unsigned char  input) {
	unsigned char  serialNum;
 
	for (serialNum = 8; serialNum >= 1; serialNum--) 
	{
		if (input & 0x80) {//判断最高位是否为1
			SN7325_I2C_SDA_H;
		}
		else {
			SN7325_I2C_SDA_L;
		}
		SN7325_I2C_SCL_H;
		I2C_Delay();
		SN7325_I2C_SCL_L;
 
	    input <<= 1;//数据左移一位
	}
}
 
/*
* FunctionName: I2CTREAD8BIT
* Purpose:模拟I2C接收一个字节数据
* Parameters: 无
*/
static unsigned char  SN7325_i2c_READ8B(void)
{
	unsigned char  serialNum;
	unsigned char  I2CBUF = 0;
	unsigned long SDAStatus = 0;
 
	SetPhysLong((PBYTE)KEY_IO5_ADDR, 0x00908200);		//设置SDA/串口为输入模式
	for (serialNum = 8; serialNum >=1; serialNum--) {
		I2CBUF  <<= 1;
		SN7325_I2C_SCL_H;
		GetPhysLong((PBYTE)KEY_IO5_ADDR, (PDWORD)&SDAStatus); 
		if (SDAStatus) {
			I2CBUF |= 0x01;
			//I2CBUF++;//表示读取数据
		}
		SN7325_I2C_SCL_L;
	}
	printf("I2CBUF = %x", I2CBUF);
	return I2CBUF;
}
 
/*
写寄存器的标准流程为
1.    Master发起START
2.    Master发送I2C addr(7bit)和w操作0(1bit),等待ACK
3.    Slave发送ACK
4.    Master发送reg addr(8bit),等待ACK
5.    Slave发送ACK
6.   Master发送data(8bit),即要写入寄存器中的数据,等待ACK
7.    Slave发送ACK
8.    第6步和第7步可以重复多次,即顺序写多个寄存器
9.    Master发起STOP
*/
void SN7325_Write_i2c(unsigned char WriteDeviceAddress, unsigned char Command, unsigned char Wdata)
{
	SN7325_i2c_START();
 
	SN7325_i2c_WRITE8B(WriteDeviceAddress);
	SN7325_i2c_WAITACK();
 
	SN7325_i2c_WRITE8B(Command);
	SN7325_i2c_WAITACK();
 
	SN7325_i2c_WRITE8B(Wdata);
	SN7325_i2c_NOACK();
	SN7325_i2c_STOP();
}
 
/*
I2C读寄存器函数的时序:
1、主设备发出开始信号
2、写入从设备地址
3、主设备接收从设备发来的应答信号
4、写入寄存器地址
5、主设备接收应答信号
6、主设备再次发出开始信号
7、主设备向从设备写入(从设备的地址+1),此时加1表示要从寄存器中读数据
8、从设备给出应答信号
9、从从设备的寄存器中读出数据传给变量
10、主设备发出停止信号
11、返回读出的数据
*/
unsigned short SN7325_Read_i2c(unsigned char ReadDeviceAddress, unsigned char Command)
{
 
	unsigned char r_byte;
	SN7325_i2c_START();
	SN7325_i2c_WRITE8B(ReadDeviceAddress - 1);		//先写入从设备的地址。表示要向从设备中写地址和数据
	SN7325_i2c_WAITACK();
	SN7325_i2c_WRITE8B(Command);					//写入寄存器的地址,数据将从些地址中读出
	SN7325_i2c_WAITACK();
 
	//SN7325_i2c_RESTART();
	SN7325_i2c_START();
	SN7325_i2c_WRITE8B(ReadDeviceAddress);			//发送器件地址,地址LSB最后一位为0代表写入,1代表读取  
	SN7325_i2c_WAITACK();
	r_byte = SN7325_i2c_READ8B();
	//SN7325_i2c_WAITACK();//lsx add
	SN7325_i2c_NOACK();
	SN7325_i2c_STOP();
 
	//r_byte = SN7325_i2c_READ8B();					//从地址regaddr中读出数据
	return r_byte;
}