单片机模拟IIC和SPI: 调试RTC(RX8010) 和Flash(GD25Q128)

本文详细介绍了在合泰8位单片机BA45F5260上如何调试模拟I2C和SPI通信。通过提供读写ID和数据的函数,成功实现了对GD25Q12芯片的SPI通信。对于I2C,文章指出了初始地址设置的错误并提供了修正后的代码,确保了ACK信号的正常。此外,还涉及到了RTC和Flash在时间对应和数据收集中的应用。
摘要由CSDN通过智能技术生成

应开发需求,在单片机BA45F5260调试模拟I2C和SPI。该单片机为合泰8位专用型单片机,主要应用于烟雾报警器。因UL标准认证需求,本测试板主要用于认证过程数据收集,同时为了更好的时间对应关系,固增加RTC和Flash。

一、模拟SPI

1.1  调试GD25Q12无特别注意试项,读取ID成功,即通信无问题

    

#ifdef SUPPORT_SPI


#define SPI_CLK(data)	(SPI_CLK_PIN = data)
#define SPI_MISO()		(((SPI_MISO_PIN&0x01)==0x01)?1:0)
#define SPI_MOSI(data)	(SPI_MOSI_PIN = data)
/**********************************************************************/
//Name: 		SpiDelayUs()
//Description:															
//Parameters:															
//Return:																
//Date: 		  
//Author:		quanwu.xu  
/**********************************************************************/
static void SpiDelayUs(uint8_t Cnt)
{
	while (Cnt--);
}


/**********************************************************************/
//Name: 		SpiReadWriteByte()
//Description:															
//Parameters:															
//Return:																
//Date: 		  
//Author:		quanwu.xu  
/**********************************************************************/
uint8_t SpiReadWriteByte(uint8_t data)
{
	uint8_t i;
	uint8_t redata = 0;
	
	for(i=0;i<8;i++)
	{
		SPI_CLK(0);
		SpiDelayUs(5);
		if(data & 0x80)
		{
			SPI_MOSI(1);
		}
		else
		{
			SPI_MOSI(0);
		}
		data <<= 1;
		SPI_CLK(1);
		SpiDelayUs(5);
		redata<<=1;
		if(SPI_MISO())
		{
			redata++;
		}
	}
	SPI_CLK(0);
	
	return redata;
}

#endif

1.2 简单测试读写


/**********************************************************************/
//Description:  FlashReadID()												
//Parameters:                        										
//Return:   																
//Date: 
//Author:		quanwu.xu  
/**********************************************************************/
static void FlashReadID(void)
{
	uint16_t Id = 0;
	
	SPI_CHIP_SEL();
	SpiReadWriteByte(DRV_SPI_FLASH_READ_DEVICE_ID);
	SpiReadWriteByte(0x00);
	SpiReadWriteByte(0x00);
	SpiReadWriteByte(0x00);
	Id = SpiReadWriteByte(0x00)<<8;
	Id += SpiReadWriteByte(0x00);
	SPI_CHIP_NSEL();
	if(Id == GD25Q128_DEVICE_ID)
	{
		printf("Device_ID:%x\r\n",Id);
	}
	else
	{
		printf("Read ID err\n");
	}
}


/**********************************************************************/
//Description:  FlashWriteNoCheck()														  
//Parameters:                        												  
//Return:   																  
//Date: 
//Author:		quanwu.xu  
/**********************************************************************/
void FlashWriteNoCheck(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t Length)
{
	uint16_t PageRemainBytes = PAGE_MAX_BYTES - WriteAddr%PAGE_MAX_BYTES;     //the page remain bytes

	if(Length<=PageRemainBytes)
	{
	    PageRemainBytes = Length;
	}

	while(1)
	{
	    FlashWritePage(pBuffer, WriteAddr, PageRemainBytes);
	    if(Length == PageRemainBytes)
	    {
	        break;
	    }
	    else
	    {            
	        pBuffer += PageRemainBytes;
	        WriteAddr+= PageRemainBytes;
	        Length -= PageRemainBytes;
	        if(Length > PAGE_MAX_BYTES)
	        {
	            PageRemainBytes = PAGE_MAX_BYTES;
	        }
	        else
	        {
	            PageRemainBytes = Length;  
	        }
	    }
	}
}


