合泰HTF52352 IIC 驱动外部RTC时钟BM8563

IIC类型

              ⑴模拟IIC

              ⑵硬件IIC

ACK:确认字符ACK (Acknowledge character)即是确认字符,在数据通信中,接收站发给发送站的一种传输类控制字符。表示发来的数据已确认接收无误。在TCP/IP协议中,如果接收方成功的接收到数据,那么会回复一个ACK数据。通常ACK信号有自己固定的格式,长度大小,由接收方回复给发送方。

NACK:否认字符NACK(Negative Acknowledge) 含义为接收站对所收到的报文进行检查,若发现错误,便向发送站发送否认回答NAK,表示报文有错,并要求重发。

SYN:同步字符SYN( Synchronousidle)表示无论是中心结点还是远地结点,在发送信息或回答之前,都要先发送同步字符,用以实现或保持发送站和接收站之间的同步。

DLE:转义字符DLE( Data Link Escape)用于改变紧随其后的有限个字符的意义,以提供附加的数据链路控制字符。

IIC总线:IIC一共有两条总线,一条是SDA(Serial Data)数据总线,用来传输数据的;一条是SCL(Serial clock line)时钟线,用来控制发送数据时序的。总线不忙时,数据线和时钟线保持高电平。

BM8563 IIC起始信号:时钟线为高电平时,数据线出现一个下降沿为起始信号。注意:最后时钟线要拉低

BM8563 IIC终止信号:时钟线为高电平时,数据线出现一个上升沿为终止信号。

BM8563 IIC数据位传送:每个时钟信号(即SCL总线的由一个高电平跳变为低电平的周期信号)传送一个数据位;在SCL时钟线低电平时才允许SDA数据线改变,SCL时钟线高电平时SDA数据线应该保持稳定,否则SDA数据线上的数据会变成起始、终止信号。

BM8563 IIC应答位:每8个字节后,后面会有一个应答位。主设备写操作时,写完8位字节后需要读取从设备发过来的应答;主设备读操作时,读完8位字节后需要给给从设备主动发送一个应答。

BM8563从地址:前面七位为从设备地址,第八位为读写操作位。即写操作为0xA2,读操作为0xA3。

BM8563 写时序:⑴IIC Start起始信号

                              ⑵IIC Write从地址0xA2

                              ⑶读取从器件应答信号

                              ⑷IIC Write字地址(寄存器地址)

                             ⑸读取从器件应答信号

                              ⑹IIC Write数据

                              ⑺读取从器件应答信号

                              ⑻IIC Stop终止信号

注意:如果需要一次性写进去,利用数组重复⑹⑺操作即可。

自动增量寄存器字地址:第一个操作的寄存器是所写的寄存器字地址所对应的寄存器,重复⑹⑺下一个操作的的寄存器为所写字地址+1。

BM8563 读时序:⑴IIC Start起始信号

                              ⑵IIC Write从地址0xA2

                              ⑶读取从器件应答信号

                              ⑷IIC Write字地址(寄存器地址)

                              ⑸读取从器件应答信号

                              ⑹IIC Start起始信号

                              ⑺IIC Write从地址0xA3

                              ⑻读取从器件应答信号

                              ⑼IIC Read数据

                              ⑽给从设备发送应答信号

                                ⑾IIC Stop终止信号

注意:如果需要一次性读出来,利用数组存重复⑹⑺操作即可。

寄存器地址

#ifndef _IIC_H_
#define _IIC_H_
 
#define EEPROM_I2C_WR				0		/* 写控制bit */
#define EEPROM_I2C_RD				1		/* 读控制bit */
#define EEPROM_DEV_ADDR				0xA0	/* 24xx02的设备地址 */
#define EEPROM_PAGE_SIZE		  	8		/* 24xx02的页面大小 */
#define EEPROM_SIZE				  	256		/* 24xx02总容量 */
 

 
#define IIC_SCL_SET()						GPIO_SetOutBits(HT_GPIOA, GPIO_PIN_0)
#define IIC_SCL_RESET()					GPIO_ClearOutBits(HT_GPIOA, GPIO_PIN_0)
	
#define IIC_SDA_SET()						GPIO_SetOutBits(HT_GPIOA, GPIO_PIN_1)
#define IIC_SDA_RESET()					GPIO_ClearOutBits(HT_GPIOA, GPIO_PIN_1)