/**********************************************************************/
//Description:  FlashReadByte()														  
//Parameters:                        												  
//Return:   																  
//Date: 
//Author:		quanwu.xu  
/**********************************************************************/
void FlashReadByte(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t Length)
{
	GlobalIntDisable();
	SPI_CHIP_SEL();    

	SpiReadWriteByte(DRV_SPI_FLASH_READ_DATA);  //Fast Read CMD
	SpiReadWriteByte((uint8_t)(ReadAddr>>16));  //24 bits Addr
	SpiReadWriteByte((uint8_t)(ReadAddr>>8));
	SpiReadWriteByte((uint8_t)(ReadAddr));
	while (Length--)
	{		
		*pBuffer = SpiReadWriteByte(0x00);
		pBuffer++;
	}

	SPI_CHIP_NSEL();
	GlobalIntEnable(); 
}

/**********************************************************************/
//Description:  FlashInit()														  
//Parameters:                        												  
//Return:   																  
//Date: 
//Author:		quanwu.xu  
/**********************************************************************/
void FlashInit(void)
{
	uint8_t i = 0;
	uint8_t TestBuf[4] ={'1', '3', '5', '7'};
	uint8_t Read[4] = {0};

	FlashReadID();

	//FlashEraseChip();
	//FlashEraseSector(0);
	FlashWriteNoCheck(TestBuf, 2, 4);
	FlashReadByte(Read, 2, 4);

	for(i=0; i<4; i++)
	{
	    printf("%x ", Read[i]);
	}
	printf("\n");
}

二、模拟I2C

2.1 需要注意规格书地址描述,一开始看到设备地址0x32。直接将读写写成如下

实际地址是7bit,固得不到ACK。

固重新修改读写命令后,ACK信号正常

 2.2 主要代码参考如下

/**********************************************************************/
//Name: 		I2cDelayUs()
//Description:															
//Parameters:															
//Return:																
//Date: 		  
//Author:		quanwu.xu  
/**********************************************************************/
static void I2cDelayUs(uint8_t Cnt)
{
	while(Cnt--);
	GCC_DELAY(5);
}

/**********************************************************************/
//Name:			I2c1Init()
//Description:															
//Parameters:                        									
//Return:   															
//Date:           
//Author:		quanwu.xu  
/**********************************************************************/
void I2c1Init(void)
{
	IIC_1_SCL_OUT();
	IIC_1_SDA_OUT();
	IIC_1_SCL = 0;
	IIC_1_SDA = 0;
}

/**********************************************************************/
//Name:			I2c1DeInit()
//Description:															
//Parameters:                        									
//Return:   															
//Date:           
//Author:		quanwu.xu  
/**********************************************************************/
void I2c1DeInit(void)
{
	IIC_1_SCL_OUT();
	IIC_1_SDA_OUT();
	IIC_1_SCL = 0;
	IIC_1_SDA = 0;
}


/**********************************************************************/
//Name:			I2c1Start()
//Description:															
//Parameters:                        									
//Return:   															
//Date:           
//Author:		quanwu.xu  
/**********************************************************************/
void I2c1Start(void)
{
	IIC_1_SDA_OUT();
	
	IIC_1_SDA=1;
	I2cDelayUs(2);
	IIC_1_SCL=1;
	I2cDelayUs(2);
	IIC_1_SDA=0; 
	I2cDelayUs(2);
	IIC_1_SCL=0;
	I2cDelayUs(2);
}


/**********************************************************************/
//Name:			I2c1Stop()
//Description:															
//Parameters:                        									
//Return:   															
//Date:           
//Author:		quanwu.xu  
/**********************************************************************/
void I2c1Stop(void)
{
	IIC_1_SDA_OUT();
	IIC_1_SDA=0;
	I2cDelayUs(2);
	IIC_1_SCL=1;
	I2cDelayUs(2);
	IIC_1_SDA=1;
	I2cDelayUs(2);
}

/**********************************************************************/
//Name:			I2c1Ack()
//Description:															
//Parameters:                        									
//Return:   															
//Date:           
//Author:		quanwu.xu  
/**********************************************************************/
void I2c1Ack(void)
{
	IIC_1_SCL=0;
	IIC_1_SDA_OUT();
	IIC_1_SDA=0;
	I2cDelayUs(2);
	IIC_1_SCL=1;
	I2cDelayUs(2);
	IIC_1_SCL=0;
}