void IIC_Init(void);
void Systick_Delay_ms(u32 ms);
void Systick_Delay_us(u32 us);
void IIC_Start(void);
void IIC_Stop(void);
uint8_t IN_SDA(void);
void IIC_RTC_SDA_IN(void);
void IIC_RTC_SDA_OUT(void);
void IIC_Ack(uint8_t a);
void IIC_Write_Byte(uint8_t data);
uint8_t IIC_Read_Byte(void);
void BM8563_Write_Byte(void);
void BM8563_Read_Byte(void);
uint8_t BM8563_Write(uint8_t sla,uint8_t suba,uint8_t data);
uint8_t BM8563_Read(uint8_t sla,uint8_t suba);
uint8_t BM8563_Read_data(uint8_t sla,uint8_t suba,uint8_t *s, uint8_t length);
void BM8563_Write_Byte(void);
void BM8563_Init(void);

	
#endif
#include "ht32.h"
#include "ht32_board.h"
#include "iic.h"
#include "usart.h"

uint8_t ReadData[7] = {0};

volatile uint8_t ack = 0;
volatile uint8_t bm_status = 0;//如果BM时钟芯片无应答,则为0,。应答正常则为1.

void IIC_Init(void)
{
	CKCU_PeripClockConfig_TypeDef CCLOCK;
	
	CCLOCK.Bit.PA    = 1;
	CCLOCK.Bit.AFIO  = 1;
	
	CKCU_PeripClockConfig(CCLOCK, ENABLE);
	
	AFIO_GPxConfig(GPIO_PA, GPIO_PIN_0, AFIO_FUN_GPIO);
	AFIO_GPxConfig(GPIO_PA, GPIO_PIN_1, AFIO_FUN_GPIO);
	
	/* Configure the GPIO pin                                                                                 */
	//GPIO_PullResistorConfig(HT_GPIOA, GPIO_PIN_0, GPIO_PR_DISABLE);
	//GPIO_DriveConfig(HT_GPIOA, GPIO_PIN_0, GPIO_DV_8MA);
	GPIO_DirectionConfig(HT_GPIOA, GPIO_PIN_0, GPIO_DIR_OUT);
	
//	GPIO_PullResistorConfig(HT_GPIOA, GPIO_PIN_1, GPIO_PR_DISABLE);
//	GPIO_DriveConfig(HT_GPIOA, GPIO_PIN_1, GPIO_DV_8MA);
	GPIO_DirectionConfig(HT_GPIOA, GPIO_PIN_1, GPIO_DIR_OUT);
	
	IIC_Stop();
}


void IIC_RTC_SDA_IN(void)
{

	GPIO_DirectionConfig(HT_GPIOA, GPIO_PIN_1, GPIO_DIR_IN);
	GPIO_InputConfig(HT_GPIOA, GPIO_PIN_1, ENABLE);
}



void IIC_RTC_SDA_OUT(void)
{
	GPIO_DirectionConfig(HT_GPIOA, GPIO_PIN_1, GPIO_DIR_OUT);
}

void Systick_Delay_ms(uint32_t ms)
{
	uint32_t i;
	
	/* SYSTICK configuration */
	SYSTICK_ClockSourceConfig(SYSTICK_SRC_STCLK);       // 即默认选择了外部参考时钟HSI(8MHz/8)
	SYSTICK_SetReloadValue(SystemCoreClock / 8 / 1000); // (CK_SYS/8/1000) = 1ms 
	SYSTICK_IntConfig(DISABLE);                         // 不开启中断
 
	/* 打开SysTick计数器 */
	SYSTICK_CounterCmd(SYSTICK_COUNTER_CLEAR);
	SYSTICK_CounterCmd(SYSTICK_COUNTER_ENABLE);
	
	for( i = 0;i < ms;i++ )
	{
		while( !( (SysTick->CTRL) & (1<<16) ) ); 
	}
 
	/* 关闭SysTick计数器 */
	SYSTICK_CounterCmd(SYSTICK_COUNTER_DISABLE);
	/* 复位SysTick计数器 */
	SYSTICK_CounterCmd(SYSTICK_COUNTER_CLEAR);
}
 