/**********************************************************************/
//Name:			I2C1NAck()
//Description:															
//Parameters:                        									
//Return:   															
//Date:           
//Author:		quanwu.xu  
/**********************************************************************/
void I2C1NAck(void)
{
	IIC_1_SCL=0;
	IIC_1_SDA_OUT();
	IIC_1_SDA=1;
	I2cDelayUs(2);
	IIC_1_SCL=1;
	I2cDelayUs(2);
	IIC_1_SCL=0;
}

/**********************************************************************/
//Name:			I2c1SendByte()
//Description:															
//Parameters:                        									
//Return:   															
//Date:           
//Author:		quanwu.xu  
/**********************************************************************/
Res I2c1SendByte(uint8_t Data)
{
	uint8_t t = 0;
	uint8_t ucErrTime = 0;


	IIC_1_SDA_OUT();
	IIC_1_SCL=0;				//拉低时钟开始数据传输
	for(t=0;t<8;t++)
	{
		if(Data&0x80)
		{
			IIC_1_SDA=1;
		}
		else
		{
			IIC_1_SDA=0;
		}
		Data<<=1;
		I2cDelayUs(2);
		IIC_1_SCL=1;
		I2cDelayUs(2);
		IIC_1_SCL=0;
	}

	IIC_1_SDA=0;				//SDA输出置0,设为INPUT
	I2cDelayUs(2);
	IIC_1_SCL=1;
	I2cDelayUs(2);

	IIC_1_SDA_IN();
	while(IIC_1_SDA)			//等待应答,也就是等待从设备把SDA拉低
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			IIC_1_SCL=0;
			return FAIL;
		}
	}
	IIC_1_SCL=0;
	return OK; 
}


/**********************************************************************/
//Name:			I2c1ReadByte()
//Description:															
//Parameters:                        									
//Return:   															
//Date:           
//Author:		quanwu.xu  
/**********************************************************************/
uint8_t I2c1ReadByte(void)
{
	uint8_t i=0, Data=0;
	
	IIC_1_SDA_IN();
	I2cDelayUs(2);
	for(i=0;i<8;i++)
	{
		IIC_1_SCL=1;
		I2cDelayUs(2);
		Data<<=1;
		Data|=IIC_1_SDA;
		I2cDelayUs(2);
		IIC_1_SCL=0;
		I2cDelayUs(2);
	}
	return Data;
}

RX8010时钟获取

#define RX8010_ADDR					0x32
#define RX8010_ADDR_W               ((RX8010_ADDR<<1)&0xFE)
#define RX8010_ADDR_R               ((RX8010_ADDR<<1)|0x01)
#define RX8010_REG_WATCH_SEC        0x10
#define RX8010_REG_WATCH_MIN        0x11
#define RX8010_REG_WATCH_HOUR       0x12
#define RX8010_REG_WATCH_WEEK       0x13
#define RX8010_REG_WATCH_DAY        0x14
#define RX8010_REG_WATCH_MON        0x15
#define RX8010_REG_WATCH_YEAR       0x16

/**********************************************************************/
//Description:	Bm8563Init()															  
//Parameters:                        												  
//Return:   																  
//Date:           
//Author:       quanwu.xu  
/**********************************************************************/
void RX8010Init(void)
{
	pTimeTag->Sec = 0;
	pTimeTag->Min = 0;  
	pTimeTag->Hour = 0;
	pTimeTag->Days = 0;
	pTimeTag->WeekDays = 0;  
	pTimeTag->Month = 0;
	pTimeTag->Year = 0;

	GetRX8010Data();
}




/**********************************************************************/
//Description:	BcdFormatConversion()									
//Parameters:                        									
//Return:   															
//Date:           
//Author:       quanwu.xu  
/**********************************************************************/
void BcdToDecConversion(TimeApi* pTime, uint8_t* DataBuf)
{
	pTime->Sec = ((DataBuf[Sec]>>4)&0x07)*10 + (DataBuf[Sec]&0x0F);
	pTime->Min = ((DataBuf[Min]>>4)&0x07)*10 + (DataBuf[Min]&0x0F);
	pTime->Hour = ((DataBuf[Hour]>>4)&0x03)*10 + (DataBuf[Hour]&0x0F);
	pTime->Days = ((DataBuf[Days]>>4)&0x03)*10 + (DataBuf[Days]&0x0F);
	pTime->WeekDays = (DataBuf[WeekDays]&0x07);
	pTime->Month = ((DataBuf[Mon]>>4)&0x01)*10 + (DataBuf[Mon]&0x0F);
	pTime->Year = ((DataBuf[Years]>>4)&0x0F)*10 + (DataBuf[Years]&0x0F);
}