void Systick_Delay_us(uint32_t us)
{
	uint32_t i;
	
	/* SYSTICK configuration */
	SYSTICK_ClockSourceConfig(SYSTICK_SRC_STCLK);       // 即默认选择了外部参考时钟HSI(8MHz/8)
	SYSTICK_SetReloadValue(SystemCoreClock / 8 / 1000000); // (CK_SYS/8/1000000) = 1us 
	SYSTICK_IntConfig(DISABLE);                         // 不开启中断
 
	/* 打开SysTick计数器 */
	SYSTICK_CounterCmd(SYSTICK_COUNTER_CLEAR);
	SYSTICK_CounterCmd(SYSTICK_COUNTER_ENABLE);
 
	for( i = 0;i < us;i++ )
	{
		while( !( (SysTick->CTRL) & (1<<16) ) ); 
	}
 
	/* 关闭SysTick计数器 */
	SYSTICK_CounterCmd(SYSTICK_COUNTER_DISABLE);
	/* 复位SysTick计数器 */
	SYSTICK_CounterCmd(SYSTICK_COUNTER_CLEAR);
}

/******************************************************************************
* Function Name --> IIC启动
* Description   --> SCL高电平期间,SDA由高电平突变到低电平时启动总线
*                   SCL: __________
*                                  \__________
*                   SDA: _____
*                             \_______________
* Input         --> none
* Output        --> none
* Reaturn       --> none 
******************************************************************************/
void IIC_Start(void)
{	
	IIC_RTC_SDA_OUT();
	
	IIC_SDA_SET();
	IIC_SCL_SET();	//在SCL高电平时,SDA为下降沿时候总线停止
	Systick_Delay_us(2);
	IIC_SDA_RESET();	
	Systick_Delay_us(2);
	IIC_SCL_RESET();

}
/******************************************************************************
* Function Name --> IIC停止
* Description   --> SCL高电平期间,SDA由低电平突变到高电平时停止总线
*                   SCL: --------
*                                  __________
*                   SDA: _________/
* Input         --> none
* Output        --> none
* Reaturn       --> none 
******************************************************************************/
void IIC_Stop(void)
{
	IIC_RTC_SDA_OUT();
	
	IIC_SDA_RESET();
	IIC_SCL_SET();
	Systick_Delay_us(2);
	IIC_SDA_SET();

}

/******************************************************************************
* Function Name --> IIC应答
* Description   --> 
                           _   _
*                   SCL: _/ \_/ \_
*                       ___   _
*                   SDA:   \_/
* Input         --> none
* Output        --> none
* Reaturn       --> none 
******************************************************************************/
uint8_t IN_SDA(void)
{
	IIC_RTC_SDA_IN();
		
	
	if(GPIO_ReadInBit(HT_GPIOA, GPIO_PIN_1))
	{
//		Usart_Sendbyte(HT_USART1,0x01);
		return 1;
		
	}
		else
	{
//		Usart_Sendbyte(HT_USART1,0x00);
		return 0;	
	}
	
}


void IIC_Ack(uint8_t a)
{
	IIC_RTC_SDA_OUT();
	
	if(a) IIC_SDA_SET();
	else  IIC_SDA_RESET();
	
	IIC_SCL_SET();
	Systick_Delay_us(2);
	IIC_SCL_RESET();
}
/******************************************************************************
* Function Name --> 向IIC总线发送一个字节数据
* Description   --> 向 BM8563 写一个字节的数据
* Input         --> dat:要发送的数据
* Output        --> none
* Reaturn       --> ack:返回应答信号
******************************************************************************/
void IIC_Write_Byte(uint8_t data)
{
	uint8_t i;

	IIC_RTC_SDA_OUT();

	IIC_SCL_RESET();
	
	for(i=0;i<8;i++)
	{
		
		
		if((data<<i)&0x80)
		{
			IIC_SDA_SET();		
		}
		else
		{
			IIC_SDA_RESET();
		}
		
		IIC_SCL_SET();	
		Systick_Delay_us(2);
		IIC_SCL_RESET();
	}	
	
	IIC_SDA_RESET();	//释放数据线
	Systick_Delay_us(2);
	
	if(IN_SDA())//读取应答信号
	{
		ack = 1;
	}
	else
	{
		ack = 0;	
	}

	
	
	IIC_SCL_SET();	//为SCL下降做准备
	Systick_Delay_us(2);
	IIC_SCL_RESET();	
	
}