/**********************************************************************/
//Description:	DecToBcdConversion()								
//Parameters:                        								
//Return:   														
//Date:           
//Author:       quanwu.xu  
/**********************************************************************/
void DecToBcdConversion(TimeApi* pTime, uint8_t* DataBuf)
{
	DataBuf[Sec] = ((((pTime->Sec)/10)&0x07)<<4) + (((pTime->Sec)%10)&0x0F);
	DataBuf[Min] = ((((pTime->Min)/10)&0x07)<<4) + (((pTime->Min)%10)&0x0F);
	DataBuf[Hour] = ((((pTime->Hour)/10)&0x03)<<4) + (((pTime->Hour)%10)&0x0F);
	DataBuf[Days] = ((((pTime->Days)/10)&0x03)<<4) + (((pTime->Days)%10)&0x0F);
	DataBuf[WeekDays] = (pTime->WeekDays)&0x07;     
	DataBuf[Mon] = ((((pTime->Month)/10)&0x01)<<4) + (((pTime->Month)%10)&0x0F);
	DataBuf[Years] = ((((pTime->Year)/10)&0x0F)<<4) + (((pTime->Year)%10)&0x0F);
}


/**********************************************************************/
//Description:	Bm8563Init()															  
//Parameters:                        												  
//Return:   																  
//Date:           
//Author:       quanwu.xu  
/**********************************************************************/
void GetRX8010Data(void)
{
	uint8_t i = 0;
	uint8_t ReadBuf[BUF_LENGTH] = {0};
	//uint8_t WriteBuf[BUF_LENGTH] = {0};

	//1、start
	I2c1Start();

	//2、write addr
	I2c1SendByte(RX8010_ADDR_W);

	//3、write data reg
	I2c1SendByte(RX8010_REG_WATCH_SEC);

	//4、start
	I2c1Start();

	//5、read addr reg
	I2c1SendByte(RX8010_ADDR_R);

	//6、read data
	GCC_DELAY(1000);
	for(i=0; i<BUF_LENGTH; i++)
	{
		ReadBuf[i]=I2c1ReadByte();
		if(i == (BUF_LENGTH-1))
		{
			I2C1NAck();
		}
		else
		{
			I2c1Ack();
		}
		GCC_DELAY(100);
	}

	//7、stop
	I2c1Stop();

	//printf("\nIIC:\n");
	//printf("%x, ", ReadBuf[2]);
	//printf("%x, ", ReadBuf[1]);
	//printf("%x\n", ReadBuf[0]);

	BcdToDecConversion(pTimeTag, ReadBuf);
	printf("T>>%d:%d:%d\n", pTimeTag->Hour, pTimeTag->Min, pTimeTag->Sec);

	//DecToBcdConversion(pTimeTag, WriteBuf);
	//printf("%x:%x:%x\n\n\n", WriteBuf[2]|(ReadBuf[2]&0xC0), WriteBuf[1]|(ReadBuf[1]&0x80), WriteBuf[0]|(ReadBuf[0]&0x80));
}


/**********************************************************************/
//Description:	Bm8563Init()															  
//Parameters:                        												  
//Return:   																  
//Date:           
//Author:       quanwu.xu  
/**********************************************************************/
void SetRX8010Data(TimeApi* pTime)
{
	uint8_t i = 0;
	uint8_t WriteBuf[BUF_LENGTH] = {0};

	DecToBcdConversion(pTime, WriteBuf);

	//1、start
	I2c1Start();

	//2、write addr
	I2c1SendByte(RX8010_ADDR_W);

	//3、write data reg
	I2c1SendByte(RX8010_REG_WATCH_SEC);

	//4、Write Data
	GCC_DELAY(1000);
	for(i=0; i<BUF_LENGTH; i++)
	{
		I2c1SendByte(WriteBuf[i]);
	}

	//5、stop
	I2c1Stop();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值