/******************************************************************************
* Function Name --> 从IIC总线上读取一个字节数据
* Description   --> none
* Input         --> none
* Output        --> none
* Reaturn       --> x:读取到的数据
******************************************************************************/
uint8_t IIC_Read_Byte(void)
{
	uint8_t i;
	uint8_t data = 0;

	IIC_RTC_SDA_IN();
	
	for(i=0;i<8;i++)
	{	
		
		data = data << 1;
		
		if(IN_SDA())
		{
			
			data = data+1;
//			Usart_Sendbyte(HT_USART1,data);
	
			
		}
		
		IIC_SCL_SET();
		Systick_Delay_us(2);
		IIC_SCL_RESET();
	}
	
	return data;	//返回读取到的数据
}

uint8_t BM8563_Write(uint8_t sla,uint8_t suba,uint8_t data)
{
	IIC_Start();
	
	IIC_Write_Byte(sla);
	if(ack==1) return 0;
	IIC_Write_Byte(suba);
	if(ack==1) return 0;
	
	
	IIC_Write_Byte(data);
	if(ack==1) return 0;
	
	IIC_Stop();
	return 1;
}

uint8_t BM8563_Read(uint8_t sla,uint8_t suba)
{
	uint8_t data;
	uint8_t i;
	uint8_t trdata[7]={0};
	
	IIC_Start();
	
	IIC_Write_Byte(sla-1);
	if(ack==1) return 0;
	
	IIC_Write_Byte(suba);
	if(ack==1) return 0;
	
	IIC_Start();

	IIC_Write_Byte(sla);
	if(ack==1) return 0;
	
	for(i=0; i<7; i++)
	{
		data = IIC_Read_Byte();
	
		IIC_Ack(0);
		
		if(i==0) trdata[i] = data&0x7F;//秒
		if(i==1) trdata[i] = data&0x7F;//分
		if(i==2) trdata[i] = data&0x3F;//时
		if(i==3) trdata[i] = data&0x3F;//日
		if(i==4) trdata[i] = data&0x07;//星期
		if(i==5) trdata[i] = data&0x1F;//月
		if(i==6) trdata[i] = data&0xFF;//年

		Usart_Sendbyte(HT_USART1,trdata[i]);
	}
	
	
	IIC_Stop();
	
	return 1;
}

uint8_t BM8563_Read_data(uint8_t sla,uint8_t suba,uint8_t *s, uint8_t length)
{
	uint8_t data;
	uint8_t i;
	
	IIC_Start();
	
	IIC_Write_Byte(sla-1);
	if(ack==1) return 0;
	
	IIC_Write_Byte(suba);
	if(ack==1) return 0;
	
	IIC_Start();

	IIC_Write_Byte(sla);
	if(ack==1) return 0;
	
	for(i=0; i<length; i++)
	{
		data = IIC_Read_Byte();
	
		IIC_Ack(0);
		
		ReadData[i] = data;

	}
	
	
	IIC_Stop();
	
	return 1;
}

void BM8563_Init(void)//时间初始化2022.8.15.星期一.16:31:50 
{
	BM8563_Write(0xA2,0x00,0x00);//控制状态寄存器0
	BM8563_Write(0xA2,0x01,0x00);//控制状态寄存器1
	BM8563_Write(0xA2,0x02,0x50);//秒
	BM8563_Write(0xA2,0x03,0x31);//分
	BM8563_Write(0xA2,0x04,0x16);//小时
	BM8563_Write(0xA2,0x05,0x15);//日
	BM8563_Write(0xA2,0x06,0x01);//星期
	BM8563_Write(0xA2,0x07,0x08);//月
	BM8563_Write(0xA2,0x08,0x22);//年   
}


//-----------------------------------------------------------------------------
#include "ht32.h"
#include "ht32_board.h"
#include "led.h"
#include "key.h"
#include "time.h"
#include "pwm.h"
#include "usart.h"
#include "ht32f5xxxx_gpio.h"
#include "iic.h"
#include "stdio.h"

//-----------------------------------------------------------------------------
//static void delay(uint16_t data)
//{
//	uint16_t i;
//	
//	while(data--)
//	{
//		for(i=0; i<1000; i++);
//	}
//	
//}
uint8_t i;

static void Init()
{
	Key_Init();
	Timer_Init();
  Led_Init();
	USART_Configuration();//串口初始化
	IIC_Init();
//	GPTM_PWM_init();
}

int main(void)
{
	
	Init();
	
	Systick_Delay_ms(20);

	BM8563_Init();
	
	Systick_Delay_ms(20);

	
	while(1)
	{
		BM8563_Read(0xA3,0x02);

		Systick_Delay_ms(1000);

	}
}

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值